What is everything?

Someone asked me to explain all the files. Let’s try to do that. Look at the most complicated one.

https://github.com/nesdoug/26_Full_Game

in BG/

The .tmx files are from tiled map editor. Tiled uses the Metatiles.png and Sprites.png files to as its tileset, and the exported tilemaps are the .csv files. You can’t import a csv into a c project, so I wrote some python scripts to convert .csv files into .c files. Two different python files, one for background and one for sprites, so all the .c files with “SP” are sprite object lists.

All the .c files are included into the project.

in BUILD/

The .nes file is our game that can be run in an emulator.

The .s file is the assembly generated by the cc65 compiler, just in case you want to debug by looking though the ASM.

The labels.txt file is a list of all the addresses of every label in the code. You can also use this for debugging, by setting breakpoints for these addresses.

in LIB/

is all the neslib files (neslib.h and neslib.s) and all the funtions that I wrote (nesdoug.h and nesdoug.s). The .s files are included in crt0.s near the bottom. The .h files are included in the main c file.

in MUSIC/

The .ftm files are Famitracker 0.4.6 files. 1 for music and 1 for sfx. The music file was exported as a .txt file (included here) and processed with text2data (from Shiru’s famitone2 files) into TestMusic3.s. The sfx was exported as .nsf (Nintendo Sound Format) and then processed with nsf2data (also famitone2) into SoundFx.s.

famitone2.s is the famitone code (again, Shiru’s website). All the .s files are included somewhere in crt0.s. If we had DPCM samples, they would also be included in crt0.s in the “SAMPLES” segment.

in NES_ST/

The .nss files are NES Screen Tool 2.3 files. I saved one (title) as a .h compressed RLE, which the game includes and decompresses. I made a .nss file with all the kinds of block in the game (metatiles), and save to .nam (uncompressed list of the entire screen), which meta.py python script converted into a C array in metatiles.txt. Also I did a print screen from both the metatile.nss and sprite.nss files and cropped down in GIMP and save those as the .png files up in the BG/ folder (used by tiled map editor).

The other files are…

License.txt – just the MIT licence

Sprites.h – arrays of all the metasprite definitions, generated by NES Screen Tool (or by hand, which is sometimes faster)

compile.bat – to recompile the project (on Windows)

crt0.s – is all the startup code, but also a convenient place to include asm or binary files.

full_game.c – the game code. I like to use notepad++ to write my code.

full_game.chr – the graphics file, split into 2 sections, the 256 BG tiles, and the 256 Sprite tiles.

full_game.h – variables and constants and prototypes, and some constant arrays

level_data.c – lists of game data and things included for each level

nrom_32k_vert.cfg – the linker file for ld65, tells where each segment goes in the final binary.

screenshot26.png – just a picture of the game.


And some more info on compile.bat

This is a list of command line inputs for compiling the game from scratch. If you change the name of your project, change set name=full_game” to match the main code filename. Or you can change this line

cc65 -Oirs %name%.c –add-source

to

cc65 -Oirs filename.c –add-source

where filename is the name of the .c file. You can process multiple C files this way, just make sure to also use ca65 to convert each .s file into a .o object file.

-Oirs are optimizations.

–add-source tells it to put the source code in comments in the asm file.

If you have multiple object files you need to change the linker (ld65) line to list every .o file.

ld65 -C nrom_32k_vert.cfg -o %name%.nes crt0.o %name%.o nes.lib -Ln labels.txt

to

ld65 -C nrom_32k_vert.cfg -o targetname.nes crt0.o file1.o file2.o file3.o nes.lib -Ln labels.txt

-o blah tell it what to name the output file.

If you use cl65 instead of cc65/ca65/ld65, then make sure to set target = NES. It sets a strange default target, which does not use standard ASCII encoding.

del *.o deletes the object files.

move /Y labels.txt BUILD\
move /Y %name%.s BUILD\
move /Y %name%.nes BUILD\

moves these files into the BUILD folder

BUILD\%name%.nes

just runs the game, which is in the BUILD folder.

 

