Appendix, nesdoug library

Appendix, nesdoug library

//Written by Doug Fraker 2018 void set_vram_buffer(void); // sets the vram update to point to the vram_buffer. VRAM_BUF defined in crt0.s // this can be undone by set_vram_update(NULL)

void __fastcall__ one_vram_buffer(unsigned char data, int ppu_address); // to push a single byte write to the vram_buffer

void __fastcall__ multi_vram_buffer_horz(const char * data, unsigned char len, int ppu_address); // to push multiple writes as one sequential horizontal write to the vram_buffer

void __fastcall__ multi_vram_buffer_vert(const char * data, unsigned char len, int ppu_address); // to push multiple writes as one sequential vertical write to the vram_buffer

void clear_vram_buffer(void); // just sets the index into the vram buffer to zero // this should be done at the beginning of each frame, if using the vram_buffer

unsigned char __fastcall__ get_pad_new(unsigned char pad); // pad 0 or 1, use AFTER pad_poll() to get the trigger / new button presses // more efficient than pad_trigger, which runs the entire pad_poll code again

unsigned char __fastcall__ get_frame_count(void); // use this internal value to time events, this ticks up every frame

void __fastcall__ set_music_speed(unsigned char tempo); // this will alter the tempo of music, range 1-12 are reasonable, low is faster // default is 6 // music_play also sets the tempo, and any Fxx effect in the song will too // you will probably have to repeatedly set_music_speed() every frame // music_stop() and music_pause() also overwrite this value

unsigned char __fastcall__ check_collision(void * object1, void * object2); // expects an object (struct) where the first 4 bytes are X, Y, width, height // you will probably have to pass the address of the object like &object // the struct can be bigger than 4 bytes, as long as the first 4 bytes are X, Y, width, height

void __fastcall__ pal_fade_to(unsigned char from, unsigned char to); // adapted from Shiru’s “Chase” game code // values must be 0-8, 0 = all black, 8 = all white, 4 = normal

void __fastcall__ set_scroll_x(unsigned int x); // x can be in the range 0-0x1ff, but any value would be fine, it discards higher bits

void __fastcall__ set_scroll_y(unsigned int y); // y can be in the range 0-0x1ff, but any value would be fine, it discards higher bits // NOTE – different system than neslib (which needs y in range 0-0x1df) // the advantage here, is you can set Y scroll to 0xff (-1) to shift the screen down 1, // which aligns it with sprites, which are shifted down 1 pixel

int __fastcall__ add_scroll_y(unsigned char add, unsigned int scroll); // add a value to y scroll, keep the low byte in the 0-0xef range // returns y scroll, which will have to be passed to set_scroll_y

int __fastcall__ sub_scroll_y(unsigned char sub, unsigned int scroll); // subtract a value from y scroll, keep the low byte in the 0-0xef range // returns y scroll, which will have to be passed to set_scroll_y

int __fastcall__ get_ppu_addr(char nt, char x, char y); // gets a ppu address from x and y coordinates (in pixels) // x is screen pixels 0-255, y is screen pixels 0-239, nt is nametable 0-3

int __fastcall__ get_at_addr(char nt, char x, char y); // gets a ppu address in the attribute table from x and y coordinates (in pixels) // x is screen pixels 0-255, y is screen pixels 0-239, nt is nametable 0-3 // the next 4 functions are for my metatile system, as described in my tutorial // nesdoug.com

void __fastcall__ set_data_pointer(const char * data); // for the metatile system, pass it the addresses of the room data // room data should be exactly 240 bytes (16×15) // each byte represents a 16×16 px block of the screen

void __fastcall__ set_mt_pointer(const char * metatiles); // for the metatile system, pass it the addresses of the metatile data // a metatile is a 16×16 px block // metatiles is variable length, 5 bytes per metatile… // TopL, TopR, BottomL, BottomR, then 1 byte of palette 0-3 // max metatiles = 51 (because 51 x 5 = 255)

void __fastcall__ buffer_1_mt(int ppu_address, char metatile); // will push 1 metatile and 0 attribute bytes to the vram_buffer // make sure to set_vram_buffer(), and clear_vram_buffer(), // and set_mt_pointer() // “metatile” should be 0-50, like the metatile data

void __fastcall__ buffer_4_mt(int ppu_address, char index); // will push 4 metatiles (2×2 box) and 1 attribute byte to the vram_buffer // this affects a 32×32 px area of the screen, and pushes 17 bytes to the vram_buffer. // make sure to set_vram_buffer(), and clear_vram_buffer(), // set_data_pointer(), and set_mt_pointer() // “index” is which starting byte in the room data, to convert to tiles. // use index = (y & 0xf0) + (x >> 4); where x 0-255 and y 0-239; // index should be 0-239, like the room data it represents

void flush_vram_update_nmi(void); // same as flush_vram_update, but assumes that a pointer to the vram has been set already // this is for when the screen is OFF, but you still want to write to the PPU // with the vram_buffer system // “nmi” is a misnomer. this doesn’t have to happen during nmi.

void __fastcall__ color_emphasis(char color); // change the PPU’s color emphasis bits

`#define COL_EMP_BLUE 0x80

define COL_EMP_GREEN 0x40

define COL_EMP_RED 0x20

define COL_EMP_NORMAL 0x00

define COL_EMP_DARK 0xe0`

void __fastcall__ xy_split(unsigned int x, unsigned int y); // a version of split that actually changes the y scroll midscreen // requires a sprite zero hit, or will crash

void gray_line(void); // For debugging. Insert at the end of the game loop, to see how much frame is left. // Will print a gray line on the screen. Distance to the bottom = how much is left. // No line, possibly means that you are in v-blank.

`#define high_byte(a) ((unsigned char)&a+1)

define low_byte(a) ((unsigned char)&a)

// for getting or modifying just 1 byte of an int`

`#define POKE(addr,val) ((unsigned char) (addr) = (val))

define PEEK(addr) ((unsigned char) (addr))

// examples // POKE(0xD800, 0x12); // stores 0x12 at address 0xd800, useful for hardware registers // B = PEEK(0xD800); // read a value from address 0xd800, into B, which should be a char`

void seed_rng(void); // get from the frame count. You can use a button (start on title screen) to trigger

Last updated