diff --git a/editstorage.html b/editstorage.html index 6558bfe8..0474a9ec 100644 --- a/editstorage.html +++ b/editstorage.html @@ -60,6 +60,7 @@ $("#deleteitem").click(function(e) { })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-54497476-9', 'auto'); + ga('set', 'anonymizeIp', true); ga('send', 'pageview'); diff --git a/presets/nes/crypto.c b/presets/nes/crypto.c index a2c08b9d..0dd719a9 100644 --- a/presets/nes/crypto.c +++ b/presets/nes/crypto.c @@ -1,6 +1,9 @@ - + #include "neslib.h" +#pragma data-name (push,"CHARS") +#pragma data-name (pop) + //#define DEBUG #define HAS_DEBUGGER @@ -34,6 +37,8 @@ static const unsigned char paused_palette[]={ #pragma bss-name(push,"ZEROPAGE") #pragma data-name(push,"ZEROPAGE") +unsigned char oam_off; + static unsigned char i, j; static unsigned char player_dir[2]; @@ -2632,14 +2637,20 @@ void __fastcall__ init(void){ bank_spr(0); bank_bg(1); - unrle_vram(bg_top_left, NAMETABLE_A); - unrle_vram(bg_top_right, NAMETABLE_B); - unrle_vram(bg_bottom_left, NAMETABLE_C); - unrle_vram(bg_bottom_right, NAMETABLE_D); + vram_adr(NAMETABLE_A); + vram_unrle(bg_top_left); + vram_adr(NAMETABLE_B); + vram_unrle(bg_top_right); + vram_adr(NAMETABLE_C); + vram_unrle(bg_bottom_left); + vram_adr(NAMETABLE_D); + vram_unrle(bg_bottom_right); // copy tilesets - vram_write((unsigned char*)0x0000, 0x0, 0x2000); - vram_write((unsigned char*)0x2000, 0x0, 0x2000); + vram_adr(0x0); + vram_write((unsigned char*)0x0000, 0x2000); + vram_adr(0x2000); + vram_write((unsigned char*)0x2000, 0x2000); ppu_on_all(); @@ -2823,20 +2834,21 @@ void main(void){ while(1){ pal_all(paused_palette); scroll(0, 0); - ppu_waitnmi(); + ppu_wait_nmi(); ppu_off(); - unrle_vram(bg_menu, NAMETABLE_A); + vram_adr(NAMETABLE_A); + vram_unrle(bg_menu); ppu_on_all(); pal_all(palette); - ppu_waitnmi(); + ppu_wait_nmi(); - ppu_waitnmi(); + ppu_wait_nmi(); while(1){ - ppu_waitnmi(); + ppu_wait_nmi(); spr=0; oam_clear(); frame++; @@ -2894,20 +2906,21 @@ void main(void){ oam_clear(); pal_all(paused_palette); - ppu_waitnmi(); + ppu_wait_nmi(); ppu_off(); - unrle_vram(bg_top_left, NAMETABLE_A); + vram_adr(NAMETABLE_A); + vram_unrle(bg_top_left); ppu_on_all(); - ppu_waitnmi(); + ppu_wait_nmi(); difficulty = 0; next_level = 1; while(1){ - ppu_waitnmi(); + ppu_wait_nmi(); spr=0; oam_clear(); @@ -2941,7 +2954,7 @@ void main(void){ frame = 0; while(1) { - ppu_waitnmi(); + ppu_wait_nmi(); frame++; if((frame > 100) && (frame == 255 || ((pad_trigger(0)|pad_trigger(1))&(PAD_A|PAD_B|PAD_START)))) { @@ -2981,7 +2994,7 @@ void main(void){ frame = 0; while(1) { - ppu_waitnmi(); + ppu_wait_nmi(); frame++; if(frame == 255) { @@ -3014,7 +3027,7 @@ void main(void){ while(!(pad_trigger(0) & PAD_START)) { - ppu_waitnmi(); + ppu_wait_nmi(); } pal_all(palette); diff --git a/presets/nes/neslib.h b/presets/nes/neslib.h new file mode 100644 index 00000000..e9f9355e --- /dev/null +++ b/presets/nes/neslib.h @@ -0,0 +1,292 @@ +/* + (C) 2015 Alex Semenov (Shiru) + (C) 2016 Lauri Kasanen + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +// NES hardware-dependent functions by Shiru (shiru@mail.ru) +// Feel free to do anything you want with this code, consider it Public Domain + +// Versions history: +// 280215 - fixed palette glitch caused with the active DMC DMA glitch +// 030914 - minor fixes in the vram update system +// 310814 - added vram_flush_update +// 120414 - removed adr argument from vram_write and vram_read, +// unrle_vram renamed to vram_unrle, with adr argument removed +// 060414 - many fixes and improvements, including sequental VRAM updates +// previous versions were created since mid-2011, there were many updates + + + + + +// set bg and spr palettes, data is 32 bytes array +void __fastcall__ pal_all(const char *data); + +// set bg palette only, data is 16 bytes array +void __fastcall__ pal_bg(const char *data); + +// set spr palette only, data is 16 bytes array +void __fastcall__ pal_spr(const char *data); + +// set a palette entry, index is 0..31 +void __fastcall__ pal_col(unsigned char index, unsigned char color); + +// reset palette to $0f +void __fastcall__ pal_clear(void); + +// set virtual bright both for sprites and background, 0 is black, 4 is normal, 8 is white +void __fastcall__ pal_bright(unsigned char bright); + +// set virtual bright for sprites only +void __fastcall__ pal_spr_bright(unsigned char bright); + +// set virtual bright for sprites background only +void __fastcall__ pal_bg_bright(unsigned char bright); + + + +// wait actual TV frame, 50hz for PAL, 60hz for NTSC +void __fastcall__ ppu_wait_nmi(void); + +// wait virtual frame, it is always 50hz, frame-to-frame in PAL, frameskip in NTSC +void __fastcall__ ppu_wait_frame(void); + +// turn off rendering, nmi still enabled when rendering is disabled +void __fastcall__ ppu_off(void); + +// turn on bg, spr +void __fastcall__ ppu_on_all(void); + +// turn on bg only +void __fastcall__ ppu_on_bg(void); + +// turn on spr only +void __fastcall__ ppu_on_spr(void); + +// set PPU_MASK directly +void __fastcall__ ppu_mask(unsigned char mask); + +// get current video system, 0 for PAL, not 0 for NTSC +unsigned char __fastcall__ ppu_system(void); + +// Return an 8-bit counter incremented at each vblank +unsigned char __fastcall__ nesclock(void); + +// get/set the internal ppu ctrl cache var for manual writing +unsigned char __fastcall__ get_ppu_ctrl_var(void); +void __fastcall__ set_ppu_ctrl_var(unsigned char var); + + +// clear OAM buffer, all the sprites are hidden +void __fastcall__ oam_clear(void); + +// set sprite display mode, 0 for 8x8 sprites, 1 for 8x16 sprites +void __fastcall__ oam_size(unsigned char size); + +// set sprite in OAM buffer, chrnum is tile, attr is attribute, sprid is offset in OAM in bytes +// returns sprid+4, which is offset for a next sprite +unsigned char __fastcall__ oam_spr(unsigned char x, unsigned char y, + unsigned char chrnum, unsigned char attr, + unsigned char sprid); + +// set metasprite in OAM buffer +// meta sprite is a const unsigned char array, it contains four bytes per sprite +// in order x offset, y offset, tile, attribute +// x=128 is end of a meta sprite +// returns sprid+4, which is offset for a next sprite +unsigned char __fastcall__ oam_meta_spr(unsigned char x, unsigned char y, + unsigned char sprid, const unsigned char *data); + +// hide all remaining sprites from given offset +void __fastcall__ oam_hide_rest(unsigned char sprid); + + + +// play a music in FamiTone format +void __fastcall__ music_play(unsigned char song); + +// stop music +void __fastcall__ music_stop(void); + +// pause and unpause music +void __fastcall__ music_pause(unsigned char pause); + +// play FamiTone sound effect on channel 0..3 +void __fastcall__ sfx_play(unsigned char sound, unsigned char channel); + +// play a DPCM sample, 1..63 +void __fastcall__ sample_play(unsigned char sample); + + + +// poll controller and return flags like PAD_LEFT etc, input is pad number (0 or 1) +unsigned char __fastcall__ pad_poll(unsigned char pad); + +// poll controller in trigger mode, a flag is set only on button down, not hold +// if you need to poll the pad in both normal and trigger mode, poll it in the +// trigger mode for first, then use pad_state +unsigned char __fastcall__ pad_trigger(unsigned char pad); + +// get previous pad state without polling ports +unsigned char __fastcall__ pad_state(unsigned char pad); + + +// set scroll, including rhe top bits +// it is always applied at beginning of a TV frame, not at the function call +void __fastcall__ scroll(unsigned int x, unsigned int y); + +// set scroll after screen split invoked by the sprite 0 hit +// warning: all CPU time between the function call and the actual split point will be wasted! +// warning: the program loop has to fit into the frame time, ppu_wait_frame should not be used +// otherwise empty frames without split will be inserted, resulting in jumpy screen +// warning: only X scroll could be changed in this version +void __fastcall__ split(unsigned int x, unsigned int y); + + +// select current chr bank for sprites, 0..1 +void __fastcall__ bank_spr(unsigned char n); + +// select current chr bank for background, 0..1 +void __fastcall__ bank_bg(unsigned char n); + + + +// get random number 0..255 or 0..65535 +unsigned char __fastcall__ rand8(void); +unsigned int __fastcall__ rand16(void); + +// set random seed +void __fastcall__ set_rand(unsigned int seed); + + + +// when display is enabled, vram access could only be done with this vram update system +// the function sets a pointer to the update buffer that contains data and addresses +// in a special format. It allows to write non-sequental bytes, as well as horizontal or +// vertical nametable sequences. +// buffer pointer could be changed during rendering, but it only takes effect on a new frame +// number of transferred bytes is limited by vblank time +// to disable updates, call this function with NULL pointer + +// the update data format: +// MSB, LSB, byte for a non-sequental write +// MSB|NT_UPD_HORZ, LSB, LEN, [bytes] for a horizontal sequence +// MSB|NT_UPD_VERT, LSB, LEN, [bytes] for a vertical sequence +// NT_UPD_EOF to mark end of the buffer + +// length of this data should be under 256 bytes + +void __fastcall__ set_vram_update(unsigned char *buf); + +// all following vram functions only work when display is disabled + +// do a series of VRAM writes, the same format as for set_vram_update, but writes done right away +void __fastcall__ flush_vram_update(unsigned char *buf); + +// set vram pointer to write operations if you need to write some data to vram +void __fastcall__ vram_adr(unsigned int adr); + +// put a byte at current vram address, works only when rendering is turned off +void __fastcall__ vram_put(unsigned char n); + +// fill a block with a byte at current vram address, works only when rendering is turned off +void __fastcall__ vram_fill(unsigned char n, unsigned int len); + +// set vram autoincrement, 0 for +1 and not 0 for +32 +void __fastcall__ vram_inc(unsigned char n); + +// read a block from current address of vram, works only when rendering is turned off +void __fastcall__ vram_read(unsigned char *dst, unsigned int size); + +// write a block to current address of vram, works only when rendering is turned off +void __fastcall__ vram_write(const unsigned char *src, unsigned int size); + + +// unpack RLE data to current address of vram, mostly used for nametables +void __fastcall__ vram_unrle(const unsigned char *data); + +// unpack LZ4 data to this address +void __fastcall__ vram_unlz4(const unsigned char *in, unsigned char *out, + const unsigned uncompressed_size); +/* + Rough speeds for a full 1024 nametable: + - rle takes 0.5 frames + - uncompressed takes 1.3 frames + - lz4 takes 2.8 frames +*/ + + +// like memset, but does not return anything +void __fastcall__ memfill(void *dst, unsigned char value, unsigned int len); + +// delay for N frames +void __fastcall__ delay(unsigned char frames); + +// display.sinc functions +void __fastcall__ oam_clear_fast(void); +void __fastcall__ oam_meta_spr_pal(unsigned char x,unsigned char y,unsigned char pal,const unsigned char *metasprite); +void __fastcall__ oam_meta_spr_clip(signed int x,unsigned char y,const unsigned char *metasprite); + + + +#define PAD_A 0x01 +#define PAD_B 0x02 +#define PAD_SELECT 0x04 +#define PAD_START 0x08 +#define PAD_UP 0x10 +#define PAD_DOWN 0x20 +#define PAD_LEFT 0x40 +#define PAD_RIGHT 0x80 + +#define OAM_FLIP_V 0x80 +#define OAM_FLIP_H 0x40 +#define OAM_BEHIND 0x20 + +#define MAX(x1,x2) ((x1)<(x2)?(x2):(x1)) +#define MIN(x1,x2) ((x1)<(x2)?(x1):(x2)) + +#define MASK_SPR 0x10 +#define MASK_BG 0x08 +#define MASK_EDGE_SPR 0x04 +#define MASK_EDGE_BG 0x02 + +#define NAMETABLE_A 0x2000 +#define NAMETABLE_B 0x2400 +#define NAMETABLE_C 0x2800 +#define NAMETABLE_D 0x2c00 + +#define NULL 0 +#define TRUE 1 +#define FALSE 0 + +#define NT_UPD_HORZ 0x40 +#define NT_UPD_VERT 0x80 +#define NT_UPD_EOF 0xff + +// macro to calculate nametable address from X,Y in compile time + +#define NTADR_A(x,y) (NAMETABLE_A|(((y)<<5)|(x))) +#define NTADR_B(x,y) (NAMETABLE_B|(((y)<<5)|(x))) +#define NTADR_C(x,y) (NAMETABLE_C|(((y)<<5)|(x))) +#define NTADR_D(x,y) (NAMETABLE_D|(((y)<<5)|(x))) + +// macro to get MSB and LSB + +#define MSB(x) (((x)>>8)) +#define LSB(x) (((x)&0xff)) diff --git a/presets/nes/neslib1.c b/presets/nes/neslib1.c index 6201b3f3..740e6815 100644 --- a/presets/nes/neslib1.c +++ b/presets/nes/neslib1.c @@ -3,7 +3,11 @@ #include "neslib.h" -// tileset data +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:128,brev:1}*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7c,0x7c,0x7c,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0xfe,0x6c,0xfe,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xfe,0xd0,0xfe,0x16,0xfe,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0xdc,0x38,0x76,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6c,0x7c,0xec,0xee,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xfe,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x1e,0x3c,0x78,0xf0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -12,6 +16,8 @@ const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:128,brev:1}*/ 0x00,0xfc,0xee,0xee,0xee,0xfc,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0xee,0xec,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xee,0xee,0xee,0xfc,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0x7c,0x0e,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xee,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xee,0x6c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xfe,0xfe,0xee,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0x7c,0x38,0x7c,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xee,0x7c,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x1c,0x38,0x70,0xe0,0xfe,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; +#pragma data-name(pop) + //this macro is used remove need of calculation of the nametable address in runtime #define NTADR(x,y) ((0x2000|((y)<<5)|x)) @@ -32,7 +38,8 @@ void put_str(unsigned int adr,const char *str) void main(void) { //copy tileset to RAM - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); //rendering is disabled at the startup, and palette is all black pal_col(1,0x30);//set while color diff --git a/presets/nes/neslib2.c b/presets/nes/neslib2.c index 5a8b5959..63180aad 100644 --- a/presets/nes/neslib2.c +++ b/presets/nes/neslib2.c @@ -4,6 +4,13 @@ #include "neslib.h" +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + //#link "tileset1.c" // palette for balls, there are four sets for different ball colors @@ -35,7 +42,8 @@ static unsigned char ball_dy[BALLS_MAX]; void main(void) { //copy tileset to RAM - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); pal_spr(palSprites);//set palette for sprites oam_size(1); @@ -69,7 +77,7 @@ void main(void) while(1) { - ppu_waitnmi();//wait for next TV frame + ppu_wait_nmi();//wait for next TV frame spr=0; diff --git a/presets/nes/neslib3.c b/presets/nes/neslib3.c index a38c50b2..e869c72f 100644 --- a/presets/nes/neslib3.c +++ b/presets/nes/neslib3.c @@ -2,8 +2,17 @@ //this example shows how to set up a palette and use 8x8 HW sprites //also shows how fast (or slow) C code is +#include + #include "neslib.h" +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + //#link "tileset1.c" // tile set, two planes for 4 colors @@ -13,9 +22,6 @@ extern unsigned char TILESET[8*256]; //and how to use nametable update system that allows to modify nametable //while rendering is enabled -#include "neslib.h" - - //these macro are needed to simplify defining update list constants #define NTADR(x,y) ((0x2000|((y)<<5)|x)) @@ -35,27 +41,27 @@ static unsigned char list[6*3]; //init data for the update list, it contains MSB and LSB of a tile address //in the nametable, then the tile number -const unsigned char list_init[6*3]={ - MSB(NTADR(2,2)),LSB(NTADR(2,2)),0, - MSB(NTADR(3,2)),LSB(NTADR(3,2)),0, - MSB(NTADR(4,2)),LSB(NTADR(4,2)),0, - MSB(NTADR(6,2)),LSB(NTADR(6,2)),0, - MSB(NTADR(7,2)),LSB(NTADR(7,2)),0, - MSB(NTADR(8,2)),LSB(NTADR(8,2)),0 +const unsigned char list_init[6*3+1]={ + MSB(NTADR(2,2)),LSB(NTADR(2,2)),0, + MSB(NTADR(3,2)),LSB(NTADR(3,2)),0, + MSB(NTADR(4,2)),LSB(NTADR(4,2)),0, + MSB(NTADR(6,2)),LSB(NTADR(6,2)),0, + MSB(NTADR(7,2)),LSB(NTADR(7,2)),0, + MSB(NTADR(8,2)),LSB(NTADR(8,2)),0, + NT_UPD_EOF }; - - void main(void) { //copy tileset to RAM - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); pal_col(1,0x21);//blue color for text pal_col(17,0x30);//white color for sprite memcpy(list,list_init,sizeof(list_init)); - set_vram_update(6,list); + set_vram_update(list); ppu_on_all();//enable rendering @@ -66,7 +72,7 @@ void main(void) while(1) { - ppu_waitnmi();//wait for next TV frame + ppu_wait_nmi();//wait for next TV frame oam_spr(x,y,0x41,0,0);//put sprite diff --git a/presets/nes/neslib4.c b/presets/nes/neslib4.c index c4e43e99..72429f89 100644 --- a/presets/nes/neslib4.c +++ b/presets/nes/neslib4.c @@ -1,6 +1,13 @@ #include "neslib.h" +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + //#link "tileset1.c" // tile set, two planes for 4 colors @@ -54,7 +61,8 @@ const unsigned char metaCat2[]={ void main(void) { //copy tileset to RAM - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); ppu_on_all();//enable rendering @@ -74,7 +82,7 @@ void main(void) while(1) { - ppu_waitnmi();//wait for next TV frame + ppu_wait_nmi();//wait for next TV frame //flashing color for touch diff --git a/presets/nes/neslib5.c b/presets/nes/neslib5.c index 063429fd..9baabc4d 100644 --- a/presets/nes/neslib5.c +++ b/presets/nes/neslib5.c @@ -4,6 +4,13 @@ #include "neslib.h" +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + const unsigned char test[308]={ 0x01,0x00,0x01,0xa3,0x10,0x01,0x04,0x00,0x10,0x01,0x04,0x00,0x10,0x01,0x04,0x00, 0x10,0x01,0x04,0x00,0x01,0x0a,0x10,0x00,0x01,0x02,0x10,0x00,0x01,0x04,0x10,0x00, @@ -41,10 +48,12 @@ void main(void) pal_bg(palette);//set background palette from an array //copy tileset to RAM - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); //unpack nametable into the VRAM - unrle_vram(test,0x2000); + vram_adr(0x2000); + vram_unrle(test); //enable rendering ppu_on_all(); diff --git a/presets/nes/shoot2.c b/presets/nes/shoot2.c new file mode 100644 index 00000000..fed7441f --- /dev/null +++ b/presets/nes/shoot2.c @@ -0,0 +1,808 @@ + +#include +#include +#include +#include + +#include "neslib.h" + +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + +#pragma static-locals (1); + +#define COLS 32 +#define ROWS 28 + +typedef unsigned char byte; +typedef signed char sbyte; +typedef unsigned short word; + +/// + +const char PALETTE[32] = { + 0x0f, + + 0x11,0x24,0x3c, 0, + 0x01,0x15,0x25, 0, + 0x01,0x10,0x20, 0, + 0x06,0x16,0x26, 0, + + 0x11,0x24,0x3c, 0, + 0x01,0x15,0x25, 0, + 0x31,0x35,0x3c, 0, + 0x01,0x17,0x30 +}; + +#define COLOR_PLAYER 3 +#define COLOR_FORMATION 1 +#define COLOR_ATTACKER 1 +#define COLOR_MISSILE 3 +#define COLOR_BOMB 2 +#define COLOR_SCORE 2 +#define COLOR_EXPLOSION 3 + +const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7C,0x7C,0x7C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0x6C,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xFE,0xD0,0xFE,0x16,0xFE,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xDC,0x38,0x76,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x7C,0xEC,0xEE,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xFE,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1E,0x3C,0x78,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x7C,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x78,0x38,0x38,0x38,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x0E,0x7C,0xE0,0xEE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0E,0x3C,0x0E,0x0E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0xEE,0xEE,0xFE,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xE0,0xFC,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0xFC,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xEE,0x1C,0x1C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x7C,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0x7E,0x0E,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x38,0x70,0x70,0x38,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x1C,0x1C,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x1C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x7C,0xEE,0xEE,0xEE,0xE0,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xFE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xEE,0xFC,0xEE,0xEE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xE0,0xE0,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEC,0xEE,0xEE,0xEE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xE0,0xF0,0xE0,0xE0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xE0,0xF8,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0xEE,0xEE,0xEE,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x38,0x38,0x38,0x38,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xFC,0xF8,0xEC,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xEE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xEE,0xFE,0xFE,0xEE,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xFC,0xEE,0xEE,0xEE,0xFC,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xEC,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xEE,0xEE,0xEE,0xFC,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0x7C,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xFE,0xFE,0xEE,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x7C,0x38,0x7C,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0x7C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x1C,0x38,0x70,0xE0,0xFE,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +// formation enemy (66) +0x0C,0x13,0x03,0x03,0x03,0x01,0x01,0x00,0x0C,0x10,0x01,0x0C,0x30,0x02,0x04,0x18, +0x18,0x64,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x18,0x04,0x40,0x18,0x06,0x20,0x10,0x0C, +// attackers (68) +0x00,0x00,0x04,0x08,0x04,0x00,0x01,0x0C,0x00,0x00,0x04,0x08,0x04,0x03,0x03,0x03, +0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x30,0x02,0x04,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x08,0x10,0x60,0xE0,0xE0,0x00,0x00,0x10,0x08,0x10,0x00,0x40,0x18, +0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x06,0x20,0x10,0x0C,0x00,0x00,0x00,0x00, + +0x00,0x00,0x02,0x04,0x04,0x03,0x03,0x03,0x00,0x00,0x02,0x04,0x04,0x20,0x11,0x0C, +0x03,0x07,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x20,0x1C,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x08,0x08,0x10,0xE0,0xE0,0x00,0x00,0x00,0x08,0x08,0x10,0x00,0x40, +0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x10,0x0C,0x02,0x20,0x10,0x0C,0x00,0x00, + +0x00,0x00,0x0C,0x04,0x02,0x03,0x07,0x27,0x00,0x00,0x0C,0x04,0x00,0x00,0x01,0x20, +0x3F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x08,0x10,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0x00,0x00,0x00,0x20,0x40,0x84,0x08,0x10, +0xE0,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x00,0x00,0x00, + +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x18,0x21,0x44,0x08,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x20,0x40,0x80,0x98,0x20,0x00, +0xE0,0xFC,0xC4,0x80,0x80,0x80,0xC0,0x00,0x40,0x0C,0x04,0x00,0x00,0x80,0xC0,0x00, + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x02,0x11,0x08,0x04, +0x03,0x03,0x07,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x20,0x60,0xF0,0xFC,0x00,0x00,0x00,0x30,0x20,0x00,0x40,0x04, +0xFC,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x2C,0x00,0x20,0x18,0x80,0x40,0x60,0x00, + +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x00,0x00,0x00,0x10,0x10,0x08,0x04,0x00, +0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x00,0x00, +0x00,0x00,0x00,0x08,0x34,0xE0,0xE0,0xF0,0x00,0x80,0x80,0x88,0x94,0x00,0x40,0x00, +0xFA,0xE4,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x04,0x80,0x40,0x20,0x00,0x00,0x00, + +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x00,0x00,0x01,0x09,0x08,0x04,0x02,0x00, +0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x04,0x08,0x09,0x01,0x00, +0x00,0x00,0x00,0x00,0x08,0x14,0xE0,0xE0,0x00,0x00,0x00,0x00,0x88,0x94,0x00,0x40, +0xC0,0xE0,0xE0,0x14,0x08,0x00,0x00,0x00,0x00,0x40,0x00,0x94,0x88,0x00,0x00,0x00, + +0x01,0x01,0x01,0x00,0x00,0x01,0x11,0x11,0x01,0x01,0x02,0x07,0x01,0x21,0x21,0x2B, +0x11,0x16,0x1E,0x15,0x10,0x10,0x10,0x10,0x3F,0x3F,0x3F,0x3D,0x3B,0x3C,0x28,0x28, +0x40,0x40,0xC0,0x00,0x00,0x40,0x44,0x44,0xC0,0xC0,0x20,0xF0,0xC0,0xC2,0xC2,0xEA, +0x44,0x34,0x3C,0x54,0x04,0x04,0x04,0x04,0xFE,0xFE,0xFE,0xDE,0xEE,0x1E,0x0A,0x0A, + +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x18,0x08,0x18,0x08,0x18,0x18,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +// explosions +0x00,0x00,0x00,0x08,0x04,0x03,0x06,0x05,0x00,0x00,0x00,0x0C,0x06,0x04,0x00,0x18, +0x05,0x06,0x07,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x08,0x09,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x08,0x90,0xE0,0x90,0xD0,0x00,0x00,0x00,0x18,0x30,0x10,0x00,0x0C, +0xF0,0x20,0xE0,0x80,0x00,0x00,0x00,0x00,0x0C,0x10,0x18,0xC8,0x00,0x00,0x00,0x00, + +0x00,0x04,0x12,0x0C,0x42,0x30,0x00,0x19,0x00,0x00,0x00,0x0A,0x00,0x06,0x08,0x00, +0x11,0x04,0x0C,0x00,0x21,0x46,0x00,0x00,0x04,0x10,0x02,0x0C,0x00,0x00,0x00,0x00, +0x00,0x40,0x08,0x91,0xA2,0x04,0x80,0xCC,0x00,0x00,0x00,0x20,0x00,0x30,0x08,0x00, +0xC4,0x10,0x1A,0x80,0x20,0x10,0x00,0x00,0x10,0x04,0xA0,0x98,0x80,0x00,0x00,0x00, + +0x61,0x20,0x00,0x04,0x00,0xC4,0x08,0x10,0x00,0x00,0x04,0x06,0x09,0x02,0x10,0x14, +0x10,0x00,0x42,0xC8,0x80,0x00,0x10,0x30,0x34,0x10,0x11,0x02,0x00,0x00,0x00,0x00, +0x86,0xC4,0x00,0x10,0x01,0x10,0x08,0x04,0x00,0x00,0x10,0x30,0x48,0x20,0x04,0x14, +0x04,0x00,0x20,0x89,0x00,0x84,0xC6,0x43,0x16,0x04,0x44,0xA0,0x00,0x00,0x00,0x00, + +0x00,0x00,0x02,0x08,0x00,0x06,0x02,0x00,0x00,0x00,0x08,0x01,0x11,0x15,0x00,0x38, +0x30,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x20,0x08,0x00,0x30,0x20,0x00,0x00,0x00,0x08,0x40,0x44,0x54,0x00,0x0E, +0x06,0x20,0x80,0x80,0x00,0x00,0x00,0x00,0x0C,0x80,0x04,0x80,0x00,0x00,0x00,0x00, +}; + +#define CHAR(x) ((x)-' ') +#define BLANK 0 + +// VRAM UPDATE BUFFER + +#define VBUFSIZE 64 +byte updbuf[VBUFSIZE]; +byte updptr = 0; + +void cendbuf() { + updbuf[updptr] = NT_UPD_EOF; +} + +void cflushnow() { + cendbuf(); + ppu_wait_nmi(); + flush_vram_update(updbuf); + updptr = 0; + cendbuf(); + vram_adr(0x0); +} + +void vdelay(byte count) { + while (count--) cflushnow(); +} + +void putchar(byte x, byte y, char ch) { + word addr = NTADR_A(x,y); + if (updptr >= VBUFSIZE-4) cflushnow(); + updbuf[updptr++] = addr >> 8; + updbuf[updptr++] = addr & 0xff; + updbuf[updptr++] = ch; + cendbuf(); +} + +void putbytes(byte x, byte y, char* str, byte len) { + word addr = NTADR_A(x,y); + if (updptr >= VBUFSIZE-4-len) cflushnow(); + updbuf[updptr++] = (addr >> 8) | NT_UPD_HORZ; + updbuf[updptr++] = addr & 0xff; + updbuf[updptr++] = len; + while (len--) { + updbuf[updptr++] = *str++; + } + cendbuf(); +} + +void putstring(byte x, byte y, char* str) { + putbytes(x, y, str, strlen(str)); +} + +void clrscr() { + updptr = 0; + cendbuf(); + ppu_off(); + vram_adr(0x2000); + vram_fill(BLANK, 32*28); + vram_adr(0x0); + ppu_on_all(); +} + +///// + +char in_rect(byte x, byte y, byte x0, byte y0, byte w, byte h) { + return ((byte)(x-x0) < w && (byte)(y-y0) < h); // unsigned +} + +void draw_bcd_word(byte col, byte row, word bcd) { + byte j; + static char buf[5]; + buf[4] = CHAR('0'); + for (j=3; j<0x80; j--) { + buf[j] = CHAR('0'+(bcd&0xf)); + bcd >>= 4; + } + putbytes(col, row, buf, 5); +} + +word bcd_add(word a, word b) { + word result = 0; + byte c = 0; + byte shift = 0; + while (shift < 16) { + byte d = (a & 0xf) + (b & 0xf) + c; + c = 0; + while (d >= 10) { + c++; + d -= 10; + } + result |= d << shift; + shift += 4; + a >>= 4; + b >>= 4; + } + return result; +} + +// GAME CODE + +#define NSPRITES 16 +#define NMISSILES 8 +#define YOFFSCREEN 239 + +#define SPRI_SHIP 96 +#define SPRI_MISSILE 100 +#define SPRI_BOMB 104 +#define SPRI_EXPLODE 112 +#define SPRI_ENEMY 68 + +#define SSRC_FORM1 66 +#define SDST_FORM1 128 + +typedef struct { + byte shape; +} FormationEnemy; + +// should be power of 2 length +typedef struct { + byte findex; + byte shape; + word x; + word y; + byte dir; + byte returning; +} AttackingEnemy; + +typedef struct { + signed char dx; + byte xpos; + signed char dy; + byte ypos; +} Missile; + +typedef struct { + byte name; + byte tag; + byte x; + byte y; +} Sprite; + +#define ENEMIES_PER_ROW 8 +#define ENEMY_ROWS 4 +#define MAX_IN_FORMATION (ENEMIES_PER_ROW*ENEMY_ROWS) +#define MAX_ATTACKERS 6 + +FormationEnemy formation[MAX_IN_FORMATION]; +AttackingEnemy attackers[MAX_ATTACKERS]; +Missile missiles[NMISSILES]; +Sprite vsprites[NSPRITES]; + +byte formation_offset_x; +signed char formation_direction; +byte current_row; +byte player_x; +const byte player_y = 190; +byte player_exploding; +byte enemy_exploding; +byte enemies_left; +word player_score; +byte framecount; + +void copy_sprites() { + byte i; + byte oamid = 0; + for (i=0; iy != YOFFSCREEN) { + byte y = spr->y; + byte x = spr->x; + byte chr = spr->name; + byte attr = spr->tag; + if (attr & 0x40) chr += 2; // horiz flip, swap tiles + oamid = oam_spr(x, y, chr, attr, oamid); + oamid = oam_spr(x+8, y, chr^2, attr, oamid); + } + } + // copy all "shadow missiles" to video memory + for (i=0; iypos != YOFFSCREEN) { + oamid = oam_spr(mis->xpos, mis->ypos, SPRI_MISSILE, + (i==7)?COLOR_MISSILE:COLOR_BOMB, + oamid); + } + } + oam_hide_rest(oamid); +} + +void add_score(word bcd) { + player_score = bcd_add(player_score, bcd); + draw_bcd_word(1, 1, player_score); +} + +void clrobjs() { + byte i; + memset(vsprites, 0, sizeof(vsprites)); + for (i=0; ifindex) { + byte code = DIR_TO_CODE[(a->dir)&31]; + vsprites[i].name = SPRI_ENEMY + (code&7)*4; // tile + vsprites[i].tag = code & 0xc0; // flip h/v + vsprites[i].x = a->x >> 8; + vsprites[i].y = a->y >> 8; + } else { + vsprites[i].y = YOFFSCREEN; + } +} + +void draw_attackers() { + byte i; + for (i=0; ifindex-1; + byte destx = get_attacker_x(fi); + byte desty = get_attacker_y(fi); + byte ydist = desty - (a->y >> 8); + // are we close to our formation slot? + if (ydist == 0) { + // convert back to formation enemy + formation[fi].shape = a->shape; + a->findex = 0; + } else { + a->dir = (ydist + 16) & 31; + a->x = destx << 8; + a->y += 128; + } +} + +void fly_attacker(AttackingEnemy* a) { + a->x += isin(a->dir) * 2; + a->y += icos(a->dir) * 2; + if ((a->y >> 8) == 0) { + a->returning = 1; + } +} + +void move_attackers() { + byte i; + for (i=0; ifindex) { + if (a->returning) + return_attacker(a); + else + fly_attacker(a); + } + } +} + +void think_attackers() { + byte i; + for (i=0; ifindex) { + // rotate? + byte x = a->x >> 8; + byte y = a->y >> 8; + // don't shoot missiles after player exploded + if (y < 112 || player_exploding) { + if (x < 128) { + a->dir++; + } else { + a->dir--; + } + } else { + // lower half of screen + // shoot a missile? + if (missiles[i].ypos == YOFFSCREEN) { + missiles[i].ypos = y+16; + missiles[i].xpos = x; + missiles[i].dy = 2; + } + } + } + } +} + +void formation_to_attacker(byte formation_index) { + byte i; + // out of bounds? return + if (formation_index >= MAX_IN_FORMATION) + return; + // nobody in formation? return + if (!formation[formation_index].shape) + return; + // find an empty attacker slot + for (i=0; ifindex == 0) { + a->x = get_attacker_x(formation_index) << 8; + a->y = get_attacker_y(formation_index) << 8; + a->shape = formation[formation_index].shape; + a->findex = formation_index+1; + a->dir = 0; + a->returning = 0; + formation[formation_index].shape = 0; + break; + } + } +} + +void draw_player() { + vsprites[7].x = player_x; + vsprites[7].y = player_y; + vsprites[7].name = SPRI_SHIP; + vsprites[7].tag = COLOR_PLAYER; +} + +void move_player() { + byte joy = joy_read(JOY_1); + // move left/right? + if ((joy & JOY_LEFT_MASK) && player_x > 16) player_x--; + if ((joy & JOY_RIGHT_MASK) && player_x < 224) player_x++; + // shoot missile? + if ((joy & JOY_BTN_A_MASK) && missiles[7].ypos == YOFFSCREEN) { + missiles[7].ypos = player_y-8; // must be multiple of missile speed + missiles[7].xpos = player_x; // player X position + missiles[7].dy = -4; // player missile speed + } + vsprites[7].x = player_x; +} + +void move_missiles() { + byte i; + for (i=0; i<8; i++) { + if (missiles[i].ypos != YOFFSCREEN) { + // hit the bottom or top? + if ((byte)(missiles[i].ypos += missiles[i].dy) > YOFFSCREEN) { + missiles[i].ypos = YOFFSCREEN; + } + } + } +} + +void blowup_at(byte x, byte y) { + vsprites[6].tag = COLOR_EXPLOSION; + vsprites[6].name = SPRI_EXPLODE; // TODO + vsprites[6].x = x; + vsprites[6].y = y; + enemy_exploding = 1; +} + +void animate_enemy_explosion() { + if (enemy_exploding) { + // animate next frame + if (enemy_exploding >= 8) { + enemy_exploding = 0; // hide explosion after 4 frames + vsprites[6].y = YOFFSCREEN; + } else { + vsprites[6].name = SPRI_EXPLODE + (enemy_exploding += 4); // TODO + } + } +} + +void animate_player_explosion() { + byte z = player_exploding; + if (z <= 3) { + if (z == 3) { + vsprites[7].y = YOFFSCREEN; + } else { + vsprites[7].name = SPRI_EXPLODE + z*4; + } + } +} + +void hide_player_missile() { + missiles[7].ypos = YOFFSCREEN; +} + +void does_player_shoot_formation() { + byte mx = missiles[7].xpos + 8; + byte my = missiles[7].ypos; + signed char row = (my - FORMATION_Y0) / FORMATION_YSPACE; + if (row >= 0 && row < ENEMY_ROWS) { + // ok if unsigned (in fact, must be due to range) + byte xoffset = mx - FORMATION_X0 - formation_offset_x; + byte column = xoffset / FORMATION_XSPACE; + byte localx = xoffset - column * FORMATION_XSPACE; + if (column < ENEMIES_PER_ROW && localx < 16) { + char index = column + row * ENEMIES_PER_ROW; + if (formation[index].shape) { + formation[index].shape = 0; + enemies_left--; + blowup_at(get_attacker_x(index), get_attacker_y(index)); + hide_player_missile(); + add_score(2); + } + } + } +} + +void does_player_shoot_attacker() { + byte mx = missiles[7].xpos + 8; + byte my = missiles[7].ypos; + byte i; + for (i=0; ifindex && in_rect(mx, my, a->x >> 8, a->y >> 8, 16, 16)) { + blowup_at(a->x >> 8, a->y >> 8); + a->findex = 0; + enemies_left--; + hide_player_missile(); + add_score(5); + break; + } + } +} + +void does_missile_hit_player() { + byte i; + if (player_exploding) + return; + for (i=0; i> 8; + if (y >= 0x80) { + cv_set_frequency(CV_SOUNDCHANNEL_2, 4000+y*8); + cv_set_attenuation(CV_SOUNDCHANNEL_2, 28); + break; + } + } + } + */ +} + +void wait_for_frame() { + ppu_wait_nmi(); +} + +void play_round() { + byte end_timer = 255; + player_score = 0; + add_score(0); + putstring(0, 0, "PLAYER 1"); + setup_formation(); + clrobjs(); + formation_direction = 1; + framecount = 0; + new_player_ship(); + while (end_timer) { + if (player_exploding) { + if ((framecount & 7) == 1) { + animate_player_explosion(); + if (++player_exploding > 32 && enemies_left) { + new_player_ship(); + } + } + } else { + if ((framecount & 0x7f) == 0 || enemies_left < 8) { + new_attack_wave(); + } + move_player(); + does_missile_hit_player(); + } + if ((framecount & 3) == 2) animate_enemy_explosion(); + move_attackers(); + move_missiles(); + if (framecount & 1) + does_player_shoot_formation(); + else + does_player_shoot_attacker(); + draw_next_row(); + draw_attackers(); + if ((framecount & 0xf) == 0) think_attackers(); + set_sounds(); + framecount++; + if (!enemies_left) end_timer--; + cflushnow(); + copy_sprites(); + } +} + +void set_shifted_pattern(const byte* src, word dest, byte shift) { + static byte buf[16*3]; + byte y; + for (y=0; y<16; y++) { + byte a = src[y]; + byte b = src[y+16]; + buf[y] = a>>shift; + buf[y+16] = b>>shift | a<<(8-shift); + buf[y+32] = b<<(8-shift); + } + vram_adr(dest); + vram_write(buf, sizeof(buf)); +} + +void setup_tileset() { + byte i; + word src; + word dest; + // copy background + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); + // copy sprites + vram_adr(0x1000); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); + // write shifted versions of formation ships + src = SSRC_FORM1*16; + dest = SDST_FORM1*16; + for (i=0; i<8; i++) { + set_shifted_pattern(&TILESET[src], dest, i); + dest += 3*16; + } +} + +void main() { + joy_install (joy_static_stddrv); + setup_tileset(); + pal_all(PALETTE); + oam_clear(); + oam_size(1); // 8x16 sprites + clrscr(); + play_round(); + main(); +} + diff --git a/presets/nes/siegegame.c b/presets/nes/siegegame.c index 7d5d8a46..a0cd6a6e 100644 --- a/presets/nes/siegegame.c +++ b/presets/nes/siegegame.c @@ -1,21 +1,28 @@ #include #include -#include #include #include #include "neslib.h" +#pragma bss-name (push,"ZEROPAGE") +unsigned char oam_off; +#pragma bss-name (pop) + +#pragma data-name (push,"CHARS") +#pragma data-name(pop) + //#link "tileset1.c" extern unsigned char palSprites[16]; extern unsigned char TILESET[8*256]; - #define COLS 32 #define ROWS 28 +#define NTADR(x,y) ((0x2000|((y)<<5)|(x))) + typedef unsigned char byte; typedef signed char sbyte; typedef unsigned short word; @@ -27,25 +34,68 @@ typedef unsigned short word; // back to the start of the frame. byte getchar(byte x, byte y) { // compute VRAM read address - word addr = 0x2020+x+y*32; + word addr = NTADR(x,y); byte rd; // wait for VBLANK to start waitvsync(); - // set VRAM read address in PPU - PPU.vram.address = addr>>8; - PPU.vram.address = addr&0xff; - // read the char from PPUDATA - rd = PPU.vram.data; // discard - rd = PPU.vram.data; // keep this one - // reset the VRAM address to start of frame - PPU.vram.address = 0x00; - PPU.vram.address = 0x00; - // return result - return rd; + vram_adr(addr); + vram_read(&rd, 1); + vram_adr(0x0); + return rd + 0x20; +} + +// VRAM UPDATE BUFFER + +byte updbuf[64]; +byte updptr = 0; + +void cendbuf() { + updbuf[updptr] = NT_UPD_EOF; +} + +void cflushnow() { + cendbuf(); + waitvsync(); + flush_vram_update(updbuf); + updptr = 0; + cendbuf(); + vram_adr(0x0); } void vdelay(byte count) { - while (count--) waitvsync(); + while (count--) cflushnow(); +} + +void cputcxy(byte x, byte y, char ch) { + word addr = NTADR(x,y); + if (updptr >= 60) cflushnow(); + updbuf[updptr++] = addr >> 8; + updbuf[updptr++] = addr & 0xff; + updbuf[updptr++] = ch - 0x20; + cendbuf(); +} + +void cputsxy(byte x, byte y, char* str) { + word addr = NTADR(x,y); + byte len = strlen(str); + if (updptr >= 60 - len) cflushnow(); + updbuf[updptr++] = (addr >> 8) | NT_UPD_HORZ; + updbuf[updptr++] = addr & 0xff; + updbuf[updptr++] = len; + while (len--) { + updbuf[updptr++] = *str++ - 0x20; + } + cendbuf(); +} + +void clrscr() { + updptr = 0; + cendbuf(); + ppu_off(); + vram_adr(0x2000); + vram_fill(0, 32*28); + vram_adr(0x0); + ppu_on_bg(); } ////////// GAME DATA @@ -63,7 +113,8 @@ typedef struct { Player players[2]; -byte credits = 0; +byte attract; +byte gameover; byte frames_per_move; #define START_SPEED 12 @@ -72,7 +123,7 @@ byte frames_per_move; /////////// -const char BOX_CHARS[8] = { 17, 8, 20, 18, 11, 11, 14, 14 }; +const char BOX_CHARS[8] = { '+','+','+','+','-','-','!','!' }; void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) { byte x1 = x; @@ -91,11 +142,15 @@ void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) { } void draw_playfield() { - draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS); - cputsxy(0,0,"Plyr1:"); - cputsxy(20,0,"Plyr2:"); - cputcxy(7,0,players[0].score+'0'); - cputcxy(27,0,players[1].score+'0'); + draw_box(1,2,COLS-2,ROWS-1,BOX_CHARS); + cputcxy(9,1,players[0].score+'0'); + cputcxy(28,1,players[1].score+'0'); + if (attract) { + cputsxy(5,ROWS-1,"ATTRACT MODE - PRESS 1"); + } else { + cputsxy(1,1,"PLYR1:"); + cputsxy(20,1,"PLYR2:"); + } } typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t; @@ -106,8 +161,8 @@ void init_game() { memset(players, 0, sizeof(players)); players[0].head_attr = '1'; players[1].head_attr = '2'; - players[0].tail_attr = 1; - players[1].tail_attr = 9; + players[0].tail_attr = '#'; + players[1].tail_attr = '*'; frames_per_move = START_SPEED; } @@ -136,8 +191,12 @@ void move_player(Player* p) { void human_control(Player* p) { byte dir = 0xff; byte joy; - if (!p->human) return; joy = joy_read (JOY_1); + // start game if attract mode + if (attract && (joy & JOY_START_MASK)) + gameover = 1; + // do not allow movement unless human player + if (!p->human) return; if (joy & JOY_LEFT_MASK) dir = D_LEFT; if (joy & JOY_RIGHT_MASK) dir = D_RIGHT; if (joy & JOY_UP_MASK) dir = D_UP; @@ -175,8 +234,6 @@ void ai_control(Player* p) { } } -byte gameover; - void flash_colliders() { byte i; // flash players that collided @@ -219,13 +276,13 @@ void declare_winner(byte winner) { gameover = 1; } -#define AE(a,b,c,d) (((a)<<0)|((b)<<2)|((c)<<4)|((d)<<6)) +#define AE(tl,tr,bl,br) (((tl)<<0)|((tr)<<2)|((bl)<<4)|((br)<<6)) // this is attribute table data, // each 2 bits defines a color palette // for a 16x16 box const unsigned char Attrib_Table[0x40]={ -AE(3,3,1,1),AE(3,3,1,1),AE(3,3,1,1),AE(3,3,1,1), AE(2,2,1,1),AE(2,2,1,1),AE(2,2,1,1),AE(2,2,1,1), +AE(3,3,1,0),AE(3,3,0,0),AE(3,3,0,0),AE(3,3,0,0), AE(2,2,0,0),AE(2,2,0,0),AE(2,2,0,0),AE(2,2,0,1), AE(1,0,1,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0), AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,1,0,1), AE(1,0,1,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0), AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,1,0,1), AE(1,0,1,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0), AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,1,0,1), @@ -235,24 +292,37 @@ AE(1,0,1,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0), AE(0,0,0,0),AE(0,0,0,0),AE(0,0, AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1), AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1), }; +// this is palette data +const unsigned char Palette_Table[16]={ + 0x02, + 0x31,0x31,0x31,0x00, + 0x34,0x34,0x34,0x00, + 0x39,0x39,0x39,0x00, +}; + // put 8x8 grid of palette entries into the PPU void setup_attrib_table() { - byte index; - waitvsync(); // wait for VBLANK - PPU.vram.address = 0x23; - PPU.vram.address = 0xc0; - for( index = 0; index < 0x40; ++index ){ - PPU.vram.data = Attrib_Table[index]; - } + vram_adr(0x23c0); + vram_write(Attrib_Table, 0x40); +} + +void setup_palette() { + int i; + // only set palette entries 0-15 (background only) + for (i=0; i<15; i++) + pal_col(i, Palette_Table[i] ^ attract); } void play_round() { - reset_players(); - clrscr(); + ppu_off(); setup_attrib_table(); + setup_palette(); + clrscr(); draw_playfield(); + reset_players(); while (1) { make_move(); + if (gameover) return; // attract mode -> start if (players[0].collided || players[1].collided) break; } flash_colliders(); @@ -273,14 +343,21 @@ void play_round() { void play_game() { gameover = 0; init_game(); - players[0].human = 1; + if (!attract) + players[0].human = 1; while (!gameover) { play_round(); } } void main() { - vram_write((unsigned char*)TILESET, 0x0, sizeof(TILESET)); + vram_adr(0x0); + vram_write((unsigned char*)TILESET, sizeof(TILESET)); joy_install (joy_static_stddrv); - play_game(); + while (1) { + attract = 1; + play_game(); + attract = 0; + play_game(); + } } diff --git a/presets/nes/skeleton.dasm b/presets/nes/skeleton.dasm new file mode 100644 index 00000000..09f6d651 --- /dev/null +++ b/presets/nes/skeleton.dasm @@ -0,0 +1,46 @@ + + include "nesdefs.asm" + +;;;;; VARIABLES + + seg.u RAM + org $0 + +;;;;; NES CARTRIDGE HEADER + + NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, vertical + +;;;;; START OF CODE + +Start: + NES_INIT ; set up stack pointer, turn off PPU + jsr WaitSync ; wait for VSYNC + jsr ClearRAM ; clear RAM + jsr WaitSync ; wait for VSYNC (and PPU warmup) + + lda #$3f ; $3F -> A register + ldy #$00 ; $00 -> Y register + sta PPU_ADDR ; write high byte first + sty PPU_ADDR ; $3F00 -> PPU address + lda #$1c ; $1C = light blue color + sta PPU_DATA ; $1C -> PPU data + lda #CTRL_NMI + sta PPU_CTRL ; enable NMI + lda #MASK_COLOR + sta PPU_MASK ; enable rendering +.endless + jmp .endless ; endless loop + +;;;;; COMMON SUBROUTINES + + include "nesppu.asm" + +;;;;; INTERRUPT HANDLERS + +NMIHandler: + rti + +;;;;; CPU VECTORS + + NES_VECTORS + diff --git a/presets/vicdual/asmtest.s b/presets/vicdual/asmtest.s new file mode 100644 index 00000000..e9b5233f --- /dev/null +++ b/presets/vicdual/asmtest.s @@ -0,0 +1,135 @@ +.area _HOME +.area _CODE +.area _INITIALIZER +.area _DATA +.area _INITIALIZED +.area _BSEG +.area _BSS +.area _HEAP +;-------------------------------------------------------- +; File Created by SDCC : free open source ANSI-C Compiler +; Version 3.6.5 # (UNIX) +;-------------------------------------------------------- + .module minimal + .optsdcc -mz80 + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- + .globl _start + .globl _tileram + .globl _cellram + .globl _main +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +_palette = 0x0040 +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + .area _DATA +_cellram = 0xe000 +_tileram = 0xe800 +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + .area _INITIALIZED +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- + .area _DABS (ABS) +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- + .area _HOME + .area _GSINIT + .area _GSFINAL + .area _GSINIT +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- + .area _HOME + .area _HOME +;-------------------------------------------------------- +; code +;-------------------------------------------------------- + .area _CODE +;:15: +; --------------------------------- +; Function start +; --------------------------------- +_start:: +;:19: + LD SP,#0xE800 ; set up stack pointer + DI ; disable interrupts +;:20: + jp _main +;:23: +; --------------------------------- +; Function main +; --------------------------------- +_main:: +;:26: + ld a,#0x01 + out (_palette),a +;:27: + ld hl,#_tileram + ld (hl), #0xfe + ld e, l + ld d, h + inc de + ld bc, #0x07ff + ldir +;:28: + ld hl,#_cellram + ld (hl), #0x00 + ld e, l + ld d, h + inc de + ld bc, #0x07ff + ldir +;:29: + ld c,#0x00 +;:30: +00112$: + ld a,c + rlca + rlca + rlca + and a,#0xf8 + ld e,a + ld d,#0x00 +00106$: +;:31: + ld l,d + ld h,#0x00 + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + ld a,#<(_cellram) + add a, l + ld l,a + ld a,#>(_cellram) + adc a, h + ld h,a + ld b,#0x00 + add hl, bc + ld (hl),e +;:30: + inc d + ld a,d + sub a, #0x20 + jr C,00106$ +;:29: + inc c + ld a,c + sub a, #0x20 + jr C,00112$ +;:34: +00104$: + jr 00104$ + .area _CODE + .area _INITIALIZER + .area _CABS (ABS) diff --git a/src/pixed/pixeleditor.ts b/src/pixed/pixeleditor.ts index 147f0f71..e6508923 100644 --- a/src/pixed/pixeleditor.ts +++ b/src/pixed/pixeleditor.ts @@ -332,6 +332,7 @@ function convertBytesToImages(bytes, fmt) { } function convertImagesToBytes(images, fmt) { + if (fmt.destfmt) fmt = fmt.destfmt; var width = fmt.w; var height = fmt.h; var count = fmt.count || 1; diff --git a/src/platform/nes.js b/src/platform/nes.js index 12685e15..54d77cbb 100644 --- a/src/platform/nes.js +++ b/src/platform/nes.js @@ -12,6 +12,7 @@ var JSNES_PRESETS = [ {id:'neslib4.c', name:'Metasprites'}, {id:'neslib5.c', name:'RLE Unpack'}, {id:'siegegame.c', name:'Siege Game'}, + {id:'shoot2.c', name:'Solarian Game'}, ]; var NES_NESLIB_PRESETS = [ diff --git a/src/project.ts b/src/project.ts index 4ad43f23..c8b0ac07 100644 --- a/src/project.ts +++ b/src/project.ts @@ -92,9 +92,10 @@ export class CodeProject { var linkfiles = this.parseLinkDependencies(text); var allfiles = includes.concat(linkfiles); this.loadFiles(allfiles, (err:string, result?:Dependency[]) => { + // set 'link' property on files that are link dependencies (must match filename) if (result) for (var dep of result) - dep.link = linkfiles.indexOf(dep.filename) >= 0; + dep.link = linkfiles.indexOf(dep.filename) >= 0 || linkfiles.indexOf('local/'+dep.filename) >= 0; //TODO!!! callback(err, result); }); } diff --git a/src/views.ts b/src/views.ts index 0127f221..8bff2d03 100644 --- a/src/views.ts +++ b/src/views.ts @@ -184,6 +184,7 @@ export class SourceEditor implements ProjectView { var insnstr = info.insns.length > 9 ? ("...") : info.insns; this.setGutter("gutter-bytes", info.line-1, insnstr); if (info.iscode) { + // TODO: labels trick this part? var opcode = parseInt(info.insns.split(" ")[0], 16); if (platform.getOpcodeMetadata) { var meta = platform.getOpcodeMetadata(opcode, info.offset); @@ -415,7 +416,18 @@ export class DisassemblerView implements ProjectView { bytes += hex(platform.readAddress(a+i)); while (bytes.length < 14) bytes += ' '; - var dline = hex(parseInt(a)) + "\t" + bytes + "\t" + disasm.line + "\n"; + var dstr = disasm.line; + if (addr2symbol) { + dstr = dstr.replace(/([^#])[$]([0-9A-F]+)/, (substr:string, ...args:any[]):string => { + var addr = parseInt(args[1], 16); + var sym = addr2symbol[addr]; + if (sym) return (args[0] + sym); + sym = addr2symbol[addr+1]; + if (sym) return (args[0] + sym + "+1"); + return substr; + }); + } + var dline = hex(parseInt(a)) + "\t" + bytes + "\t" + dstr + "\n"; s += dline; if (a == pc) selline = curline; curline++; diff --git a/src/worker/lib/nes/crt0.o b/src/worker/lib/nes/crt0.o new file mode 100644 index 00000000..7e8c327f Binary files /dev/null and b/src/worker/lib/nes/crt0.o differ diff --git a/src/worker/workermain.js b/src/worker/workermain.js index 25d8ab66..a01935e0 100644 --- a/src/worker/workermain.js +++ b/src/worker/workermain.js @@ -105,7 +105,13 @@ var PLATFORM_PARAMS = { 'nes': { //TODO define: '__NES__', cfgfile: 'neslib.cfg', - libargs: ['neslib.lib', 'nes.lib'], + libargs: ['crt0.o', 'nes.lib', + '-D', 'NES_MAPPER=0', + '-D', 'NES_PRG_BANKS=2', + '-D', 'NES_CHR_BANKS=0', // TODO: >0 doesn't seem to work + '-D', 'NES_MIRRORING=0', + ], + extrafiles: ['crt0.o'], }, 'nes-conio': { cfgfile: 'nes.cfg', @@ -247,6 +253,28 @@ function populateFiles(step, fs, options) { } } +function populateExtraFiles(step, fs) { + // TODO: cache extra files + var extrafiles = step.params.extrafiles; + if (extrafiles) { + for (var i=0; i