Hope this helps.

 

 

Advertisements

22. Zapper / Power Pad

Zapper

cof

The zapper gun came with many NES consoles. They are pretty common, but you need a CRT TV for them to work. You can also play on most emulators using the mouse to click on the screen (make sure you set the 2nd player input to “zapper”).

It is possible to play a modified game on an non-CRT TV using a Tommee brand Zapp Gun. You would need to add a 3-4 frame delay in the code, since LCD screens typically have 3-4 frames of lag. You couldn’t play the standard Duck Hunt, but some people have been working on modifying zapper games to have a delay before reading the zapper.

Ok, so we’ve all seen Duck Hunt. Do you know how it works?

DuckHunt3

The game reads the 2nd player port until it gets a signal that the trigger has been pulled. Once that happens, it blacks out the background and replaces 1 object per frame with a big white blob. If there are 2 objects on screen, it will display the first object on 1 frame and the other object on the next frame… to tell which object you hit (if any).

Duck Hunt uses 32×32 pixel box for standard ducks (4 sprites by 4 sprites). Which is about the size you want for a medium level difficulty. Other games had much bigger things to shoot and much bigger white boxes. To vary the difficulty, they would then change the amount of time that the target was on screen.

DuckHunt1

Duck Hunt used 24×16 pixel box for clay pidgeons. (3 wide by 2 high). Which is kind of difficult to hit. 24×24 is a little more reasonable, and that’s what I used.

DuckHunt2

I had to write a different controller reading routine, due to the zapper using completely different pins than the standard controllers. I threw in this zaplib.s and zablib.h files.

zap_shoot(1) takes 1 arg, 0 for port 1, 1 for port 2. And, it returns 0 or 1 if it reads the trigger has been pulled.

I also checked to make sure the last frame didn’t also have trigger pulled.

zapper_ready = pad2_zapper^1;

zapper_ready is just the opposite of the last frame. That’s a bitwise XOR, if you’re not familiar with the caret operator “^”.

So when we get that signal, I turn off the BG… ppu_mask(0x16); and draw a white box where the star was… draw_box();

0x16 is 0001 0110 in binary, see the xxxx 0xxx bit is zero. That’s the “show BG” bit. It’s off, but the sprites are still on.

Then immediately, I turn the BG back on, ppu_mask(0x1e); so the flicker is minimized.

0x1e is standard display. 0001 1110 in binary has the xxxx 1xxx bit active again.

And I call zap_read(1) takes 1 arg, 0 for port 1, 1 for port 2.

which is a loop that waits till it either gets a signal that the gun sees white, or that the end of the frame has been reached. It returns 0 for fail and 1 for success.

I tested this on a real CRT on a real NES, and it seems to work fine at 5 ft. This game uses port 2 for the zapper, which is kind of standard. But, you could make a game that uses port 1, if you wanted to. zaplib.s will have to be included in crt0.s and zaplib.h will have to be included in your main c file.

screenshot28

https://github.com/nesdoug/28_Zapper

Also see the wiki for more technical info.

https://wiki.nesdev.com/w/index.php/Zapper

 

 

Power Pad

PowerPad

The Power Pad is a little less standard. There weren’t many games that used it. Just like the zapper, the Power Pad uses different pins than the standard controller, so I had to rewrite the code that reads the input. See padlib.s and padlib.h.

read_powerpad(1) takes 1 arg, 0 for port 1, 1 for port 2.

And, it returns a 2 byte value (unsigned int). And I made these contants to represent each foot pad.

#define POWERPAD_4 0x8000
#define POWERPAD_2 0x4000
#define POWERPAD_3 0x2000
#define POWERPAD_1 0x1000
#define POWERPAD_12 0x0800
#define POWERPAD_5 0x0400
#define POWERPAD_8 0x0200
#define POWERPAD_9 0x0100

#define POWERPAD_6 0x0040
#define POWERPAD_10 0x0010
#define POWERPAD_11 0x0004
#define POWERPAD_7 0x0001

