1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-05-28 23:41:32 +00:00

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? - how to revert included files?
- go to error in include files - go to error in include files
- BOM in upload/download? - 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 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? 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": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "npm run test-node", "test": "npm run test-node",
"test-one": "mocha --recursive --timeout 60000", "test-one": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000",
"test-node": "mocha --recursive --timeout 60000 test/cli", "test-node": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli",
"test-worker": "mocha --recursive --timeout 60000 test/cli/testworker.js", "test-worker": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli/testworker.js",
"test-profile": "mocha --recursive --timeout 60000 --prof test/cli" "test-profile": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 --prof test/cli"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -36,6 +36,16 @@ body {
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<script src="bootstrap/js/bootstrap.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script>
<script src="FileSaver.js/FileSaver.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/util.js"></script>
<script src="gen/pixed/pixeleditor.js"></script> <script src="gen/pixed/pixeleditor.js"></script>

View File

@ -5,7 +5,7 @@
#pragma data-name (push,"CHARS") #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,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,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, 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() { void set_sounds() {
/*
byte i; byte i;
byte enable = 0x1 | 0x2 | 0x8;
// missile fire sound // missile fire sound
if (missiles[7].ypos != YOFFSCREEN) { if (missiles[PLYRMISSILE].ypos != YOFFSCREEN) {
cv_set_frequency(CV_SOUNDCHANNEL_0, 2000-missiles[7].ypos*4); APU.pulse[0].period_low = missiles[PLYRMISSILE].ypos ^ 0xff;
cv_set_attenuation(CV_SOUNDCHANNEL_0, 18); APU.pulse[0].len_period_high = 0;
APU.pulse[0].control = 0x80 | 0x30 | 6;
} else { } else {
cv_set_attenuation(CV_SOUNDCHANNEL_0, 32); APU.pulse[0].control = 0x30;
} }
// enemy explosion sound // enemy explosion sound
if (enemy_exploding) { if (player_exploding && player_exploding < 8) {
cv_set_frequency(CV_SOUNDCHANNEL_1, 500+enemy_exploding*64); APU.noise.control = 4;
cv_set_attenuation(CV_SOUNDCHANNEL_1, 14); APU.noise.period = 8 + player_exploding;
} else { APU.noise.len = 15;
cv_set_attenuation(CV_SOUNDCHANNEL_1, 32); } 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); // set diving sounds for spaceships
// player explosion for (i=0; i<2; i++) {
if (player_exploding && player_exploding < 15) { register AttackingEnemy* a = i ? &attackers[4] : &attackers[0];
cv_set_frequency(CV_SOUNDCHANNEL_2, player_exploding*256); if (a->findex && !a->returning) {
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 4+player_exploding); byte y = a->y >> 8;
cv_set_noise(true, 3); APU.triangle.counter = 0xc0;
} else { APU.triangle.period_low = y;
// set diving sounds for spaceships APU.triangle.len_period_high = 1;
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 32); enable |= 0x4;
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;
}
} }
} }
*/ APU.status = enable;
} }
static char starx[32]; 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() { void main() {
setup_tileset(); setup_tileset();
init_apu();
init_stars(); init_stars();
player_score = 0; player_score = 0;
while (1) { 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 { export interface OpcodeMetadata {
minCycles: number; minCycles: number;
maxCycles: number; maxCycles: number;
insnLength: number; insnlength: number;
opcode: number;
} }
interface CpuState { 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, A:number, X:number, Y:number, SP:number, R:boolean,
N,V,D,Z,C:boolean*/ N,V,D,Z,C:boolean*/
}; };
interface EmuState {c:CpuState}; interface EmuState {c:CpuState, b?:number[]};
type DisasmLine = {line:string, nbytes:number}; type DisasmLine = {line:string, nbytes:number};
export interface Platform { export interface Platform {
@ -44,6 +51,7 @@ export interface Platform {
saveState?() : EmuState; saveState?() : EmuState;
getDebugCallback?() : any; // TODO getDebugCallback?() : any; // TODO
getSP?() : number; getSP?() : number;
getOriginPC?() : number;
getDebugCategories() : string[]; getDebugCategories() : string[];
getDebugInfo(category:string, state:EmuState) : string; getDebugInfo(category:string, state:EmuState) : string;
@ -188,7 +196,7 @@ abstract class BaseFrameBasedPlatform extends BaseDebugPlatform {
////// 6502 ////// 6502
function getToolForFilename_6502(fn:string) : string { export function getToolForFilename_6502(fn:string) : string {
if (fn.endsWith(".pla")) return "plasm"; if (fn.endsWith(".pla")) return "plasm";
if (fn.endsWith(".c")) return "cc65"; if (fn.endsWith(".c")) return "cc65";
if (fn.endsWith(".s")) return "ca65"; if (fn.endsWith(".s")) return "ca65";
@ -231,14 +239,19 @@ export abstract class Base6502Platform extends BaseFrameBasedPlatform {
getToolForFilename = getToolForFilename_6502; getToolForFilename = getToolForFilename_6502;
getDefaultExtension() { return ".a"; }; getDefaultExtension() { return ".a"; };
// TODO: Memory category getDebugCategories() {
getDebugCategories() { return ["CPU"]; } return ['CPU','ZPRAM','Stack'];
getDebugInfo(category:string, state:EmuState) { }
return cpuStateToLongString_6502(state.c); 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) { function decodeFlags(c) {
var s = ""; var s = "";
s += c.N ? " N" : " -"; 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 // TODO: more intelligent maximum cycles
return { return {
opcode:opcode, opcode:opcode,
@ -282,7 +295,7 @@ function getOpcodeMetadata_6502(opcode, address) {
////// Z80 ////// Z80
function cpuStateToLongString_Z80(c) { export function cpuStateToLongString_Z80(c) {
function decodeFlags(flags) { function decodeFlags(flags) {
var flagspec = "SZ-H-VNC"; var flagspec = "SZ-H-VNC";
var s = ""; var s = "";
@ -298,7 +311,7 @@ function cpuStateToLongString_Z80(c) {
; ;
} }
function BusProbe(bus : MemoryBus) { export function BusProbe(bus : MemoryBus) {
var active = false; var active = false;
var callback; var callback;
this.activate = function(_callback) { this.activate = function(_callback) {
@ -328,7 +341,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
_cpu; _cpu;
probe; probe;
newCPU(membus, iobus) { newCPU(membus : MemoryBus, iobus : MemoryBus) {
this.probe = new BusProbe(membus); this.probe = new BusProbe(membus);
this._cpu = Z80_fast({ this._cpu = Z80_fast({
display: {}, display: {},
@ -442,13 +455,17 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
// TODO // TODO
//this.getOpcodeMetadata = function() { } //this.getOpcodeMetadata = function() { }
getDebugCategories() { return ["CPU"]; } getDebugCategories() {
getDebugInfo(category:string, state:EmuState) { return ['CPU'];
return cpuStateToLongString_Z80(state.c); }
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(".c")) return "sdcc";
if (fn.endsWith(".s")) return "sdasz80"; if (fn.endsWith(".s")) return "sdasz80";
if (fn.endsWith(".ns")) return "naken"; if (fn.endsWith(".ns")) return "naken";
@ -456,6 +473,60 @@ function getToolForFilename_z80(fn) {
return "z80asm"; 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 /// MAME SUPPORT
declare var FS, ENV, Module; // mame emscripten declare var FS, ENV, Module; // mame emscripten
@ -733,3 +804,4 @@ export function BaseMAMEPlatform() {
return null; // TODO return null; // TODO
} }
} }

View File

@ -1,15 +1,17 @@
"use strict"; "use strict";
import { hex } from "./util";
// external modules // external modules
declare var jt, Javatari, Z80_fast, CPU6809; declare var jt, Javatari, Z80_fast, CPU6809;
// Emulator classes // 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; return (Math.random() * 256) & 0xff;
} }
@ -29,7 +31,7 @@ function __createCanvas(mainElement:HTMLElement, width:number, height:number) {
return canvas; 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 self = this;
var canvas, ctx; var canvas, ctx;
var imageData, arraybuf, buf8, datau32; 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 self = this;
var canvas, ctx; var canvas, ctx;
var persistenceAlpha = 0.5; var persistenceAlpha = 0.5;
@ -207,12 +209,14 @@ var VectorVideo = function(mainElement:HTMLElement, width:number, height:number)
} }
} }
var RAM = function(size:number) { export class RAM {
var memArray = new ArrayBuffer(size); mem : Uint8Array;
this.mem = new Uint8Array(memArray); 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 intervalMsec = 1000.0 / frequencyHz;
var running; var running;
var lastts = 0; 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 = ""; var s = "";
// TODO: show scrollable RAM for other platforms // TODO: show scrollable RAM for other platforms
for (var ofs=0; ofs<ramlen; ofs+=0x10) { for (var ofs=0; ofs<ramlen; ofs+=0x10) {
@ -285,7 +289,7 @@ function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
return s; return s;
} }
var Keys = { export const Keys = {
VK_ESCAPE: {c: 27, n: "Esc"}, VK_ESCAPE: {c: 27, n: "Esc"},
VK_F1: {c: 112, n: "F1"}, VK_F1: {c: 112, n: "F1"},
VK_F2: {c: 113, n: "F2"}, 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); 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) { video.setKeyboardEvents(function(key,code,flags) {
var o = map[key]; var o = map[key];
if (o && func) { if (o && func) {
@ -415,7 +419,7 @@ function setKeyboardFromMap(video, switches, map, func) {
}); });
} }
function makeKeycodeMap(table) { export function makeKeycodeMap(table) {
var map = {}; var map = {};
for (var i=0; i<table.length; i++) { for (var i=0; i<table.length; i++) {
var entry = table[i]; var entry = table[i];
@ -424,7 +428,7 @@ function makeKeycodeMap(table) {
return map; return map;
} }
function padBytes(data, len) { export function padBytes(data, len) {
if (data.length > len) { if (data.length > len) {
throw Error("Data too long, " + data.length + " > " + len); throw Error("Data too long, " + data.length + " > " + len);
} }
@ -433,8 +437,12 @@ function padBytes(data, len) {
return r.mem; 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 // TODO: better performance, check values
function AddressDecoder(table, options) { export function AddressDecoder(table : AddressDecoderEntry[], options?:AddressDecoderOptions) {
var self = this; var self = this;
function makeFunction(lo, hi) { function makeFunction(lo, hi) {
var s = ""; var s = "";
@ -458,3 +466,45 @@ function AddressDecoder(table, options) {
return makeFunction(0x0, 0xffff).bind(self); 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"; "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 self = this;
var width = fmt.w; var width = fmt.w;
var height = fmt.h; var height = fmt.h;
@ -232,7 +234,7 @@ function convertToHexStatements(s) {
}); });
} }
function parseHexBytes(s) { export function parseHexBytes(s) {
var arr = []; var arr = [];
var m; var m;
while (m = pixel_re.exec(s)) { while (m = pixel_re.exec(s)) {
@ -248,7 +250,7 @@ function parseHexBytes(s) {
return arr; return arr;
} }
function replaceHexBytes(s, bytes) { export function replaceHexBytes(s, bytes) {
var result = ""; var result = "";
var m; var m;
var li = 0; var li = 0;
@ -384,20 +386,20 @@ function convertPaletteBytes(arr,r0,r1,g0,g1,b0,b1) {
return result; return result;
} }
var palette; export var palette;
var paletteSets; export var paletteSets;
var paletteSetIndex=0; export var paletteSetIndex=0;
var currentPixelEditor; export var currentPixelEditor;
var parentSource; export var parentSource;
var parentOrigin; export var parentOrigin;
var allimages; export var allimages;
var currentFormat; export var currentFormat;
var currentByteStr; export var currentByteStr;
var currentPaletteStr; export var currentPaletteStr;
var currentPaletteFmt; export var currentPaletteFmt;
var allthumbs; export var allthumbs;
function pixelEditorDecodeMessage(e) { export function pixelEditorDecodeMessage(e) {
parentSource = e.source; parentSource = e.source;
parentOrigin = e.origin; parentOrigin = e.origin;
currentFormat = e.data.fmt; currentFormat = e.data.fmt;

View File

@ -1,5 +1,11 @@
"use strict"; "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 = [ var APPLE2_PRESETS = [
{id:'sieve.c', name:'Sieve'}, {id:'sieve.c', name:'Sieve'},
{id:'mandel.c', name:'Mandelbrot'}, {id:'mandel.c', name:'Mandelbrot'},
@ -19,6 +25,8 @@ var GR_HIRES = 8;
var Apple2Platform = function(mainElement) { var Apple2Platform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new (Base6502Platform as any)();
var cpuFrequency = 1023000; var cpuFrequency = 1023000;
var cpuCyclesPerLine = 65; var cpuCyclesPerLine = 65;
var cpu, ram, bus; var cpu, ram, bus;
@ -39,9 +47,7 @@ var Apple2Platform = function(mainElement) {
// value to add when reading & writing each of these banks // value to add when reading & writing each of these banks
// bank 1 is E000-FFFF, bank 2 is D000-DFFF // bank 1 is E000-FFFF, bank 2 is D000-DFFF
var bank2rdoffset=0, bank2wroffset=0; var bank2rdoffset=0, bank2wroffset=0;
this.__proto__ = new Base6502Platform();
this.getPresets = function() { this.getPresets = function() {
return APPLE2_PRESETS; return APPLE2_PRESETS;
} }

View File

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

View File

@ -1,5 +1,8 @@
"use strict"; "use strict";
import { Platform, BaseZ80Platform, BaseMAMEPlatform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes } from "../emu";
var BASEZ80_PRESETS = [ var BASEZ80_PRESETS = [
{id:'simple1.c', name:'Multiply by 2'}, {id:'simple1.c', name:'Multiply by 2'},
{id:'simple2.c', name:'Divide by 4'}, {id:'simple2.c', name:'Divide by 4'},
@ -11,7 +14,7 @@ var BASEZ80_PRESETS = [
var Base_Z80Platform = function(mainElement) { var Base_Z80Platform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom, timer; var cpu, ram, membus, iobus, rom, timer;
@ -22,13 +25,13 @@ var Base_Z80Platform = function(mainElement) {
this.start = function() { this.start = function() {
ram = new RAM(0x8000); ram = new RAM(0x8000);
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }], [0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }],
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }], [0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }],
]), ]),
isContended: function() { return false; }, isContended: function() { return false; },
}; };
this.readAddress = membus.read; 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"; "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 = [ var GALAXIAN_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'}, {id:'gfxtest.c', name:'Graphics Test'},
{id:'shoot2.c', name:'Solarian Game'}, {id:'shoot2.c', name:'Solarian Game'},
@ -35,7 +39,7 @@ var SCRAMBLE_KEYCODE_MAP = makeKeycodeMap([
var GalaxianPlatform = function(mainElement, options) { var GalaxianPlatform = function(mainElement, options) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
options = options || {}; options = options || {};
var romSize = options.romSize || 0x4000; var romSize = options.romSize || 0x4000;
@ -45,7 +49,9 @@ var GalaxianPlatform = function(mainElement, options) {
var missileWidth = options.missileWidth || 4; var missileWidth = options.missileWidth || 4;
var missileOffset = options.missileOffset || 0; 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 video, audio, timer, pixels;
var psg1, psg2; var psg1, psg2;
var inputs; var inputs;
@ -96,7 +102,7 @@ var GalaxianPlatform = function(mainElement, options) {
for (var sprnum=7; sprnum>=0; sprnum--) { for (var sprnum=7; sprnum>=0; sprnum--) {
var base = (sprnum<<2) + 0x40; var base = (sprnum<<2) + 0x40;
var base0 = oram.mem[base]; 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); var yy = (sl - sy);
if (yy >= 0 && yy < 16) { if (yy >= 0 && yy < 16) {
var sx = oram.mem[base+3] + 1; // +1 pixel offset from tiles var sx = oram.mem[base+3] + 1; // +1 pixel offset from tiles
@ -133,7 +139,7 @@ var GalaxianPlatform = function(mainElement, options) {
var missile = 0xff; var missile = 0xff;
for (var which=0; which<8; which++) { for (var which=0; which<8; which++) {
var sy = oram.mem[0x60 + (which<<2)+1]; 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) if (which != 7)
shell = which; shell = which;
else else
@ -202,7 +208,7 @@ var GalaxianPlatform = function(mainElement, options) {
if (options.scramble) { if (options.scramble) {
inputs = [0xff,0xfc,0xf1]; inputs = [0xff,0xfc,0xf1];
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }], [0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }],
// [0x4800, 0x4fff, 0x3ff, function(a) { return vram.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) [0x9212, 0x9212, 0, function(a) { return m_protection_result; }], // scramble (protection)
//[0, 0xffff, 0, function(a) { console.log(hex(a)); return 0; }] //[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; }], [0x4000, 0x47ff, 0x7ff, function(a,v) { ram.mem[a] = v; }],
[0x4800, 0x4fff, 0x3ff, function(a,v) { vram.mem[a] = v; }], [0x4800, 0x4fff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5000, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }], [0x5000, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],
@ -240,7 +246,7 @@ var GalaxianPlatform = function(mainElement, options) {
} else { } else {
inputs = [0xe,0x8,0x0]; inputs = [0xe,0x8,0x0];
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x3ff, function(a) { return ram.mem[a]; }], [0x4000, 0x47ff, 0x3ff, function(a) { return ram.mem[a]; }],
[0x5000, 0x57ff, 0x3ff, function(a) { return vram.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]; }], [0x7000, 0x7000, 0, function(a) { return inputs[2]; }],
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }], [0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x4000, 0x47ff, 0x3ff, function(a,v) { ram.mem[a] = v; }], [0x4000, 0x47ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x5000, 0x57ff, 0x3ff, function(a,v) { vram.mem[a] = v; }], [0x5000, 0x57ff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5800, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }], [0x5800, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],

View File

@ -1,5 +1,9 @@
"use strict"; "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/ // http://www.computerarcheology.com/Arcade/
var MW8080BW_PRESETS = [ var MW8080BW_PRESETS = [
@ -10,7 +14,7 @@ var MW8080BW_PRESETS = [
var Midway8080BWPlatform = function(mainElement) { var Midway8080BWPlatform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom; var cpu, ram, membus, iobus, rom;
var probe; var probe;
@ -45,11 +49,11 @@ var Midway8080BWPlatform = function(mainElement) {
ram = new RAM(0x2000); ram = new RAM(0x2000);
//displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2)); //displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x1fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }], [0x0000, 0x1fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
[0x2000, 0x3fff, 0x1fff, function(a) { return ram.mem[a]; }], [0x2000, 0x3fff, 0x1fff, function(a) { return ram.mem[a]; }],
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x2000, 0x23ff, 0x3ff, function(a,v) { ram.mem[a] = v; }], [0x2000, 0x23ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x2400, 0x3fff, 0x1fff, function(a,v) { [0x2400, 0x3fff, 0x1fff, function(a,v) {
ram.mem[a] = v; ram.mem[a] = v;

View File

@ -1,5 +1,11 @@
"use strict"; "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 = [ var JSNES_PRESETS = [
{id:'ex0.asm', name:'Initialization (ASM)'}, {id:'ex0.asm', name:'Initialization (ASM)'},
{id:'ex1.asm', name:'Scrolling Demo (ASM)'}, {id:'ex1.asm', name:'Scrolling Demo (ASM)'},
@ -56,7 +62,7 @@ var JSNES_KEYCODE_MAP = makeKeycodeMap([
var JSNESPlatform = function(mainElement) { var JSNESPlatform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new Base6502Platform(); this.__proto__ = new (Base6502Platform as any)();
this.debugPCDelta = 1; this.debugPCDelta = 1;
var nes; var nes;
@ -147,7 +153,7 @@ var JSNESPlatform = function(mainElement) {
this.runToVsync = function() { this.runToVsync = function() {
var frame0 = frameindex; var frame0 = frameindex;
platform.runEval(function(c) { return frameindex>frame0; }); this.runEval(function(c) { return frameindex>frame0; });
} }
this.getCPUState = function() { this.getCPUState = function() {
@ -160,7 +166,7 @@ var JSNESPlatform = function(mainElement) {
var s = nes.toJSON(); var s = nes.toJSON();
s.c = s.cpu; s.c = s.cpu;
this.copy6502REGvars(s.c); 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.vramMem = s.ppu.vramMem.slice(0);
s.ppu.spriteMem = s.ppu.spriteMem.slice(0); s.ppu.spriteMem = s.ppu.spriteMem.slice(0);
return s; return s;
@ -197,13 +203,14 @@ var JSNESPlatform = function(mainElement) {
} }
this.getDebugCategories = function() { this.getDebugCategories = function() {
return ['CPU','ZPRAM','PPU']; return ['CPU','ZPRAM','Stack','PPU'];
} }
this.getDebugInfo = function(category, state) { this.getDebugInfo = function(category, state) {
switch (category) { switch (category) {
case 'CPU': return cpuStateToLongString_6502(state.c); case 'CPU': return cpuStateToLongString_6502(state.c);
case 'ZPRAM': return dumpRAM(state.cpu.mem, 0, 0x100); case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
case 'PPU': return this.ppuStateToLongString(state.ppu, state.cpu.mem); 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) { this.ppuStateToLongString = function(ppu, mem) {

View File

@ -1,10 +1,15 @@
"use strict"; "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 KONAMISOUND_PRESETS = [
]; ];
var KonamiSoundPlatform = function(mainElement) { var KonamiSoundPlatform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus; var cpu, ram, rom, membus, iobus;
var audio, master; var audio, master;
@ -25,11 +30,11 @@ var KonamiSoundPlatform = function(mainElement) {
this.start = function() { this.start = function() {
ram = new RAM(0x400); ram = new RAM(0x400);
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x5fff, 0x3ff, function(a) { return ram.mem[a]; }] [0x4000, 0x5fff, 0x3ff, function(a) { return ram.mem[a]; }]
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x4000, 0x5fff, 0x3ff, function(a,v) { ram.mem[a] = v; }], [0x4000, 0x5fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]), ]),
isContended: function() { return false; }, isContended: function() { return false; },

View File

@ -1,5 +1,9 @@
"use strict"; "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 = [ var WILLIAMS_SOUND_PRESETS = [
{id:'swave.c', name:'Wavetable Synth'}, {id:'swave.c', name:'Wavetable Synth'},
]; ];
@ -30,7 +34,7 @@ var WILLIAMS_SOUND_PRESETS = [
var WilliamsSoundPlatform = function(mainElement) { var WilliamsSoundPlatform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus; var cpu, ram, rom, membus, iobus;
var audio, master; var audio, master;
@ -60,11 +64,11 @@ var WilliamsSoundPlatform = function(mainElement) {
this.start = function() { this.start = function() {
ram = new RAM(0x400); ram = new RAM(0x400);
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }] [0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }], [0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]), ]),
isContended: function() { return false; }, isContended: function() { return false; },

View File

@ -1,5 +1,13 @@
"use strict"; "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 = [ var VCS_PRESETS = [
{id:'examples/hello', chapter:4, name:'Hello 6502 and TIA'}, {id:'examples/hello', chapter:4, name:'Hello 6502 and TIA'},
{id:'examples/vsync', chapter:5, name:'Painting on the CRT', title:'Color Bars'}, {id:'examples/vsync', chapter:5, name:'Painting on the CRT', title:'Color Bars'},
@ -100,7 +108,7 @@ var VCSPlatform = function() {
} }
*/ */
this.readAddress = function(addr) { 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() { this.runUntilReturn = function() {
var depth = 1; var depth = 1;
@ -215,7 +223,7 @@ function getClockCountsAtPC(pc) {
return meta; // minCycles, maxCycles 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); //console.log("trace", hex(pc), minclocks, maxclocks);
if (!minclocks) minclocks = 0; if (!minclocks) minclocks = 0;
if (!maxclocks) maxclocks = 0; if (!maxclocks) maxclocks = 0;
@ -274,7 +282,7 @@ function _traceInstructions(pc, minclocks, maxclocks, subaddr, constraints) {
pc = addr; // TODO: make sure in ROM space pc = addr; // TODO: make sure in ROM space
break; break;
case 0x60: // RTS case 0x60: // RTS
if (subaddr) { if (subaddr) { // TODO: 0 doesn't work
// TODO: combine with previous result // TODO: combine with previous result
var result = jsrresult[subaddr]; var result = jsrresult[subaddr];
if (!result) { if (!result) {
@ -325,7 +333,7 @@ function showLoopTimingForPC(pc, sourcefile, ed) {
pc2maxclocks = {}; pc2maxclocks = {};
jsrresult = {}; jsrresult = {};
// recurse through all traces // 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"); ed.editor.clearGutter("gutter-bytes");
// show the lines // show the lines
for (var line in sourcefile.line2offset) { for (var line in sourcefile.line2offset) {

View File

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

View File

@ -1,5 +1,8 @@
"use strict"; "use strict";
import { Platform } from "../baseplatform";
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
var VERILOG_PRESETS = [ var VERILOG_PRESETS = [
{id:'clock_divider.v', name:'Clock Divider'}, {id:'clock_divider.v', name:'Clock Divider'},
{id:'hvsync_generator.v', name:'Video Sync Generator'}, {id:'hvsync_generator.v', name:'Video Sync Generator'},
@ -53,12 +56,14 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
var vl_finished = false; var vl_finished = false;
var vl_stopped = false; var vl_stopped = false;
var VL_UL = function(x) { return x|0; } // TODO: these have to be global
var VL_ULL = function(x) { return x|0; }
var VL_TIME_Q = function() { return (new Date().getTime())|0; } 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 /// 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)))); } 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_NEGATE_I = this.VL_NEGATE_I = function(x) { return -x; }
var VL_LTS_III = this.VL_LTS_III = function(x,lbits,y,lhs,rhs) { 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) { 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) { 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) { 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) { var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
return (((rhs)==0)?0:(lhs)%(rhs)); } return (((rhs)==0)?0:(lhs)%(rhs)); }
@ -561,13 +566,13 @@ var VerilogPlatform = function(mainElement, options) {
vcanvas.mousedown(function(e) { vcanvas.mousedown(function(e) {
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16); scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
mouse_pressed = true; 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; dirty = true;
refreshFrame(); refreshFrame();
}); });
vcanvas.mouseup(function(e) { vcanvas.mouseup(function(e) {
mouse_pressed = false; 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; dirty = true;
refreshFrame(); 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; PLATFORMS['verilog'] = VerilogPlatform;

View File

@ -1,5 +1,9 @@
"use strict"; "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 = [ var VICDUAL_PRESETS = [
{id:'minimal.c', name:'Minimal Example'}, {id:'minimal.c', name:'Minimal Example'},
{id:'hello.c', name:'Hello World'}, {id:'hello.c', name:'Hello World'},
@ -12,7 +16,7 @@ var VICDUAL_PRESETS = [
var VicDualPlatform = function(mainElement) { var VicDualPlatform = function(mainElement) {
var self = this; var self = this;
this.__proto__ = new BaseZ80Platform(); this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom; var cpu, ram, membus, iobus, rom;
var video, audio, psg, timer, pixels; var video, audio, psg, timer, pixels;
@ -99,11 +103,11 @@ var VicDualPlatform = function(mainElement) {
this.start = function() { this.start = function() {
ram = new RAM(0x1000); ram = new RAM(0x1000);
membus = { membus = {
read: new AddressDecoder([ read: newAddressDecoder([
[0x0000, 0x7fff, 0x3fff, function(a) { return rom ? rom[a] : null; }], [0x0000, 0x7fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x0fff, function(a) { return ram.mem[a]; }], [0x8000, 0xffff, 0x0fff, function(a) { return ram.mem[a]; }],
]), ]),
write: new AddressDecoder([ write: newAddressDecoder([
[0x8000, 0xffff, 0x0fff, function(a,v) { ram.mem[a] = v; }], [0x8000, 0xffff, 0x0fff, function(a,v) { ram.mem[a] = v; }],
]), ]),
isContended: function() { return false; }, isContended: function() { return false; },

View File

@ -1,5 +1,9 @@
"use strict"; "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 = [ var WILLIAMS_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'}, {id:'gfxtest.c', name:'Graphics Test'},
{id:'sprites.c', name:'Sprite Test'}, {id:'sprites.c', name:'Sprite Test'},
@ -81,14 +85,14 @@ var WilliamsPlatform = function(mainElement, proto) {
// Defender // Defender
var ioread_defender = new AddressDecoder([ var ioread_defender = newAddressDecoder([
[0x400, 0x5ff, 0x1ff, function(a) { return nvram.mem[a]; }], [0x400, 0x5ff, 0x1ff, function(a) { return nvram.mem[a]; }],
[0x800, 0x800, 0, function(a) { return video_counter; }], [0x800, 0x800, 0, function(a) { return video_counter; }],
[0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }], [0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }],
[0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }], [0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }],
]); ]);
var iowrite_defender = new AddressDecoder([ var iowrite_defender = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette], [0x0, 0xf, 0xf, setPalette],
[0x3fc, 0x3ff, 0, function(a,v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }], [0x3fc, 0x3ff, 0, function(a,v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
[0x400, 0x5ff, 0x1ff, function(a,v) { nvram.mem[a] = v; }], [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)); }], [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]; }], [0x0000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, function(a) { [0xc000, 0xcfff, 0x0fff, function(a) {
switch (banksel) { switch (banksel) {
@ -111,7 +115,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0xd000] : 0; }], [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], [0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }], [0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_defender], [0xc000, 0xcfff, 0x0fff, iowrite_defender],
@ -121,7 +125,7 @@ var WilliamsPlatform = function(mainElement, proto) {
// Robotron, Joust, Bubbles, Stargate // Robotron, Joust, Bubbles, Stargate
var ioread_williams = new AddressDecoder([ var ioread_williams = newAddressDecoder([
[0x804, 0x807, 0x3, function(a) { return pia6821[a]; }], [0x804, 0x807, 0x3, function(a) { return pia6821[a]; }],
[0x80c, 0x80f, 0x3, function(a) { return pia6821[a+4]; }], [0x80c, 0x80f, 0x3, function(a) { return pia6821[a+4]; }],
[0xb00, 0xbff, 0, function(a) { return video_counter; }], [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)); */ }], [0x0, 0xfff, 0, function(a) { /* console.log('ioread',hex(a)); */ }],
]); ]);
var iowrite_williams = new AddressDecoder([ var iowrite_williams = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette], [0x0, 0xf, 0xf, setPalette],
[0x80c, 0x80c, 0xf, function(a,v) { if (worker) worker.postMessage({command:v}); }], [0x80c, 0x80c, 0xf, function(a,v) { if (worker) worker.postMessage({command:v}); }],
//[0x804, 0x807, 0x3, function(a,v) { console.log('iowrite',a); }], // TODO: sound //[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)); }], //[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]; }], [0x0000, 0x8fff, 0xffff, function(a) { return banksel ? rom[a] : ram.mem[a]; }],
[0x9000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }], [0x9000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, ioread_williams], [0xc000, 0xcfff, 0x0fff, ioread_williams],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0x4000] : 0; }], [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], [0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }], [0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_williams], [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; ram.mem[a] = v;
drawDisplayByte(a, v); drawDisplayByte(a, v);
if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter
@ -228,7 +232,7 @@ var WilliamsPlatform = function(mainElement, proto) {
else else
sstart += syinc; 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) { function blit_pixel(dstaddr, srcdata, flags) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,21 +2,17 @@
var vm = require('vm'); var vm = require('vm');
var fs = require('fs'); var fs = require('fs');
var assert = require('assert'); var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
includeInThisContext("gen/util.js"); var util = require("gen/util.js");
includeInThisContext("gen/pixed/pixeleditor.js"); var pixed = require("gen/pixed/pixeleditor.js");
describe('Pixel editor', function() { describe('Pixel editor', function() {
it('Should decode', function() { it('Should decode', function() {
var paldatastr = " 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x38, 0x70, 0x7f, 0xf8, "; 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 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,"; 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}}); pixed.pixelEditorDecodeMessage({data:{fmt:fmt,bytestr:datastr,palfmt:{pal:332,n:16},palstr:paldatastr}});
assert.deepEqual(palette, [0xff000000, assert.deepEqual(pixed.palette, [0xff000000,
0xff000060, 0xff000060,
0xff006020, 0xff006020,
0xff404000, 0xff404000,
@ -33,8 +29,8 @@ describe('Pixel editor', function() {
0xff40e0e0, 0xff40e0e0,
0xffc0e000, 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, ", 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 vm = require('vm');
var fs = require('fs'); var fs = require('fs');
var assert = require('assert'); var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
var localItems = {}; var localItems = {};
var localMods = 0; var localMods = 0;
@ -44,12 +40,10 @@ global.localStorage = {
} }
}; };
includeInThisContext("localForage/dist/localforage.js"); global.localforage = require("localForage/dist/localforage.js");
includeInThisContext("gen/util.js"); var util = require("gen/util.js");
includeInThisContext("gen/store.js"); var mstore = require("gen/store.js");
//var sto = require("../../gen/store.js"); var prj = require("gen/project.js");
//var wtypes = require("../../gen/workertypes.js");
var prj = require("../../gen/project.js");
var test_platform_id = "_TEST"; var test_platform_id = "_TEST";
@ -59,7 +53,7 @@ describe('Store', function() {
localStorage.setItem('_TEST/test', 'a'); localStorage.setItem('_TEST/test', 'a');
localStorage.setItem('_TEST/local/test', 'b'); localStorage.setItem('_TEST/local/test', 'b');
assert.equal(2, localMods); 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']); assert.equal('true', localItems['__migrated__TEST']);
store.getItem('test', function(err, result) { store.getItem('test', function(err, result) {
if (err) done(err); if (err) done(err);
@ -77,7 +71,7 @@ describe('Store', function() {
it('Should load local project', function(done) { it('Should load local project', function(done) {
localStorage.clear(); localStorage.clear();
localStorage.setItem('_TEST/test', 'a'); localStorage.setItem('_TEST/test', 'a');
var store = createNewPersistentStore(test_platform_id, function() { var store = mstore.createNewPersistentStore(test_platform_id, function() {
var worker = {}; var worker = {};
var platform = {}; var platform = {};
var project = new prj.CodeProject(worker, test_platform_id, platform, store); 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 = { var worker = {
postMessage: function(m) { msgs.push(m); }, postMessage: function(m) { msgs.push(m); },
}; };
@ -131,7 +125,7 @@ describe('Store', function() {
localStorage.clear(); localStorage.clear();
localItems['__migrated__TEST'] = 'true'; localItems['__migrated__TEST'] = 'true';
var msgs = []; var msgs = [];
var store = createNewPersistentStore(test_platform_id); var store = mstore.createNewPersistentStore(test_platform_id);
var worker = { var worker = {
}; };
var platform = { var platform = {

View File

@ -2,18 +2,111 @@
var vm = require('vm'); var vm = require('vm');
var fs = require('fs'); var fs = require('fs');
var assert = require('assert'); var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
includeInThisContext("gen/emu.js"); var emu = require("gen/emu.js");
includeInThisContext("gen/util.js"); var util = require("gen/util.js");
includeInThisContext("src/platform/nes.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() { describe('LZG', function() {
it('Should decode 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); assert.equal(40977, rom.length);
}); });
}); });

View File

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