{"id":113,"date":"2018-03-03T09:07:21","date_gmt":"2018-03-03T09:07:21","guid":{"rendered":"https:\/\/www.betelge.com\/blog\/?p=113"},"modified":"2018-03-03T11:02:16","modified_gmt":"2018-03-03T11:02:16","slug":"making-an-8-bit-nes-game-part-1-a-minimal-rom","status":"publish","type":"post","link":"https:\/\/www.betelge.com\/blog\/2018\/03\/03\/making-an-8-bit-nes-game-part-1-a-minimal-rom\/","title":{"rendered":"Making an 8-bit NES game (Part 1): A minimal ROM"},"content":{"rendered":"<p>Can we start with a completely empty source file, compile it to a NES ROM and run it in an emulator? Let&#8217;s try!<\/p>\n<p>Create an empty plain text file <code>game.s<\/code> and save it in a folder. It now needs to be compiled with <code>ca65<\/code> and linked with <code>ld65<\/code>. Let&#8217;s see what happens.<\/p>\n<p>If you don&#8217;t know what <code>ca65<\/code> and <code>ld65<\/code> are, check out <a href=\"https:\/\/www.betelge.com\/blog\/2018\/03\/03\/making-an-8-bit-nes-game-part-0-tools-needed\/\">Part 0: Tools needed<\/a>.<\/p>\n<p>Start with compiling the source file into an object file.<\/p>\n<p><code>ca65 game.s<\/code><\/p>\n<p>No error and a 251 byte <code>game.o<\/code> was created. Good so far! Now link the object file.<\/p>\n<p><code>ld65 game.o<br \/>\nld65: Error: Memory configuration missing<\/code><\/p>\n<p>So, the <code>cc65<\/code>\u00a0tools can build binaries for a bunch of different 6502 based systems with different memory layouts, the NES being just one of them.<\/p>\n<p>Usually you&#8217;d now need to write a detailed memory map configuration file. Luckily we don&#8217;t have to do any of that, since there is already one for the NES bundled with the compiler.<\/p>\n<p>I&#8217;ll go into more technical details later on, for now let&#8217;s postpone learning about the memory layout and just get this thing working.<\/p>\n<p>To use the bundled config file just specify <code>nes<\/code> as the system type. And let&#8217;s also name our output file.<\/p>\n<p><code>ld65 -t nes game.o -o game.nes<\/code><code><br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `HEADER' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `STARTUP' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `VECTORS' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `CHARS' does not exist<\/code><\/p>\n<p>A few warnings, but no errors, and a 40976 byte game.nes containing all zeroes was created.<\/p>\n<p>Let&#8217;s try running it in the emualtor<\/p>\n<p><code>fceux.exe game.nes<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-121\" src=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-300x278.png\" alt=\"\" width=\"300\" height=\"278\" srcset=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-300x278.png 300w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-324x300.png 324w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error.png 335w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Alright, so we&#8217;re missing something. Not surprising since the ROM contains all zeroes.<\/p>\n<p>ROMs need to start with the NES header. And the NES header starts with 4 specific bytes, the ASCII characters NES and the hexadecimal value 1A.<\/p>\n<p>Add the following to <code>game.s<\/code><\/p>\n<pre>.byte \"NES\"\r\n.byte $1A<\/pre>\n<p>And try again<\/p>\n<p><code>ca65 game.s<br \/>\nld65 -t nes game.o -o game.nes<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `HEADER' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `STARTUP' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `VECTORS' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `CHARS' does not exist<br \/>\nfceux.exe game.nes<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-121\" src=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-300x278.png\" alt=\"\" width=\"300\" height=\"278\" srcset=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-300x278.png 300w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error-324x300.png 324w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux_error.png 335w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Same warnings and same error.<\/p>\n<p>Something is wrong. Examining <code>game.nes<\/code> in a hex editor we see this:<br \/>\n<code>00000000   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................<br \/>\n00000010   4E 45 53 1A  00 00 00 00  00 00 00 00  00 00 00 00  NES.............<br \/>\n<\/code><\/p>\n<p>That&#8217;s strange! Our header is in there, but not at the start of the file. Instead it somehow ended up at offset $10, after 16 bytes of zeroes.<\/p>\n<p>To investigate I opened up <code>nes.cfg<\/code>, the NES memory map configuration that came with cc65 and found this.<\/p>\n<p><code>    # INES Cartridge Header<br \/>\nHEADER: file = %O, start = $0000, size = $0010, fill = yes;<br \/>\n<\/code><\/p>\n<p>So the first 16 bytes are reserved for the header, and to use them we have to put our assembly into the HEADER segment. Should have known not to ignore those warnings.<\/p>\n<p>Segments are parts of the code and data that end up in different specific areas of RAM and ROM. In the source file they are specified as <code>.segment \"SEGMEMT_NAME\"<\/code>.<\/p>\n<p>This is our new <code>game.s<\/code> that specifies that our 4 bytes go into the HEADER segment.<\/p>\n<pre>.segment \"HEADER\"\r\n    .byte \"NES\"\r\n    .byte $1A\r\n<\/pre>\n<p>Try this again now.<\/p>\n<p><code>ca65 game.s<br \/>\nld65 -t nes game.o -o game.nes<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `STARTUP' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `VECTORS' does not exist<br \/>\nld65: Warning: (...)\/nes.cfg(63): Segment `CHARS' does not exist<\/code><\/p>\n<p>Ooh! One less warning this time.<\/p>\n<p>And this is what <code>game.nes<\/code> looks like in the hex editor.<\/p>\n<p><code>00000000   4E 45 53 1A  00 00 00 00  00 00 00 00  00 00 00 00  NES.............<br \/>\n00000010   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................<\/code><\/p>\n<p>Nice, the header is in the right place. The rest of the file is all zeroes.<\/p>\n<p>Let&#8217;s run it in the emulator<\/p>\n<p><code>fceux.exe game.nes<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-123\" src=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux-grey-300x278.png\" alt=\"\" width=\"300\" height=\"278\" srcset=\"https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux-grey-300x278.png 300w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux-grey-324x300.png 324w, https:\/\/www.betelge.com\/blog\/wp-content\/uploads\/2018\/03\/fceux-grey.png 335w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>It works!<\/p>\n<p>I realise this is a post about a making a ROM that doesn&#8217;t even contain any code and just draws a gray background.<\/p>\n<p>It&#8217;s not useless though. This is now a ready template to fill with code and we know how to compile it.<\/p>\n<p>Finally let&#8217;s just add those missing segments to get rid of the remaining warnings.<\/p>\n<p>This is what <code>game.s<\/code> looks like in the end<\/p>\n<pre>.segment \"HEADER\"\r\n    .byte \"NES\"\r\n    .byte $1A\r\n\r\n.segment \"STARTUP\"\r\n\r\n.segment \"VECTORS\"\r\n\r\n.segment \"CHARS\"<\/pre>\n<p>In the next part we&#8217;ll actually be putting something on the screen and we&#8217;ll have to talk about the different segments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Can we start with a completely empty source file, compile it to a NES ROM and run it in an emulator? Let&#8217;s try! Create an empty plain text file game.s and save it in a folder. It now needs to &hellip; <a href=\"https:\/\/www.betelge.com\/blog\/2018\/03\/03\/making-an-8-bit-nes-game-part-1-a-minimal-rom\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-113","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/posts\/113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/comments?post=113"}],"version-history":[{"count":10,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/posts\/113\/revisions"}],"predecessor-version":[{"id":144,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/posts\/113\/revisions\/144"}],"wp:attachment":[{"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/media?parent=113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/categories?post=113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.betelge.com\/blog\/wp-json\/wp\/v2\/tags?post=113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}