/* 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