{"id":28,"date":"2007-06-29T02:02:03","date_gmt":"2007-06-29T10:02:03","guid":{"rendered":"http:\/\/www.pagetable.com\/?p=28"},"modified":"2007-06-29T02:02:03","modified_gmt":"2007-06-29T10:02:03","slug":"game-development-archeology-zelda-on-game-boy-comes-with-source","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=28","title":{"rendered":"Game Development Archeology: Zelda on Game Boy comes with source"},"content":{"rendered":"<p>Imagine you&#8217;re writing a Game Boy game, and the resulting ROM with all the code and data is just a little over one megabyte in size. No big deal, just pad the game to two megabytes, and use a 2 MB ROM in the cartridge. Just tell the linker to allocate 2 MB or RAM, put the actual data at the beginning, and then write a 2 MB &#8220;.gb&#8221; image to disk, which will then be sent to the ROM chip factory.<\/p>\n<p>Now imagine you&#8217;re doing this in MS-DOS. Your linker, probably written in C, calls malloc() of the runtime library of the C compiler. You already know where this is going?<\/p>\n<p>While modern operating systems will always clear all malloc()ed memory, so that you cannot get to other processes&#8217; data, this was uncommon in the single-user MS-DOS days. If you allocate 2 MB of RAM (the linker must have used a DOS extender or XMS), you&#8217;d get memory with random data in it: leftovers from whatever was in this memory before. (seppel tells me that this can also be caused by seek()ing over EOF in MS-DOS, in which case the previous data on the hard disk will be in the image.)<\/p>\n<p>This is what happened with the 1998 Game Boy\/Game Boy Color game &#8220;The Legend of Zelda &#8211; Link&#8217;s Awakening DX&#8221; (MD5: ee0424cf1523f67c5007566aed70696d). If you look at the image starting at 0x106000, you will find all kinds of interesting data, which will tell you a lot about the game&#8217;s development. Let&#8217;s call this &#8220;game development archeology&#8221;&#8230;<\/p>\n<p>The ROM image includes big chunks of Borland&#8217;s Turbo C IDE (Turbo Vision interface) for DOS, as well as traces of the &#8220;QBasic&#8221; MS-DOS Editor. It is unclear which editor they used for what, but they might have used Turbo C to write DOS code to support building, as there is a complete copy of this C program in the ROM:<\/p>\n<pre>\n#include<stdio.h>\n#include<conio.h>\n\nint main(void) {\n\tFILE *fp,*f1;\n\tint a=0xcd;\n\tint b=0xc6;\n\tint c=0x29;\n\tint ch;\n\tunsigned long i=0;\n\n\tif((fp=fopen(\"zeldag.gb\",\"rb\"))==NULL) {\n\t\tprintf(\"can't open the file\");\n\t\treturn 0;\n\t}\n\n\tif((f1=fopen(\"ttmp.asm\",\"wt\"))==NULL) {\n\t\tprintf(\"can't new file ttmp.asm\");\n\t\treturn 0;\n\t}\n\n\twhile((ch=fgetc(fp))!=EOF) {\n\t\tif(a==ch) {\n\t\t\ti++;\n\t\t\tch=fgetc(fp);\n\t\t\tif(b==ch) {\n\t\t\t\ti++;\n\t\t\t\tch=fgetc(fp);\n\t\t\t\tif(c==ch)\n\t\t\t\t\tfprintf(f1,\"%lXH, \" , i);\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n\n\tfclose(fp);\n\tfclose(f1);\n}\n<\/pre>\n<p>This writes the file offsets at which 0xcd,0xc6,0x29 was found in the ROM image into ttmp.asm. These bytes, interpreted as Z80 machine code, mean &#8220;CALL 0x29C6&#8221;. In the final ROM image, this sequence appears once, at 0x442B. If you have any idea why they look for this, please post it in the comments.<\/p>\n<p>This is the list of files in their project directory at D:GAMEBOY:<br \/>\nBANK37.ASM<br \/>\nCLEARKU.ASM<br \/>\nDAMA1.ASM<br \/>\nDAMA2.ASM<br \/>\nEND.CPP<br \/>\nENDEND.ASM<br \/>\nENDEND.LST<br \/>\nENDEND1.ASM<br \/>\nFEND1.ASM<br \/>\nFEND2.ASM<br \/>\nFEND3.ASM<br \/>\nFIND.ASM<br \/>\nFIND.CPP<br \/>\nIFCHAENL.ASM<br \/>\nINTWCHA.ASM<br \/>\nTEST.ASM<br \/>\nTTMP.ASM<br \/>\nTTMP.TXT<br \/>\nZIPUTP.CPP<\/p>\n<p>These filenames also appear in the ROM:<br \/>\nADDPLAG.ASM<br \/>\nADDPLAGF.ASM<br \/>\nCH64TBL.ASM<br \/>\nFEND.ASM<br \/>\nG.ASM<br \/>\nH.ASM<br \/>\nINSERTKU.ASM<br \/>\nINTWIN.ASM<br \/>\nKKKKKK.ASM<br \/>\nL.ASM<br \/>\nNOPLAY1.ASM<br \/>\nTAB.ASM<br \/>\nY.ASM<br \/>\nZXHPDM.ASM<\/p>\n<p>And here comes the interesting part: There is actually some assembly source in the ROM; here is a small snippet:<\/p>\n<pre>\nJoyPort_1:\n                 AND $02 ;LEFT\n                 JR  NZ, JoyPort_2\n                 CALL LEFTScroll\n                 RET\nJoyPort_2:\n                 AND $04 ;UP\n                 JR  NZ, JoyPort_3\n                 CALL UPScroll\n                 RET\nJoyPort_3:\n                 AND $08 ;DOWN\n                 JR  NZ, JoyPort_4\n                 CALL DOWNScroll\n<\/pre>\n<p>Well-documented, it seems. But there is also some assembly code that looks like this:<\/p>\n<pre>\nL_B000_28F7:\n                LD A,$7F\n                LD BC,$0800\n                LD D,A\n                LD HL,$9800\nL_B000_2900:\n                LD A,D\n                LD (HLI),A\n                DEC BC\n                LD  A,B\n                OR  A,C\n                JR  NZ,L_B000_2900\n                RET\nL_B000_2914:\n                LD  A,(HLI)\n                LD  (DE),A\n                INC DE\n                DEC BC\n                LD  A,B\n                OR  A,C\n                JR  NZ,L_B000_2914\n                RET\n<\/pre>\n<p>The label names suggest that this code has been disassembled from existing Z80 machine code. Link&#8217;s Awakening DX is a color remake of an older Game Boy game, so it might very well be that they lost the original source, disassembled the old code and used it again for the remake. This could be easily proven by disassembling the original version and looking for this code.<\/p>\n<p>If you want to do game development archeology yourself, you might want to look at titles like &#8220;X-Men &#8211; Wolverine&#8217;s Rage&#8221; (MD5: b1729716baaea01d4baa795db31800b0), which contains Windows 9x registry keys and INF files, &#8220;Mortal Kombat 4&#8221; (MD5: 7311f937a542baadf113e9115158cde3), in which you can find some small source fragments, &#8220;Gift&#8221; (MD5: e6a51088c8fea7980649064bd3a9f9ff), which will tell you that the developers had some Game Boy emulators installed on their system, or the &#8220;BIT-MANAGERS&#8221; games &#8220;Spirou&#8221; (MD5:5aa012cf540a5267d6adea6659764441, Turbo C, MAP file, source) and &#8220;TinTin in Tibet&#8221; (Game Boy Color version, MD5: 8150a3978211939d367f48ffcd49f979), which, amongst other things, contains references to Nintendo&#8217;s Game Boy Advance (!) SDK (&#8220;C:Cygnusthumbelf-000512H-i686-cygwin32libgcc-libthumb-elf2.9-arm-000512&#8221;, &#8220;\/tantor\/build\/nintendo\/arm-000512\/i686-cygwin32\/src\/newlib\/libc\/stdio\/stdio.c&#8221;).<\/p>\n<p>If you find any more things like these, please post them (or links to your stories) as comments! Happy hacking!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine you&#8217;re writing a Game Boy game, and the resulting ROM with all the code and data is just a little over one megabyte in size. No big deal, just pad the game to two megabytes, and use a 2 MB ROM in the cartridge. Just tell the linker to allocate 2 MB or RAM, &#8230; <a title=\"Game Development Archeology: Zelda on Game Boy comes with source\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=28\" aria-label=\"Read more about Game Development Archeology: Zelda on Game Boy comes with source\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,14,33],"tags":[],"class_list":["post-28","post","type-post","status-publish","format-standard","hentry","category-archeology","category-game-boy","category-trivia"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/28","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=28"}],"version-history":[{"count":0,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/28\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=28"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=28"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}