padlib.s will have to be included in crt0.s and padlib.h will have to be included in your main c file. This was tested on a real Power Pad on a real NES.

screenshot29

https://github.com/nesdoug/29_Powerpad

Also see the wiki for more technical info.

https://wiki.nesdev.com/w/index.php/Power_Pad

 

21. Finished Platformer

First thing I added was a title screen. To be honest, I made this as quickly as possible, just to show the proof of concept. I made it in NES Screen Tool, and exported the background as a compressed RLE .h file “title.h”. So the title mode waits for the user to press start, and cycles the color a bit to be a little less boring.

26_full_game1

temp1 = get_frame_count();
temp1 = (temp1 >> 3) & 3;
pal_col(3,title_color_rotate[temp1]);

title_color_rotate is an array of 4 possible colors.

Now, I didn’t like making 1 room at a time, so I made it so you could have 1 long Tiled file, and export it to csv, and convert it to arrays with CSV2C_BIG.py.

26_Tiled

(I had it auto generate an array of pointers at the bottom, but I didn’t end up using those, so I delete them, and instead made 1 larger array of pointers, with all levels in it).

const unsigned char * const Levels_list[]={
Level1_0,Level1_1,Level1_2,Level1_3,Level1_4,Level1_5,Level1_6,Level1_7,
Level2_0,Level2_1,Level2_2,Level2_3,Level2_4,Level2_5,Level2_6,Level2_7,
Level3_0,Level3_1,Level3_2,Level3_3,Level3_4,Level3_5,Level3_6,Level3_7
};

I am using 2 kinds of enemies and 2 kinds of coins.

And then, I made a picture with all the Sprite objects on it (with transparency for background), and imported that as a separate tileset in Tiled, and added another layer, where the Sprite objects are placed. I placed the enemies on that 2nd layer (as tiles), and exported another csv file. Then I wrote another .py file “CSV2C_SP.py” to convert those into arrays.

26_Tiled2

Well, I didn’t end up using it exactly like this. It mixes the coins and the enemies, and I want them in separate arrays. So, I cut and pasted the different kinds of objects into 2 different arrays. But the .py file is helpful, and definitely sped this up.

These arrays might need to be edited slightly, like if we need coins at a different X offset from the tile grid.

 

Again, I made 2 kinds of enemies. The chasers now collide with walls. I was going to use the same code that the hero used, but decided it was too slow to check many objects this way, so I wrote a much simpler one.

bg_collision_fast(). This only checks 2 points instead of 4.

The chaser code isn’t very smart, they only move X and never change Y. If you put them on a platform, they would float right off it like a ghost. Maybe in the future I will edit this with improved enemy move logic, so he won’t float off a platform, but rather change directions, or fall, or something.

The other enemy is the bouncer. He just bounces up and down. He checks the floor below when falling, to stop exactly at the floor point, reusing the same code from the hero checking the floor.

bg_check_low();

The second kind of coin is just an end-of-level marker. I suppose we could have added some cool sound fx for reaching the end of the level, or an animation. That would have been nice. Currently, it just fades to black in the switch mode.

Oh, yeah. I added more modes. More game states. title, game, pause, end, switch (transition from one level to another). These are fairly obvious as how they work.

Debugging wasn’t too bad. Mostly I was worried about running past the frame and getting slowdown. I was testing code by placing gray_line() around functions. This helped me speed up things. I combined some of the enemy steps to speed them up. And I would put a gray_line() at the end of the game logic to see how far down on the screen we were. Here’s one of the tests, back when I thought I was going to use sprite zero hit and a HUD above.

full_game_debug

We don’t want to make our enemy logic too much more complex, nor put too many objects on the same screen, or we might get slow down, so we need to test as we go, and see how many enemies we can fit on a screen before it crawls to a halt. I think we can handle 7 or 8. That’s more than I need, so we’re still ok.

And finally, I put the # of coins as sprites in the top left. I didn’t put it too high up, where it might get cut off on some old TVs. 16 pixels down is fine.

