diff --git a/README.md b/README.md index f1f9be36..b8c2d3b6 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg? * https://github.com/dmsc/fastbasic * https://github.com/wiz-lang/wiz * https://github.com/sylefeb/Silice +* https://github.com/steux/cc7800 ### Assemblers/Linkers diff --git a/index.html b/index.html index fccd22fd..9be4b488 100644 --- a/index.html +++ b/index.html @@ -167,7 +167,6 @@ body {
  • MSX (libCV)
  • Apple ][+
  • ZX Spectrum
  • -
  • x86 (FreeDOS)
  • Amstrad CPC6128
  • @@ -209,6 +208,7 @@ body {
  • NES (MAME)

  • Williams (6809)
  • +
  • x86 (FreeDOS)
  • diff --git a/presets/atari7800/example_small_sprites.c78 b/presets/atari7800/example_small_sprites.c78 new file mode 100644 index 00000000..e8de02f9 --- /dev/null +++ b/presets/atari7800/example_small_sprites.c78 @@ -0,0 +1,59 @@ +// example from https://github.com/steux/cc7800 - license: GPLv3 + +#include "prosystem.h" +#include "multisprite.h" + +char i, xpos, ypos; + +#define NB_SMALL_SPRITES 128 +ramchip short sp_xpos[NB_SMALL_SPRITES], sp_ypos[NB_SMALL_SPRITES]; +ramchip char sp_direction[NB_SMALL_SPRITES]; + +const signed short dx[24] = {300, 289, 259, 212, 149, 77, 0, -77, -150, -212, -259, -289, -300, -289, -259, -212, -149, -77, 0, 77, 149, 212, 259, 289}; +const signed short dy[24] = {0, 124, 240, 339, 415, 463, 480, 463, 415, 339, 240, 124, 0, -124, -239, -339, -415, -463, -480, -463, -415, -339, -240, -124}; +const char horizontal_pingpong[24] = { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13 }; +const char vertical_pingpong[24] = { 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + +// Generated with sprites7800 missile.yaml +holeydma reversed scattered(16,1) char missile[16] = { + 0x18, 0x96, 0x7a, 0x7e, 0x7e, 0x6e, 0x9a, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void main() +{ + multisprite_init(); + + *P0C1 = multisprite_color(0x1c); // Yellow + *P0C2 = multisprite_color(0x37); // Orange + *P0C3 = multisprite_color(0x43); // Red + + // Initialize small sprites + for (ypos = 0, xpos = 0, i = 0, X = 0; X != NB_SMALL_SPRITES; xpos++, ypos++, X++) { + sp_xpos[X] = xpos << 8; + sp_ypos[X] = ypos << 8; + sp_direction[X] = i++; + if (i == 24) i = 0; + } + + // Main loop + do { + multisprite_flip(); + for (i = 0; i != NB_SMALL_SPRITES; i++) { + X = i; + Y = sp_direction[X]; + sp_xpos[X] += dx[Y]; + sp_ypos[X] += dy[Y]; + xpos = sp_xpos[X] >> 8; + ypos = sp_ypos[X] >> 8; + if ((xpos < 5 && (dx[Y] >> 8) < 0) || + (xpos >= 150 && (dx[Y] >> 8) >= 0)) { + sp_direction[X] = horizontal_pingpong[Y]; + } + if ((ypos < 5 && (dy[Y] >> 8) < 0) || + (ypos >= MS_YMAX - 20 && (dy[Y] >> 8) >= 0)) { + sp_direction[X] = vertical_pingpong[Y]; + } + multisprite_display_small_sprite(xpos, ypos, missile, 1, 0, 8); + } + } while(1); +} diff --git a/presets/atari7800/example_vertical_scrolling.c78 b/presets/atari7800/example_vertical_scrolling.c78 new file mode 100644 index 00000000..b78eae87 --- /dev/null +++ b/presets/atari7800/example_vertical_scrolling.c78 @@ -0,0 +1,110 @@ +// example from https://github.com/steux/cc7800 - license: GPLv3 + +#include "prosystem.h" +#include "gfx.h" +#define DMA_CHECK +#define VERTICAL_SCROLLING +#define _MS_DL_SIZE 64 +#define _MS_DL_MALLOC(y) ((y == 6 || y == 7 || y == 8)?_MS_DL_SIZE * 2:_MS_DL_SIZE) +#include "multisprite.h" + +char i, counter, xpos, ypos; +char *ptr; +char xchest; + +#define NB_SPRITES 32 +ramchip short sp_xpos[NB_SPRITES], sp_ypos[NB_SPRITES]; +ramchip char sp_direction[NB_SPRITES]; + +const signed short dx[24] = {300, 289, 259, 212, 149, 77, 0, -77, -150, -212, -259, -289, -300, -289, -259, -212, -149, -77, 0, 77, 149, 212, 259, 289}; +const signed short dy[24] = {0, 124, 240, 339, 415, 463, 480, 463, 415, 339, 240, 124, 0, -124, -239, -339, -415, -463, -480, -463, -415, -339, -240, -124}; +const char horizontal_pingpong[24] = { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13 }; +const char vertical_pingpong[24] = { 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + +const char background[22] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 }; +#define LTR(x) (((x) - ' ') * 2) +const char hello_world[] = { LTR('H'), LTR('E'), LTR('L'), LTR('L'), LTR('O'), LTR(' '), LTR('W'), LTR('O'), LTR('R'), LTR('L'), LTR('D') }; + +void main() +{ + counter = 0; + + multisprite_init(); + multisprite_set_charbase(tiles); + + // Set up a full background + for (counter = 0; counter < _MS_DLL_ARRAY_SIZE; counter++) { + if (counter & 2) { + ptr = background + 2; + } else { + ptr = background; + } + multisprite_display_tiles(0, _MS_DLL_ARRAY_SIZE - 1 - counter, ptr, 20, 1); + } + multisprite_save(); + + *P0C1 = multisprite_color(0x1c); // Setup Palette 0: Yellow + *P0C2 = multisprite_color(0xc5); // Green + *P0C3 = 0x0f; // White + + *P1C1 = multisprite_color(0x55); // Dark pink + *P1C2 = multisprite_color(0x5B); // Light pink + + *P2C1 = multisprite_color(0x32); + *P2C2 = multisprite_color(0x3D); + *P2C3 = multisprite_color(0x37); + + *P3C1 = multisprite_color(0x92); + *P3C2 = multisprite_color(0x97); + *P3C3 = multisprite_color(0x9D); + + // Initialize sprites + for (ypos = 0, xpos = 0, i = 0, X = 0; X != NB_SPRITES; xpos++, ypos++, X++) { + sp_xpos[X] = xpos << 8; + sp_ypos[X] = ypos << 8; + sp_direction[X] = i++; + if (i == 24) i = 0; + } + + // Main loop + do { + // Prepare scrolling data + if (multisprite_vscroll_buffer_empty()) { + if (counter & 2) { + ptr = background + 2; + } else { + ptr = background; + } + multisprite_vscroll_buffer_tiles(0, ptr, 20, 1); + multisprite_vscroll_buffer_sprite(xchest, chest, 2, 3); + xchest += 45; + counter++; + } + + while (*MSTAT & 0x80); + multisprite_flip(); + multisprite_vertical_scrolling(-1); + multisprite_reserve_dma(104, sizeof(hello_world), 2); + for (i = 0; i != NB_SPRITES; i++) { + X = i; + Y = sp_direction[X]; + sp_xpos[X] += dx[Y]; + sp_ypos[X] += dy[Y]; + xpos = sp_xpos[X] >> 8; + ypos = sp_ypos[X] >> 8; + if ((xpos < 5 && (dx[Y] >> 8) < 0) || + (xpos >= 150 && (dx[Y] >> 8) >= 0)) { + sp_direction[X] = horizontal_pingpong[Y]; + } + if ((ypos < 5 && (dy[Y] >> 8) < 0) || + (ypos >= MS_YMAX - 20 && (dy[Y] >> 8) >= 0)) { + sp_direction[X] = vertical_pingpong[Y]; + } + multisprite_display_sprite(xpos, ypos, bb_char1, 2, 0); + } + for (xpos = 40, i = 0; i != sizeof(hello_world); xpos += 8, i++) { + ptr = chars0 + hello_world[X = i]; + multisprite_display_sprite_fast(xpos, 104, ptr, 2, 2); + } + } while(1); +} diff --git a/presets/atari7800/gfx.h b/presets/atari7800/gfx.h new file mode 100644 index 00000000..5ab7562e --- /dev/null +++ b/presets/atari7800/gfx.h @@ -0,0 +1,152 @@ +// example from https://github.com/steux/cc7800 - license: GPLv3 + +reversed scattered(16,4) char tiles[64] = { + 0x5a, 0x5a, 0x95, 0x95, 0x69, 0x69, 0x65, 0x65, 0x69, 0x69, 0x95, 0x95, 0xa5, 0xa5, 0x65, 0x65, + 0xa5, 0xa5, 0xa9, 0xa9, 0x96, 0x96, 0xa6, 0xa6, 0x96, 0x96, 0xa9, 0xa9, 0x5a, 0x5a, 0xa6, 0xa6, + 0x5a, 0x5a, 0x95, 0x95, 0x69, 0x69, 0x65, 0x65, 0x69, 0x69, 0x95, 0x95, 0xa5, 0xa5, 0x65, 0x65, + 0xa5, 0xa5, 0xa9, 0xa9, 0x96, 0x96, 0xa6, 0xa6, 0x96, 0x96, 0xa9, 0xa9, 0x5a, 0x5a, 0xa6, 0xa6 +}; +holeydma reversed scattered(16,32) char chars0[512] = { + 0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x40, 0x05, 0x00, 0x50, 0x10, 0x15, 0x40, 0x00, 0x50, + 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x40, 0x05, 0x00, 0x50, 0x10, 0x15, 0x40, 0x00, 0x50, + 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x60, 0x90, 0x62, 0x40, 0x16, 0x60, 0x90, 0x60, 0x5f, 0x90, 0x01, 0xb0, + 0x06, 0xc0, 0x36, 0x00, 0x90, 0x60, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x80, 0x25, 0x50, 0x50, 0x50, 0x90, 0x60, 0x01, 0x40, + 0x05, 0x00, 0x05, 0x00, 0x50, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x09, 0x00, 0x50, 0x92, 0x65, 0x90, 0x6f, 0xf0, 0xf2, 0x70, 0xd9, 0x70, 0x09, 0xc0, + 0x27, 0x00, 0x0e, 0x40, 0xd6, 0x70, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, + 0x00, 0x00, 0x06, 0x00, 0x90, 0x61, 0x99, 0x60, 0x50, 0x00, 0x01, 0x80, 0x26, 0x40, 0x06, 0x00, + 0x18, 0x00, 0x01, 0x80, 0x25, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x06, 0x00, 0xf0, 0xf3, 0x6e, 0x70, 0xe6, 0x40, 0x06, 0xc0, 0x26, 0xc0, 0x0f, 0x00, + 0x24, 0x00, 0x02, 0x42, 0x66, 0x64, 0x66, 0x60, 0x00, 0x00, 0x66, 0x60, 0x00, 0x00, 0x02, 0x70, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x40, 0x26, 0x40, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x02, 0x42, 0x66, 0x64, 0x66, 0x60, 0x00, 0x00, 0x66, 0x60, 0x00, 0x00, 0x02, 0x40, + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x6a, 0x60, 0x3f, 0xa0, 0x1b, 0x00, 0x6d, 0xa0, 0x00, 0x00, + 0x28, 0x00, 0x02, 0x83, 0xda, 0x7c, 0xf6, 0xf0, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x09, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa6, 0x90, 0x00, 0x90, 0x28, 0x00, 0x92, 0x60, 0x00, 0x00, + 0x24, 0x00, 0x01, 0x80, 0x29, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xae, 0xb0, 0x6a, 0xb0, 0xac, 0xa0, 0xa2, 0x70, 0x00, 0x00, + 0x36, 0x00, 0x0a, 0xc0, 0xaf, 0xa0, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x27, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0xa6, 0x80, 0x90, 0x60, 0x62, 0x80, 0x00, 0x00, + 0x0a, 0x00, 0x06, 0x00, 0x90, 0x60, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa2, 0x80, 0xfa, 0xc0, 0xb0, 0xa0, 0xea, 0xa0, 0x00, 0x00, + 0x0e, 0x80, 0x2b, 0x00, 0xf0, 0xf0, 0x0f, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xac, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa2, 0x80, 0x0a, 0x00, 0x80, 0xa0, 0x2a, 0xa0, 0x00, 0x00, + 0x02, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xa0, 0x00, + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf3, 0xc0, 0x0f, 0x00, 0xc0, 0xf0, 0x3f, 0xf0, 0x00, 0x00, + 0x03, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xf0, 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 +}; +holeydma reversed scattered(16,32) char chars1[512] = { + 0x15, 0x40, 0x05, 0x00, 0x15, 0x40, 0x15, 0x40, 0x01, 0x40, 0x55, 0x50, 0x15, 0x40, 0x55, 0x50, + 0x15, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x54, 0x00, 0x15, 0x40, + 0x15, 0x40, 0x05, 0x00, 0x15, 0x40, 0x15, 0x40, 0x01, 0x40, 0x55, 0x50, 0x15, 0x40, 0x55, 0x50, + 0x15, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x54, 0x00, 0x15, 0x40, + 0x5a, 0x70, 0x0d, 0x00, 0x7a, 0xd0, 0x7a, 0x50, 0x07, 0x40, 0xda, 0xa0, 0x5a, 0xd0, 0x7a, 0xd0, + 0x7a, 0x50, 0xda, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0xa7, 0x00, 0xda, 0x70, + 0x70, 0xd0, 0x05, 0x00, 0x50, 0x50, 0x50, 0xd0, 0x05, 0x40, 0x50, 0x00, 0xd0, 0x70, 0x50, 0x50, + 0x50, 0xd0, 0x70, 0x50, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x50, 0x50, + 0x51, 0x70, 0x1d, 0x00, 0xa0, 0xd0, 0xa0, 0xd0, 0x37, 0x40, 0xd7, 0x40, 0xd0, 0xa0, 0xa1, 0xe0, + 0x70, 0xd0, 0x70, 0x50, 0x07, 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x75, 0xd0, 0x0b, 0x40, 0xa0, 0x70, + 0xd3, 0x50, 0x37, 0x00, 0x00, 0x70, 0x00, 0x70, 0x1d, 0xc0, 0x75, 0xc0, 0x70, 0x00, 0x03, 0x40, + 0xd0, 0x70, 0x50, 0xd0, 0x05, 0x00, 0x07, 0x00, 0x14, 0x00, 0xdd, 0x70, 0x01, 0xc0, 0x00, 0xd0, + 0x76, 0xd0, 0x27, 0x00, 0x03, 0x60, 0x07, 0x60, 0x6b, 0x40, 0xaa, 0x70, 0x77, 0x40, 0x07, 0x80, + 0xb7, 0x60, 0xb7, 0x70, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0xaa, 0xa0, 0x02, 0x70, 0x03, 0x60, + 0xdc, 0x70, 0x07, 0x00, 0x03, 0x40, 0x07, 0x40, 0x43, 0x40, 0x00, 0x70, 0x77, 0x40, 0x07, 0x00, + 0x37, 0x40, 0x37, 0x70, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x70, 0x03, 0x40, + 0xd8, 0xf0, 0x0d, 0x00, 0x36, 0x80, 0x0a, 0x70, 0xf7, 0xf0, 0x00, 0x70, 0x7a, 0xf0, 0x07, 0x00, + 0x7a, 0x70, 0x2a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xdf, 0x70, 0x03, 0xe0, 0x0d, 0x80, + 0xf0, 0x70, 0x0f, 0x00, 0x1c, 0x00, 0x00, 0xd0, 0x7d, 0xd0, 0x00, 0xf0, 0xd0, 0x70, 0x0f, 0x00, + 0xf0, 0xd0, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x7d, 0xf0, 0x03, 0x40, 0x07, 0x00, + 0xf0, 0xd0, 0x0f, 0x00, 0xf8, 0x00, 0xf0, 0xf0, 0xab, 0xe0, 0xf0, 0xf0, 0xf0, 0x70, 0x0f, 0x00, + 0xf0, 0xf0, 0x70, 0xf0, 0x0f, 0x00, 0x0f, 0x00, 0x2f, 0x00, 0xaa, 0xa0, 0x0f, 0x80, 0x0a, 0x00, + 0xd0, 0xf0, 0x0f, 0x00, 0xd0, 0x00, 0xf0, 0x70, 0x03, 0xc0, 0xd0, 0x70, 0x70, 0xf0, 0x0d, 0x00, + 0x70, 0x70, 0xf0, 0xd0, 0x0f, 0x00, 0x0d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0xbd, 0xe0, 0xff, 0xf0, 0xff, 0xf0, 0xbf, 0xe0, 0x03, 0xc0, 0xbf, 0xe0, 0xbf, 0xe0, 0x0f, 0x00, + 0xbf, 0xe0, 0xbf, 0xe0, 0x0a, 0x00, 0x3e, 0x00, 0x0b, 0xf0, 0x00, 0x00, 0xfe, 0x00, 0x0d, 0x00, + 0x3f, 0xc0, 0xff, 0xf0, 0xff, 0xf0, 0x3f, 0xc0, 0x03, 0xc0, 0x3f, 0xc0, 0x3f, 0xc0, 0x0f, 0x00, + 0x3f, 0xc0, 0x3f, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xf0, 0x00, 0x00, 0xfc, 0x00, 0x0f, 0x00, + 0x2a, 0x80, 0xaa, 0xa0, 0xaa, 0xa0, 0x2a, 0x80, 0x02, 0x80, 0x2a, 0x80, 0x2a, 0x80, 0x0a, 0x00, + 0x2a, 0x80, 0x2a, 0x80, 0x00, 0x00, 0x28, 0x00, 0x02, 0xa0, 0x00, 0x00, 0xa8, 0x00, 0x0a, 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 +}; +holeydma reversed scattered(16,32) char chars2[512] = { + 0x15, 0x40, 0x05, 0x00, 0x55, 0x40, 0x15, 0x40, 0x55, 0x00, 0x55, 0x50, 0x55, 0x50, 0x15, 0x40, + 0x50, 0x50, 0x15, 0x40, 0x05, 0x50, 0x50, 0x50, 0x50, 0x00, 0x50, 0x14, 0x50, 0x50, 0x15, 0x40, + 0x15, 0x40, 0x05, 0x00, 0x55, 0x40, 0x15, 0x40, 0x55, 0x00, 0x55, 0x50, 0x55, 0x50, 0x15, 0x40, + 0x50, 0x50, 0x15, 0x40, 0x05, 0x50, 0x50, 0x50, 0x50, 0x00, 0x50, 0x14, 0x50, 0x50, 0x15, 0x40, + 0x5a, 0x70, 0x1d, 0xc0, 0x7a, 0xd0, 0x7a, 0x50, 0xdb, 0x40, 0xda, 0xa0, 0x5a, 0xa0, 0x7a, 0xd0, + 0x70, 0x50, 0x27, 0x80, 0x09, 0x60, 0x51, 0xe0, 0x70, 0x00, 0x74, 0x5c, 0xd4, 0x70, 0xda, 0x70, + 0x70, 0xd0, 0x15, 0x40, 0x50, 0x50, 0x50, 0xd0, 0x71, 0x40, 0x50, 0x00, 0xd0, 0x00, 0x50, 0x50, + 0x50, 0xd0, 0x05, 0x00, 0x03, 0x40, 0xd1, 0x40, 0x50, 0x00, 0x54, 0xd4, 0x74, 0x50, 0x50, 0x50, + 0x51, 0x70, 0xda, 0x70, 0x50, 0xd0, 0x70, 0xa0, 0x72, 0x50, 0xd0, 0x00, 0xd0, 0x00, 0x50, 0xa0, + 0x70, 0xd0, 0x07, 0x00, 0x03, 0x40, 0xdd, 0x80, 0x50, 0x00, 0x75, 0xdc, 0x77, 0x50, 0xd0, 0x70, + 0xd3, 0x50, 0x70, 0x50, 0xd0, 0x70, 0xd0, 0x00, 0x50, 0xd0, 0x70, 0x00, 0x70, 0x00, 0xd0, 0x00, + 0xd0, 0x70, 0x0d, 0x00, 0x01, 0xc0, 0x77, 0x00, 0xd0, 0x00, 0xdd, 0x74, 0x5d, 0xd0, 0x70, 0xd0, + 0x73, 0xd0, 0x77, 0x70, 0x77, 0x60, 0x70, 0x00, 0x70, 0x70, 0x77, 0x00, 0x77, 0x00, 0x73, 0x70, + 0x77, 0x70, 0x07, 0x00, 0x03, 0x40, 0x76, 0x00, 0x70, 0x00, 0x7b, 0xb4, 0x77, 0x70, 0x70, 0x70, + 0xd1, 0x70, 0x77, 0x70, 0x77, 0x40, 0x70, 0x00, 0x70, 0x70, 0x77, 0x00, 0x77, 0x00, 0x73, 0x70, + 0x77, 0x70, 0x07, 0x00, 0x03, 0x40, 0x74, 0x00, 0x70, 0x00, 0x73, 0x34, 0x77, 0x70, 0x70, 0x70, + 0xd2, 0xa0, 0x7a, 0xf0, 0xfa, 0xd0, 0x70, 0x00, 0xf0, 0xf0, 0xda, 0x00, 0x7a, 0x00, 0xf2, 0xd0, + 0x7a, 0x70, 0x07, 0x00, 0x03, 0x40, 0xf7, 0x00, 0x70, 0x00, 0xd2, 0x3c, 0xfb, 0xd0, 0x70, 0xf0, + 0xf0, 0x00, 0xd0, 0x70, 0xd0, 0x70, 0xf0, 0x00, 0x70, 0xd0, 0x70, 0x00, 0xd0, 0x00, 0xd0, 0x70, + 0xf0, 0xd0, 0x0d, 0x00, 0x01, 0xc0, 0xdf, 0x00, 0xf0, 0x00, 0x70, 0x34, 0xd3, 0x70, 0xf0, 0xd0, + 0xf0, 0x10, 0xf0, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0x73, 0xe0, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0xf0, + 0xf0, 0xf0, 0x0f, 0x00, 0xf3, 0xc0, 0xfb, 0xc0, 0xf0, 0x00, 0xf0, 0x3c, 0xf2, 0xf0, 0xf0, 0xf0, + 0xd0, 0x30, 0xd0, 0xf0, 0xd0, 0x70, 0xf0, 0x70, 0xf3, 0xc0, 0xd0, 0x00, 0x70, 0x00, 0xd0, 0xd0, + 0x70, 0x70, 0x07, 0x00, 0xd3, 0x40, 0xd1, 0xc0, 0x70, 0x00, 0xd0, 0x34, 0xd0, 0xf0, 0xf0, 0xf0, + 0xbd, 0xe0, 0xf0, 0xf0, 0xff, 0xe0, 0xbf, 0xe0, 0xff, 0x80, 0xff, 0xf0, 0xf0, 0x00, 0xbf, 0xe0, + 0xf0, 0xf0, 0x3f, 0xc0, 0xbf, 0x80, 0xf2, 0xf0, 0xff, 0xf0, 0xf0, 0x3c, 0xf0, 0xf0, 0xbd, 0xe0, + 0x3f, 0xc0, 0xf0, 0xf0, 0xff, 0xc0, 0x3f, 0xc0, 0xff, 0x00, 0xff, 0xf0, 0xf0, 0x00, 0x3f, 0xc0, + 0xf0, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x3c, 0xf0, 0xf0, 0x3f, 0xc0, + 0x2a, 0x80, 0xa0, 0xa0, 0xaa, 0x80, 0x2a, 0x80, 0xaa, 0x00, 0xaa, 0xa0, 0xa0, 0x00, 0x2a, 0x80, + 0xa0, 0xa0, 0x2a, 0x80, 0x2a, 0x00, 0xa0, 0xa0, 0xaa, 0xa0, 0xa0, 0x28, 0xa0, 0xa0, 0x2a, 0x80, + 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 +}; +holeydma reversed scattered(16,32) char chars3[512] = { + 0x55, 0x40, 0x15, 0x40, 0x55, 0x40, 0x15, 0x40, 0x55, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x14, + 0x50, 0x50, 0x50, 0x50, 0x55, 0x50, 0x15, 0x40, 0x00, 0x50, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x40, 0x15, 0x40, 0x55, 0x40, 0x15, 0x40, 0x55, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x14, + 0x50, 0x50, 0x50, 0x50, 0x55, 0x50, 0x15, 0x40, 0x00, 0x50, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0x70, 0x5a, 0xd0, 0x7a, 0xd0, 0x7a, 0x50, 0xa7, 0xa0, 0xd0, 0x70, 0x50, 0xd0, 0x70, 0x1c, + 0x70, 0x50, 0xd0, 0x70, 0xaa, 0x70, 0x1e, 0x80, 0x01, 0xac, 0x2b, 0x40, 0x07, 0x00, 0x0c, 0x00, + 0x70, 0xd0, 0xd0, 0x70, 0x50, 0x50, 0x50, 0xd0, 0x05, 0x00, 0x50, 0x50, 0xd0, 0x70, 0x50, 0x14, + 0x50, 0xd0, 0x70, 0x50, 0x00, 0x50, 0x14, 0x00, 0x01, 0x04, 0x01, 0xc0, 0x05, 0x00, 0x04, 0x00, + 0x50, 0x70, 0xd0, 0x70, 0x50, 0xd0, 0x70, 0xa0, 0x07, 0x00, 0xd0, 0x70, 0xd0, 0x70, 0x50, 0x14, + 0xb5, 0xe0, 0x70, 0x50, 0x03, 0x60, 0x1c, 0x00, 0x0d, 0x08, 0x01, 0xc0, 0x37, 0x40, 0x14, 0x00, + 0xd0, 0x50, 0x70, 0x50, 0xd0, 0x70, 0xd0, 0x00, 0x0d, 0x00, 0x70, 0xd0, 0x70, 0x50, 0xd0, 0x34, + 0x1d, 0x40, 0x50, 0xd0, 0x01, 0xc0, 0x34, 0x00, 0x07, 0x00, 0x01, 0x40, 0x1d, 0xc0, 0x34, 0x00, + 0x77, 0xe0, 0x70, 0x70, 0x77, 0x60, 0xb7, 0x40, 0x07, 0x00, 0x70, 0x70, 0x70, 0x70, 0x73, 0x34, + 0x27, 0x80, 0xb7, 0x60, 0x07, 0x80, 0x34, 0x00, 0x37, 0x70, 0x03, 0x40, 0x77, 0x70, 0x77, 0x74, + 0xdd, 0x40, 0x70, 0x70, 0x77, 0x40, 0x37, 0x40, 0x07, 0x00, 0x70, 0x70, 0x70, 0x70, 0x73, 0x34, + 0x07, 0x00, 0x37, 0x40, 0x07, 0x00, 0x34, 0x00, 0x37, 0x70, 0x03, 0x40, 0x77, 0x70, 0x77, 0x74, + 0xda, 0x80, 0x70, 0xf0, 0xf7, 0x80, 0x2a, 0x70, 0x07, 0x00, 0xd0, 0x70, 0x70, 0xf0, 0xf7, 0xdc, + 0x3f, 0x40, 0x27, 0x80, 0x1e, 0x00, 0x34, 0x00, 0x2d, 0xa0, 0x03, 0x40, 0xa7, 0xa0, 0x7d, 0xf4, + 0xf0, 0x00, 0xd0, 0x70, 0xdf, 0x00, 0x00, 0xd0, 0x0d, 0x00, 0x70, 0xf0, 0xd0, 0x70, 0xdf, 0x7c, + 0x37, 0xc0, 0x0d, 0x00, 0x3c, 0x00, 0x1c, 0x00, 0x07, 0x00, 0x01, 0xc0, 0x0f, 0x00, 0xf7, 0xdc, + 0xf0, 0x00, 0xbf, 0x60, 0xfb, 0xc0, 0xf0, 0xf0, 0x0f, 0x00, 0xf0, 0xf0, 0xbf, 0x60, 0xfe, 0xfc, + 0xfa, 0xf0, 0x0f, 0x00, 0xf8, 0x00, 0x3c, 0x00, 0x3e, 0x0c, 0x03, 0xc0, 0x0f, 0x00, 0xb6, 0xa8, + 0xd0, 0x00, 0x1f, 0xc0, 0xd3, 0x40, 0xf0, 0x70, 0x07, 0x00, 0xd0, 0x70, 0x3f, 0xc0, 0xdc, 0xdc, + 0x70, 0x70, 0x07, 0x00, 0xd0, 0x00, 0x1c, 0x00, 0x34, 0x0c, 0x03, 0x40, 0x0d, 0x00, 0x3c, 0x00, + 0xf0, 0x00, 0x2b, 0xf0, 0xf2, 0xf0, 0xbf, 0xe0, 0x0f, 0x00, 0xbf, 0xe0, 0x2f, 0x80, 0xf8, 0xbc, + 0xf0, 0xf0, 0x0f, 0x00, 0xff, 0xf0, 0x3f, 0xc0, 0xff, 0xf8, 0x3f, 0xc0, 0x0f, 0x00, 0x2c, 0x00, + 0xf0, 0x00, 0x03, 0xf0, 0xf0, 0xf0, 0x3f, 0xc0, 0x0f, 0x00, 0x3f, 0xc0, 0x0f, 0x00, 0xf0, 0x3c, + 0xf0, 0xf0, 0x0f, 0x00, 0xff, 0xf0, 0x3f, 0xc0, 0xff, 0xf0, 0x3f, 0xc0, 0x0f, 0x00, 0x0c, 0x00, + 0xa0, 0x00, 0x02, 0xa0, 0xa0, 0xa0, 0x2a, 0x80, 0x0a, 0x00, 0x2a, 0x80, 0x0a, 0x00, 0xa0, 0x28, + 0xa0, 0xa0, 0x0a, 0x00, 0xaa, 0xa0, 0x2a, 0x80, 0xaa, 0xa0, 0x2a, 0x80, 0x0a, 0x00, 0x08, 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 +}; +holeydma reversed scattered(16,2) char bb_char1[32] = { + 0x01, 0x00, 0x01, 0x40, 0x0a, 0x94, 0x2a, 0x90, 0x3b, 0xa0, 0xc8, 0xe5, 0xc8, 0xe4, 0xc8, 0xd0, + 0xc8, 0xe5, 0xbb, 0x84, 0x0c, 0x20, 0x2a, 0x90, 0x0e, 0x50, 0x3f, 0x94, 0x3d, 0x68, 0x5d, 0x6a +}; +reversed scattered(16,2) char chest[32] = { + 0x00, 0x00, 0x05, 0x50, 0x2b, 0xf4, 0x96, 0xfc, 0x69, 0xbd, 0xbe, 0x6a, 0x55, 0x55, 0xaa, 0xbf, + 0xd5, 0xd5, 0xd9, 0xb7, 0xef, 0x9d, 0xef, 0x9d, 0xef, 0x9d, 0xdd, 0x9d, 0xd5, 0xf7, 0xff, 0x95 +}; diff --git a/presets/atari7800/skeleton.cc7800 b/presets/atari7800/skeleton.cc7800 new file mode 100644 index 00000000..5468f3df --- /dev/null +++ b/presets/atari7800/skeleton.cc7800 @@ -0,0 +1,16 @@ +// example from https://github.com/steux/cc7800 - license: GPLv3 + +#include "conio.h" + +char i; + +void main() +{ + clrscr(); + for (i = 0; i != 8; i++) { + textcolor(i); + gotoxy(0, i); + cputs("Hello World!"); + } + while(1); +} diff --git a/presets/atari7800/test_conio.c78 b/presets/atari7800/test_conio.c78 new file mode 100644 index 00000000..ffae0eda --- /dev/null +++ b/presets/atari7800/test_conio.c78 @@ -0,0 +1,69 @@ +// example from https://github.com/steux/cc7800 - license: GPLv3 + +#include "conio.h" +#include "assert.h" + +char i; + +reversed scattered(8,1) char special_char[8] = { + 0x66, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00 +}; + +void main() +{ + clrscr(); + // Draw a square + gotoxy(0, 0); + textcolor(7); + putch(CONIO_TL_CORNER); + for (i = 0; i != 20; i++) { + putch(CONIO_HBAR); + } + putch(CONIO_TR_CORNER); + for (i = 0; i != 8; i++) { + gotoxy(0, i + 1); + putch(CONIO_VBAR); + gotoxy(21, i + 1); + putch(CONIO_VBAR); + } + gotoxy(0, 9); + putch(CONIO_BL_CORNER); + for (i = 0; i != 20; i++) { + putch(CONIO_HBAR); + } + putch(CONIO_BR_CORNER); + // Write some text + for (i = 0; i != 8; i++) { + textcolor(i); + gotoxy(i + 1, i + 1); + cputs("Hello World!"); + } + // Long text test + gotoxy(0, 10); + cputs("This is a long text that fits in a line."); + + gotoxy(10, 11); + cputs("World!"); + gotoxy(4, 11); + cputs("Hello"); + + gotoxy(10, 12); + cputs("World!"); + gotoxy(4, 12); + textcolor(4); + cputs("Hello"); + + gotoxy(0, 13); + for (i = 0; i != 8; i++) { + textcolor(i); + putch('!'); + } + + gotoxy(0, 14); + for (i = 0; i != 8; i++) { + textcolor(7 - i); + putch(128); // Special character + } + + while(1); +} diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index b63bbb13..09e83d94 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -957,7 +957,7 @@ export abstract class BaseMachinePlatform extends BaseDebugPl export abstract class Base6502MachinePlatform extends BaseMachinePlatform { getOpcodeMetadata = getOpcodeMetadata_6502; - getToolForFilename = getToolForFilename_6502; + getToolForFilename(fn) { return getToolForFilename_6502(fn); } disassemble(pc:number, read:(addr:number)=>number) : DisasmLine { return disassemble6502(pc, read(pc), read(pc+1), read(pc+2)); diff --git a/src/common/wasi/wasishim.ts b/src/common/wasi/wasishim.ts index e94fad48..9a752442 100644 --- a/src/common/wasi/wasishim.ts +++ b/src/common/wasi/wasishim.ts @@ -9,6 +9,7 @@ const use_debug = true; const debug = use_debug ? console.log : () => { }; +const warning = console.log; export enum FDType { UNKNOWN = 0, @@ -202,6 +203,9 @@ export class WASIFileDescriptor { getBytes() { return this.data.subarray(0, this.size); } + getBytesAsString() { + return new TextDecoder().decode(this.getBytes()); + } toString() { return `FD(${this.fdindex} "${this.name}" 0x${this.type.toString(16)} 0x${this.rights.toString(16)} ${this.offset}/${this.size}/${this.data.byteLength})`; } @@ -218,13 +222,21 @@ class WASIStreamingFileDescriptor extends WASIFileDescriptor { } } -export class WASIFilesystem { +export interface WASIFilesystem { + getFile(name: string) : WASIFileDescriptor; +} + +export class WASIMemoryFilesystem implements WASIFilesystem { + private parent: WASIFilesystem | null = null; private files: Map = new Map(); private dirs: Map = new Map(); constructor() { this.putDirectory("/"); } + setParent(parent: WASIFilesystem) { + this.parent = parent; + } putDirectory(name: string, rights?: number) { if (!rights) rights = FDRights.PATH_OPEN | FDRights.PATH_CREATE_DIRECTORY | FDRights.PATH_CREATE_FILE; const dir = new WASIFileDescriptor(name, FDType.DIRECTORY, rights); @@ -243,29 +255,62 @@ export class WASIFilesystem { return file; } getFile(name: string) { - return this.files.get(name); + let file = this.files.get(name); + if (!file) { + file = this.parent?.getFile(name); + } + return file; } } export class WASIRunner { - #compiled: WebAssembly.Module; #instance; // TODO #memarr8: Uint8Array; #memarr32: Int32Array; #args: Uint8Array[] = []; + #envvars: Uint8Array[] = []; - stdin = new WASIStreamingFileDescriptor(0, '', FDType.CHARACTER_DEVICE, FDRights.FD_READ, process.stdin); - stdout = new WASIStreamingFileDescriptor(1, '', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE, process.stdout); - stderr = new WASIStreamingFileDescriptor(2, '', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE, process.stderr); + stdin : WASIFileDescriptor; + stdout : WASIFileDescriptor; + stderr : WASIFileDescriptor; - fds: WASIFileDescriptor[] = [this.stdin, this.stdout, this.stderr]; + fds: WASIFileDescriptor[] = []; exited = false; errno = -1; - fs = new WASIFilesystem(); + fs = new WASIMemoryFilesystem(); + constructor() { + this.createStdioBrowser(); + } + createStdioNode() { + this.stdin = new WASIStreamingFileDescriptor(0, '', FDType.CHARACTER_DEVICE, FDRights.FD_READ, process.stdin); + this.stdout = new WASIStreamingFileDescriptor(1, '', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE, process.stdout); + this.stderr = new WASIStreamingFileDescriptor(2, '', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE, process.stderr); + this.fds[0] = this.stdin; + this.fds[1] = this.stdout; + this.fds[2] = this.stderr; + } + createStdioBrowser() { + this.stdin = new WASIFileDescriptor('', FDType.CHARACTER_DEVICE, FDRights.FD_READ); + this.stdout = new WASIFileDescriptor('', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE); + this.stderr = new WASIFileDescriptor('', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE); + this.stdin.fdindex = 0; + this.stdout.fdindex = 1; + this.stderr.fdindex = 2; + this.fds[0] = this.stdin; + this.fds[1] = this.stdout; + this.fds[2] = this.stderr; + } + initSync(wasmModule: WebAssembly.Module) { + this.#instance = new WebAssembly.Instance(wasmModule, this.getImportObject()); + } + loadSync(wasmSource: Uint8Array) { + let wasmModule = new WebAssembly.Module(wasmSource); + this.initSync(wasmModule); + } async loadAsync(wasmSource: Uint8Array) { - this.#compiled = await WebAssembly.compile(wasmSource); - this.#instance = await WebAssembly.instantiate(this.#compiled, this.getImportObject()); + let wasmModule = await WebAssembly.compile(wasmSource); + this.#instance = await WebAssembly.instantiate(wasmModule, this.getImportObject()); } setArgs(args: string[]) { this.#args = args.map(arg => new TextEncoder().encode(arg + '\0')); @@ -296,6 +341,8 @@ export class WASIRunner { if (o_flags & FDOpenFlags.EXCL) return WASIErrors.INVAL; // already exists if (o_flags & FDOpenFlags.TRUNC) { // truncate file.truncate(); + } else { + file.llseek(0, 0); // seek to start } } file.fdindex = this.fds.length; @@ -371,14 +418,11 @@ export class WASIRunner { //let errno_ptr = this.#instance.exports.__errno_location(); //return this.peek32(errno_ptr); } - args_sizes_get(argcount_ptr: number, argv_buf_size_ptr: number) { - debug("args_sizes_get", argcount_ptr, argv_buf_size_ptr); - this.poke32(argcount_ptr, this.#args.length); - this.poke32(argv_buf_size_ptr, this.#args.reduce((acc, arg) => acc + arg.length, 0)); - return 0; + poke_str_array_sizes(strs: Uint8Array[], count_ptr: number, buf_size_ptr: number) { + this.poke32(count_ptr, strs.length); + this.poke32(buf_size_ptr, strs.reduce((acc, arg) => acc + arg.length, 0)); } - args_get(argv_ptr: number, argv_buf_ptr: number) { - debug("args_get", argv_ptr, argv_buf_ptr); + poke_str_args(strs: Uint8Array[], argv_ptr: number, argv_buf_ptr: number) { let argv = argv_ptr; let argv_buf = argv_buf_ptr; for (let arg of this.#args) { @@ -389,10 +433,28 @@ export class WASIRunner { argv_buf++; } } + } + args_sizes_get(argcount_ptr: number, argv_buf_size_ptr: number) { + debug("args_sizes_get", argcount_ptr, argv_buf_size_ptr); + this.poke_str_array_sizes(this.#args, argcount_ptr, argv_buf_size_ptr); return 0; } - fd_write(fd, iovs, iovs_len) { - debug("fd_write", fd, iovs, iovs_len); + args_get(argv_ptr: number, argv_buf_ptr: number) { + debug("args_get", argv_ptr, argv_buf_ptr); + this.poke_str_args(this.#args, argv_ptr, argv_buf_ptr); + return 0; + } + environ_sizes_get(environ_count_ptr: number, environ_buf_size_ptr: number) { + debug("environ_sizes_get", environ_count_ptr, environ_buf_size_ptr); + this.poke_str_array_sizes(this.#envvars, environ_count_ptr, environ_buf_size_ptr); + return 0; + } + environ_get(environ_ptr: number, environ_buf_ptr: number) { + debug("environ_get", environ_ptr, environ_buf_ptr); + this.poke_str_args(this.#envvars, environ_ptr, environ_buf_ptr); + return 0; + } + fd_write(fd, iovs, iovs_len, nwritten_ptr) { const stream = this.fds[fd]; const iovecs = this.mem32().subarray(iovs >>> 2, (iovs + iovs_len * 8) >>> 2); let total = 0; @@ -403,7 +465,9 @@ export class WASIRunner { total += len; stream.write(chunk); } - return total; + this.poke32(nwritten_ptr, total); + debug("fd_write", fd, iovs, iovs_len, '->', total); + return 0; } fd_read(fd, iovs, iovs_len, nread_ptr) { const stream = this.fds[fd]; @@ -500,32 +564,50 @@ export class WASIRunner { } return WASIErrors.SUCCESS; } + path_filestat_get(dirfd: number, dirflags: number, path_ptr: number, path_len: number, filestat_ptr: number) { + const dir = this.fds[dirfd]; + if (dir == null) return WASIErrors.BADF; + if (dir.type !== FDType.DIRECTORY) return WASIErrors.NOTDIR; + const filename = this.peekUTF8(path_ptr, path_len); + const path = dir.name + '/' + filename; + const fd = this.fs.getFile(path); + console.log("path_filestat_get", dir+"", path, filestat_ptr, '->', fd+""); + if (!fd) return WASIErrors.NOENT; + this.poke64(filestat_ptr, fd.fdindex); // dev + this.poke64(filestat_ptr + 8, 0); // ino + this.poke8(filestat_ptr + 16, fd.type); // filetype + this.poke64(filestat_ptr + 24, 1); // nlink + this.poke64(filestat_ptr + 32, fd.size); // size + this.poke64(filestat_ptr + 40, 0); // atim + this.poke64(filestat_ptr + 48, 0); // mtim + this.poke64(filestat_ptr + 56, 0); // ctim + } getWASISnapshotPreview1() { return { args_sizes_get: this.args_sizes_get.bind(this), args_get: this.args_get.bind(this), + environ_sizes_get: this.environ_sizes_get.bind(this), + environ_get: this.environ_get.bind(this), proc_exit: this.proc_exit.bind(this), path_open: this.path_open.bind(this), fd_prestat_get: this.fd_prestat_get.bind(this), fd_prestat_dir_name: this.fd_prestat_dir_name.bind(this), fd_fdstat_get: this.fd_fdstat_get.bind(this), - fd_fdstat_set_flags() { debug("fd_fdstat_set_flags"); return 0; }, fd_read: this.fd_read.bind(this), fd_write: this.fd_write.bind(this), fd_seek: this.fd_seek.bind(this), fd_close: this.fd_close.bind(this), - fd_readdir() { debug("fd_readdir"); return 0; }, - path_unlink_file() { debug("path_unlink_file"); return 0; }, - environ_sizes_get() { debug("environ_sizes_get"); return 0; }, - environ_get() { debug("environ_get"); return 0; }, - clock_time_get() { debug("clock_time_get"); return 0; }, - path_filestat_get() { debug("path_filestat_get"); return 0; }, + path_filestat_get: this.path_filestat_get.bind(this), random_get: this.random_get.bind(this), + fd_fdstat_set_flags() { warning("TODO: fd_fdstat_set_flags"); return WASIErrors.NOTSUP; }, + fd_readdir() { warning("TODO: fd_readdir"); return WASIErrors.NOTSUP; }, + path_unlink_file() { warning("TODO: path_unlink_file"); return WASIErrors.NOTSUP; }, + clock_time_get() { warning("TODO: clock_time_get"); return WASIErrors.NOTSUP; }, } } getEnv() { return { - __syscall_unlinkat() { debug('unlink'); return 0; }, + __syscall_unlinkat() { warning('TODO: unlink'); return 0; }, } } } diff --git a/src/ide/ui.ts b/src/ide/ui.ts index 81920514..b119acb9 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -127,6 +127,7 @@ const TOOL_TO_SOURCE_STYLE = { 'armips': 'vasm', 'ecs': 'ecs', 'remote:llvm-mos': 'text/x-csrc', + 'cc7800': 'text/x-csrc', } // TODO: move into tool class diff --git a/src/platform/atari7800.ts b/src/platform/atari7800.ts index 50c97548..11160c7a 100644 --- a/src/platform/atari7800.ts +++ b/src/platform/atari7800.ts @@ -1,13 +1,18 @@ import { Atari7800 } from "../machine/atari7800"; -import { Platform, Base6502MachinePlatform } from "../common/baseplatform"; +import { Platform, Base6502MachinePlatform, getToolForFilename_6502 } from "../common/baseplatform"; import { PLATFORMS } from "../common/emu"; var Atari7800_PRESETS = [ - {id:'sprites.dasm', name:'Sprites (ASM)'}, - {id:'wsync.c', name:'WSYNC'}, + {id:'sprites.dasm', name:'Sprites (ASM)', category:'Assembler'}, + + {id:'wsync.c', name:'WSYNC', category:'CC65'}, {id:'sprites.c', name:'Double Buffering'}, {id:'scroll.c', name:'Scrolling'}, + + {id:'test_conio.c78', name:'Conio Test', category:'cc7800'}, + {id:'example_small_sprites.c78', name:'Small Sprites'}, + {id:'example_vertical_scrolling.c78', name:'Vertical Scrolling'}, ]; class Atari7800Platform extends Base6502MachinePlatform implements Platform { @@ -33,6 +38,11 @@ class Atari7800Platform extends Base6502MachinePlatform implements Pl tree['display_list'] = this.machine.getDebugDisplayLists(); return tree; } + getToolForFilename(filename: string) { + if (filename.endsWith(".cc7800")) return "cc7800"; + if (filename.endsWith(".c78")) return "cc7800"; + return getToolForFilename_6502(filename); + } } /// diff --git a/src/worker/fs/cc7800-fs.zip b/src/worker/fs/cc7800-fs.zip new file mode 100755 index 00000000..3323ee0f Binary files /dev/null and b/src/worker/fs/cc7800-fs.zip differ diff --git a/src/worker/tools/acme.ts b/src/worker/tools/acme.ts index 65197301..90d63b12 100644 --- a/src/worker/tools/acme.ts +++ b/src/worker/tools/acme.ts @@ -53,7 +53,7 @@ export function assembleACME(step: BuildStep): BuildStepResult { var binpath = step.prefix + ".bin"; var lstpath = step.prefix + ".lst"; var sympath = step.prefix + ".sym"; - if (staleFiles(step, [binpath, lstpath])) { + if (staleFiles(step, [binpath])) { var binout, lstout, symout; var ACME: EmscriptenModule = emglobal.acme({ instantiateWasm: moduleInstFn('acme'), diff --git a/src/worker/tools/cc7800.ts b/src/worker/tools/cc7800.ts new file mode 100644 index 00000000..363b2be1 --- /dev/null +++ b/src/worker/tools/cc7800.ts @@ -0,0 +1,89 @@ +import { WASIFilesystem, WASIMemoryFilesystem, WASIRunner } from "../../common/wasi/wasishim"; +import { BuildStep, BuildStepResult, gatherFiles, getWASMBinary, loadNative, loadWASMBinary, makeErrorMatcher, putWorkFile, staleFiles, store } from "../workermain"; +import JSZip from 'jszip'; + +let cc7800_fs: WASIFilesystem | null = null; +let wasiModule: WebAssembly.Module | null = null; + +function loadBlobSync(path: string) { + var xhr = new XMLHttpRequest(); + xhr.responseType = 'blob'; + xhr.open("GET", path, false); // synchronous request + xhr.send(null); + return xhr.response; +} + +async function loadWASIFilesystemZip(zippath: string) { + const jszip = new JSZip(); + const path = '../../src/worker/fs/' + zippath; + const zipdata = loadBlobSync(path); + console.log(zippath, zipdata); + await jszip.loadAsync(zipdata); + let fs = new WASIMemoryFilesystem(); + let promises = []; + jszip.forEach(async (relativePath, zipEntry) => { + if (zipEntry.dir) { + fs.putDirectory(relativePath); + } else { + let path = './' + relativePath; + let prom = zipEntry.async("uint8array").then((data) => { + fs.putFile(path, data); + }); + promises.push(prom); + } + }); + await Promise.all(promises); + return fs; +} + + +export async function compileCC7800(step: BuildStep): Promise { + const errors = []; + gatherFiles(step, { mainFilePath: "main.c" }); + const destpath = "./a.out"; + if (staleFiles(step, [destpath])) { + if (!cc7800_fs) { + cc7800_fs = await loadWASIFilesystemZip("cc7800-fs.zip"); + } + if (!wasiModule) { + wasiModule = new WebAssembly.Module(loadWASMBinary("cc7800")); + } + const wasi = new WASIRunner(); + wasi.initSync(wasiModule); + wasi.fs.setParent(cc7800_fs); + for (let file of step.files) { + wasi.fs.putFile("./" + file, store.getFileData(file)); + } + wasi.addPreopenDirectory("headers"); + wasi.addPreopenDirectory("."); + wasi.setArgs(["cc7800", "-v", "-g", "-S", "-I", "headers", step.path]); + try { + wasi.run(); + } catch (e) { + errors.push(e); + } + // TODO + let stdout = wasi.fds[1].getBytesAsString(); + let stderr = wasi.fds[2].getBytesAsString(); + console.log('stdout', stdout); + console.log('stderr', stderr); + // Syntax error: Unknown identifier cputes on line 11 of test.c78 + if (stderr.indexOf("Syntax error:") >= 0) { + const matcher = makeErrorMatcher(errors, /^Syntax error: (.+?) on line (\d+) of (.+)/, 2, 1, step.path, 3); + for (let line of stderr.split('\n')) { + matcher(line); + } + } + if (errors.length) { + return { errors }; + } + const combinedasm = wasi.fs.getFile(destpath).getBytesAsString(); + putWorkFile(destpath, combinedasm); + } + return { + nexttool: "dasm", + path: destpath, + args: [destpath], + files: [destpath] + }; +} diff --git a/src/worker/tools/z80.ts b/src/worker/tools/z80.ts index 39ccea37..0c5292d7 100644 --- a/src/worker/tools/z80.ts +++ b/src/worker/tools/z80.ts @@ -11,7 +11,7 @@ export function assembleZMAC(step: BuildStep): BuildStepResult { gatherFiles(step, { mainFilePath: "main.asm" }); var lstpath = step.prefix + ".lst"; var binpath = step.prefix + ".cim"; - if (staleFiles(step, [binpath, lstpath])) { + if (staleFiles(step, [binpath])) { /* error1.asm(4) : 'l18d4' Undeclared JP L18D4 diff --git a/src/worker/wasm/cc7800.wasm b/src/worker/wasm/cc7800.wasm new file mode 100755 index 00000000..52f6d9db Binary files /dev/null and b/src/worker/wasm/cc7800.wasm differ diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index 9615e4eb..371807b2 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -50,7 +50,9 @@ export function getWASMMemory() { } return wasmMemory; } - +export function getWASMBinary(module_id:string) { + return wasmBlob[module_id]; +} function getWASMModule(module_id:string) { var module = _WASM_module_cache[module_id]; if (!module) { @@ -813,9 +815,8 @@ export function load(modulename:string, debug?:boolean) { loaded[modulename] = 1; } } -export function loadWASM(modulename:string, debug?:boolean) { +export function loadWASMBinary(modulename:string) { if (!loaded[modulename]) { - importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js")); var xhr = new XMLHttpRequest(); xhr.responseType = 'arraybuffer'; xhr.open("GET", PWORKER+"wasm/"+modulename+".wasm", false); // synchronous request @@ -828,6 +829,13 @@ export function loadWASM(modulename:string, debug?:boolean) { throw Error("Could not load WASM file " + modulename + ".wasm"); } } + return wasmBlob[modulename]; +} +export function loadWASM(modulename:string, debug?:boolean) { + if (!loaded[modulename]) { + importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js")); + loadWASMBinary(modulename); + } } export function loadNative(modulename:string) { // detect WASM @@ -1140,6 +1148,7 @@ import * as arm from './tools/arm' import * as ecs from './tools/ecs' import * as remote from './tools/remote' import * as acme from './tools/acme' +import * as cc7800 from './tools/cc7800' var TOOLS = { 'dasm': dasm.assembleDASM, @@ -1175,7 +1184,8 @@ var TOOLS = { 'armips': arm.assembleARMIPS, 'vasmarm': arm.assembleVASMARM, 'ecs': ecs.assembleECS, - 'remote': remote.buildRemote + 'remote': remote.buildRemote, + 'cc7800': cc7800.compileCC7800, } var TOOL_PRELOADFS = {