mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-12 18:42:14 +00:00
Compare commits
10 Commits
9b0c397977
...
4cd000d70d
Author | SHA1 | Date | |
---|---|---|---|
|
4cd000d70d | ||
|
611c174aed | ||
|
d9001df5d4 | ||
|
e6c3dc98e1 | ||
|
43d844fa79 | ||
|
c5bcd8ad9b | ||
|
c189875be3 | ||
|
16fcf33881 | ||
|
8091985fde | ||
|
0a3741872f |
|
@ -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
|
||||
|
||||
|
|
|
@ -167,7 +167,6 @@ body {
|
|||
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=cpc.6128">Amstrad CPC6128</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -209,6 +208,7 @@ body {
|
|||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||
<hr>
|
||||
<li><a class="dropdown-item" href="?platform=williams">Williams (6809)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
2871
package-lock.json
generated
2871
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
55
presets/apple2/lz4test.c
Normal file
55
presets/apple2/lz4test.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
/*
|
||||
Test of the LZ4 decompression library
|
||||
with a hires graphics image.
|
||||
*/
|
||||
|
||||
// CC65 config, reserves space for the HGR1 screen buffer
|
||||
#define CFGFILE apple2-hgr.cfg
|
||||
|
||||
#pragma data-name(push,"HGR")
|
||||
// this segment is required, but we leave it empty
|
||||
// since we're going to decompress the image here
|
||||
#pragma data-name(pop)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <apple2.h>
|
||||
#include <peekpoke.h>
|
||||
#include <lz4.h>
|
||||
|
||||
// STROBE = write any value to an I/O address
|
||||
#define STROBE(addr) __asm__ ("sta %w", addr)
|
||||
|
||||
// start address of the two hi-res graphics regions
|
||||
#define HGR1 0x2000
|
||||
#define HGR2 0x4000
|
||||
|
||||
// the LZ4 compressed data
|
||||
const unsigned char BITMAP_DATA_LZ4[] = {
|
||||
#embed "parrot-apple2.hires.lz4"
|
||||
};
|
||||
|
||||
|
||||
// clear screen and set graphics mode
|
||||
void clear_hgr1() {
|
||||
memset((char*)HGR1, 0, 0x2000); // clear page 1
|
||||
STROBE(0xc052); // turn off mixed-mode
|
||||
STROBE(0xc054); // page 1
|
||||
STROBE(0xc057); // hi-res
|
||||
STROBE(0xc050); // set graphics mode
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
// set hgr1 mode and clear
|
||||
clear_hgr1();
|
||||
// skip the header (usually 11 bytes)
|
||||
decompress_lz4(BITMAP_DATA_LZ4+11, (char*)HGR1, 0x2000);
|
||||
// wait for a key
|
||||
cgetc();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
BIN
presets/apple2/parrot-apple2.hires.lz4
Normal file
BIN
presets/apple2/parrot-apple2.hires.lz4
Normal file
Binary file not shown.
59
presets/atari7800/example_small_sprites.c78
Normal file
59
presets/atari7800/example_small_sprites.c78
Normal file
|
@ -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);
|
||||
}
|
110
presets/atari7800/example_vertical_scrolling.c78
Normal file
110
presets/atari7800/example_vertical_scrolling.c78
Normal file
|
@ -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);
|
||||
}
|
152
presets/atari7800/gfx.h
Normal file
152
presets/atari7800/gfx.h
Normal file
|
@ -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
|
||||
};
|
16
presets/atari7800/skeleton.cc7800
Normal file
16
presets/atari7800/skeleton.cc7800
Normal file
|
@ -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);
|
||||
}
|
69
presets/atari7800/test_conio.c78
Normal file
69
presets/atari7800/test_conio.c78
Normal file
|
@ -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);
|
||||
}
|
|
@ -5,6 +5,10 @@ void raster_wait(byte line) {
|
|||
while (VIC.rasterline < line) ;
|
||||
}
|
||||
|
||||
void wait_vblank(void) {
|
||||
raster_wait(250);
|
||||
}
|
||||
|
||||
static byte VIC_BANK_PAGE[4] = {
|
||||
0xc0, 0x80, 0x40, 0x00
|
||||
};
|
||||
|
@ -24,3 +28,13 @@ char __fastcall__ poll_keyboard() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void set_raster_irq(char scanline) {
|
||||
// deactivate CIA interrupts (keyboard, etc)
|
||||
CIA1.icr = 0x7f;
|
||||
// set raster line for interrupt
|
||||
VIC.ctrl1 &= 0x7f; // clear raster line bit 8
|
||||
VIC.rasterline = scanline;
|
||||
// activate VIC raster interrupts
|
||||
VIC.imr = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,10 +80,10 @@ typedef enum { false, true } bool; // boolean
|
|||
|
||||
// set scrolling registers
|
||||
#define SET_SCROLL_Y(_y) \
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | (_y);
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | (_y & 7);
|
||||
|
||||
#define SET_SCROLL_X(_x) \
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | (_x);
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | (_x & 7);
|
||||
|
||||
|
||||
// enable RAM from 0xa000-0xffff, disable interrupts
|
||||
|
@ -102,6 +102,9 @@ typedef enum { false, true } bool; // boolean
|
|||
// wait until specific raster line
|
||||
void raster_wait(byte line);
|
||||
|
||||
// wait until end of frame
|
||||
void wait_vblank();
|
||||
|
||||
// get current VIC bank start address
|
||||
char* get_vic_bank_start();
|
||||
|
||||
|
@ -132,4 +135,9 @@ inline void waitvsync() {
|
|||
}
|
||||
#endif
|
||||
|
||||
// for use with set_irq()
|
||||
// sets up the VIC to send raster interrupts
|
||||
// and disables CIA interrupts
|
||||
void set_raster_irq(char scanline);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@ A simple music player.
|
|||
#include "sidmacros.h"
|
||||
|
||||
#include <cbm_petscii_charmap.h>
|
||||
#include <6502.h>
|
||||
|
||||
// SID frequency table (PAL version)
|
||||
const int note_table_pal[96] = {
|
||||
|
@ -149,7 +150,7 @@ void drawParams() {
|
|||
}
|
||||
}
|
||||
|
||||
void setParamValues() {
|
||||
void setSIDRegisters() {
|
||||
char i;
|
||||
word val;
|
||||
char buf[30];
|
||||
|
@ -179,16 +180,16 @@ void setParamValues() {
|
|||
music_wavebits = buf[0x04];
|
||||
}
|
||||
|
||||
void tick(int i) {
|
||||
while (i--) {
|
||||
wait_vblank();
|
||||
char music_update() {
|
||||
if (!music_ptr) start_music(music1);
|
||||
play_music();
|
||||
}
|
||||
return IRQ_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void handleInput() {
|
||||
char key = 0;
|
||||
char joy = joy_read(0);
|
||||
if (joy == 0) return;
|
||||
if (JOY_UP(joy)) key = 'i';
|
||||
if (JOY_DOWN(joy)) key = 'k';
|
||||
if (JOY_LEFT(joy)) key = 'j';
|
||||
|
@ -199,7 +200,6 @@ void handleInput() {
|
|||
--currentParam;
|
||||
drawValue(currentParam+1);
|
||||
drawValue(currentParam);
|
||||
tick(3);
|
||||
}
|
||||
break;
|
||||
case 'k': // DOWN
|
||||
|
@ -207,29 +207,34 @@ void handleInput() {
|
|||
++currentParam;
|
||||
drawValue(currentParam-1);
|
||||
drawValue(currentParam);
|
||||
tick(3);
|
||||
}
|
||||
break;
|
||||
case 'j': // LEFT
|
||||
if (paramValues[currentParam] > SID_PARAMS[currentParam].low) {
|
||||
paramValues[currentParam]--;
|
||||
drawValue(currentParam);
|
||||
setParamValues();
|
||||
setSIDRegisters();
|
||||
}
|
||||
break;
|
||||
case 'l': // RIGHT
|
||||
if (paramValues[currentParam] < SID_PARAMS[currentParam].high) {
|
||||
paramValues[currentParam]++;
|
||||
drawValue(currentParam);
|
||||
setParamValues();
|
||||
setSIDRegisters();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// delay a few frames to slow down movement
|
||||
waitvsync();
|
||||
waitvsync();
|
||||
waitvsync();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
joy_install (joy_static_stddrv);
|
||||
|
||||
// set initial SID parameters
|
||||
paramValues[0] = 15;
|
||||
paramValues[1] = 8;
|
||||
paramValues[2] = 8;
|
||||
|
@ -237,14 +242,19 @@ void main(void)
|
|||
paramValues[4] = 4;
|
||||
paramValues[5] = 4;
|
||||
paramValues[7] = 1; // pulse
|
||||
drawParams();
|
||||
setParamValues();
|
||||
setSIDRegisters();
|
||||
|
||||
// draw the UI
|
||||
drawParams();
|
||||
|
||||
// set IRQ routine called every frame
|
||||
set_irq(music_update, (void*)0x9f00, 0x100);
|
||||
|
||||
// main loop to handle UI
|
||||
music_ptr = 0;
|
||||
while (1) {
|
||||
waitvsync();
|
||||
handleInput();
|
||||
if (!music_ptr) start_music(music1);
|
||||
tick(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ void main(void) {
|
|||
|
||||
// infinite loop
|
||||
while (1) {
|
||||
// wait for vsync
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// scroll one pixel to the left
|
||||
// and move screen memory every 8 pixels
|
||||
scroll_one_pixel_left();
|
||||
|
|
|
@ -23,8 +23,8 @@ void scroll_one_pixel_left() {
|
|||
src = scrnbuf[visbuf] + (scroll_x & 7) * 128;
|
||||
// destination = hidden buffer
|
||||
dst = scrnbuf[visbuf ^ 1] + (scroll_x & 7) * 128;
|
||||
// wait for vsync
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// scroll hidden buffer
|
||||
memcpy(dst, src+1, 128);
|
||||
// every 8 pixels, switch visible and hidden buffers
|
||||
|
|
|
@ -17,8 +17,8 @@ void scroll_update_regs() {
|
|||
void scroll_swap() {
|
||||
// swap hidden and visible buffers
|
||||
hidbuf ^= 1;
|
||||
// wait for vblank and update registers
|
||||
waitvsync();
|
||||
// wait for end of frame and update registers
|
||||
wait_vblank();
|
||||
scroll_update_regs();
|
||||
SET_VIC_SCREEN(hidbuf ? 0x8000 : 0x8400);
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ void main(void) {
|
|||
// animate sprite in shadow sprite ram
|
||||
sprite_draw(0, n++, 70, 192);
|
||||
sprite_draw(0, 172, 145, 192);
|
||||
// wait for vblank
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// update scroll registers
|
||||
// and swap screens if we must
|
||||
scroll_update();
|
||||
|
|
|
@ -118,7 +118,7 @@ void main(void) {
|
|||
// animate sprite in shadow sprite ram
|
||||
update_player();
|
||||
// wait for end of frame
|
||||
waitvsync();
|
||||
wait_vblank();
|
||||
// then update sprite registers
|
||||
sprite_update(visbuf);
|
||||
// update scroll registers
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//#link "common.c"
|
||||
|
||||
#include <tgi.h>
|
||||
#include <6502.h>
|
||||
|
||||
//#resource "c64-sid.cfg"
|
||||
#define CFGFILE c64-sid.cfg
|
||||
|
@ -57,6 +58,11 @@ void show_envelope() {
|
|||
if (++sweep == 320) sweep = 0;
|
||||
}
|
||||
|
||||
char music_update() {
|
||||
sid_update();
|
||||
return IRQ_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
// install TGI graphics driver
|
||||
tgi_install(tgi_static_stddrv);
|
||||
|
@ -71,6 +77,9 @@ void main(void) {
|
|||
// install joystick driver
|
||||
joy_install(joy_static_stddrv);
|
||||
|
||||
// set IRQ routine called every frame
|
||||
set_irq(music_update, (void*)0x9f00, 0x100);
|
||||
|
||||
while (1) {
|
||||
// play sound effect when joystick is moved
|
||||
byte joy = joy_read(0);
|
||||
|
@ -81,8 +90,6 @@ void main(void) {
|
|||
}
|
||||
// sync with frame rate
|
||||
waitvsync();
|
||||
// update SID player
|
||||
sid_update();
|
||||
// update graphs
|
||||
show_envelope();
|
||||
show_signal();
|
||||
|
|
50
presets/c64/test_setirq.c
Normal file
50
presets/c64/test_setirq.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <peekpoke.h>
|
||||
#include <string.h>
|
||||
#include <c64.h>
|
||||
#include <cbm_petscii_charmap.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include <6502.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
char interrupt_handler() {
|
||||
// only needed if CIA interupts are still active
|
||||
if (!(VIC.irr & VIC_IRR_IRST)) return IRQ_NOT_HANDLED;
|
||||
// change colors so we can see where the IRQ fired
|
||||
VIC.bgcolor0++;
|
||||
VIC.bordercolor++;
|
||||
// reading VIC.rasterline returns the current line
|
||||
// setting it changes the line where the IRQ fires
|
||||
if (VIC.rasterline >= 245) {
|
||||
VIC.rasterline = 40;
|
||||
} else {
|
||||
VIC.rasterline = 245;
|
||||
}
|
||||
// acknowledge VIC raster interrupt (bit 0)
|
||||
VIC.irr = 1;
|
||||
// change colors back to where they were
|
||||
VIC.bgcolor0--;
|
||||
VIC.bordercolor--;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
clrscr();
|
||||
printf("\nHello World!\n");
|
||||
|
||||
// set interrupt routine
|
||||
set_irq(interrupt_handler, (void*)0x9f00, 0x100);
|
||||
|
||||
// disable CIA interrupt, activate VIC interrupt
|
||||
set_raster_irq(255);
|
||||
|
||||
while (1) {
|
||||
printf("%d ", VIC.rasterline);
|
||||
}
|
||||
}
|
|
@ -957,7 +957,7 @@ export abstract class BaseMachinePlatform<T extends Machine> extends BaseDebugPl
|
|||
export abstract class Base6502MachinePlatform<T extends Machine> extends BaseMachinePlatform<T> {
|
||||
|
||||
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));
|
||||
|
|
|
@ -243,6 +243,8 @@ export abstract class BasicHeadlessMachine implements HasCPU, Bus, AcceptsROM, P
|
|||
}
|
||||
loadROM(data: Uint8Array, title?: string): void {
|
||||
if (!this.rom) this.rom = new Uint8Array(this.defaultROMSize);
|
||||
if (data.length > this.rom.length)
|
||||
throw new Error(`ROM too big: ${data.length} > ${this.rom.length}}`);
|
||||
this.rom.set(data);
|
||||
}
|
||||
loadState(state) {
|
||||
|
|
613
src/common/wasi/wasishim.ts
Normal file
613
src/common/wasi/wasishim.ts
Normal file
|
@ -0,0 +1,613 @@
|
|||
|
||||
// https://dev.to/ndesmic/building-a-minimal-wasi-polyfill-for-browsers-4nel
|
||||
// http://www.wasmtutor.com/webassembly-barebones-wasi
|
||||
// https://github.com/emscripten-core/emscripten/blob/c017fc2d6961962ee87ae387462a099242dfbbd2/src/library_wasi.js#L451
|
||||
// https://github.com/emscripten-core/emscripten/blob/c017fc2d6961962ee87ae387462a099242dfbbd2/src/library_fs.js
|
||||
// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/sources/preopens.c
|
||||
// https://fossies.org/linux/wasm3/source/extra/wasi_core.h
|
||||
// https://wasix.org/docs/api-reference/wasi/fd_read
|
||||
|
||||
const use_debug = true;
|
||||
const debug = use_debug ? console.log : () => { };
|
||||
const warning = console.log;
|
||||
|
||||
export enum FDType {
|
||||
UNKNOWN = 0,
|
||||
BLOCK_DEVICE = 1,
|
||||
CHARACTER_DEVICE = 2,
|
||||
DIRECTORY = 3,
|
||||
REGULAR_FILE = 4,
|
||||
SOCKET_DGRAM = 5,
|
||||
SOCKET_STREAM = 6,
|
||||
SYMBOLIC_LINK = 7,
|
||||
}
|
||||
|
||||
export enum FDRights {
|
||||
FD_DATASYNC = 1,
|
||||
FD_READ = 2,
|
||||
FD_SEEK = 4,
|
||||
FD_FDSTAT_SET_FLAGS = 8,
|
||||
FD_SYNC = 16,
|
||||
FD_TELL = 32,
|
||||
FD_WRITE = 64,
|
||||
FD_ADVISE = 128,
|
||||
FD_ALLOCATE = 256,
|
||||
PATH_CREATE_DIRECTORY = 512,
|
||||
PATH_CREATE_FILE = 1024,
|
||||
PATH_LINK_SOURCE = 2048,
|
||||
PATH_LINK_TARGET = 4096,
|
||||
PATH_OPEN = 8192,
|
||||
FD_READDIR = 16384,
|
||||
PATH_READLINK = 32768,
|
||||
PATH_RENAME_SOURCE = 65536,
|
||||
PATH_RENAME_TARGET = 131072,
|
||||
PATH_FILESTAT_GET = 262144,
|
||||
PATH_FILESTAT_SET_SIZE = 524288,
|
||||
PATH_FILESTAT_SET_TIMES = 1048576,
|
||||
FD_FILESTAT_GET = 2097152,
|
||||
FD_FILESTAT_SET_SIZE = 4194304,
|
||||
FD_FILESTAT_SET_TIMES = 8388608,
|
||||
PATH_SYMLINK = 16777216,
|
||||
PATH_REMOVE_DIRECTORY = 33554432,
|
||||
PATH_UNLINK_FILE = 67108864,
|
||||
POLL_FD_READWRITE = 134217728,
|
||||
SOCK_SHUTDOWN = 268435456,
|
||||
FD_ALL = 536870911, // TODO?
|
||||
}
|
||||
|
||||
export enum FDFlags {
|
||||
APPEND = 1,
|
||||
DSYNC = 2,
|
||||
NONBLOCK = 4,
|
||||
RSYNC = 8,
|
||||
SYNC = 16,
|
||||
}
|
||||
|
||||
export enum FDOpenFlags {
|
||||
CREAT = 1,
|
||||
DIRECTORY = 2,
|
||||
EXCL = 4,
|
||||
TRUNC = 8,
|
||||
}
|
||||
|
||||
export enum WASIErrors {
|
||||
SUCCESS = 0,
|
||||
TOOBIG = 1,
|
||||
ACCES = 2,
|
||||
ADDRINUSE = 3,
|
||||
ADDRNOTAVAIL = 4,
|
||||
AFNOSUPPORT = 5,
|
||||
AGAIN = 6,
|
||||
ALREADY = 7,
|
||||
BADF = 8,
|
||||
BADMSG = 9,
|
||||
BUSY = 10,
|
||||
CANCELED = 11,
|
||||
CHILD = 12,
|
||||
CONNABORTED = 13,
|
||||
CONNREFUSED = 14,
|
||||
CONNRESET = 15,
|
||||
DEADLK = 16,
|
||||
DESTADDRREQ = 17,
|
||||
DOM = 18,
|
||||
DQUOT = 19,
|
||||
EXIST = 20,
|
||||
FAULT = 21,
|
||||
FBIG = 22,
|
||||
HOSTUNREACH = 23,
|
||||
IDRM = 24,
|
||||
ILSEQ = 25,
|
||||
INPROGRESS = 26,
|
||||
INTR = 27,
|
||||
INVAL = 28,
|
||||
IO = 29,
|
||||
ISCONN = 30,
|
||||
ISDIR = 31,
|
||||
LOOP = 32,
|
||||
MFILE = 33,
|
||||
MLINK = 34,
|
||||
MSGSIZE = 35,
|
||||
MULTIHOP = 36,
|
||||
NAMETOOLONG = 37,
|
||||
NETDOWN = 38,
|
||||
NETRESET = 39,
|
||||
NETUNREACH = 40,
|
||||
NFILE = 41,
|
||||
NOBUFS = 42,
|
||||
NODEV = 43,
|
||||
NOENT = 44,
|
||||
NOEXEC = 45,
|
||||
NOLCK = 46,
|
||||
NOLINK = 47,
|
||||
NOMEM = 48,
|
||||
NOMSG = 49,
|
||||
NOPROTOOPT = 50,
|
||||
NOSPC = 51,
|
||||
NOSYS = 52,
|
||||
NOTCONN = 53,
|
||||
NOTDIR = 54,
|
||||
NOTEMPTY = 55,
|
||||
NOTRECOVERABLE = 56,
|
||||
NOTSOCK = 57,
|
||||
NOTSUP = 58,
|
||||
NOTTY = 59,
|
||||
NXIO = 60,
|
||||
OVERFLOW = 61,
|
||||
OWNERDEAD = 62,
|
||||
PERM = 63,
|
||||
PIPE = 64,
|
||||
PROTO = 65,
|
||||
PROTONOSUPPORT = 66,
|
||||
PROTOTYPE = 67,
|
||||
RANGE = 68,
|
||||
ROFS = 69,
|
||||
SPIPE = 70,
|
||||
SRCH = 71,
|
||||
STALE = 72,
|
||||
TIMEDOUT = 73,
|
||||
TXTBSY = 74,
|
||||
XDEV = 75,
|
||||
NOTCAPABLE = 76,
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class WASIFileDescriptor {
|
||||
fdindex: number = -1;
|
||||
data: Uint8Array = new Uint8Array(16);
|
||||
flags: number = 0;
|
||||
size: number = 0;
|
||||
offset: number = 0;
|
||||
|
||||
constructor(public name: string, public type: FDType, public rights: number) {
|
||||
this.rights = -1; // TODO?
|
||||
}
|
||||
ensureCapacity(size: number) {
|
||||
if (this.data.byteLength < size) {
|
||||
const newdata = new Uint8Array(size * 2); // TODO?
|
||||
newdata.set(this.data);
|
||||
this.data = newdata;
|
||||
}
|
||||
}
|
||||
write(chunk: Uint8Array) {
|
||||
this.ensureCapacity(this.offset + chunk.byteLength);
|
||||
this.data.set(chunk, this.offset);
|
||||
this.offset += chunk.byteLength;
|
||||
this.size = Math.max(this.size, this.offset);
|
||||
}
|
||||
read(chunk: Uint8Array) {
|
||||
const len = Math.min(chunk.byteLength, this.size - this.offset);
|
||||
chunk.set(this.data.subarray(this.offset, this.offset + len));
|
||||
this.offset += len;
|
||||
return len;
|
||||
}
|
||||
truncate() {
|
||||
this.size = 0;
|
||||
this.offset = 0;
|
||||
}
|
||||
llseek(offset: number, whence: number) {
|
||||
switch (whence) {
|
||||
case 0: // SEEK_SET
|
||||
this.offset = offset;
|
||||
break;
|
||||
case 1: // SEEK_CUR
|
||||
this.offset += offset;
|
||||
break;
|
||||
case 2: // SEEK_END
|
||||
this.offset = this.size + offset;
|
||||
break;
|
||||
}
|
||||
if (this.offset < 0) this.offset = 0;
|
||||
if (this.offset > this.size) this.offset = this.size;
|
||||
}
|
||||
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})`;
|
||||
}
|
||||
}
|
||||
|
||||
class WASIStreamingFileDescriptor extends WASIFileDescriptor {
|
||||
constructor(fdindex: number, name: string, type: FDType, rights: number,
|
||||
private stream: NodeJS.WritableStream) {
|
||||
super(name, type, rights);
|
||||
this.fdindex = fdindex;
|
||||
}
|
||||
write(chunk: Uint8Array) {
|
||||
this.stream.write(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
export interface WASIFilesystem {
|
||||
getFile(name: string) : WASIFileDescriptor;
|
||||
}
|
||||
|
||||
export class WASIMemoryFilesystem implements WASIFilesystem {
|
||||
private parent: WASIFilesystem | null = null;
|
||||
private files: Map<string, WASIFileDescriptor> = new Map();
|
||||
private dirs: Map<string, WASIFileDescriptor> = 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);
|
||||
this.dirs.set(name, dir);
|
||||
return dir;
|
||||
}
|
||||
putFile(name: string, data: string | Uint8Array, rights?: number) {
|
||||
if (typeof data === 'string') {
|
||||
data = new TextEncoder().encode(data);
|
||||
}
|
||||
if (!rights) rights = FDRights.FD_READ | FDRights.FD_WRITE;
|
||||
const file = new WASIFileDescriptor(name, FDType.REGULAR_FILE, rights);
|
||||
file.write(data);
|
||||
file.offset = 0;
|
||||
this.files.set(name, file);
|
||||
return file;
|
||||
}
|
||||
getFile(name: string) {
|
||||
let file = this.files.get(name);
|
||||
if (!file) {
|
||||
file = this.parent?.getFile(name);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
export class WASIRunner {
|
||||
#instance; // TODO
|
||||
#memarr8: Uint8Array;
|
||||
#memarr32: Int32Array;
|
||||
#args: Uint8Array[] = [];
|
||||
#envvars: Uint8Array[] = [];
|
||||
|
||||
stdin : WASIFileDescriptor;
|
||||
stdout : WASIFileDescriptor;
|
||||
stderr : WASIFileDescriptor;
|
||||
|
||||
fds: WASIFileDescriptor[] = [];
|
||||
exited = false;
|
||||
errno = -1;
|
||||
fs = new WASIMemoryFilesystem();
|
||||
|
||||
constructor() {
|
||||
this.createStdioBrowser();
|
||||
}
|
||||
createStdioNode() {
|
||||
this.stdin = new WASIStreamingFileDescriptor(0, '<stdin>', FDType.CHARACTER_DEVICE, FDRights.FD_READ, process.stdin);
|
||||
this.stdout = new WASIStreamingFileDescriptor(1, '<stdout>', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE, process.stdout);
|
||||
this.stderr = new WASIStreamingFileDescriptor(2, '<stderr>', 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('<stdin>', FDType.CHARACTER_DEVICE, FDRights.FD_READ);
|
||||
this.stdout = new WASIFileDescriptor('<stdout>', FDType.CHARACTER_DEVICE, FDRights.FD_WRITE);
|
||||
this.stderr = new WASIFileDescriptor('<stderr>', 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) {
|
||||
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'));
|
||||
}
|
||||
addPreopenDirectory(name: string) {
|
||||
return this.openFile(name, FDOpenFlags.DIRECTORY | FDOpenFlags.CREAT);
|
||||
}
|
||||
openFile(path: string, o_flags: number, mode?: number): WASIFileDescriptor | number {
|
||||
let file = this.fs.getFile(path);
|
||||
mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode;
|
||||
if (o_flags & FDOpenFlags.CREAT) {
|
||||
if (file == null) {
|
||||
if (o_flags & FDOpenFlags.DIRECTORY) {
|
||||
file = this.fs.putDirectory(path);
|
||||
} else {
|
||||
file = this.fs.putFile(path, new Uint8Array(), FDRights.FD_ALL);
|
||||
}
|
||||
} else {
|
||||
if (o_flags & FDOpenFlags.TRUNC) { // truncate
|
||||
file.truncate();
|
||||
} else return WASIErrors.INVAL;
|
||||
}
|
||||
} else {
|
||||
if (file == null) return WASIErrors.NOSYS;
|
||||
if (o_flags & FDOpenFlags.DIRECTORY) { // check type
|
||||
if (file.type !== FDType.DIRECTORY) return WASIErrors.NOSYS;
|
||||
}
|
||||
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;
|
||||
this.fds.push(file);
|
||||
return file;
|
||||
}
|
||||
mem8() {
|
||||
if (!this.#memarr8?.byteLength) {
|
||||
this.#memarr8 = new Uint8Array(this.#instance.exports.memory.buffer);
|
||||
}
|
||||
return this.#memarr8;
|
||||
}
|
||||
mem32() {
|
||||
if (!this.#memarr32?.byteLength) {
|
||||
this.#memarr32 = new Int32Array(this.#instance.exports.memory.buffer);
|
||||
}
|
||||
return this.#memarr32;
|
||||
}
|
||||
run() {
|
||||
try {
|
||||
this.#instance.exports._start();
|
||||
if (!this.exited) {
|
||||
this.exited = true;
|
||||
this.errno = 0;
|
||||
}
|
||||
} catch (err) {
|
||||
if (!this.exited) throw err;
|
||||
}
|
||||
return this.getErrno();
|
||||
}
|
||||
getImportObject() {
|
||||
return {
|
||||
"wasi_snapshot_preview1": this.getWASISnapshotPreview1(),
|
||||
"env": this.getEnv(),
|
||||
}
|
||||
}
|
||||
peek8(ptr: number) {
|
||||
return this.mem8()[ptr];
|
||||
}
|
||||
peek16(ptr: number) {
|
||||
return this.mem8()[ptr] | (this.mem8()[ptr + 1] << 8);
|
||||
}
|
||||
peek32(ptr: number) {
|
||||
return this.mem32()[ptr >>> 2];
|
||||
}
|
||||
poke8(ptr: number, val: number) {
|
||||
this.mem8()[ptr] = val;
|
||||
}
|
||||
poke16(ptr: number, val: number) {
|
||||
this.mem8()[ptr] = val;
|
||||
this.mem8()[ptr + 1] = val >> 8;
|
||||
}
|
||||
poke32(ptr: number, val: number) {
|
||||
this.mem32()[ptr >>> 2] = val;
|
||||
}
|
||||
poke64(ptr: number, val: number) {
|
||||
this.mem32()[ptr >>> 2] = val;
|
||||
this.mem32()[(ptr >>> 2) + 1] = 0;
|
||||
}
|
||||
pokeUTF8(str: string, ptr: number, maxlen: number) {
|
||||
const enc = new TextEncoder();
|
||||
const bytes = enc.encode(str);
|
||||
const len = Math.min(bytes.length, maxlen);
|
||||
this.mem8().set(bytes.subarray(0, len), ptr);
|
||||
}
|
||||
peekUTF8(ptr: number, maxlen: number) {
|
||||
const bytes = this.mem8().subarray(ptr, ptr + maxlen);
|
||||
const dec = new TextDecoder();
|
||||
return dec.decode(bytes);
|
||||
}
|
||||
getErrno() {
|
||||
return this.errno;
|
||||
//let errno_ptr = this.#instance.exports.__errno_location();
|
||||
//return this.peek32(errno_ptr);
|
||||
}
|
||||
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));
|
||||
}
|
||||
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) {
|
||||
this.poke32(argv, argv_buf);
|
||||
argv += 4;
|
||||
for (let i = 0; i < arg.length; i++) {
|
||||
this.poke8(argv_buf, arg[i]);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
for (let i = 0; i < iovs_len; i++) {
|
||||
const ptr = iovecs[i * 2];
|
||||
const len = iovecs[i * 2 + 1];
|
||||
const chunk = this.mem8().subarray(ptr, ptr + len);
|
||||
total += len;
|
||||
stream.write(chunk);
|
||||
}
|
||||
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];
|
||||
const iovecs = this.mem32().subarray(iovs >>> 2, (iovs + iovs_len * 8) >>> 2);
|
||||
let total = 0;
|
||||
for (let i = 0; i < iovs_len; i++) {
|
||||
const ptr = iovecs[i * 2];
|
||||
const len = iovecs[i * 2 + 1];
|
||||
const chunk = this.mem8().subarray(ptr, ptr + len);
|
||||
total += stream.read(chunk);
|
||||
}
|
||||
this.poke32(nread_ptr, total);
|
||||
debug("fd_read", fd, iovs, iovs_len, '->', total);
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
fd_seek(fd: number, offset: number, whence: number, newoffset_ptr: number) {
|
||||
const file = this.fds[fd];
|
||||
debug("fd_seek", fd, offset, whence, file);
|
||||
if (file != null) {
|
||||
file.llseek(offset, whence);
|
||||
this.poke64(newoffset_ptr, file.offset);
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
return WASIErrors.BADF;
|
||||
}
|
||||
fd_close(fd: number) {
|
||||
debug("fd_close", fd);
|
||||
const file = this.fds[fd];
|
||||
if (file != null) {
|
||||
this.fds[fd] = null;
|
||||
return 0;
|
||||
}
|
||||
return WASIErrors.BADF;
|
||||
}
|
||||
proc_exit(errno: number) {
|
||||
debug("proc_exit", errno);
|
||||
this.errno = errno;
|
||||
this.exited = true;
|
||||
}
|
||||
fd_prestat_get(fd: number, prestat_ptr: number) {
|
||||
const file = this.fds[fd];
|
||||
debug("fd_prestat_get", fd, prestat_ptr, file?.name);
|
||||
if (file && file.type === FDType.DIRECTORY) {
|
||||
const enc_name = new TextEncoder().encode(file.name);
|
||||
this.poke8(prestat_ptr + 0, 0); // __WASI_PREOPENTYPE_DIR
|
||||
this.poke64(prestat_ptr + 8, enc_name.length);
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
return WASIErrors.BADF;
|
||||
}
|
||||
fd_fdstat_get(fd: number, fdstat_ptr: number) {
|
||||
const file = this.fds[fd];
|
||||
debug("fd_fdstat_get", fd, fdstat_ptr, file + "");
|
||||
if (file != null) {
|
||||
this.poke16(fdstat_ptr + 0, file.type); // fs_filetype
|
||||
this.poke16(fdstat_ptr + 2, file.flags); // fs_flags
|
||||
this.poke64(fdstat_ptr + 8, file.rights); // fs_rights_base
|
||||
this.poke64(fdstat_ptr + 16, file.rights); // fs_rights_inheriting
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
return WASIErrors.BADF;
|
||||
}
|
||||
fd_prestat_dir_name(fd: number, path_ptr: number, path_len: number) {
|
||||
const file = this.fds[fd];
|
||||
debug("fd_prestat_dir_name", fd, path_ptr, path_len);
|
||||
if (file != null) {
|
||||
this.pokeUTF8(file.name, path_ptr, path_len);
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
return WASIErrors.INVAL;
|
||||
}
|
||||
path_open(dirfd: number, dirflags: number, path_ptr: number, path_len: number,
|
||||
o_flags: number, fs_rights_base: number, fs_rights_inheriting: number,
|
||||
fd_flags: number, fd_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.openFile(path, o_flags, fd_flags);
|
||||
debug("path_open", path, dirfd, dirflags,
|
||||
o_flags, //fs_rights_base, fs_rights_inheriting,
|
||||
fd_flags, fd_ptr, '->', fd + "");
|
||||
if (typeof fd === 'number') return fd; // error msg
|
||||
this.poke32(fd_ptr, fd.fdindex);
|
||||
return WASIErrors.SUCCESS;
|
||||
}
|
||||
random_get(ptr: number, len: number) {
|
||||
debug("random_get", ptr, len);
|
||||
for (let i=0; i<len; i++) {
|
||||
// TODO: don't use for crypto
|
||||
this.poke8(ptr + i, Math.floor(Math.random() * 256));
|
||||
}
|
||||
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_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),
|
||||
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() { warning('TODO: unlink'); return 0; },
|
||||
}
|
||||
}
|
||||
}
|
|
@ -120,7 +120,14 @@ export type CodeListingMap = {[path:string]:CodeListing};
|
|||
export type VerilogOutput =
|
||||
{program_rom_variable:string, program_rom:Uint8Array, code:string, name:string, ports:any[], signals:any[]};
|
||||
|
||||
export type Segment = {name:string, start:number, size:number, last?:number, type?:string};
|
||||
export type Segment = {
|
||||
name:string,
|
||||
start:number,
|
||||
size:number,
|
||||
last?:number,
|
||||
type?:string,
|
||||
source?:'native'|'linker'
|
||||
};
|
||||
|
||||
export type WorkerResult = WorkerErrorResult | WorkerOutputResult<any> | WorkerUnchangedResult;
|
||||
|
||||
|
|
|
@ -409,8 +409,12 @@ export class CodeProject {
|
|||
|
||||
processBuildSegments(data: WorkerOutputResult<any>) {
|
||||
// save and sort segment list
|
||||
var segs = (this.platform.getMemoryMap && this.platform.getMemoryMap()["main"]) || [];
|
||||
if (data.segments) { segs = segs.concat(data.segments || []); }
|
||||
var segs : Segment[] = (this.platform.getMemoryMap && this.platform.getMemoryMap()["main"]) || [];
|
||||
if (segs?.length) { segs.forEach(seg => seg.source = 'native'); }
|
||||
if (data.segments) {
|
||||
data.segments.forEach(seg => seg.source = 'linker');
|
||||
segs = segs.concat(data.segments || []);
|
||||
}
|
||||
segs.sort((a,b) => {return a.start-b.start});
|
||||
this.segments = segs;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -245,6 +245,8 @@ export class MemoryMapView implements ProjectView {
|
|||
this.maindiv = newDiv(parent, 'vertical-scroll');
|
||||
this.maindiv.css('display', 'grid');
|
||||
this.maindiv.css('grid-template-columns', '5em 40% 40%');
|
||||
//this.maindiv.css('grid-template-rows', '2em auto auto');
|
||||
this.maindiv.css('align-content', 'start');
|
||||
return this.maindiv[0];
|
||||
}
|
||||
|
||||
|
@ -256,17 +258,15 @@ export class MemoryMapView implements ProjectView {
|
|||
this.maindiv.append(offset);
|
||||
}
|
||||
var segdiv = $('<div class="segment"/>');
|
||||
if (!newrow)
|
||||
segdiv.text(seg.name);
|
||||
let alttext = `$${hex(seg.start)} - $${hex(seg.last || seg.start+seg.size-1)}`
|
||||
alttext += ` (${seg.size} bytes)`;
|
||||
// set alttext of div
|
||||
segdiv.attr('title', alttext);
|
||||
if (!newrow || seg.source == 'linker')
|
||||
segdiv.css('grid-column-start', 3); // make sure it's on right side
|
||||
if (seg.last)
|
||||
segdiv.text(seg.name+" ("+(seg.last-seg.start)+" / "+seg.size+" bytes used)");
|
||||
else
|
||||
segdiv.text(seg.name+" ("+seg.size+" bytes)");
|
||||
if (seg.size >= 256) {
|
||||
var pad = (Math.log(seg.size) - Math.log(256)) * 0.5;
|
||||
segdiv.css('padding-top', pad+'em');
|
||||
segdiv.css('padding-bottom', pad+'em');
|
||||
}
|
||||
var pad = Math.max(3.0, Math.log(seg.size+1)) * 0.5;
|
||||
segdiv.css('height', pad+'em');
|
||||
if (seg.type) {
|
||||
segdiv.addClass('segment-'+seg.type);
|
||||
}
|
||||
|
@ -288,9 +288,10 @@ export class MemoryMapView implements ProjectView {
|
|||
var curofs = 0;
|
||||
var laststart = -1;
|
||||
for (var seg of segments) {
|
||||
//var used = seg.last ? (seg.last-seg.start) : seg.size;
|
||||
if (seg.start > curofs)
|
||||
this.addSegment({name:'',start:curofs, size:seg.start-curofs}, true);
|
||||
// add free space
|
||||
if (seg.start > curofs) {
|
||||
this.addSegment({ name: '', start: curofs, size: seg.start - curofs }, true);
|
||||
}
|
||||
this.addSegment(seg, laststart != seg.start);
|
||||
laststart = seg.start;
|
||||
curofs = seg.start + seg.size;
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
import { MOS6502, MOS6502State } from "../common/cpu/MOS6502";
|
||||
import { Bus, BasicScanlineMachine, SavesState, AcceptsBIOS } from "../common/devices";
|
||||
import { KeyFlags } from "../common/emu"; // TODO
|
||||
import { hex, lzgmini, stringToByteArray, RGBA, printFlags } from "../common/util";
|
||||
|
||||
// TODO: read prodos/ca65 header?
|
||||
const VM_BASE = 0x803; // where to JMP after pr#6
|
||||
const LOAD_BASE = VM_BASE;
|
||||
const PGM_BASE = VM_BASE;
|
||||
const HDR_SIZE = PGM_BASE - LOAD_BASE;
|
||||
import { hex, lzgmini, stringToByteArray, RGBA, printFlags, arrayCompare } from "../common/util";
|
||||
|
||||
interface AppleIIStateBase {
|
||||
ram : Uint8Array;
|
||||
|
@ -43,7 +37,11 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS {
|
|||
canvasWidth = 280;
|
||||
numVisibleScanlines = 192;
|
||||
numTotalScanlines = 262;
|
||||
defaultROMSize = 0xbf00-0x803; // TODO
|
||||
defaultROMSize = 0x13000; // we'll never need one that big, but...
|
||||
|
||||
// these are set later
|
||||
LOAD_BASE = 0;
|
||||
HDR_SIZE = 0;
|
||||
|
||||
ram = new Uint8Array(0x13000); // 64K + 16K LC RAM - 4K hardware + 12K ROM
|
||||
bios : Uint8Array;
|
||||
|
@ -78,8 +76,8 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS {
|
|||
// SHOULD load program into RAM here, but have to do it
|
||||
// below instead.
|
||||
return 0;
|
||||
case 1: return VM_BASE&0xff;
|
||||
case 2: return (VM_BASE>>8)&0xff;
|
||||
case 1: return this.LOAD_BASE&0xff;
|
||||
case 2: return (this.LOAD_BASE>>8)&0xff;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +95,7 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS {
|
|||
// into RAM and returning the JMP here, instead of above
|
||||
// where it would otherwise belong.
|
||||
if (this.rom) {
|
||||
console.log(`Loading program into Apple ][ RAM at \$${PGM_BASE.toString(16)}`);
|
||||
this.ram.set(this.rom.slice(HDR_SIZE), PGM_BASE);
|
||||
this.loadRAMWithProgram();
|
||||
}
|
||||
return 0x4c; // JMP
|
||||
case 1: return 0x20;
|
||||
|
@ -168,26 +165,57 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS {
|
|||
console.log("will load BIOS to end of memory anyway...");
|
||||
}
|
||||
this.bios = Uint8Array.from(data);
|
||||
this.ram.set(this.bios, 0x10000 - this.bios.length);
|
||||
this.ram[0xbf00] = 0x4c; // fake DOS detect for C
|
||||
this.ram[0xbf6f] = 0x01; // fake DOS detect for C
|
||||
}
|
||||
loadROM(data) {
|
||||
if (data.length == 35*16*256) { // is it a disk image?
|
||||
// is it a 16-sector 35-track disk image?
|
||||
if (data.length == 16 * 35 * 256) {
|
||||
var diskii = new DiskII(this, data);
|
||||
this.slots[6] = diskii;
|
||||
this.reset();
|
||||
} else { // it's a binary, use a fake drive
|
||||
// set this.rom variable
|
||||
super.loadROM(data);
|
||||
// AppleSingle header? https://github.com/cc65/cc65/blob/master/libsrc/apple2/exehdr.s
|
||||
if (arrayCompare(this.rom.slice(0, 4), [0x00, 0x05, 0x16, 0x00])) {
|
||||
this.LOAD_BASE = this.rom[0x39] | (this.rom[0x38] << 8); // big endian
|
||||
this.HDR_SIZE = 58;
|
||||
} else {
|
||||
// 4-byte DOS header? (TODO: hacky detection)
|
||||
const origin = this.rom[0] | (this.rom[1] << 8);
|
||||
const size = this.rom[2] | (this.rom[3] << 8);
|
||||
let isPlausible = origin < 0xc000
|
||||
&& origin + size < 0x13000
|
||||
&& (origin == 0x803 || (origin & 0xff) == 0);
|
||||
if (size == data.length - 4 && isPlausible) {
|
||||
this.LOAD_BASE = origin;
|
||||
this.HDR_SIZE = 4;
|
||||
} else {
|
||||
// default = raw binary @ $803
|
||||
this.LOAD_BASE = 0x803;
|
||||
this.HDR_SIZE = 0;
|
||||
}
|
||||
}
|
||||
this.slots[6] = this.fakeDrive;
|
||||
}
|
||||
}
|
||||
loadRAMWithProgram() {
|
||||
console.log(`Loading program into Apple ][ RAM at \$${this.LOAD_BASE.toString(16)}`);
|
||||
// truncate if needed to fit into RAM
|
||||
const exedata = this.rom.slice(this.HDR_SIZE, this.HDR_SIZE + this.ram.length - this.LOAD_BASE);
|
||||
this.ram.set(exedata, this.LOAD_BASE);
|
||||
// fake DOS detect for CC65 (TODO?)
|
||||
if (this.HDR_SIZE == 58) {
|
||||
this.ram[0xbf00] = 0x4c;
|
||||
this.ram[0xbf6f] = 0x01;
|
||||
}
|
||||
}
|
||||
reset() {
|
||||
super.reset();
|
||||
this.auxRAMselected = false;
|
||||
this.auxRAMbank = 1;
|
||||
this.writeinhibit = true;
|
||||
this.ram.fill(0, 0x300, 0x400); // Clear soft-reset vector
|
||||
// (force hard reset)
|
||||
super.reset();
|
||||
this.skipboot();
|
||||
}
|
||||
skipboot() {
|
||||
|
@ -281,12 +309,12 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS {
|
|||
if (address < 0xc000) {
|
||||
this.ram[address] = val;
|
||||
this.grdirty[address>>7] = 1;
|
||||
this.probe.logIOWrite(address, val);
|
||||
} else if (address < 0xc080) {
|
||||
this.read(address); // strobe address, discard result
|
||||
} else if (address < 0xc100) {
|
||||
var slot = (address >> 4) & 0x0f;
|
||||
this.slots[slot-8] && this.slots[slot-8].write(address & 0xf, val);
|
||||
this.probe.logIOWrite(address, val);
|
||||
} else if (address >= 0xd000 && !this.writeinhibit) {
|
||||
if (address >= 0xe000)
|
||||
this.ram[address] = val;
|
||||
|
@ -479,7 +507,7 @@ var Apple2Display = function(pixels : Uint32Array, apple : AppleGRParams) {
|
|||
var oldgrmode = -1;
|
||||
var textbuf = new Array(40*24);
|
||||
|
||||
const flashInterval = 500;
|
||||
const flashInterval = 250;
|
||||
|
||||
// https://mrob.com/pub/xapple2/colors.html
|
||||
const loresColor = [
|
||||
|
|
|
@ -16,7 +16,7 @@ const APPLE2_PRESETS : Preset[] = [
|
|||
{id:'cosmic.c', name:'Cosmic Impalas'},
|
||||
{id:'farmhouse.c', name:"Farmhouse Adventure"},
|
||||
{id:'yum.c', name:"Yum Dice Game"},
|
||||
{id:'lzgtest.c', name:"LZG Decompressor"},
|
||||
{id:'lz4test.c', name:"LZ4 Decompressor"},
|
||||
{id:'hgrtest.a', name:"HGR Test", category:"Assembly Language"},
|
||||
{id:'conway.a', name:"Conway's Game of Life"},
|
||||
{id:'lz4fh.a', name:"LZ4FH Decompressor"},
|
||||
|
@ -77,7 +77,7 @@ class NewApple2Platform extends Base6502MachinePlatform<AppleII> implements Plat
|
|||
{name:'Hires Page 2',start:0x4000,size:0x2000,type:'ram'},
|
||||
{name:'RAM',start:0x6000,size:0x6000,type:'ram'},
|
||||
{name:'I/O',start:0xc000,size:0x1000,type:'io'},
|
||||
{name:'ROM',start:0xd000,size:0x3000-6,type:'rom'},
|
||||
{name:'ROM',start:0xd000,size:0x3000,type:'rom'},
|
||||
] } };
|
||||
getROMExtension(rom:Uint8Array) {
|
||||
if (rom && rom.length == 35*16*256) return ".dsk"; // DSK image
|
||||
|
|
|
@ -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<Atari7800> implements Platform {
|
||||
|
@ -24,7 +29,8 @@ class Atari7800Platform extends Base6502MachinePlatform<Atari7800> implements Pl
|
|||
{name:'RAM (6166 Block 1)',start:0x140,size:0xc0,type:'ram'},
|
||||
{name:'PIA',start:0x280,size:0x18,type:'io'},
|
||||
{name:'RAM',start:0x1800,size:0x1000,type:'ram'}, // TODO: shadow ram
|
||||
{name:'Cartridge ROM',start:0x4000,size:0xc000,type:'rom'},
|
||||
{name:'Cartridge ROM',start:0x4000,size:0xc000-6,type:'rom'},
|
||||
{name:'CPU Vectors',start:0xfffa,size:0x6,type:'rom'},
|
||||
] } };
|
||||
getROMExtension() { return ".a78"; }
|
||||
getDebugTree() {
|
||||
|
@ -32,6 +38,11 @@ class Atari7800Platform extends Base6502MachinePlatform<Atari7800> 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);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
|
@ -10,7 +10,8 @@ const C64_PRESETS : Preset[] = [
|
|||
{id:'joymove.c', name:'Sprite Movement'},
|
||||
{id:'sprite_collision.c', name:'Sprite Collision'},
|
||||
{id:'scroll1.c', name:'Scrolling (Single Buffer)'},
|
||||
{id:'test_display_list.c', name:'Display List / Raster IRQ'},
|
||||
{id:'test_setirq.c', name:'Raster Interrupts'},
|
||||
{id:'test_display_list.c', name:'Raster IRQ Library'},
|
||||
{id:'scrolling_text.c', name:'Big Scrolling Text'},
|
||||
{id:'side_scroller.c', name:'Side-Scrolling Game'},
|
||||
{id:'scroll2.c', name:'Scrolling (Double Buffer)'},
|
||||
|
|
|
@ -363,7 +363,8 @@ class VCSPlatform extends BasePlatform {
|
|||
{name:'TIA Registers',start:0x00,size:0x80,type:'io'},
|
||||
{name:'PIA RAM',start:0x80,size:0x80,type:'ram'},
|
||||
{name:'PIA Ports and Timer',start:0x280,size:0x18,type:'io'},
|
||||
{name:'Cartridge ROM',start:0xf000,size:0x1000,type:'rom'},
|
||||
{name:'Cartridge ROM',start:0xf000,size:0x1000-6,type:'rom'},
|
||||
{name:'CPU Vectors',start:0xfffa,size:0x6,type:'rom'},
|
||||
]}};
|
||||
|
||||
// probing
|
||||
|
|
79
src/test/testwasishim.ts
Normal file
79
src/test/testwasishim.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
import assert from "assert";
|
||||
import { WASIRunner } from "../common/wasi/wasishim";
|
||||
import * as fs from "fs";
|
||||
|
||||
async function loadWASM(filename: string) {
|
||||
const wasmdata = fs.readFileSync(`./src/worker/wasm/${filename}.wasm`);
|
||||
let shim = new WASIRunner();
|
||||
await shim.loadAsync(wasmdata);
|
||||
return shim;
|
||||
}
|
||||
|
||||
async function loadDASM() {
|
||||
return loadWASM('dasm-wasisdk');
|
||||
}
|
||||
async function loadCC7800() {
|
||||
return loadWASM('cc7800');
|
||||
}
|
||||
|
||||
describe('test WASI DASM', function () {
|
||||
it('dasm help', async function () {
|
||||
let shim = await loadDASM();
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 1);
|
||||
});
|
||||
it('dasm file not found', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "file_not_found.asm"]);
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 2);
|
||||
});
|
||||
it('dasm file not found 2', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "/file.asm", "-d"]);
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 2);
|
||||
});
|
||||
it('dasm bad args 1', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "file_not_found.asm", "extra_arg.asm"]);
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 1);
|
||||
});
|
||||
it('dasm bad args 2', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "file_not_found.asm", "-E9"]);
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 1);
|
||||
});
|
||||
it('dasm empty file', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "empty.asm"]);
|
||||
shim.addPreopenDirectory("/root");
|
||||
shim.fs.putFile("/root/empty.asm", "");
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 0);
|
||||
});
|
||||
it('dasm small file', async function () {
|
||||
let shim = await loadDASM();
|
||||
shim.setArgs(["dasm", "empty.asm"]);
|
||||
shim.addPreopenDirectory("/root");
|
||||
shim.fs.putFile("/root/empty.asm", " processor 6502\n org $100\n nop");
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 0);
|
||||
let aout = shim.fs.getFile("/root/a.out");
|
||||
assert.deepStrictEqual(Array.from(aout.getBytes()), [0x00, 0x01, 0xea]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test WASI cc7800', function () {
|
||||
it('cc7800 help', async function () {
|
||||
let shim = await loadCC7800();
|
||||
shim.setArgs(["cc7800", '-h']);
|
||||
let errno = shim.run();
|
||||
assert.strictEqual(errno, 0);
|
||||
const stdout = shim.fds[1].getBytesAsString();
|
||||
console.log(stdout);
|
||||
assert.ok(stdout.indexOf('Usage: cc7800') >= 0);
|
||||
});
|
||||
});
|
BIN
src/worker/fs/cc7800-fs.zip
Executable file
BIN
src/worker/fs/cc7800-fs.zip
Executable file
Binary file not shown.
|
@ -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'),
|
||||
|
|
|
@ -213,10 +213,7 @@ export function linkLD65(step: BuildStep): BuildStepResult {
|
|||
}
|
||||
}
|
||||
}
|
||||
// TODO: move to Platform class
|
||||
var segments = [];
|
||||
segments.push({ name: 'CPU Stack', start: 0x100, size: 0x100, type: 'ram' });
|
||||
segments.push({ name: 'CPU Vectors', start: 0xfffa, size: 0x6, type: 'rom' });
|
||||
// TODO: CHR, banks, etc
|
||||
let re_seglist = /(\w+)\s+([0-9A-F]+)\s+([0-9A-F]+)\s+([0-9A-F]+)\s+([0-9A-F]+)/;
|
||||
let parseseglist = false;
|
||||
|
|
89
src/worker/tools/cc7800.ts
Normal file
89
src/worker/tools/cc7800.ts
Normal file
|
@ -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<BuildStepResult> {
|
||||
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]
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
BIN
src/worker/wasm/cc7800.wasm
Executable file
BIN
src/worker/wasm/cc7800.wasm
Executable file
Binary file not shown.
BIN
src/worker/wasm/dasm-wasisdk.wasm
Executable file
BIN
src/worker/wasm/dasm-wasisdk.wasm
Executable file
Binary file not shown.
|
@ -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) {
|
||||
|
@ -249,7 +251,7 @@ var PLATFORM_PARAMS = {
|
|||
arch: '6502',
|
||||
define: ['__APPLE2__'],
|
||||
cfgfile: 'apple2.cfg',
|
||||
libargs: [ '--lib-path', '/share/target/apple2/drv', '-D', '__EXEHDR__=0', 'apple2.lib'],
|
||||
libargs: [ '--lib-path', '/share/target/apple2/drv', 'apple2.lib'],
|
||||
__CODE_RUN__: 16384,
|
||||
code_start: 0x803,
|
||||
acmeargs: ['-f', 'apple'],
|
||||
|
@ -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 = {
|
||||
|
|
|
@ -119,6 +119,7 @@ function checkForBigNonTypedArrays(obj, path='') {
|
|||
}
|
||||
|
||||
async function testPlatform(platid, romname, maxframes, callback) {
|
||||
if (!emu.PLATFORMS[platid]) throw new Error("no platform " + platid);
|
||||
var platform = new emu.PLATFORMS[platid](emudiv);
|
||||
await platform.start();
|
||||
var emudiv = document.getElementById('emulator');
|
||||
|
|
|
@ -11,6 +11,12 @@ global.onmessage({data:{preload:'cc65', platform:'apple2'}});
|
|||
global.onmessage({data:{preload:'ca65', platform:'apple2'}});
|
||||
global.onmessage({data:{preload:'cc65', platform:'c64'}});
|
||||
global.onmessage({data:{preload:'ca65', platform:'c64'}});
|
||||
global.onmessage({data:{preload:'cc65', platform:'atari8'}});
|
||||
global.onmessage({data:{preload:'ca65', platform:'atari8'}});
|
||||
global.onmessage({data:{preload:'cc65', platform:'atari2600'}});
|
||||
global.onmessage({data:{preload:'ca65', platform:'atari2600'}});
|
||||
global.onmessage({data:{preload:'cc65', platform:'pce'}});
|
||||
global.onmessage({data:{preload:'ca65', platform:'pce'}});
|
||||
global.onmessage({data:{preload:'sdcc'}});
|
||||
global.onmessage({data:{preload:'inform6'}});
|
||||
|
||||
|
@ -231,7 +237,7 @@ describe('Worker', function() {
|
|||
});
|
||||
it('should compile apple2 skeleton with CC65', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/apple2/skeleton.cc65'));
|
||||
compile('cc65', csource, 'apple2', done, 3023, 4, 0);
|
||||
compile('cc65', csource, 'apple2', done, 3023+58, 4, 0);
|
||||
});
|
||||
// TODO: test if compile, errors, then compile same file
|
||||
// TODO: params persist because of fixParamsWithDefines()
|
||||
|
@ -262,7 +268,7 @@ describe('Worker', function() {
|
|||
doBuild(msgs, done2, 205, 0, 0);
|
||||
});
|
||||
it('should compile CC65 flags', function(done) {
|
||||
compile('cc65', '#define CC65_FLAGS -Or,-g,-j\nint main() {\nint x=1;\nreturn x+2;\n}', 'apple2', done, 416, 3);
|
||||
compile('cc65', '#define CC65_FLAGS -Or,-g,-j\nint main() {\nint x=1;\nreturn x+2;\n}', 'apple2', done, 416+58, 3);
|
||||
});
|
||||
/*
|
||||
it('should compile ACME', function(done) {
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user