diff --git a/doc/notes.txt b/doc/notes.txt
index e9eced25..cb50e293 100644
--- a/doc/notes.txt
+++ b/doc/notes.txt
@@ -48,7 +48,7 @@ TODO:
- how to revert included files?
- go to error in include files
- BOM in upload/download?
-- find version of neslib.h compatible with cc65
+- stack view for Z80 platforms using memory map
FYI: Image links for the books on http://8bitworkshop.com/ are broken
On the website the additional grey spacing next to the program line numbers is not dynamically resized when the web browser window size is changed. Intentional?
diff --git a/package.json b/package.json
index 1d66240b..67767694 100644
--- a/package.json
+++ b/package.json
@@ -20,10 +20,10 @@
"scripts": {
"build": "tsc",
"test": "npm run test-node",
- "test-one": "mocha --recursive --timeout 60000",
- "test-node": "mocha --recursive --timeout 60000 test/cli",
- "test-worker": "mocha --recursive --timeout 60000 test/cli/testworker.js",
- "test-profile": "mocha --recursive --timeout 60000 --prof test/cli"
+ "test-one": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000",
+ "test-node": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli",
+ "test-worker": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli/testworker.js",
+ "test-profile": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 --prof test/cli"
},
"repository": {
"type": "git",
diff --git a/pixels.html b/pixels.html
index 46c1c6f8..86f4e27d 100644
--- a/pixels.html
+++ b/pixels.html
@@ -36,6 +36,16 @@ body {
+
+
+
diff --git a/presets/nes/neslib1.c b/presets/nes/neslib1.c
index 49c368fb..a5d42c6c 100644
--- a/presets/nes/neslib1.c
+++ b/presets/nes/neslib1.c
@@ -5,7 +5,7 @@
#pragma data-name (push,"CHARS")
-const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:128,brev:1}*/
+const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:64,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7c,0x7c,0x7c,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0xfe,0x6c,0xfe,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xfe,0xd0,0xfe,0x16,0xfe,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0xdc,0x38,0x76,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6c,0x7c,0xec,0xee,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xfe,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x1e,0x3c,0x78,0xf0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7c,0xee,0xee,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x78,0x38,0x38,0x38,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x0e,0x7c,0xe0,0xee,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x0e,0x3c,0x0e,0x0e,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7e,0xee,0xee,0xfe,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xe0,0xfc,0x0e,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0xfc,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xee,0x1c,0x1c,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0x7c,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0x7e,0x0e,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x70,0x70,0x38,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x1c,0x1c,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0x1c,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7c,0xee,0xee,0xee,0xe0,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0xee,0xfe,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xee,0xfc,0xee,0xee,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xe0,0xe0,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xec,0xee,0xee,0xee,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xe0,0xf0,0xe0,0xe0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xe0,0xf8,0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0xee,0xee,0xee,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xfe,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x38,0x38,0x38,0x38,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0e,0x0e,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xfc,0xf8,0xec,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0xee,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0xee,0xfe,0xfe,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0xee,0xfe,0xfe,0xee,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
diff --git a/presets/nes/shoot2.c b/presets/nes/shoot2.c
index 425523cb..092191e5 100644
--- a/presets/nes/shoot2.c
+++ b/presets/nes/shoot2.c
@@ -692,41 +692,38 @@ void new_player_ship() {
}
void set_sounds() {
- /*
byte i;
+ byte enable = 0x1 | 0x2 | 0x8;
// missile fire sound
- if (missiles[7].ypos != YOFFSCREEN) {
- cv_set_frequency(CV_SOUNDCHANNEL_0, 2000-missiles[7].ypos*4);
- cv_set_attenuation(CV_SOUNDCHANNEL_0, 18);
+ if (missiles[PLYRMISSILE].ypos != YOFFSCREEN) {
+ APU.pulse[0].period_low = missiles[PLYRMISSILE].ypos ^ 0xff;
+ APU.pulse[0].len_period_high = 0;
+ APU.pulse[0].control = 0x80 | 0x30 | 6;
} else {
- cv_set_attenuation(CV_SOUNDCHANNEL_0, 32);
+ APU.pulse[0].control = 0x30;
}
// enemy explosion sound
- if (enemy_exploding) {
- cv_set_frequency(CV_SOUNDCHANNEL_1, 500+enemy_exploding*64);
- cv_set_attenuation(CV_SOUNDCHANNEL_1, 14);
- } else {
- cv_set_attenuation(CV_SOUNDCHANNEL_1, 32);
+ if (player_exploding && player_exploding < 8) {
+ APU.noise.control = 4;
+ APU.noise.period = 8 + player_exploding;
+ APU.noise.len = 15;
+ } else if (enemy_exploding) {
+ APU.noise.control = 2;
+ APU.noise.period = 8 + enemy_exploding;
+ APU.noise.len = 8;
}
- cv_set_attenuation(CV_SOUNDCHANNEL_2, 32);
- // player explosion
- if (player_exploding && player_exploding < 15) {
- cv_set_frequency(CV_SOUNDCHANNEL_2, player_exploding*256);
- cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 4+player_exploding);
- cv_set_noise(true, 3);
- } else {
- // set diving sounds for spaceships
- cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 32);
- for (i=0; i<3; i++) {
- byte y = attackers[i].y >> 8;
- if (y >= 0x80) {
- cv_set_frequency(CV_SOUNDCHANNEL_2, 4000+y*8);
- cv_set_attenuation(CV_SOUNDCHANNEL_2, 28);
- break;
- }
+ // set diving sounds for spaceships
+ for (i=0; i<2; i++) {
+ register AttackingEnemy* a = i ? &attackers[4] : &attackers[0];
+ if (a->findex && !a->returning) {
+ byte y = a->y >> 8;
+ APU.triangle.counter = 0xc0;
+ APU.triangle.period_low = y;
+ APU.triangle.len_period_high = 1;
+ enable |= 0x4;
}
}
- */
+ APU.status = enable;
}
static char starx[32];
@@ -843,8 +840,24 @@ void setup_tileset() {
}
}
+const byte APUINIT[0x13] = {
+ 0x30,0x08,0x00,0x00,
+ 0x30,0x08,0x00,0x00,
+ 0x80,0x00,0x00,0x00,
+ 0x30,0x00,0x00,0x00,
+ 0x00,0x00,0x00
+};
+
+void init_apu() {
+ // from https://wiki.nesdev.com/w/index.php/APU_basics
+ memcpy((void*)0x4000, APUINIT, sizeof(APUINIT));
+ APU.fcontrol = 0x40; // frame counter 5-step
+ APU.status = 0x0f; // turn on all channels except DMC
+}
+
void main() {
setup_tileset();
+ init_apu();
init_stars();
player_score = 0;
while (1) {
diff --git a/presets/nes/transtable.c b/presets/nes/transtable.c
new file mode 100644
index 00000000..16bda3b3
--- /dev/null
+++ b/presets/nes/transtable.c
@@ -0,0 +1,137 @@
+
+//this example code shows how to put some text in nametable
+
+#include "neslib.h"
+
+#include
+
+#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
+}
diff --git a/src/baseplatform.ts b/src/baseplatform.ts
index 28d3e0a8..690bf5ed 100644
--- a/src/baseplatform.ts
+++ b/src/baseplatform.ts
@@ -1,17 +1,24 @@
+import { RAM, RasterVideo, dumpRAM, dumpStackToString } from "./emu";
+import { hex } from "./util";
+
+declare var Z80_fast, jt, CPU6809;
+
export interface OpcodeMetadata {
minCycles: number;
maxCycles: number;
- insnLength: number;
+ insnlength: number;
+ opcode: number;
}
interface CpuState {
- PC:number, T?:number, o?:number/*opcode*/,
+ PC:number, T?:number, o?:number,/*opcode*/
+ SP?:number
/*
A:number, X:number, Y:number, SP:number, R:boolean,
N,V,D,Z,C:boolean*/
};
-interface EmuState {c:CpuState};
+interface EmuState {c:CpuState, b?:number[]};
type DisasmLine = {line:string, nbytes:number};
export interface Platform {
@@ -44,6 +51,7 @@ export interface Platform {
saveState?() : EmuState;
getDebugCallback?() : any; // TODO
getSP?() : number;
+ getOriginPC?() : number;
getDebugCategories() : string[];
getDebugInfo(category:string, state:EmuState) : string;
@@ -188,7 +196,7 @@ abstract class BaseFrameBasedPlatform extends BaseDebugPlatform {
////// 6502
-function getToolForFilename_6502(fn:string) : string {
+export function getToolForFilename_6502(fn:string) : string {
if (fn.endsWith(".pla")) return "plasm";
if (fn.endsWith(".c")) return "cc65";
if (fn.endsWith(".s")) return "ca65";
@@ -231,14 +239,19 @@ export abstract class Base6502Platform extends BaseFrameBasedPlatform {
getToolForFilename = getToolForFilename_6502;
getDefaultExtension() { return ".a"; };
- // TODO: Memory category
- getDebugCategories() { return ["CPU"]; }
- getDebugInfo(category:string, state:EmuState) {
- return cpuStateToLongString_6502(state.c);
+ getDebugCategories() {
+ return ['CPU','ZPRAM','Stack'];
+ }
+ getDebugInfo(category:string, state:EmuState) : string {
+ switch (category) {
+ case 'CPU': return cpuStateToLongString_6502(state.c);
+ case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
+ case 'Stack': return dumpStackToString(state.b, 0x100, 0x1ff, 0x100+state.c.SP);
+ }
}
}
-function cpuStateToLongString_6502(c) : string {
+export function cpuStateToLongString_6502(c) : string {
function decodeFlags(c) {
var s = "";
s += c.N ? " N" : " -";
@@ -270,7 +283,7 @@ var OPMETA_6502 = {
],
}
-function getOpcodeMetadata_6502(opcode, address) {
+export function getOpcodeMetadata_6502(opcode, address) {
// TODO: more intelligent maximum cycles
return {
opcode:opcode,
@@ -282,7 +295,7 @@ function getOpcodeMetadata_6502(opcode, address) {
////// Z80
-function cpuStateToLongString_Z80(c) {
+export function cpuStateToLongString_Z80(c) {
function decodeFlags(flags) {
var flagspec = "SZ-H-VNC";
var s = "";
@@ -298,7 +311,7 @@ function cpuStateToLongString_Z80(c) {
;
}
-function BusProbe(bus : MemoryBus) {
+export function BusProbe(bus : MemoryBus) {
var active = false;
var callback;
this.activate = function(_callback) {
@@ -328,7 +341,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
_cpu;
probe;
- newCPU(membus, iobus) {
+ newCPU(membus : MemoryBus, iobus : MemoryBus) {
this.probe = new BusProbe(membus);
this._cpu = Z80_fast({
display: {},
@@ -442,13 +455,17 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
// TODO
//this.getOpcodeMetadata = function() { }
- getDebugCategories() { return ["CPU"]; }
- getDebugInfo(category:string, state:EmuState) {
- return cpuStateToLongString_Z80(state.c);
+ getDebugCategories() {
+ return ['CPU'];
+ }
+ getDebugInfo(category:string, state:EmuState) : string {
+ switch (category) {
+ case 'CPU': return cpuStateToLongString_Z80(state.c);
+ }
}
}
-function getToolForFilename_z80(fn) {
+export function getToolForFilename_z80(fn) {
if (fn.endsWith(".c")) return "sdcc";
if (fn.endsWith(".s")) return "sdasz80";
if (fn.endsWith(".ns")) return "naken";
@@ -456,6 +473,60 @@ function getToolForFilename_z80(fn) {
return "z80asm";
}
+////// 6809
+
+export function cpuStateToLongString_6809(c) {
+ function decodeFlags(flags) {
+ var flagspec = "EFHINZVC";
+ var s = "";
+ for (var i=0; i<8; i++)
+ s += (flags & (128>>i)) ? flagspec.slice(i,i+1) : "-";
+ return s; // TODO
+ }
+ return "PC " + hex(c.PC,4) + " " + decodeFlags(c.CC) + "\n"
+ + "SP " + hex(c.SP,4) + "\n"
+ + " A " + hex(c.A,2) + "\n"
+ + " B " + hex(c.B,2) + "\n"
+ + " X " + hex(c.X,4) + "\n"
+ + " Y " + hex(c.Y,4) + "\n"
+ + " U " + hex(c.U,4) + "\n"
+ ;
+}
+
+export abstract class Base6809Platform extends BaseZ80Platform {
+
+ newCPU(membus : MemoryBus) {
+ var cpu = new CPU6809();
+ cpu.init(membus.write, membus.read, 0);
+ return cpu;
+ }
+
+ runUntilReturn() {
+ var depth = 1;
+ this.runEval((c:CpuState) => {
+ if (depth <= 0)
+ return true;
+ var op = this.readAddress(c.PC);
+ // TODO: 6809 opcodes
+ if (op == 0x9d || op == 0xad || op == 0xbd) // CALL
+ depth++;
+ else if (op == 0x3b || op == 0x39) // RET
+ --depth;
+ return false;
+ });
+ }
+
+ cpuStateToLongString(c:CpuState) {
+ return cpuStateToLongString_6809(c);
+ }
+ disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
+ // TODO: don't create new CPU
+ return new CPU6809().disasm(read(pc), read(pc+1), read(pc+2), read(pc+3), read(pc+4), pc);
+ }
+ getDefaultExtension() { return ".asm"; };
+ //this.getOpcodeMetadata = function() { }
+}
+
/// MAME SUPPORT
declare var FS, ENV, Module; // mame emscripten
@@ -733,3 +804,4 @@ export function BaseMAMEPlatform() {
return null; // TODO
}
}
+
diff --git a/src/emu.ts b/src/emu.ts
index 72c9a492..2ac47983 100644
--- a/src/emu.ts
+++ b/src/emu.ts
@@ -1,15 +1,17 @@
"use strict";
+import { hex } from "./util";
+
// external modules
declare var jt, Javatari, Z80_fast, CPU6809;
// Emulator classes
-var PLATFORMS = {};
+export var PLATFORMS = {};
-var frameUpdateFunction : (Canvas) => void = null;
+export var frameUpdateFunction : (Canvas) => void = null;
-function noise() {
+export function noise() {
return (Math.random() * 256) & 0xff;
}
@@ -29,7 +31,7 @@ function __createCanvas(mainElement:HTMLElement, width:number, height:number) {
return canvas;
}
-var RasterVideo = function(mainElement:HTMLElement, width:number, height:number, options?) {
+export var RasterVideo = function(mainElement:HTMLElement, width:number, height:number, options?) {
var self = this;
var canvas, ctx;
var imageData, arraybuf, buf8, datau32;
@@ -134,7 +136,7 @@ mainElement.appendChild(borderElement);
*/
}
-var VectorVideo = function(mainElement:HTMLElement, width:number, height:number) {
+export var VectorVideo = function(mainElement:HTMLElement, width:number, height:number) {
var self = this;
var canvas, ctx;
var persistenceAlpha = 0.5;
@@ -207,12 +209,14 @@ var VectorVideo = function(mainElement:HTMLElement, width:number, height:number)
}
}
-var RAM = function(size:number) {
- var memArray = new ArrayBuffer(size);
- this.mem = new Uint8Array(memArray);
+export class RAM {
+ mem : Uint8Array;
+ constructor(size:number) {
+ this.mem = new Uint8Array(new ArrayBuffer(size));
+ }
}
-var AnimationTimer = function(frequencyHz:number, callback:() => void) {
+export var AnimationTimer = function(frequencyHz:number, callback:() => void) {
var intervalMsec = 1000.0 / frequencyHz;
var running;
var lastts = 0;
@@ -269,7 +273,7 @@ var AnimationTimer = function(frequencyHz:number, callback:() => void) {
//
-function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
+export function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
var s = "";
// TODO: show scrollable RAM for other platforms
for (var ofs=0; ofs len) {
throw Error("Data too long, " + data.length + " > " + len);
}
@@ -433,8 +437,12 @@ function padBytes(data, len) {
return r.mem;
}
+type AddressReadWriteFn = ((a:number) => number) | ((a:number,v:number) => void);
+type AddressDecoderEntry = [number, number, number, AddressReadWriteFn];
+type AddressDecoderOptions = {gmask:number}
+
// TODO: better performance, check values
-function AddressDecoder(table, options) {
+export function AddressDecoder(table : AddressDecoderEntry[], options?:AddressDecoderOptions) {
var self = this;
function makeFunction(lo, hi) {
var s = "";
@@ -458,3 +466,45 @@ function AddressDecoder(table, options) {
return makeFunction(0x0, 0xffff).bind(self);
}
+export function newAddressDecoder(table : AddressDecoderEntry[], options?:AddressDecoderOptions) : (a:number,v?:number) => number {
+ return new (AddressDecoder as any)(table, options);
+}
+
+// STACK DUMP
+
+declare var addr2symbol; // address to symbol name map (TODO: import)
+
+function lookupSymbol(addr) {
+ var start = addr;
+ while (addr >= 0) {
+ var sym = addr2symbol[addr];
+ // TODO: what about asm?
+ if (sym && sym.startsWith('_')) {
+ return addr2symbol[addr] + " + " + (start-addr);
+ }
+ addr--;
+ }
+}
+
+export function dumpStackToString(mem:number[], start:number, end:number, sp:number) : string {
+ var s = "";
+ var nraw = 0;
+ //s = dumpRAM(mem.slice(start,start+end+1), start, end-start+1);
+ while (sp < end) {
+ sp++;
+ var addr = mem[sp] + mem[sp+1]*256;
+ var opcode = mem[addr-2];
+ if (opcode == 0x20) { // JSR
+ s += "\n$" + hex(sp) + ": ";
+ s += hex(addr,4) + " " + lookupSymbol(addr);
+ sp++;
+ nraw = 0;
+ } else {
+ if (nraw == 0)
+ s += "\n$" + hex(sp) + ": ";
+ s += hex(mem[sp+1]) + " ";
+ if (++nraw == 8) nraw = 0;
+ }
+ }
+ return s+"\n";
+}
diff --git a/src/pixed/pixeleditor.ts b/src/pixed/pixeleditor.ts
index e6508923..f3b9d42a 100644
--- a/src/pixed/pixeleditor.ts
+++ b/src/pixed/pixeleditor.ts
@@ -1,6 +1,8 @@
"use strict";
-function PixelEditor(parentDiv:HTMLElement, fmt, palette, initialData, thumbnails?) {
+import { hex } from "../util";
+
+export function PixelEditor(parentDiv:HTMLElement, fmt, palette, initialData, thumbnails?) {
var self = this;
var width = fmt.w;
var height = fmt.h;
@@ -232,7 +234,7 @@ function convertToHexStatements(s) {
});
}
-function parseHexBytes(s) {
+export function parseHexBytes(s) {
var arr = [];
var m;
while (m = pixel_re.exec(s)) {
@@ -248,7 +250,7 @@ function parseHexBytes(s) {
return arr;
}
-function replaceHexBytes(s, bytes) {
+export function replaceHexBytes(s, bytes) {
var result = "";
var m;
var li = 0;
@@ -384,20 +386,20 @@ function convertPaletteBytes(arr,r0,r1,g0,g1,b0,b1) {
return result;
}
-var palette;
-var paletteSets;
-var paletteSetIndex=0;
-var currentPixelEditor;
-var parentSource;
-var parentOrigin;
-var allimages;
-var currentFormat;
-var currentByteStr;
-var currentPaletteStr;
-var currentPaletteFmt;
-var allthumbs;
+export var palette;
+export var paletteSets;
+export var paletteSetIndex=0;
+export var currentPixelEditor;
+export var parentSource;
+export var parentOrigin;
+export var allimages;
+export var currentFormat;
+export var currentByteStr;
+export var currentPaletteStr;
+export var currentPaletteFmt;
+export var allthumbs;
-function pixelEditorDecodeMessage(e) {
+export function pixelEditorDecodeMessage(e) {
parentSource = e.source;
parentOrigin = e.origin;
currentFormat = e.data.fmt;
diff --git a/src/platform/apple2.js b/src/platform/apple2.ts
similarity index 99%
rename from src/platform/apple2.js
rename to src/platform/apple2.ts
index d5ef9a21..21b6fcd6 100644
--- a/src/platform/apple2.js
+++ b/src/platform/apple2.ts
@@ -1,5 +1,11 @@
"use strict";
+import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502 } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM } from "../emu";
+import { hex, lzgmini } from "../util";
+
+declare var jt; // 6502
+
var APPLE2_PRESETS = [
{id:'sieve.c', name:'Sieve'},
{id:'mandel.c', name:'Mandelbrot'},
@@ -19,6 +25,8 @@ var GR_HIRES = 8;
var Apple2Platform = function(mainElement) {
var self = this;
+ this.__proto__ = new (Base6502Platform as any)();
+
var cpuFrequency = 1023000;
var cpuCyclesPerLine = 65;
var cpu, ram, bus;
@@ -39,9 +47,7 @@ var Apple2Platform = function(mainElement) {
// value to add when reading & writing each of these banks
// bank 1 is E000-FFFF, bank 2 is D000-DFFF
var bank2rdoffset=0, bank2wroffset=0;
-
- this.__proto__ = new Base6502Platform();
-
+
this.getPresets = function() {
return APPLE2_PRESETS;
}
diff --git a/src/platform/atari8.js b/src/platform/atari8.ts
similarity index 91%
rename from src/platform/atari8.js
rename to src/platform/atari8.ts
index 1d3291a1..de67af57 100644
--- a/src/platform/atari8.js
+++ b/src/platform/atari8.ts
@@ -1,5 +1,8 @@
"use strict";
+import { Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502 } from "../baseplatform";
+import { PLATFORMS } from "../emu";
+
var Atari8_PRESETS = [
{id:'hello.a', name:'Hello World (ASM)'},
{id:'hellopm.a', name:'Hello Sprites (ASM)'},
diff --git a/src/platform/base_z80.js b/src/platform/base_z80.ts
similarity index 75%
rename from src/platform/base_z80.js
rename to src/platform/base_z80.ts
index 4e04bcbe..d35048e3 100644
--- a/src/platform/base_z80.js
+++ b/src/platform/base_z80.ts
@@ -1,5 +1,8 @@
-
"use strict";
+
+import { Platform, BaseZ80Platform, BaseMAMEPlatform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes } from "../emu";
+
var BASEZ80_PRESETS = [
{id:'simple1.c', name:'Multiply by 2'},
{id:'simple2.c', name:'Divide by 4'},
@@ -11,7 +14,7 @@ var BASEZ80_PRESETS = [
var Base_Z80Platform = function(mainElement) {
var self = this;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom, timer;
@@ -22,13 +25,13 @@ var Base_Z80Platform = function(mainElement) {
this.start = function() {
ram = new RAM(0x8000);
membus = {
- read: new AddressDecoder([
- [0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }],
- [0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }],
- ]),
- write: new AddressDecoder([
- [0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }],
- ]),
+ read: newAddressDecoder([
+ [0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }],
+ [0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }],
+ ]),
+ write: newAddressDecoder([
+ [0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }],
+ ]),
isContended: function() { return false; },
};
this.readAddress = membus.read;
diff --git a/src/platform/c64.js b/src/platform/c64.js
deleted file mode 100644
index 0091687a..00000000
--- a/src/platform/c64.js
+++ /dev/null
@@ -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;
diff --git a/src/platform/coleco.js b/src/platform/coleco.js
deleted file mode 100644
index 0ebb5f7a..00000000
--- a/src/platform/coleco.js
+++ /dev/null
@@ -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=0; sprnum--) {
var base = (sprnum<<2) + 0x40;
var base0 = oram.mem[base];
- var sy = 240 - (base0 - (sprnum<3)); // the first three sprites match against y-1
+ var sy = 240 - (base0 - ((sprnum<3)?1:0)); // the first three sprites match against y-1
var yy = (sl - sy);
if (yy >= 0 && yy < 16) {
var sx = oram.mem[base+3] + 1; // +1 pixel offset from tiles
@@ -133,7 +139,7 @@ var GalaxianPlatform = function(mainElement, options) {
var missile = 0xff;
for (var which=0; which<8; which++) {
var sy = oram.mem[0x60 + (which<<2)+1];
- if (((sy + sl - (which<3))&0xff) == 0xff) {
+ if (((sy + sl - ((which<3)?1:0))&0xff) == 0xff) {
if (which != 7)
shell = which;
else
@@ -202,7 +208,7 @@ var GalaxianPlatform = function(mainElement, options) {
if (options.scramble) {
inputs = [0xff,0xfc,0xf1];
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }],
// [0x4800, 0x4fff, 0x3ff, function(a) { return vram.mem[a]; }],
@@ -220,7 +226,7 @@ var GalaxianPlatform = function(mainElement, options) {
[0x9212, 0x9212, 0, function(a) { return m_protection_result; }], // scramble (protection)
//[0, 0xffff, 0, function(a) { console.log(hex(a)); return 0; }]
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x4000, 0x47ff, 0x7ff, function(a,v) { ram.mem[a] = v; }],
[0x4800, 0x4fff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5000, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],
@@ -240,7 +246,7 @@ var GalaxianPlatform = function(mainElement, options) {
} else {
inputs = [0xe,0x8,0x0];
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x3ff, function(a) { return ram.mem[a]; }],
[0x5000, 0x57ff, 0x3ff, function(a) { return vram.mem[a]; }],
@@ -250,7 +256,7 @@ var GalaxianPlatform = function(mainElement, options) {
[0x7000, 0x7000, 0, function(a) { return inputs[2]; }],
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x4000, 0x47ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x5000, 0x57ff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5800, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],
diff --git a/src/platform/mw8080bw.js b/src/platform/mw8080bw.ts
similarity index 93%
rename from src/platform/mw8080bw.js
rename to src/platform/mw8080bw.ts
index e734f43d..73f79b98 100644
--- a/src/platform/mw8080bw.js
+++ b/src/platform/mw8080bw.ts
@@ -1,5 +1,9 @@
"use strict";
+import { Platform, BaseZ80Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
// http://www.computerarcheology.com/Arcade/
var MW8080BW_PRESETS = [
@@ -10,7 +14,7 @@ var MW8080BW_PRESETS = [
var Midway8080BWPlatform = function(mainElement) {
var self = this;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom;
var probe;
@@ -45,11 +49,11 @@ var Midway8080BWPlatform = function(mainElement) {
ram = new RAM(0x2000);
//displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x1fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
[0x2000, 0x3fff, 0x1fff, function(a) { return ram.mem[a]; }],
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x2000, 0x23ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x2400, 0x3fff, 0x1fff, function(a,v) {
ram.mem[a] = v;
diff --git a/src/platform/nes.js b/src/platform/nes.ts
similarity index 97%
rename from src/platform/nes.js
rename to src/platform/nes.ts
index e2ee983e..530a2495 100644
--- a/src/platform/nes.js
+++ b/src/platform/nes.ts
@@ -1,5 +1,11 @@
"use strict";
+import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, cpuStateToLongString_6502, getToolForFilename_6502 } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM, dumpStackToString } from "../emu";
+import { hex, lpad, lzgmini } from "../util";
+
+declare var jsnes : any;
+
var JSNES_PRESETS = [
{id:'ex0.asm', name:'Initialization (ASM)'},
{id:'ex1.asm', name:'Scrolling Demo (ASM)'},
@@ -56,7 +62,7 @@ var JSNES_KEYCODE_MAP = makeKeycodeMap([
var JSNESPlatform = function(mainElement) {
var self = this;
- this.__proto__ = new Base6502Platform();
+ this.__proto__ = new (Base6502Platform as any)();
this.debugPCDelta = 1;
var nes;
@@ -147,7 +153,7 @@ var JSNESPlatform = function(mainElement) {
this.runToVsync = function() {
var frame0 = frameindex;
- platform.runEval(function(c) { return frameindex>frame0; });
+ this.runEval(function(c) { return frameindex>frame0; });
}
this.getCPUState = function() {
@@ -160,7 +166,7 @@ var JSNESPlatform = function(mainElement) {
var s = nes.toJSON();
s.c = s.cpu;
this.copy6502REGvars(s.c);
- s.cpu.mem = s.cpu.mem.slice(0);
+ s.b = s.cpu.mem = s.cpu.mem.slice(0);
s.ppu.vramMem = s.ppu.vramMem.slice(0);
s.ppu.spriteMem = s.ppu.spriteMem.slice(0);
return s;
@@ -197,13 +203,14 @@ var JSNESPlatform = function(mainElement) {
}
this.getDebugCategories = function() {
- return ['CPU','ZPRAM','PPU'];
+ return ['CPU','ZPRAM','Stack','PPU'];
}
this.getDebugInfo = function(category, state) {
switch (category) {
- case 'CPU': return cpuStateToLongString_6502(state.c);
- case 'ZPRAM': return dumpRAM(state.cpu.mem, 0, 0x100);
- case 'PPU': return this.ppuStateToLongString(state.ppu, state.cpu.mem);
+ case 'CPU': return cpuStateToLongString_6502(state.c);
+ case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
+ case 'Stack': return dumpStackToString(state.b, 0x100, 0x1ff, 0x100+state.c.SP);
+ case 'PPU': return this.ppuStateToLongString(state.ppu, state.b);
}
}
this.ppuStateToLongString = function(ppu, mem) {
diff --git a/src/platform/sound_konami.js b/src/platform/sound_konami.ts
similarity index 91%
rename from src/platform/sound_konami.js
rename to src/platform/sound_konami.ts
index 00d063f5..7b1d8f69 100644
--- a/src/platform/sound_konami.js
+++ b/src/platform/sound_konami.ts
@@ -1,10 +1,15 @@
"use strict";
+
+import { Platform, BaseZ80Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
var KONAMISOUND_PRESETS = [
];
var KonamiSoundPlatform = function(mainElement) {
var self = this;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus;
var audio, master;
@@ -25,11 +30,11 @@ var KonamiSoundPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x400);
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x5fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x4000, 0x5fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
diff --git a/src/platform/sound_williams.js b/src/platform/sound_williams.ts
similarity index 91%
rename from src/platform/sound_williams.js
rename to src/platform/sound_williams.ts
index 60a9ae02..70ac109c 100644
--- a/src/platform/sound_williams.js
+++ b/src/platform/sound_williams.ts
@@ -1,5 +1,9 @@
"use strict";
+import { Platform, BaseZ80Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
var WILLIAMS_SOUND_PRESETS = [
{id:'swave.c', name:'Wavetable Synth'},
];
@@ -30,7 +34,7 @@ var WILLIAMS_SOUND_PRESETS = [
var WilliamsSoundPlatform = function(mainElement) {
var self = this;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus;
var audio, master;
@@ -60,11 +64,11 @@ var WilliamsSoundPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x400);
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
diff --git a/src/platform/vcs.js b/src/platform/vcs.ts
similarity index 95%
rename from src/platform/vcs.js
rename to src/platform/vcs.ts
index afb6d240..ff59ce7b 100644
--- a/src/platform/vcs.js
+++ b/src/platform/vcs.ts
@@ -1,5 +1,13 @@
"use strict";
+import { Platform, cpuStateToLongString_6502, BaseMAMEPlatform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, dumpRAM } from "../emu";
+import { hex, lpad, tobin, byte2signed } from "../util";
+
+declare var platform : Platform; // global platform object
+declare var Javatari : any;
+declare var jt : any; // 6502
+
var VCS_PRESETS = [
{id:'examples/hello', chapter:4, name:'Hello 6502 and TIA'},
{id:'examples/vsync', chapter:5, name:'Painting on the CRT', title:'Color Bars'},
@@ -100,7 +108,7 @@ var VCSPlatform = function() {
}
*/
this.readAddress = function(addr) {
- return current_output[addr & 0xfff]; // TODO: use bus to read
+ return this.current_output[addr & 0xfff]; // TODO: use bus to read
}
this.runUntilReturn = function() {
var depth = 1;
@@ -215,7 +223,7 @@ function getClockCountsAtPC(pc) {
return meta; // minCycles, maxCycles
}
-function _traceInstructions(pc, minclocks, maxclocks, subaddr, constraints) {
+function _traceInstructions(pc:number, minclocks:number, maxclocks:number, subaddr:number, constraints) {
//console.log("trace", hex(pc), minclocks, maxclocks);
if (!minclocks) minclocks = 0;
if (!maxclocks) maxclocks = 0;
@@ -274,7 +282,7 @@ function _traceInstructions(pc, minclocks, maxclocks, subaddr, constraints) {
pc = addr; // TODO: make sure in ROM space
break;
case 0x60: // RTS
- if (subaddr) {
+ if (subaddr) { // TODO: 0 doesn't work
// TODO: combine with previous result
var result = jsrresult[subaddr];
if (!result) {
@@ -325,7 +333,7 @@ function showLoopTimingForPC(pc, sourcefile, ed) {
pc2maxclocks = {};
jsrresult = {};
// recurse through all traces
- _traceInstructions(pc | platform.getOriginPC(), MAX_CLOCKS, MAX_CLOCKS);
+ _traceInstructions(pc | platform.getOriginPC(), MAX_CLOCKS, MAX_CLOCKS, 0, {});
ed.editor.clearGutter("gutter-bytes");
// show the lines
for (var line in sourcefile.line2offset) {
diff --git a/src/platform/vector.js b/src/platform/vector.ts
similarity index 96%
rename from src/platform/vector.js
rename to src/platform/vector.ts
index babba23b..f229edc6 100644
--- a/src/platform/vector.js
+++ b/src/platform/vector.ts
@@ -1,5 +1,9 @@
"use strict";
+import { Platform, BaseZ80Platform, Base6502Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, VectorVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
// http://www.computerarcheology.com/Arcade/Asteroids/DVG.html
// http://arcarc.xmission.com/Tech/neilw_xy.txt
@@ -58,7 +62,7 @@ var AtariVectorPlatform = function(mainElement) {
var switches = new RAM(16).mem;
var nmicount = cpuCyclesPerNMI;
- this.__proto__ = new Base6502Platform();
+ this.__proto__ = new (Base6502Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@@ -72,7 +76,7 @@ var AtariVectorPlatform = function(mainElement) {
// bus
bus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0, 0x3ff, 0x3ff, function(a) { return cpuram.mem[a]; }],
[0x2001, 0x2001, 0, function(a) { return ((clock/500) & 1) ? 0xff : 0x00; }],
[0x2000, 0x2007, 0x7, function(a) { return switches[a]; }],
@@ -82,7 +86,7 @@ var AtariVectorPlatform = function(mainElement) {
[0x6800, 0x7fff, 0, function(a) { return rom[a - 0x6800]; }],
], {gmask:0x7fff}),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x0, 0x3ff, 0x3ff, function(a,v) { cpuram.mem[a] = v; }],
[0x3000, 0x3000, 0, function(a,v) { dvg.runUntilHalt(0); }],
// TODO: draw asynchronous or allow poll of HALT ($2002)
@@ -183,7 +187,7 @@ var AtariColorVectorPlatform = function(mainElement) {
var nmicount = cpuCyclesPerNMI;
var earom_offset, earom_data;
- this.__proto__ = new Base6502Platform();
+ this.__proto__ = new (Base6502Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@@ -201,7 +205,7 @@ var AtariColorVectorPlatform = function(mainElement) {
// bus
bus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0, 0x7ff, 0x7ff, function(a) { return cpuram.mem[a]; }],
[0x2000, 0x27ff, 0x7ff, function(a) { return dvgram.mem[a]; }],
[0x2800, 0x5fff, 0x7fff, function(a) { return vecrom[a - 0x2800]; }],
@@ -217,7 +221,7 @@ var AtariColorVectorPlatform = function(mainElement) {
[0x9000, 0xffff, 0xffff, function(a) { return rom[a - 0x9000]; }],
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x0, 0x7ff, 0x7ff, function(a,v) { cpuram.mem[a] = v; }],
[0x2000, 0x27ff, 0x7ff, function(a,v) { dvgram.mem[a] = v; }],
[0x6000, 0x67ff, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
@@ -324,7 +328,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
var switches = new RAM(16).mem;
var mathram = new RAM(16).mem;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@@ -351,7 +355,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
// bus
bus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0, 0x7fff, 0, function(a) { return rom[a]; }],
[0x8000, 0x800f, 0xf, function(a) { return switches[a]; }],
[0x8100, 0x810f, 0xf, function(a) { return mathram[a]; } ],
@@ -359,7 +363,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
[0xe000, 0xffff, 0x1fff, function(a) { return cpuram.mem[a]; }],
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x8000, 0x800f, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
[0x8010, 0x801f, 0xf, function(a,v) { audio.pokey2.setRegister(a, v); }],
[0x8100, 0x810e, 0xf, function(a,v) { mathram[a] = v; } ],
diff --git a/src/platform/verilog.js b/src/platform/verilog.ts
similarity index 96%
rename from src/platform/verilog.js
rename to src/platform/verilog.ts
index e1d151b7..8f3e1808 100644
--- a/src/platform/verilog.js
+++ b/src/platform/verilog.ts
@@ -1,5 +1,8 @@
"use strict";
+import { Platform } from "../baseplatform";
+import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+
var VERILOG_PRESETS = [
{id:'clock_divider.v', name:'Clock Divider'},
{id:'hvsync_generator.v', name:'Video Sync Generator'},
@@ -53,12 +56,14 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
var vl_finished = false;
var vl_stopped = false;
- var VL_UL = function(x) { return x|0; }
- var VL_ULL = function(x) { return x|0; }
- var VL_TIME_Q = function() { return (new Date().getTime())|0; }
+// TODO: these have to be global
+
+ var VL_UL = this.VL_UL = function(x) { return x|0; }
+ var VL_ULL = this.VL_ULL = function(x) { return x|0; }
+ var VL_TIME_Q = this.VL_TIME_Q = function() { return (new Date().getTime())|0; }
/// Return true if data[bit] set
- var VL_BITISSET_I = this.VL_BITISSET_I = function(data,bit) { return (data & (VL_UL(1)< VL_EXTENDS_II(x,lbits,rhs)); }
+ return (VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) {
- return 0 | (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)); }
+ return (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) {
- return 0 | (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)); }
+ return (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
return (((rhs)==0)?0:(lhs)%(rhs)); }
@@ -561,13 +566,13 @@ var VerilogPlatform = function(mainElement, options) {
vcanvas.mousedown(function(e) {
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
mouse_pressed = true;
- if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
+ //if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
dirty = true;
refreshFrame();
});
vcanvas.mouseup(function(e) {
mouse_pressed = false;
- if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
+ //if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
dirty = true;
refreshFrame();
});
@@ -842,17 +847,6 @@ var VerilogPlatform = function(mainElement, options) {
};
-function traceTiming() {
- // TODO: merge with main setCode(text)
- var text = editor.getValue();
- worker.postMessage({
- code:text,
- dependencies:loadFileDependencies(text),
- platform:platform_id,
- tool:'yosys'
- });
-}
-
////////////////
PLATFORMS['verilog'] = VerilogPlatform;
diff --git a/src/platform/vicdual.js b/src/platform/vicdual.ts
similarity index 94%
rename from src/platform/vicdual.js
rename to src/platform/vicdual.ts
index ebb9c9fe..7f47a1fc 100644
--- a/src/platform/vicdual.js
+++ b/src/platform/vicdual.ts
@@ -1,5 +1,9 @@
-
"use strict";
+
+import { Platform, BaseZ80Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
var VICDUAL_PRESETS = [
{id:'minimal.c', name:'Minimal Example'},
{id:'hello.c', name:'Hello World'},
@@ -12,7 +16,7 @@ var VICDUAL_PRESETS = [
var VicDualPlatform = function(mainElement) {
var self = this;
- this.__proto__ = new BaseZ80Platform();
+ this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom;
var video, audio, psg, timer, pixels;
@@ -99,11 +103,11 @@ var VicDualPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x1000);
membus = {
- read: new AddressDecoder([
+ read: newAddressDecoder([
[0x0000, 0x7fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x0fff, function(a) { return ram.mem[a]; }],
]),
- write: new AddressDecoder([
+ write: newAddressDecoder([
[0x8000, 0xffff, 0x0fff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
diff --git a/src/platform/williams.js b/src/platform/williams.ts
similarity index 94%
rename from src/platform/williams.js
rename to src/platform/williams.ts
index e4cc9f25..91e129d7 100644
--- a/src/platform/williams.js
+++ b/src/platform/williams.ts
@@ -1,5 +1,9 @@
"use strict";
+import { Platform, BaseZ80Platform, Base6809Platform } from "../baseplatform";
+import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
+import { hex } from "../util";
+
var WILLIAMS_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'},
{id:'sprites.c', name:'Sprite Test'},
@@ -81,14 +85,14 @@ var WilliamsPlatform = function(mainElement, proto) {
// Defender
- var ioread_defender = new AddressDecoder([
+ var ioread_defender = newAddressDecoder([
[0x400, 0x5ff, 0x1ff, function(a) { return nvram.mem[a]; }],
[0x800, 0x800, 0, function(a) { return video_counter; }],
[0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }],
[0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }],
]);
- var iowrite_defender = new AddressDecoder([
+ var iowrite_defender = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x3fc, 0x3ff, 0, function(a,v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
[0x400, 0x5ff, 0x1ff, function(a,v) { nvram.mem[a] = v; }],
@@ -96,7 +100,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
- var memread_defender = new AddressDecoder([
+ var memread_defender = newAddressDecoder([
[0x0000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, function(a) {
switch (banksel) {
@@ -111,7 +115,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0xd000] : 0; }],
]);
- var memwrite_defender = new AddressDecoder([
+ var memwrite_defender = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_defender],
@@ -121,7 +125,7 @@ var WilliamsPlatform = function(mainElement, proto) {
// Robotron, Joust, Bubbles, Stargate
- var ioread_williams = new AddressDecoder([
+ var ioread_williams = newAddressDecoder([
[0x804, 0x807, 0x3, function(a) { return pia6821[a]; }],
[0x80c, 0x80f, 0x3, function(a) { return pia6821[a+4]; }],
[0xb00, 0xbff, 0, function(a) { return video_counter; }],
@@ -129,7 +133,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0x0, 0xfff, 0, function(a) { /* console.log('ioread',hex(a)); */ }],
]);
- var iowrite_williams = new AddressDecoder([
+ var iowrite_williams = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x80c, 0x80c, 0xf, function(a,v) { if (worker) worker.postMessage({command:v}); }],
//[0x804, 0x807, 0x3, function(a,v) { console.log('iowrite',a); }], // TODO: sound
@@ -141,14 +145,14 @@ var WilliamsPlatform = function(mainElement, proto) {
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
- var memread_williams = new AddressDecoder([
+ var memread_williams = newAddressDecoder([
[0x0000, 0x8fff, 0xffff, function(a) { return banksel ? rom[a] : ram.mem[a]; }],
[0x9000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, ioread_williams],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0x4000] : 0; }],
]);
- var memwrite_williams = new AddressDecoder([
+ var memwrite_williams = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_williams],
@@ -166,7 +170,7 @@ var WilliamsPlatform = function(mainElement, proto) {
}
}
- function write_display_byte(a,v) {
+ function write_display_byte(a:number,v:number) {
ram.mem[a] = v;
drawDisplayByte(a, v);
if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter
@@ -228,7 +232,7 @@ var WilliamsPlatform = function(mainElement, proto) {
else
sstart += syinc;
}
- return w * h * (2 + ((flags&0x4)!=0)); // # of memory accesses
+ return w * h * (2 + ((flags&0x4)>>2)); // # of memory accesses
}
function blit_pixel(dstaddr, srcdata, flags) {
diff --git a/src/project.ts b/src/project.ts
index c8b0ac07..ddb3d788 100644
--- a/src/project.ts
+++ b/src/project.ts
@@ -1,6 +1,7 @@
"use strict";
import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, WorkerResult } from "./workertypes";
+import { getFilenameForPath, getFilenamePrefix } from "./util";
type BuildResultCallback = (result:WorkerResult) => void;
type BuildStatusCallback = (busy:boolean) => void;
diff --git a/src/store.ts b/src/store.ts
index 7406c2cc..703858bf 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -110,7 +110,7 @@ function copyFromOldStorageFormat(platformid:string, newstore, callback:()=>void
migrateNext(); // start the conversion
}
-function createNewPersistentStore(platformid:string, callback:()=>void) {
+export function createNewPersistentStore(platformid:string, callback:()=>void) {
var store = localforage.createInstance({
name: "__" + platformid,
version: 2.0
diff --git a/src/ui.ts b/src/ui.ts
index 5a5a75f4..07e026c4 100644
--- a/src/ui.ts
+++ b/src/ui.ts
@@ -1,5 +1,7 @@
"use strict";
+import { getFilenameForPath, getFilenamePrefix, highlightDifferences, invertMap } from "./util";
+
// 8bitworkshop IDE user interface
import $ = require("jquery");
@@ -8,14 +10,13 @@ import { CodeProject } from "./project";
import { WorkerResult, SourceFile } from "./workertypes";
import { ProjectWindows } from "./windows";
import { Platform, Preset } from "./baseplatform";
+import { PLATFORMS } from "./emu";
import * as Views from "./views";
// external libs (TODO)
declare var Octokat, ga, Tour, GIF, saveAs;
declare function createNewPersistentStore(platform_id : string);
declare function showLoopTimingForPC(pc:number, sourcefile:SourceFile, wnd:Views.ProjectView);
-// loaded by platform js file
-declare var PLATFORMS;
// make sure VCS doesn't start
if (window['Javatari']) window['Javatari'].AUTO_START = false;
@@ -926,7 +927,7 @@ function startUI(loadplatform : boolean) {
} else {
// load and start platform object
if (loadplatform) {
- var scriptfn = 'src/platform/' + platform_id.split(/[.-]/)[0] + '.js';
+ var scriptfn = 'gen/platform/' + platform_id.split(/[.-]/)[0] + '.js';
var script = document.createElement('script');
script.onload = function() {
console.log("loaded platform", platform_id);
diff --git a/src/util.ts b/src/util.ts
index aa932119..085a73cb 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,37 +1,37 @@
"use strict";
-function lpad(s:string, n:number):string {
+export function lpad(s:string, n:number):string {
s += ''; // convert to string
while (s.length 0) ? s.substr(0, pos) : s;
}
-function hex(v:number, nd?:number) {
+export function hex(v:number, nd?:number) {
if (!nd) nd = 2;
return toradix(v,nd,16);
}
-function tobin(v:number, nd?:number) {
+export function tobin(v:number, nd?:number) {
if (!nd) nd = 8;
return toradix(v,nd,2);
}
-function toradix(v:number, nd:number, radix:number) {
+export function toradix(v:number, nd:number, radix:number) {
try {
var s = v.toString(radix).toUpperCase();
while (s.length < nd)
@@ -42,7 +42,7 @@ function toradix(v:number, nd:number, radix:number) {
}
}
-function arrayCompare(a:any[], b:any[]):boolean {
+export function arrayCompare(a:any[], b:any[]):boolean {
if (a == null && b == null) return true;
if (a == null) return false;
if (b == null) return false;
@@ -53,7 +53,7 @@ function arrayCompare(a:any[], b:any[]):boolean {
return true;
}
-function invertMap(m:{}):{} {
+export function invertMap(m:{}):{} {
var r = {};
if (m) {
for (var k in m) r[m[k]] = k;
@@ -61,7 +61,7 @@ function invertMap(m:{}):{} {
return r;
}
-function highlightDifferences(s1:string, s2:string):string {
+export function highlightDifferences(s1:string, s2:string):string {
var split1 = s1.split(/(\S+\s+)/).filter(function(n) {return n});
var split2 = s2.split(/(\S+\s+)/).filter(function(n) {return n});
var i = 0;
@@ -87,7 +87,7 @@ function highlightDifferences(s1:string, s2:string):string {
return result;
}
-function lzgmini() {
+export function lzgmini() {
// Constants
var LZG_HEADER_SIZE = 16;
@@ -294,14 +294,14 @@ function lzgmini() {
}
}
-function stringToByteArray(s:string) : Uint8Array {
+export function stringToByteArray(s:string) : Uint8Array {
var a = new Uint8Array(s.length);
for (var i=0; i