Oh, almost forgot. The sprite shuffing code. Remember from the Sprite page, I mentioned that you can only have 8 sprites per horizontal line? Well, since that is a possibility, we must add some kind of shuffling to the position of each object inside the OAM buffer, so that we don’t have an enemy disappear entirely.

The simplest way to do this would be to change the starting position each frame. Instead of sprid = 0, you would do sprid = rand8() * 4, or something like that. It wouldn’t be very good, though.

I decided to go through the list of enemies in a different order each frame (and keep sprid = 0 at the top of the sprite drawing code).

const unsigned char shuffle_array[]={
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15,
15,13,11,9,7,5,3,1,14,12,10,8,6,4,2,0
};

So, the first pass, it goes forward 0-15. The second pass it goes in reverse. The 3rd pass it does even then odds. The 4th pass, reverse that. This would break immediately if we changed the # of enemies, so it could use some improvement. Also, I’m not shuffling coins, so I have to make sure there aren’t too many coins on the same horizontal line.

And here’s our working game, with 3 levels, 8 rooms each. This could have been expanded a bit. It takes about 2000 bytes per level. We have about 16000 bytes left, so we could have added 7-8 more levels… so maybe 10 levels total. If we needed more than that, we would need to think about a different mapper, or maybe some kind of compression.

26_full_game2

https://github.com/nesdoug/26_Full_Game/blob/master/full_game.c

https://github.com/nesdoug/26_Full_Game

 

And, that’s all. Go make some games.

 

Links and Misc.

Here’s some example codes from Shiru’s website…(the link near the top that says “these small example programs” ).

https://shiru.untergrund.net/articles/programming_nes_games_in_c.htm

I have a copy that works with the version I’ve been using for the past 2 years, cc65 version 2.15

http://dl.dropboxusercontent.com/s/j80n6b9gfjntfip/cc65_examples.zip

 

You can import a MIDI file to famitracker (an older version). I discussed it on this post.

https://nesdoug.com/2016/01/24/25-importing-a-midi-to-famitracker/

You can download the famitracker here (4.2 is the last version that imported MIDI)

http://famitracker.com/downloads.php

.

Other projects in C.

Mojon Twins

https://github.com/mojontwins/MK1_NES

.

cppchriscpp

https://github.com/cppchriscpp/nes-starter-kit

.

.

.

I wrote 2 unofficial updates to the famitone music driver. NOTE. I fixed the bugs (I think).

famitone3.3, which adds all notes and a volume column (sacrifices some efficiency in size and speed).

https://github.com/nesdoug/famitone3.3

And famitone4.1, which adds 1xx, 2xx, and 4xx effect support.

https://github.com/nesdoug/famitone4.1

I have used these in some of my games. Jammin Honey and Flappy Jack, for example.

I added some other features and bug fixes, which I put in the original version also…

https://github.com/nesdoug/famitone2d

Changes:
-added song names to file output
-added command line switch -allin prevents removal of unused instruments
-added command line switch -Wno suppresses warnings about unsupported effects

Bugfixes:
-multiple D00 effects (different channels) incorrect pattern length
-Bxx below D00 effect (different channels) incorrect pattern length
-Bxx loop back causing wrong instrument inserted at loop point

example of new switches:
text2vol filename.txt -ca65 -allin -Wno

 

Downloads, free games

All the .nes files from this tutorial

https://github.com/nesdoug/27_NES_FILES

 

Purple Cape Man, Vigilante Ninja

http://dl.dropboxusercontent.com/s/0hnvrxix0kkoz5e/VIGD.NES

VIGD2

.

Vigilante Ninja 2

Full Game! Revised.

(hold A+B+Select on option menu for “gameboy mode”)

http://dl.dropboxusercontent.com/s/13w29q1azmyafni/Vig2-Full-revA.nes

Old Demo

http://dl.dropboxusercontent.com/s/2ipv0bgxllf1z55/Vig2-DEMO.nes

http://dl.dropboxusercontent.com/s/dw5fnwh11he26xj/VigNinjaManual4.pdf

vig2_lv4-1

.

