new neslib2.lib (from clbr/neslib) using extrafiles parameter, local .h, disasm uses symbols
This commit is contained in:
parent
4a82d341bc
commit
b29f11a1cc
|
@ -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');
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 <string.h>
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -0,0 +1,808 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <nes.h>
|
||||
#include <joystick.h>
|
||||
|
||||
#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; i<NSPRITES; i++) {
|
||||
Sprite* spr = &vsprites[i];
|
||||
if (spr->y != 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; i<NMISSILES; i++) {
|
||||
Missile* mis = &missiles[i];
|
||||
if (mis->ypos != 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; i<NSPRITES; i++) {
|
||||
vsprites[i].y = YOFFSCREEN;
|
||||
}
|
||||
for (i=0; i<NMISSILES; i++) {
|
||||
missiles[i].ypos = YOFFSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_formation() {
|
||||
byte i;
|
||||
memset(formation, 0, sizeof(formation));
|
||||
memset(attackers, 0, sizeof(attackers));
|
||||
for (i=0; i<MAX_IN_FORMATION; i++) {
|
||||
byte flagship = i < ENEMIES_PER_ROW;
|
||||
formation[i].shape = flagship ? SDST_FORM1 : SDST_FORM1;
|
||||
}
|
||||
enemies_left = MAX_IN_FORMATION;
|
||||
formation_offset_x = 8;
|
||||
}
|
||||
|
||||
void draw_row(byte row) {
|
||||
static char buf[32];
|
||||
byte i;
|
||||
byte x = formation_offset_x / 8;
|
||||
byte xd = (formation_offset_x & 7) * 3;
|
||||
byte y = 3 + row * 2;
|
||||
for (i=0; i<x; i++)
|
||||
buf[i] = BLANK;
|
||||
for (i=0; i<ENEMIES_PER_ROW; i++) {
|
||||
byte shape = formation[i + row*ENEMIES_PER_ROW].shape;
|
||||
if (shape) {
|
||||
shape += xd;
|
||||
buf[x] = shape;
|
||||
buf[x+1] = shape+1;
|
||||
buf[x+2] = shape+2;
|
||||
} else {
|
||||
buf[x] = buf[x+1] = buf[x+2] = BLANK;
|
||||
}
|
||||
x += 3;
|
||||
}
|
||||
for (; x<COLS; x++)
|
||||
buf[x] = BLANK;
|
||||
putbytes(0, y, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void draw_next_row() {
|
||||
draw_row(current_row);
|
||||
if (++current_row == ENEMY_ROWS) {
|
||||
current_row = 0;
|
||||
formation_offset_x += formation_direction;
|
||||
if (formation_offset_x == 63) {
|
||||
formation_direction = -1;
|
||||
}
|
||||
else if (formation_offset_x == 8) {
|
||||
formation_direction = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FLIPX 0x40
|
||||
#define FLIPY 0x80
|
||||
#define FLIPXY 0xc0
|
||||
|
||||
const byte DIR_TO_CODE[32] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 6,
|
||||
6|FLIPXY, 6|FLIPXY, 5|FLIPXY, 4|FLIPXY, 3|FLIPXY, 2|FLIPXY, 1|FLIPXY, 0|FLIPXY,
|
||||
0|FLIPX, 1|FLIPX, 2|FLIPX, 3|FLIPX, 4|FLIPX, 5|FLIPX, 6|FLIPX, 6|FLIPX,
|
||||
6|FLIPY, 6|FLIPY, 5|FLIPY, 4|FLIPY, 3|FLIPY, 2|FLIPY, 1|FLIPY, 0|FLIPY,
|
||||
};
|
||||
|
||||
const byte SINTBL[32] = {
|
||||
0, 25, 49, 71, 90, 106, 117, 125,
|
||||
127, 125, 117, 106, 90, 71, 49, 25,
|
||||
0, -25, -49, -71, -90, -106, -117, -125,
|
||||
-127, -125, -117, -106, -90, -71, -49, -25,
|
||||
};
|
||||
|
||||
signed char isin(byte dir) {
|
||||
return SINTBL[dir & 31];
|
||||
}
|
||||
|
||||
signed char icos(byte dir) {
|
||||
return isin(dir+8);
|
||||
}
|
||||
|
||||
#define FORMATION_X0 0
|
||||
#define FORMATION_Y0 19
|
||||
#define FORMATION_XSPACE 24
|
||||
#define FORMATION_YSPACE 16
|
||||
|
||||
byte get_attacker_x(byte formation_index) {
|
||||
byte column = (formation_index % ENEMIES_PER_ROW);
|
||||
return FORMATION_XSPACE*column + FORMATION_X0 + formation_offset_x;
|
||||
}
|
||||
|
||||
byte get_attacker_y(byte formation_index) {
|
||||
byte row = formation_index / ENEMIES_PER_ROW;
|
||||
return FORMATION_YSPACE*row + FORMATION_Y0;
|
||||
}
|
||||
|
||||
void draw_attacker(byte i) {
|
||||
AttackingEnemy* a = &attackers[i];
|
||||
if (a->findex) {
|
||||
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; i<MAX_ATTACKERS; i++) {
|
||||
draw_attacker(i);
|
||||
}
|
||||
}
|
||||
|
||||
void return_attacker(AttackingEnemy* a) {
|
||||
byte fi = a->findex-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; i<MAX_ATTACKERS; i++) {
|
||||
AttackingEnemy* a = &attackers[i];
|
||||
if (a->findex) {
|
||||
if (a->returning)
|
||||
return_attacker(a);
|
||||
else
|
||||
fly_attacker(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void think_attackers() {
|
||||
byte i;
|
||||
for (i=0; i<MAX_ATTACKERS; i++) {
|
||||
AttackingEnemy* a = &attackers[i];
|
||||
if (a->findex) {
|
||||
// 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; i<MAX_ATTACKERS; i++) {
|
||||
AttackingEnemy* a = &attackers[i];
|
||||
if (a->findex == 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; i<MAX_ATTACKERS; i++) {
|
||||
AttackingEnemy* a = &attackers[i];
|
||||
if (a->findex && 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<MAX_ATTACKERS; i++) {
|
||||
if (missiles[i].ypos != YOFFSCREEN &&
|
||||
in_rect(missiles[i].xpos + 8, missiles[i].ypos + 16,
|
||||
player_x, player_y, 16, 16)) {
|
||||
player_exploding = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void new_attack_wave() {
|
||||
byte i = rand();
|
||||
byte j;
|
||||
// find a random slot that has an enemy
|
||||
for (j=0; j<MAX_IN_FORMATION; j++) {
|
||||
i = (i+1) & (MAX_IN_FORMATION-1);
|
||||
// anyone there?
|
||||
if (formation[i].shape) {
|
||||
formation_to_attacker(i);
|
||||
formation_to_attacker(i+1);
|
||||
formation_to_attacker(i+ENEMIES_PER_ROW);
|
||||
formation_to_attacker(i+ENEMIES_PER_ROW+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void new_player_ship() {
|
||||
player_exploding = 0;
|
||||
player_x = 120;
|
||||
draw_player();
|
||||
}
|
||||
|
||||
void set_sounds() {
|
||||
/*
|
||||
byte i;
|
||||
// missile fire sound
|
||||
if (missiles[7].ypos != YOFFSCREEN) {
|
||||
cv_set_frequency(CV_SOUNDCHANNEL_0, 2000-missiles[7].ypos*4);
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_0, 18);
|
||||
} else {
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_0, 32);
|
||||
}
|
||||
// enemy explosion sound
|
||||
if (enemy_exploding) {
|
||||
cv_set_frequency(CV_SOUNDCHANNEL_1, 500+enemy_exploding*64);
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_1, 14);
|
||||
} else {
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_1, 32);
|
||||
}
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_2, 32);
|
||||
// player explosion
|
||||
if (player_exploding && player_exploding < 15) {
|
||||
cv_set_frequency(CV_SOUNDCHANNEL_2, player_exploding*256);
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 4+player_exploding);
|
||||
cv_set_noise(true, 3);
|
||||
} else {
|
||||
// set diving sounds for spaceships
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 32);
|
||||
for (i=0; i<3; i++) {
|
||||
byte y = attackers[i].y >> 8;
|
||||
if (y >= 0x80) {
|
||||
cv_set_frequency(CV_SOUNDCHANNEL_2, 4000+y*8);
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_2, 28);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
@ -1,21 +1,28 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <nes.h>
|
||||
#include <joystick.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
;<stdin>:15:
|
||||
; ---------------------------------
|
||||
; Function start
|
||||
; ---------------------------------
|
||||
_start::
|
||||
;<stdin>:19:
|
||||
LD SP,#0xE800 ; set up stack pointer
|
||||
DI ; disable interrupts
|
||||
;<stdin>:20:
|
||||
jp _main
|
||||
;<stdin>:23:
|
||||
; ---------------------------------
|
||||
; Function main
|
||||
; ---------------------------------
|
||||
_main::
|
||||
;<stdin>:26:
|
||||
ld a,#0x01
|
||||
out (_palette),a
|
||||
;<stdin>:27:
|
||||
ld hl,#_tileram
|
||||
ld (hl), #0xfe
|
||||
ld e, l
|
||||
ld d, h
|
||||
inc de
|
||||
ld bc, #0x07ff
|
||||
ldir
|
||||
;<stdin>:28:
|
||||
ld hl,#_cellram
|
||||
ld (hl), #0x00
|
||||
ld e, l
|
||||
ld d, h
|
||||
inc de
|
||||
ld bc, #0x07ff
|
||||
ldir
|
||||
;<stdin>:29:
|
||||
ld c,#0x00
|
||||
;<stdin>:30:
|
||||
00112$:
|
||||
ld a,c
|
||||
rlca
|
||||
rlca
|
||||
rlca
|
||||
and a,#0xf8
|
||||
ld e,a
|
||||
ld d,#0x00
|
||||
00106$:
|
||||
;<stdin>: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
|
||||
;<stdin>:30:
|
||||
inc d
|
||||
ld a,d
|
||||
sub a, #0x20
|
||||
jr C,00106$
|
||||
;<stdin>:29:
|
||||
inc c
|
||||
ld a,c
|
||||
sub a, #0x20
|
||||
jr C,00112$
|
||||
;<stdin>:34:
|
||||
00104$:
|
||||
jr 00104$
|
||||
.area _CODE
|
||||
.area _INITIALIZER
|
||||
.area _CABS (ABS)
|
|
@ -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;
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
14
src/views.ts
14
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++;
|
||||
|
|
Binary file not shown.
|
@ -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<extrafiles.length; i++) {
|
||||
var xfn = extrafiles[i];
|
||||
var xpath = "lib/" + step.platform + "/" + xfn;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.open("GET", xpath, false); // synchronous request
|
||||
xhr.send(null);
|
||||
if (xhr.response && xhr.status == 200) {
|
||||
var data = new Uint8Array(xhr.response);
|
||||
fs.writeFile(xfn, data, {encoding:'binary'});
|
||||
console.log(":::",xfn);
|
||||
} else {
|
||||
throw Error("Could not load extra file " + xpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function staleFiles(step, targets) {
|
||||
if (!step.maxts) throw "call populateFiles() first";
|
||||
// see if any target files are more recent than inputs
|
||||
|
@ -698,6 +726,7 @@ function linkLD65(step) {
|
|||
var cfgfile = '/' + platform + '.cfg';
|
||||
setupFS(FS, '65-'+platform.split('-')[0]);
|
||||
populateFiles(step, FS);
|
||||
populateExtraFiles(step, FS);
|
||||
var libargs = params.libargs;
|
||||
var args = ['--cfg-path', '/share/cfg',
|
||||
'--lib-path', '/share/lib',
|
||||
|
|
Loading…
Reference in New Issue