I thought this would take me 5 minutes. Boy was I wrong. Here’s some examples on neslib use for NES development. I’ve made some changes, that will probably annoy everyone. Sorry.
I changed the cfg, moving the symbols to crt0.s, adding ONCE segment
I changed PAD_STATE to _PAD_STATE in crt0.s (etc), so I can access it from c code as
extern unsigned char PAD_STATE;
I made slight changes to neslib.s (notably removing _ppu_wait_frame as potentially buggy with split screen effects)
The first example is a simple “Hello World”. Note, I have arrays of chars called “PALETTE” and “TEXT”. As stated in an earlier blog post, I have created a tile set that positions the letters and numbers exactly in their ASCII position, so I can reference them with actual letters in the code “Hello World!”.
This is how to write to the screen with rendering OFF. Set an address, vram_adr(), then write, vram_write().
void main (void) {
// rendering is disabled at the startup
// the init code set the palette brightness to
// pal_bright(4); // normal
// load the palette
pal_bg(PALETTE);
// load the text
// vram_adr(NTADR_A(x,y));
vram_adr(NTADR_A(10,14)); // screen is 32 x 30 tiles
// this sets a start position on the BG, where to draw the text, left to right
vram_write((unsigned char*)TEXT,sizeof(TEXT));
// this draws the array to the screen
// this function only works with rendering off, and should come after vram_adr()
// normally, I would reset the scroll position
// but the next function waits till v-blank and scroll is set automatically in the nmi routine
// since the RAM was blanked to 0 in init code, scroll variables will be x = 0, y = 0
// turn on screen
ppu_on_all();
// infinite loop
while (1){
// game code will go here.
}
};
Pretty straightforward way to write to the screen with rendering off. Here’s the source code.
http://dl.dropboxusercontent.com/s/5p8o0umed5k10r5/lesson21.zip

Part 2
This “Hello World” writes 1 letter at a time, then blanks it, and starts over. This is how to write to the screen when rendering is ON.
In this example, I am writing to the screen in 2 different ways, with rendering on. With rendering on, you will write data to a buffer, and set a pointer to that data. The nmi code will automatically push the data to the screen during v-blank.
Both of them are examples of set_vram_update(). The first, non-sequential data. This will write the letter A and the letter B at different screen locations.
// example of non-sequential vram data
const unsigned char TWOLETTERS[]={
MSB(NTADR_A(10,17)),
LSB(NTADR_A(10,17)),
‘A’,
MSB(NTADR_A(18,5)),
LSB(NTADR_A(18,5)),
‘B’,
NT_UPD_EOF}; // data must end in EOF
The second, using the CLEAR array, is a sequential data set. It will write 12 zeros to the screen, covering over the “Hello World!” when the loop ends. NT_UPD_HORZ or NT_UPD_VERT is required to tell the vram update to go sequentially.
// example of sequential vram data
const unsigned char CLEAR[]={
MSB(NTADR_A(10,14))|NT_UPD_HORZ, // where to write, repeat horizontally
LSB(NTADR_A(10,14)),
12, // length of write
0,0,0,0, // what to write there
0,0,0,0, // data needs to be exactly the size of length
0,0,0,0,
NT_UPD_EOF}; // data must end in EOF
And, I’m actually constructing a data set on the fly, when pushing letters of “Hello World!” one at a time to the screen.
v_ram_buffer[0] = high;
v_ram_buffer[1] = low;
data = TEXT[text_Position]; // get 1 letter of the text
v_ram_buffer[2] = data;
v_ram_buffer[3] = NT_UPD_EOF;
This is also an example of delay(), which waits a certain number of frames, before moving to the next line. Here’s the main code (with some comments edited out).
void main (void) {
// load the palette
pal_bg(PALETTE);
// set some initial values
text_Position = 0;
// turn on screen
ppu_on_all();
// load some non-sequential vram data, during rendering
memcpy(v_ram_buffer,TWOLETTERS,sizeof(TWOLETTERS)); // copy from the ROM to the RAM
set_vram_update(v_ram_buffer); // this just sets a pointer to the data, and sets a flag to draw it next v-blank
// works only when NMI is on
// infinite loop
while (1){
delay(30); // wait 30 frames = 0.5 seconds
address = NTADR_A(10,14) + text_Position; // 2 bytes wide
high = (char)(address >> 8); // get just the upper byte
low = (char)(address & 0xff); // get just the lower byte
v_ram_buffer[0] = high;
v_ram_buffer[1] = low;
data = TEXT[text_Position]; // get 1 letter of the text
v_ram_buffer[2] = data;
v_ram_buffer[3] = NT_UPD_EOF;
++text_Position;
if (text_Position >= sizeof(TEXT)){
text_Position = 0;
ppu_wait_frame();
memcpy(v_ram_buffer,CLEAR,sizeof(CLEAR)); // if at end, clear screen
// by overwriting zeros over the text
}
set_vram_update(v_ram_buffer); // set a pointer to the buffer
// it will auto-update during v-blank
}
};
So, step 1, fill the v_ram_buffer. Step 2, set_vram_update(v_ram_buffer); will set a pointer to the data and set a flag to push the data to the PPU during the next v-blank.
Note: set_vram_update(NULL); will disable v-ram updates.
And, here it the source code…
http://dl.dropboxusercontent.com/s/cupgyz9bg8ibjny/lesson22.zip