Spacy Shooty (the example code from the old tutorial)

http://dl.dropboxusercontent.com/s/4em2jpto45ds9tr/SPACY4.nes

spacy4

.

Talk NES (speech synthesizer)

http://dl.dropboxusercontent.com/s/58d3igz64p5x7md/TalkNES4.zip

talkNES3M

.

Flappy Jack

http://dl.dropboxusercontent.com/s/k3tpdfr5rj11e7s/flappy14.nes

flappy14

.

Rock Paper Scissors (Lizard Sbock)

http://dl.dropboxusercontent.com/s/fnv35n959f58dvq/Rock9b.nes

Rock9b

.

Jammin Honey

http://dl.dropboxusercontent.com/s/3gkv6onxfxypt53/JamminHoney.nes

JamminHoneyGame

.

Euchre (for 2018 nesdev competition)

http://dl.dropboxusercontent.com/s/n7etap76mkw33bm/Euchre.nes

Euchre-0

(note, only Jammin Honey and Euchre were written in C).

 

Appendix, nesdoug library

Under construction.

 

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

20. Platformer Again

I decided not to use a split screen. I was really nervous that we were going to get slowdown once we added enemies and coins, which would (with my setup) make the screen wildly go back and forth, and look terrible.

I left the split screen out, and we don’t need to worry about slowdown (having more game logic than can fit in a frame).

Now that we put the music and sound fx in, let’s add some enemies and coins to our platformer. We can use our coin sfx for collision with coins, and noise sfx for collision with enemies.

I drew some simple enemies in yy chr, and made some metasprite definitions. I could have used NES Screen Tool, but since these are fairly simple, I just cut and pasted and edited the tile # from another similar metasprite.

25_YY

It would have been nice to use an array of structs to define everything, but the 6502 is too slow. The faster way is to use a lot of char arrays, all smaller than 256 bytes, like this.

#define MAX_COINS 16
unsigned char coin_x[MAX_COINS];
unsigned char coin_y[MAX_COINS];
unsigned char coin_active[MAX_COINS];
unsigned char coin_room[MAX_COINS];
unsigned char coin_actual_x[MAX_COINS];

I even sped up the object initial code, to point out how you can make faster code by only putting 1 array per line of code. The 6502 processor only can do 1 pointer at a time, so the compiler shoves the other one in the c stack, and then does a whole dance around it, 5 times slower.

So instead of…

coin_y[index] = pointer[index2];

I did this…

temp1 = pointer[index2]; // get a byte of data
coin_y[index] = temp1;

Believe it or not, this compiles to faster code. We have to think about speed optimization, if we want a scrolling game with multiple moving objects. (And no slow down).

So, every frame, I check to see if each object is in range (on screen), and mark them “active”. I only move them if active, I only check collision if active, and I only draw them to screen if active.

check_spr_objects() checks each object to see if they are on screen, and marks them active, if true.

Right now the movement code is terribly simple. The chasers just see if the hero X is greater than theirs, and heads toward the hero. I will try to make this a little better next time.

Currently, I am using y=0xff as “doesn’t exist” (TURN_OFF). So, turning off an enemy is handled by putting their Y to 0xff. this could be handled differently, but that’s what I chose. It works as long as we don’t need enemies jumping in from below the screen.

One more thing I started to do, was add game states. I added Pause mode, which changes the song, and nothing moves, but I am darkening the screen by setting the color emphasis bits. This was something built into the NES PPU. Flipping a color emphasis will emphasize a color by darkening the other colors. The red bit will darken blue and green. If you set them all, it darkens all the color, just a little bit.

color_emphasis(COL_EMP_NORMAL);

25_platformer5

color_emphasis(COL_EMP_DARK);

25_platformer5b

https://github.com/nesdoug/25_Platform5/blob/master/platformer5.c

https://github.com/nesdoug/25_Platform5

Now that we have the it basically working, we will make some real levels. Next time… Sorry the link below doesn’t go to the next page, try this link…

https://nesdoug.com/2018/09/11/21-finished-platformer/