diff --git a/presets/nes/horizscroll.c b/presets/nes/horizscroll.c new file mode 100644 index 00000000..1f210cec --- /dev/null +++ b/presets/nes/horizscroll.c @@ -0,0 +1,227 @@ + +/* +We demonstrate horizontal scrolling of two nametables. +Vertical mirroring is set, so nametables A and B are +to the left and right of each other. + +New playfield data is randomly generated and updated +offscreen using the vrambuf module. +We update the nametable in 16-pixel-wide vertical strips, +using 2x2 blocks of tiles ("metatiles"). + +We also use the split() function to create a status bar. +*/ + +#include "neslib.h" +#include + +// 0 = horizontal mirroring +// 1 = vertical mirroring +#define NES_MIRRORING 1 + +// VRAM update buffer +#include "vrambuf.h" +//#link "vrambuf.c" + +// link the pattern table into CHR ROM +//#link "chr_generic.s" + +/// GLOBAL VARIABLES + +word x_scroll; // X scroll amount in pixels +byte seg_height; // segment height in metatiles +byte seg_width; // segment width in metatiles +byte seg_char; // character to draw +byte seg_palette; // attribute table value + +// number of rows in scrolling playfield (without status bar) +#define PLAYROWS 24 + +// buffers that hold vertical slices of nametable data +char ntbuf1[PLAYROWS]; // left side +char ntbuf2[PLAYROWS]; // right side + +// a vertical slice of attribute table entries +char attrbuf[PLAYROWS/4]; + +/// FUNCTIONS + +// convert from nametable address to attribute table address +word nt2attraddr(word a) { + return (a & 0x2c00) | 0x3c0 | + ((a >> 4) & 0x38) | ((a >> 2) & 0x07); +} + +// generate new random segment +void new_segment() { + seg_height = (rand8() & 3) + 1; + seg_width = (rand8() & 3) + 1; + seg_palette = rand8() & 3; + seg_char = 0xf4; +} + +// draw metatile into nametable buffers +// y is the metatile coordinate (row * 2) +// ch is the starting tile index in the pattern table +void set_metatile(byte y, byte ch) { + ntbuf1[y*2] = ch; + ntbuf1[y*2+1] = ch+1; + ntbuf2[y*2] = ch+2; + ntbuf2[y*2+1] = ch+3; +} + +// set attribute table entry in attrbuf +// x and y are metatile coordinates +// pal is the index to set +void set_attr_entry(byte x, byte y, byte pal) { + if (y&1) pal <<= 4; + if (x&1) pal <<= 2; + attrbuf[y/2] |= pal; +} + +// fill ntbuf with tile data +// x = metatile coordinate +void fill_buffer(byte x) { + byte i,y; + // clear nametable buffers + memset(ntbuf1, 0, sizeof(ntbuf1)); + memset(ntbuf2, 0, sizeof(ntbuf2)); + // draw a random star + ntbuf1[rand8() & 15] = '.'; + // draw segment slice to both nametable buffers + for (i=0; i