From d8a98989f5abd7c509e53a34a15153d78a642469 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Thu, 16 Aug 2018 19:19:20 -0400 Subject: [PATCH] converted src/platform to typescript; stack debug view --- doc/notes.txt | 2 +- package.json | 8 +- pixels.html | 10 + presets/nes/neslib1.c | 2 +- presets/nes/shoot2.c | 67 +++-- presets/nes/transtable.c | 137 +++++++++++ src/baseplatform.ts | 106 ++++++-- src/emu.ts | 80 ++++-- src/pixed/pixeleditor.ts | 34 +-- src/platform/{apple2.js => apple2.ts} | 12 +- src/platform/{atari8.js => atari8.ts} | 3 + src/platform/{base_z80.js => base_z80.ts} | 21 +- src/platform/c64.js | 42 ---- src/platform/coleco.js | 230 ------------------ src/platform/coleco.ts | 69 ++++++ src/platform/{galaxian.js => galaxian.ts} | 22 +- src/platform/{mw8080bw.js => mw8080bw.ts} | 10 +- src/platform/{nes.js => nes.ts} | 21 +- .../{sound_konami.js => sound_konami.ts} | 11 +- .../{sound_williams.js => sound_williams.ts} | 10 +- src/platform/{vcs.js => vcs.ts} | 16 +- src/platform/{vector.js => vector.ts} | 22 +- src/platform/{verilog.js => verilog.ts} | 36 ++- src/platform/{vicdual.js => vicdual.ts} | 12 +- src/platform/{williams.js => williams.ts} | 24 +- src/project.ts | 1 + src/store.ts | 2 +- src/ui.ts | 7 +- src/util.ts | 26 +- src/views.ts | 1 + src/worker/workermain.js | 3 +- test/cli/testdecoder.js | 11 +- test/cli/testpixelconvert.js | 16 +- test/cli/teststore.js | 22 +- test/cli/testutil.js | 109 ++++++++- test/cli/testverilog.js | 7 +- 36 files changed, 715 insertions(+), 497 deletions(-) create mode 100644 presets/nes/transtable.c rename src/platform/{apple2.js => apple2.ts} (99%) rename src/platform/{atari8.js => atari8.ts} (91%) rename src/platform/{base_z80.js => base_z80.ts} (75%) delete mode 100644 src/platform/c64.js delete mode 100644 src/platform/coleco.js create mode 100644 src/platform/coleco.ts rename src/platform/{galaxian.js => galaxian.ts} (95%) rename src/platform/{mw8080bw.js => mw8080bw.ts} (93%) rename src/platform/{nes.js => nes.ts} (97%) rename src/platform/{sound_konami.js => sound_konami.ts} (91%) rename src/platform/{sound_williams.js => sound_williams.ts} (91%) rename src/platform/{vcs.js => vcs.ts} (95%) rename src/platform/{vector.js => vector.ts} (96%) rename src/platform/{verilog.js => verilog.ts} (96%) rename src/platform/{vicdual.js => vicdual.ts} (94%) rename src/platform/{williams.js => williams.ts} (94%) 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