diff --git a/doc/notes.txt b/doc/notes.txt index d196f1b1..be4e20d3 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -46,7 +46,6 @@ TODO: - debug bankswitching for funky formats - spaces in filename don't parse code listing (DASM, maybe more) - 'undefined' for bitmap replacer -- astrocade: run to cursor in hello world messes up emulation - requestInterrupt needs to be disabled after breakpoint? - C/asm formatter - fix WebAudio (https://news.ycombinator.com/item?id=18066474) @@ -66,6 +65,7 @@ TODO: - sdcc: - can't link asm files before c files (e.g. acheader.s must be last) - figure out area names ordering + - debug inline asm - live coding URL - resize memory browser when vertical div resize - preroll the emulator so optimizer does its thing before loading rom @@ -146,7 +146,7 @@ TODO: - don't have to include bootstrap-tourist each time? - don't have to include firebase always? - squelch error msgs? - - test offline? + - test offline? (if window.firebase) - Github - gh-pages branch with embedded - handle overwrite logic diff --git a/index.html b/index.html index 00248914..85c844f2 100644 --- a/index.html +++ b/index.html @@ -275,6 +275,18 @@ if (window.location.host.endsWith('8bitworkshop.com')) { A W S D Move ←↑↓→ Fire + diff --git a/presets/astrocade-bios/bios.c b/presets/astrocade-bios/bios.c index 3ab56744..56dd2c7b 100644 --- a/presets/astrocade-bios/bios.c +++ b/presets/astrocade-bios/bios.c @@ -71,12 +71,16 @@ word* USERTB; // user routine table (-128 bytes) // from bmusic.c extern void music_update(void); -// INTERRUPT HANDLERS -// must be in 0x200 page -void hw_interrupt() __naked { - __asm__("ei"); - __asm__("exx"); +// INTERRUPT HANDLER +//#define USE_ALT_REGS +void hw_interrupt() +#ifdef USE_ALT_REGS +__naked { __asm__("ex af,af'"); + __asm__("exx"); +#else +__interrupt { +#endif CT[0]++; CT[1]++; CT[2]++; @@ -97,9 +101,12 @@ void hw_interrupt() __naked { music_update(); } } +#ifdef USE_ALT_REGS __asm__("exx"); __asm__("ex af,af'"); + __asm__("ei"); __asm__("reti"); +#endif } void add_counters(byte mask, byte delta) { @@ -134,11 +141,18 @@ void TIMEY() { void TIMEX() { } + +void DECCTS(ContextBlock *ctx) { + add_counters(_C, -1); +} + +// INTERPRETER void INTPC(ContextBlock *ctx) { while (ctx->params[0] != 2) { // 2 = exit SYSCALL(ctx); } + ctx->params++; // skip EXIT opcode } // never called, hopefully @@ -164,6 +178,10 @@ void MRET(ContextBlock *ctx) { ctx; // TODO } +void NOOP(ContextBlock *ctx) { + ctx; +} + // jump within MCALL void MJUMP(ContextBlock *ctx) { ctx->params = (byte*) _HL; // TODO? @@ -225,13 +243,7 @@ void SETOUT(ContextBlock *ctx) { // set entire palette at once (8 bytes to port 0xb) // bytes in array should be in reverse -void set_palette(byte palette[8]) __z88dk_fastcall { - palette; -__asm - ld bc,#0x80b ; B -> 8, C -> 0xb - otir ; write C bytes from HL to port[B] -__endasm; -} +void set_palette(byte palette[8]) __z88dk_fastcall; // sets color palettes from (HL) void COLSET(ContextBlock *ctx) { @@ -260,25 +272,10 @@ void PAWS(ContextBlock *ctx) { // MATH void MOVE(ContextBlock *ctx) { - byte* dest = (byte*) _DE; - const byte* src = (const byte*) _HL; - word nb = _BC; - memcpy(dest, src, nb); + memcpy((byte*)_DE, (const byte*)_HL, _BC); } -word bcdadd8(byte a, byte b, byte c) { - a;b;c; -__asm - ld a,6(ix) ; carry - rrc a ; set carry bit - ld h,#0 ; carry goes here - ld a,4(ix) ; a -> A - adc a,5(ix) ; a + b -> A - daa ; BCD conversion - ld l,a ; result -> L - rl h ; carry -> H -__endasm; -} +word bcdadd8(byte a, byte b, byte c); void BCDADD(ContextBlock *ctx) { byte* dest = (byte*) _DE; @@ -308,12 +305,7 @@ void RANGED(ContextBlock *ctx) { // input -const byte KCTASC_TABLE[25] = { - 0x00, - 0x43, 0x5e, 0x5c, 0x25, 0x52, 0x53, 0x3b, 0x2f, - 0x37, 0x38, 0x39, 0x2a, 0x34, 0x35, 0x36, 0x2d, - 0x31, 0x32, 0x33, 0x2b, 0x26, 0x30, 0x2e, 0x3d -}; +extern const byte KCTASC_TABLE[25]; void KCTASC(ContextBlock *ctx) { _A = KCTASC_TABLE[_B]; @@ -360,7 +352,7 @@ const SysCallEntry SYSCALL_TABLE[64] = { { &MJUMP, REG_HL }, { &SUCK, REG_B }, { &ACTINT, 0 }, - { 0, 0 }, + { &DECCTS, REG_C }, { &BMUSIC, REG_HL|REG_IX|REG_A }, /* 20 */ { &EMUSIC, }, @@ -369,64 +361,64 @@ const SysCallEntry SYSCALL_TABLE[64] = { { &FILL, REG_A|REG_BC|REG_DE }, { &RECTAN, REG_A|REG_B|REG_C|REG_D|REG_E }, /* 30 */ - { /*&VWRITR*/0, 0 }, + { &NOOP, REG_HL|REG_IX }, // VWRITR { &WRITR, REG_E|REG_D|REG_A|REG_HL }, { &WRITP, REG_E|REG_D|REG_A|REG_HL }, { &WRIT, REG_E|REG_D|REG_C|REG_B|REG_A|REG_HL }, - { /*&WRITA*/0, 0 }, + { &NOOP, REG_E|REG_D|REG_C|REG_B|REG_A|REG_HL }, // WRITA /* 40 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, REG_E|REG_D|REG_IX }, // VBLANK + { &NOOP, REG_E|REG_D|REG_B|REG_HL }, // BLANK + { &NOOP, REG_B|REG_C|REG_DE|REG_HL }, // SAVE + { &NOOP, REG_DE|REG_HL }, // RESTORE + { &NOOP, REG_B|REG_C|REG_DE|REG_HL }, // SCROLL /* 50 */ { &CHRDIS, REG_E|REG_D|REG_C|REG_A }, { &STRDIS, REG_E|REG_D|REG_C|REG_HL }, { &DISNUM, REG_E|REG_D|REG_C|REG_B|REG_HL }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, REG_DE|REG_A }, // RELABS + { &NOOP, REG_E|REG_D|REG_A }, // RELAB1 /* 60 */ - { 0, 0 }, - { 0, 0 }, + { &NOOP, REG_IX|REG_HL|REG_C }, // VECTC + { &NOOP, REG_IX|REG_HL }, // VECT { &KCTASC, 0 }, { &SENTRY, REG_DE }, { &DOIT, REG_HL }, /* 70 */ { &DOITB, REG_HL }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, 0 }, // PIZBRK + { &NOOP, REG_DE|REG_HL }, // MENU + { &NOOP, REG_BC|REG_HL }, // GETPAR + { &NOOP, REG_B|REG_C|REG_D|REG_E|REG_HL }, // GETNUM /* 80 */ { &PAWS, REG_B }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, REG_E|REG_D|REG_C }, // DISTIM + { &NOOP, REG_HL }, // INCSCR + { &NOOP, REG_C|REG_HL }, // INDEXN + { &NOOP, REG_HL }, // STOREN /* 90 */ - { 0, 0 }, - { 0, 0 }, + { &NOOP, REG_A|REG_HL }, // INDEXW + { &NOOP, REG_A|REG_HL }, // INDEXB { &MOVE, REG_DE|REG_BC|REG_HL }, - { 0, 0 }, + { &NOOP, 0 }, // SHIFTU { &BCDADD, REG_DE|REG_B|REG_HL }, /* 100 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, 0 }, // BCDSUB + { &NOOP, 0 }, // BCDMUL + { &NOOP, 0 }, // BCDDIV + { &NOOP, 0 }, // BCDCHS + { &NOOP, 0 }, // BCDNEG /* 110 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, 0 }, // DADD + { &NOOP, 0 }, // DSMG + { &NOOP, 0 }, // DABS + { &NOOP, 0 }, // NEGT { &RANGED, REG_A }, /* 120 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, + { &NOOP, 0 }, // QUIT + { &NOOP, REG_A|REG_HL }, // SETB + { &NOOP, REG_DE|REG_HL }, // SETW + { &NOOP, REG_C|REG_DE|REG_HL }, // MSKTD }; void SYSCALL(ContextBlock *ctx) { @@ -447,22 +439,17 @@ void SYSCALL(ContextBlock *ctx) { suckParams(ctx, argmask); } // call the routine - if (routine) { - routine(ctx); - } + routine(ctx); } void bios_init() { + ContextBlock ctx; memset((void*)0x4fce, 0, 0x5000-0x4fce); ACTINT(0); hw_verbl = 96*2; hw_horcb = 41; hw_inmod = 0x8; - // clear shifter - hw_magic = 0; - *((byte*)0x4fce) = 0; - hw_magic = 0; // call SENTRY once to set current values // (context block doesn't matter) - SENTRY((ContextBlock*)0x4fce); + SENTRY(&ctx); } diff --git a/presets/astrocade-bios/biosasm.s b/presets/astrocade-bios/biosasm.s index b35358bc..e7ff624e 100644 --- a/presets/astrocade-bios/biosasm.s +++ b/presets/astrocade-bios/biosasm.s @@ -1,10 +1,8 @@ -;#link "bioslib.c" - TEST = 1 - .module biosasm - .globl _STIMER,_CTIMER,_BIGFONT,_SMLFONT +.module biosasm +.globl _STIMER,_CTIMER,_BIGFONT,_SMLFONT BIOSStart: di ; disable interrupts @@ -33,8 +31,9 @@ FoundSentinel: ld H,(HL) ld L,A jp (HL) ; jump to cart start vector - .ds 0x38 - (. - BIOSStart) ; eat up space until 0x38 - .globl SYSCALL38 + +.ds 0x38 - (. - BIOSStart) ; eat up space until 0x38 +.globl SYSCALL38 SYSCALL38: push hl push af @@ -56,53 +55,44 @@ SYSCALL38: ret ; out to port - .globl _portOut +.globl _portOut _portOut: ld c,h out (c),l ret -; TODO? -ReloadRegs: - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc - pop iy - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc +.globl _bcdadd8 +_bcdadd8: + push ix + ld ix,#0 + add ix,sp + ld a,6(ix) ; carry + rrc a ; set carry bit + ld h,#0 ; carry goes here + ld a,4(ix) ; a -> A + adc a,5(ix) ; a + b -> A + daa ; BCD conversion + ld l,a ; result -> L + rl h ; carry -> H pop ix - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc - pop de - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc - pop af - ld c,(hl) - inc hl - ld b,(hl) - inc hl - push bc - pop hl - pop bc - ret - .ds 0x200 - (. - BIOSStart) ; eat up space until 0x200 + ret +;void set_palette(byte palette[8]) __z88dk_fastcall; +.globl _set_palette +_set_palette: + ld bc,#0x80b ; B -> 8, C -> 0xb + otir ; write C bytes from HL to port[B] + ret + +.globl _KCTASC_TABLE +_KCTASC_TABLE: +.db 0x00 +.db 0x43, 0x5e, 0x5c, 0x25, 0x52, 0x53, 0x3b, 0x2f +.db 0x37, 0x38, 0x39, 0x2a, 0x34, 0x35, 0x36, 0x2d +.db 0x31, 0x32, 0x33, 0x2b, 0x26, 0x30, 0x2e, 0x3d + + + .ds 0x200 - (. - BIOSStart) ; eat up space until 0x200 DOPEVector: JP _STIMER JP _CTIMER @@ -110,5 +100,8 @@ DOPEVector: .dw _BIGFONT .db 0xa0, 4, 6, 1, 5 ; Font descriptor (small font) .dw _SMLFONT - + .db 0x3f ; all keys mask + .db 0x3f + .db 0x3f + .db 0x3f diff --git a/presets/astrocade-bios/gfx.c b/presets/astrocade-bios/gfx.c index 70962ed8..d74eb330 100644 --- a/presets/astrocade-bios/gfx.c +++ b/presets/astrocade-bios/gfx.c @@ -147,7 +147,7 @@ void CHRDIS(ContextBlock *ctx) { } // BCD routine -const char BCDTAB[17] = "0123456789*+,-./"; +const char BCDTAB[18] = "0123456789*+,-./ "; // DISNUM - (E.D) x/y (C) options (B) ext (HL) BCD-addr void DISNUM(ContextBlock *ctx) { @@ -170,6 +170,11 @@ void DISNUM(ContextBlock *ctx) { val &= 15; pbcd--; } + if (val == 0 && noleadingzero) { + val = 16; + } else { + noleadingzero = 0; + } x += draw_char(font, BCDTAB[val]+add, x, y, opt); } } diff --git a/presets/astrocade-bios/input.c b/presets/astrocade-bios/input.c index b7ca9edb..3e62aa10 100644 --- a/presets/astrocade-bios/input.c +++ b/presets/astrocade-bios/input.c @@ -55,6 +55,7 @@ void SENTRY(ContextBlock *ctx) { } } // key up? + // TODO: race condition with KEYSEX and interrupt if (key && key != KEYSEX) { B = KEYSEX = key; A = SKYD; diff --git a/presets/astrocade-bios/test1.s b/presets/astrocade-bios/test1.s index a19d32f4..ed5ce57d 100644 --- a/presets/astrocade-bios/test1.s +++ b/presets/astrocade-bios/test1.s @@ -19,7 +19,7 @@ _main: pop ix SYSTEM INTPC DO SETOUT - .db 89*2, 23, 0x00 + .db 102*2, 23, 0x00 DONT EMUSIC DONT ACTINT DO COLSET @@ -89,11 +89,12 @@ _main: .dw 3 .dw _BCDNUM DO BMUSIC - .dw 0x4000 + .dw 0x4e80 .db 0b11111100 .dw ANTHEM ; exit interpreter EXIT + nop .loop: SYSSUK DISNUM .db 80 @@ -149,7 +150,7 @@ keymask: BCDNUM = 0x4ea0 ; RAM _BCDNUM: - .db 0x97,0x34,0x12 + .db 0x97,0x99,0x09 BCDINC: .db 0x01,0x00,0x00 ; Critter Pattern diff --git a/presets/astrocade/acbios.h b/presets/astrocade/acbios.h index 59b833a9..0dbb79eb 100644 --- a/presets/astrocade/acbios.h +++ b/presets/astrocade/acbios.h @@ -15,8 +15,41 @@ typedef struct { const byte* chartab; } FontDescriptor; -const FontDescriptor __at(0x206) FNTSYS; -const FontDescriptor __at(0x20d) FNTSML; +const FontDescriptor __at(0x206) FNTSYS; // system font +const FontDescriptor __at(0x20d) FNTSML; // small font +const byte __at(0x214) ALKEYS[4]; // "all keys" keyboard mask + +// SENTRY + +typedef enum { + SNUL, + SCT0,SCT1,SCT2,SCT3,SCT4,SCT5,SCT6,SCT7, + SF0,SF1,SF2,SF3,SF4,SF5,SF6,SF7, + SSEC, + SKYU,SKYD, + ST0,SJ0,ST1,SJ1,ST2,SJ2,ST3,SJ3, + SP0,SP1,SP2,SP3 +} SENTRYCode; + +typedef struct { + byte code; + word address; +} DOITEntry; + +#define DOIT_END 0xff + +// PATTERNS + +typedef struct { + sbyte xofs, yofs; + byte xsize, ysize; + byte pattern[0]; +} RelativeBlock; + +typedef struct { + byte xsize, ysize; + byte pattern[0]; +} PatternBlock; // FUNCTIONS @@ -47,8 +80,11 @@ void display_bcd_number(byte x, byte y, byte options, const byte* number, byte e void bcdn_add(byte* dest, byte size, const byte* n); void bcdn_sub(byte* dest, byte size, const byte* n); byte ranged_random(byte n) __z88dk_fastcall; +byte keycode_to_ascii(byte n) __z88dk_fastcall; -word sense_transition(const byte* keypad_mask) __z88dk_fastcall; +word sense_transition(const byte keypad_mask[4]) __z88dk_fastcall; +void respond_to_input(const DOITEntry* doit_table, byte a); +void respond_to_input_b(const DOITEntry* doit_table, byte b); void begin_music(const byte* stack, byte voices, const byte* musicdata); void end_music(void); @@ -69,6 +105,13 @@ void end_music(void); __asm__(".dw "#count);\ __asm__(".db "#val);\ +#define SYS_MOVE(dest,src,count)\ + __asm__("rst 0x38");\ + __asm__(".db 0x5f");\ + __asm__(".dw "#dest);\ + __asm__(".dw "#count);\ + __asm__(".dw "#src);\ + #define RESET_TIMEOUT() \ __asm__("ld a,#0xff");\ __asm__("ld (0x4FEC),a"); diff --git a/presets/astrocade/acbios.s b/presets/astrocade/acbios.s index 57b0ef24..72ebd7fb 100644 --- a/presets/astrocade/acbios.s +++ b/presets/astrocade/acbios.s @@ -3,7 +3,7 @@ ;;; C functions - .area _LIB + .area _CODE_ACBIOS ; activate interrupts .globl _activate_interrupts @@ -99,6 +99,13 @@ _ranged_random: SYSTEM RANGED ret +; KCTASC n + .globl _keycode_to_ascii +_keycode_to_ascii: + ld a,l + SYSTEM KCTASC + ret + ; BLANK w h data video-addr .globl _blank_area _blank_area: @@ -116,6 +123,20 @@ _sense_transition: ld h,b ret +; DOIT table-addr + .globl _respond_to_input +_respond_to_input: + call load5_edca_hl + SYSTEM DOIT + ret + +; DOITB table-addr + .globl _respond_to_input_b +_respond_to_input_b: + call load5_edca_hl + SYSTEM DOIT + ret + ; BMUSIC stack-addr voices score-addr .globl _begin_music _begin_music: diff --git a/presets/astrocade/acextra.h b/presets/astrocade/acextra.h index 61524515..c9e61ba9 100644 --- a/presets/astrocade/acextra.h +++ b/presets/astrocade/acextra.h @@ -4,6 +4,9 @@ #include "aclib.h" +// special case for draw_sprite() +#define M_ERASE 0x04 + // font constants #define LOCHAR 32 #define HICHAR 127 diff --git a/presets/astrocade/acfast.s b/presets/astrocade/acfast.s new file mode 100644 index 00000000..900e49f8 --- /dev/null +++ b/presets/astrocade/acfast.s @@ -0,0 +1,34 @@ + + +.area _CODE_ACFAST + +;void fast_sprite_8(const byte* src, byte* dst) { +.globl _fast_sprite_8 +_fast_sprite_8: + push ix + ld ix,#0 + add ix,sp + ld l,4(ix) ; src (HL) + ld h,5(ix) + ld e,6(ix) ; dst (DE) + ld d,7(ix) + inc hl ; skip width + ld c,(hl) ; load height -> C + sla c ; C *= 2 + ld b,#0 ; B always 0 (BC < 256) + inc hl ; move to pattern bytes +001$: + ldi + ldi ; copy 2 bytes src to dst + ld a,b ; 0 -> A, doesnt affect flags + ld (de),a ; copy 3rd 0 (for shifts) + jp po,002$ ; exit if BC == 0 + ld a,e ; E -> A + add a,#38 ; next scanline (dest += 38) + ld e,a ; A -> E + jr nc,001$ ; loop unless lo byte overflow + inc d ; inc hi byte of dest. addr + jr 001$ ; loop to next line +002$: + pop ix + ret diff --git a/presets/astrocade/aclib.h b/presets/astrocade/aclib.h index e1c5ff21..7e87e11b 100644 --- a/presets/astrocade/aclib.h +++ b/presets/astrocade/aclib.h @@ -52,14 +52,16 @@ __sfr __at(0x18) hw_sndbx; #define M_SHIFT1 0x01 #define M_SHIFT2 0x02 #define M_SHIFT3 0x03 +#define M_ROTATE 0x04 #define M_XPAND 0x08 #define M_MOVE 0x00 #define M_OR 0x10 #define M_XOR 0x20 #define M_FLOP 0x40 + #define M_SHIFT(x) ((x)&3) + #define XPAND_COLORS(off,on) (((off)&3) | (((on)&3)<<2)) -#define M_ERASE 0x04 // special case for draw_sprite() #define VTOTAL 102 // number of total scanlines #define VHEIGHT 89 // number of scanlines in use diff --git a/presets/astrocade/fastsprites.c b/presets/astrocade/fastsprites.c new file mode 100644 index 00000000..b5a2f297 --- /dev/null +++ b/presets/astrocade/fastsprites.c @@ -0,0 +1,87 @@ + +//#resource "astrocade.inc" +#include "aclib.h" +//#link "aclib.c" +#include "acbios.h" +//#link "acbios.s" +//#link "acfast.s" +//#link "hdr_autostart.s" + +#include +#include + +#pragma opt_code_speed + +/*{pal:"astrocade",layout:"astrocade"}*/ +const byte palette[8] = { + 0x77, 0xBC, 0x35, 0x01, + 0x07, 0xF2, 0x64, 0x01, +}; + +const byte SPRITE[] = { + 2,8, + /*{w:8,h:8,bpp:2,brev:1}*/ + 0x01,0x40, 0x06,0x90, 0x15,0x54, 0x47,0x51, + 0x45,0xD1, 0x05,0x50, 0x04,0x10, 0x3C,0x3C, +}; + +extern void fast_sprite_8(const byte* pattern, byte* dst); + +#define MAX_SPRITES 8 + +typedef struct { + byte x; // x coordinate + byte y; // y coordinate + byte lastmagic; // last magic byte used + byte* lastdest; // last destination address + const byte* pattern; // pattern definition + byte _unused; +} Actor; + +Actor actors[MAX_SPRITES]; + +void erase_actor(Actor* actor) { + hw_magic = actor->lastmagic; + fast_sprite_8(actor->pattern, actor->lastdest); +} + +void draw_actor(Actor* actor) { + byte op = M_XOR; + byte x = actor->x; + byte y = actor->y; + actor->lastdest = &vmagic[y][x>>2];// destination address + actor->lastmagic = M_SHIFT(x) | op; // set magic register + erase_actor(actor); +} + +void main(void) { + byte i; + // setup palette + set_palette(palette); + // set screen height + // set horizontal color split (position / 4) + // set interrupt status + SYS_SETOUT(89*2, 0, 0); + // clear screen + SYS_FILL(0x4000, 89*40, 0); + // infinite loop + activate_interrupts(); + // fill array + for (i=0; ix++; + } + hw_col0r = 0x1; + } +} diff --git a/presets/astrocade/hello.c b/presets/astrocade/hello.c index 6a009e73..fbcd607e 100644 --- a/presets/astrocade/hello.c +++ b/presets/astrocade/hello.c @@ -27,28 +27,12 @@ const byte BALL[] = { 0b01111000, }; -const byte BALL2[] = { - 0, 0, // x and y offset - 1, 6, // width (bytes) and height (lines) - /*{w:16,h:6,brev:1}*/ - 0b1111000, - 0b11011100, - 0b10111000, - 0b110100, - 0b11100000, - 0b1111000, - 0b1000000, - 0b11010100, - 0b10111100, - 0b10110100, - 0b11111000, - 0b1111000, -}; - // BCD number byte bcdnum[3] = {0x56,0x34,0x12}; const byte bcdinc[3] = {0x01,0x00,0x00}; -const byte keypadMask[4] = { 0x3f,0x3f,0x3f,0x3f }; + +void _clear() { +} void main(void) { // setup palette @@ -58,7 +42,7 @@ void main(void) { // set interrupt status SYS_SETOUT(89*2, 23, 0); // clear screen - SYS_FILL(0x4000, 89*2, 0); + SYS_FILL(0x4000, 89*40, 0); // display standard characters display_string(2, 2, OPT_ON(1), "HELLO, WORLD!\xb1\xb2\xb3\xb4\xb5"); // 2x2 must have X coordinate multiple of 2 @@ -87,8 +71,20 @@ void main(void) { // make sure screen doesn't black out RESET_TIMEOUT(); while (1) { - display_bcd_number(80, 80, OPT_ON(2), bcdnum, 6|DISBCD_SML|DISBCD_NOZERO); - bcdn_add(bcdnum, 3, bcdinc); - while (sense_transition(keypadMask) == 0); + // wait for SENTRY result + word code; + do { + code = sense_transition(ALKEYS); + } while (code == 0); + // respond to SENTRY + switch (code & 0xff) { + case SSEC: + display_bcd_number(80, 80, OPT_ON(2), bcdnum, 6|DISBCD_SML|DISBCD_NOZERO); + bcdn_add(bcdnum, 3, bcdinc); + break; + case SP0: + hw_horcb = (code>>8)>>2; + break; + } } } diff --git a/presets/nes/skeleton.cc65 b/presets/nes/skeleton.cc65 index 929c1fe5..532f09ff 100644 --- a/presets/nes/skeleton.cc65 +++ b/presets/nes/skeleton.cc65 @@ -2,12 +2,26 @@ #include #include +#include +#include + // include NESLIB header #include "neslib.h" +// include CC65 NES Header (PPU) +#include + // link the pattern table into CHR ROM //#link "chr_generic.s" +// BCD arithmetic support +#include "bcd.h" +//#link "bcd.c" + +// VRAM update buffer +#include "vrambuf.h" +//#link "vrambuf.c" + /*{pal:"nes",layout:"nes"}*/ const char PALETTE[32] = { 0x03, // screen color diff --git a/src/baseplatform.ts b/src/baseplatform.ts index 8ea6b4c9..70d61459 100644 --- a/src/baseplatform.ts +++ b/src/baseplatform.ts @@ -652,7 +652,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform { } getToolForFilename = getToolForFilename_z80; getDefaultExtension() { return ".c"; }; - // TODO + // TODO: Z80 opcode metadata //this.getOpcodeMetadata = function() { } getDebugCategories() { diff --git a/src/platform/astrocade.ts b/src/platform/astrocade.ts index 9a311e14..2a22ae60 100644 --- a/src/platform/astrocade.ts +++ b/src/platform/astrocade.ts @@ -145,18 +145,17 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { // or/xor if (magicop & 0x30) { var oldv = ram.mem[a]; + // collision detect + var icpt = 0; + if ((oldv & 0xc0) && (v & 0xc0)) icpt |= 0x1; + if ((oldv & 0x30) && (v & 0x30)) icpt |= 0x2; + if ((oldv & 0x0c) && (v & 0x0c)) icpt |= 0x4; + if ((oldv & 0x03) && (v & 0x03)) icpt |= 0x8; + // apply op if (magicop & 0x10) v |= oldv; if (magicop & 0x20) v ^= oldv; // TODO: what if both? - // collision detect - var icpt = 0; - for (var i=0; i<8; i+=2) { - icpt <<= 1; - // pixel changed from off to on? - if ( !((oldv>>i)&3) && ((v>>i)&3) ) - icpt |= 1; - } // upper 4 bits persist, lower are just since last write inputs[8] = (inputs[8] & 0xf0) | icpt | (icpt<<4); } @@ -202,9 +201,8 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { [0x0000, 0x3fff, 0xfff, magicwrite], ]), // TODO: correct values? - // TODO: no contention on hblank isContended: () => { return true; }, - contend: () => { return vidactive ? 1 : 0; }, + contend: (addr:number) => { return vidactive && addr >= 0x4000 ? 1 : 0; }, }; } else { // arcade game @@ -220,7 +218,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { [0x0000, 0x3fff, 0x3fff, magicwrite], ]), isContended: () => { return true; }, - contend: () => { return vidactive ? 1 : 0; }, + contend: (addr:number) => { return vidactive ? 1 : 0; }, }; } iobus = { @@ -266,7 +264,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { break; case 0xc: // magic register magicop = val; - //shift2 = 0; // TODO? + shift2 = 0; // TODO? xplower = false; break; case 0xd: // INFBK (interrupt feedback) diff --git a/src/platform/nes.ts b/src/platform/nes.ts index 8d5d4db9..8eff1afe 100644 --- a/src/platform/nes.ts +++ b/src/platform/nes.ts @@ -12,11 +12,11 @@ const JSNES_PRESETS = [ {id:'hello.c', name:'Hello World'}, {id:'attributes.c', name:'Attribute Table'}, {id:'scroll.c', name:'Scrolling'}, - {id:'vrambuffer.c', name:'VRAM Buffer'}, {id:'sprites.c', name:'Sprites'}, {id:'metasprites.c', name:'Metasprites'}, {id:'flicker.c', name:'Flickering Sprites'}, {id:'metacursor.c', name:'Controllers'}, + {id:'vrambuffer.c', name:'VRAM Buffer'}, {id:'tint.c', name:'Color Emphasis'}, {id:'rletitle.c', name:'Title Screen RLE'}, {id:'statusbar.c', name:'Split Status Bar'}, diff --git a/src/ui.ts b/src/ui.ts index 90359d34..cb0857e7 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -448,13 +448,15 @@ function importProjectFromGithub(githuburl:string, replaceURL:boolean) { }).catch( (e) => { setWaitDialog(false); console.log(e); - alertError("Could not import " + githuburl + ": " + e); + alertError("

Could not import " + githuburl + ".

" + e); }); } function _loginToGithub(e) { getGithubService().login().then(() => { alertInfo("You are signed in to Github."); + }).catch( (e) => { + alertError("

Could not sign in.

" + e); }); } @@ -1180,6 +1182,7 @@ function getDebugExprExamples() : string { var s = ''; if (cpu.PC) s += "c.PC == 0x" + hex(cpu.PC) + "\n"; if (cpu.SP) s += "c.SP < 0x" + hex(cpu.SP) + "\n"; + if (cpu['HL']) s += "c.HL == 0x4000\n"; if (platform.readAddress) s += "this.readAddress(0x1234) == 0x0\n"; if (platform.readVRAMAddress) s += "this.readVRAMAddress(0x1234) != 0x80\n"; if (platform['getRasterScanline']) s += "this.getRasterScanline() > 222\n"; @@ -1641,7 +1644,9 @@ function installErrorHandler() { setDebugButtonState("pause", "stopped"); // TODO? } else { // send exception msg to GA - var msg = msgevent + " (" + line + ":" + col + "): " + error + " - " + url; + var msg = msgstr; + if (typeof error == 'string') msg += ": " + error; + if (line) msg += " (" + line + ":" + col + ")"; if (msg.length > 256) { msg = msg.substring(0, 256); } if (ga) ga('send', 'exception', { 'exDescription': msg, @@ -1910,6 +1915,8 @@ function convertLegacyVCS(store) { } } +// HTTPS REDIRECT + const useHTTPSCookieName = "__use_https"; function setHTTPSCookie(val : number) {