Jekyll2020-07-03T10:31:00+02:00https://painsperdus.github.io/gboi-rocket/feed.xmlThe Gameboy of IsaacA coding journey on Nitendo Gameboy. The goal of this project is to recreate the famous game "The Binding of Isaac" on the original Gameboy, in assembly. Team RocketFinal release ?2020-07-02T00:00:00+02:002020-07-02T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/final-release<p>Hey everyone,</p>
<p>Wondered what we did during the last few days when we didn’t post anything ? We worked hard, very hard to finish what we wanted for our deadline.</p>
<p>Now this deadline has passed and we wanted to share what we achieved. To sum up, we have :</p>
<ul>
<li>Annimations</li>
<li>Music</li>
<li>Sound FX</li>
<li>Levels</li>
<li>Ennemies</li>
<li>Title screen</li>
<li>Game over screen</li>
<li>Working tears</li>
</ul>
<p>Now, how does it look ? How does it sound ?</p>
<p>Well, let’s see … (you can download the <a href="https://github.com/PainsPerdus/gboi-rocket/releases/tag/v1.0">ROM</a> )</p>
<h2 id="annimations">Annimations</h2>
<p>Thanks to the wonderful work of Pascal and Virgile, we have working annimations !</p>
<p>Isaac walking :</p>
<p><img src="../../assets/images/gboi_walking.gif" alt="walking" /></p>
<p>Flies :</p>
<p><img src="../../assets/images/gboi_flies.gif" alt="flies" /></p>
<h2 id="music">Music</h2>
<p>Melissa did the wonderful and tiresome work of transcribing the score made by Noel, our piano teacher, of the “Sacrificial” music, to our own custom format. I designed the sound driver and programmed most of it though the core code is still Melissa’s.
Listen yourself :</p>
<audio controls="">
<source src="../../assets/gameboy_of_isaac_soundtrack.mp3" type="audio/mpeg" />
<p>Link to the audio file as your browser doesn't support audio embeddings : <a href="../../assets/gameboy_of_isaac_soundtrack.mp3">link</a> .</p>
</audio>
<h2 id="sound-fx">Sound FX</h2>
<p>Melissa found some intersting Sound FX, and I tweaked and ported them to the game and made it work with our preexisting music driver.</p>
<p>Start effect :</p>
<audio controls="">
<source src="../../assets/gboi_start.mp3" type="audio/mpeg" />
<p>Link to the audio file as your browser doesn't support audio embeddings : <a href="../../assets/gboi_start.mp3">link</a> .</p>
</audio>
<p>Hit by ennemy :</p>
<audio controls="">
<source src="../../assets/gboi_hurt.mp3" type="audio/mpeg" />
<p>Link to the audio file as your browser doesn't support audio embeddings : <a href="../../assets/gboi_hurt.mp3">link</a> .</p>
</audio>
<p>Ennemy hit :</p>
<audio controls="">
<source src="../../assets/gboi_tear.mp3" type="audio/mpeg" />
<p>Link to the audio file as your browser doesn't support audio embeddings : <a href="../../assets/gboi_tear.mp3">link</a> .</p>
</audio>
<h2 id="levels">Levels</h2>
<p>If you go through the trapdoor, you end up in another level (in which the only thing you can do is die, but shhhhhht). Thanks to Thomas for the amazing work he did on level loading and Melissa for her work on the level generation algorithm.
I also implemented the RNG for this feature, though it ended up being used mostly elsewhere.</p>
<h3 id="rooms">Rooms</h3>
<p>But what are levels if you cannot switch between rooms ? Thanks to Thomas’s work for room loading and Melissa for writing the room files.</p>
<p><img src="../../assets/images/gboi_rooms2.gif" alt="rooms" /></p>
<h2 id="ennemies">Ennemies</h2>
<p>Now, the game would be quite boring without something to do, some challenge to accomplish. Well, the ennemies (only flies for now) are here to help you out on that one. Thanks for Jean-Marie for his work on collisions and ennemy movement !</p>
<p>Flies are actively trying to hug you, and as you don’t like hugs, it hurts you.</p>
<p><img src="../../assets/images/gboi_hurt.gif" alt="hurt" /></p>
<h2 id="title-screen">Title screen</h2>
<p>Thanks to Virgile for his state machine and Pascal for his work on graphics, we have a title screen !</p>
<p>See for yourself :</p>
<p><img src="../../assets/images/gboi_start.gif" alt="start" /></p>
<h3 id="game-over-screen">Game over screen</h3>
<p>Not happy with just a title screen, they implemented a “game over” screen ! Take a look :</p>
<p><img src="../../assets/images/gboi_death.gif" alt="death" /></p>
<h2 id="tears">Tears</h2>
<p>Last but not least : tears. What fun would be the game if the only thing you could do to prevent the mean flies from hugging you was to just stand there ? You can cry and shoot your tears to kill them !</p>
<p><img src="../../assets/images/gboi_tears.gif" alt="tears" /></p>
<h2 id="and-now-">And now ?</h2>
<p>For now, we rest. Those last few weeks have been really tiresome and we have other things to do and other things to worry about. But be assured this isn’t the last time you’ll hear about us. We do want to continue this game, at a slower pace, as it was an incredible experience, and we want to keep on messing with the gameboy.</p>
<p>These are our goals for the future :</p>
<ul>
<li>Transition from WLA-DX to RGBDS : WLA-DX is very obscure and we’ve been fighting against it a lot. RGBDS is more open, more documented and we should have less fighting with the assembler, and more fighting against the hardware itself.</li>
<li>More musics for the title screen and game over screen, more sound effects, etc …</li>
<li>More ennemies, as flies are cool, but variety is necessary to prevent the game from being boring. Bosses also are something we think about implementing in the future.</li>
<li>Make the level generation happen at run-time instead of preloading generated maps in the ROM.</li>
<li>ITEMS : isaac needs items to help him fight against his hug-loving foes !</li>
</ul>
<p>As you can see, we are far from finished ! These features will take time to implement, but we’re still stoked about working on this game and we can say with absolute certainty this isn’t the last blog post about this project. In the meantime you can try our game out by dowloading the ROM and run it with the emulator of your choice : <a href="https://github.com/PainsPerdus/gboi-rocket/releases/tag/v1.0">ROM</a> .</p>
<p>A huge shout out to our friends at team kirby, check out their Pineapple of Doom <a href="https://github.com/PainsPerdus/gboi-kirby">there</a> and their blog <a href="https://painsperdus.github.io/gboi-kirby/">here</a></p>
<p>See you !</p>
<p>Dorian, for the team Rocket</p>Dorian BourgeoisatHey everyone,RNG - or how to create randomness from a deterministic computer2020-06-29T00:00:00+02:002020-06-29T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/RNG<p>Hello world,</p>
<p>Today, I worked on implementing a xorshift RNG algorithm for the gameboy. It’s based on <a href="https://github.com/edrosten/8bit_rng">this implementation in C</a>.</p>
<p>Pseudo code corresponding to the assembly version I implemented looks like this :</p>
<pre><code class="language-C">void rng() {
t = x ^ (x << 4);
h = t ^ (t << 1);
x = y;
y = z;
z = a;
a = z ^ (z >> 1);
a = a ^ h
return a
}
</code></pre>
<p>A xorshift algorithm is quite easy to implement, fast (20 instructions), and remarkably good at producing randomness.</p>
<p>The one big flaw I can see is that it stores its state in 4 bytes of memory, which slows it down a little, however, it does help increase the cycle length, which is quite good for such a small algorithm. With an initial state of (0,0,0,1) it would take 2 years to go back where we started, if we generated a number each frame.</p>
<p>Our next goal for this RNG is to find a source of entropy to initialize it, we are leaning towards reading the initial state of the WRAM, but discussions are still taking place.</p>
<p>See ya !</p>
<p>Dorian</p>Dorian BourgeoisatHello world,First Milestone Completed2020-06-27T00:00:00+02:002020-06-27T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/first-milestone-completed<p>We are coding a Game Boy version of The Binding of Isaac. Therefore, we are using the gbZ80 assembly language.</p>
<p>After a little more of a week working on that project, we want to explain to you what have been done and present our prototype. Basically everything that we planned for the first milestone <a href="../first-milestone">here</a> has been achieved, appart from isaac’s tears that are still a work in progress.</p>
<p>First, we wanted to focus on displaying a room and Isaac in order to have a decent working basis. For the moment we achieved to display: a room, its walls and background and obviously, Isaac. It’s possible to interact with him because he reacts to the inputs of the user and can freely walk around to the extent of the obstacles surrounding him. In fact, we have implemented the collision between them.</p>
<p>Check out the possibilities of our project as you wish. You can download the first release <a href="https://github.com/PainsPerdus/gboi-rocket/releases/tag/v0.1">here</a></p>
<p>From now until our next milestone we want to add the tears that Isaac shoots and enemies (at least static). In a more distant future, we want to add diversity among the rooms’ skins, an automatic aim for Isaac’s tears, move from one room to another and mobility to the enemies.</p>
<p><img src="../../assets/images/first_release.png" alt="picture" height="505px" width="339px" class="align-center" /></p>Mélissa BlancheWe are coding a Game Boy version of The Binding of Isaac. Therefore, we are using the gbZ80 assembly language.Day 62020-06-27T00:00:00+02:002020-06-27T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/daily%20update/log-day6<h2 id="day-summary">Day Summary</h2>
<ul>
<li>Virgile and Pascal
<ul>
<li>added the possibility to display rocks</li>
<li>added walls on the edges of the screen
<img src="../../assets/images/06-27-preview.png" alt="preview" height="652px" width="704px" class="align-center" /></li>
<li>started working on displaying tears on the screen, with the challenge of displaying more elements on screen than the GameBoy usually allows</li>
<li>tested the possibility of recycling sprites during the HBlank</li>
</ul>
</li>
<li>Jean-Marie and Thomas
<ul>
<li>step by step implementation of collisions or Isaac : first with one rock, then several rocks, now several elemets blocking or not</li>
<li>added collisions for walls in order to prevent Isaac from leaving the screen</li>
<li>set up the mecanism letting Isaac look in the right direction</li>
<li>refactoring collisions for better performance and in order to allow Isaac to “slide” against a blocking element</li>
</ul>
</li>
<li>Mélissa and Dorian
<ul>
<li>custom version of the score of “Sacrificial” from the original game, adapted to a 2 channel player</li>
<li>first version of the map generation, coded in C</li>
<li>beginning of the translation of the C code into a Assembly code</li>
</ul>
</li>
</ul>Thomas GrenierDay Summary Virgile and Pascal added the possibility to display rocks added walls on the edges of the screen started working on displaying tears on the screen, with the challenge of displaying more elements on screen than the GameBoy usually allows tested the possibility of recycling sprites during the HBlank Jean-Marie and Thomas step by step implementation of collisions or Isaac : first with one rock, then several rocks, now several elemets blocking or not added collisions for walls in order to prevent Isaac from leaving the screen set up the mecanism letting Isaac look in the right direction refactoring collisions for better performance and in order to allow Isaac to “slide” against a blocking element Mélissa and Dorian custom version of the score of “Sacrificial” from the original game, adapted to a 2 channel player first version of the map generation, coded in C beginning of the translation of the C code into a Assembly codeSoftware engineering #3- Progression2020-06-26T00:00:00+02:002020-06-26T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/SE3<p>Ho dear! Oh dear! I shall be too late!,</p>
<p>Ho dear, I’m 3 days late.</p>
<p>Short version:</p>
<ul>
<li>
<p>I spent time in the wla-dx (the assembler) doc to find how the make modular code. And this doc is, well, let’s says it’s lacking some informations. For instance I know there are namespaces, but first the syntax use in the doc doesn’t compile, and second, they are no information about how to access a global value from a namespace. So no namespace. Instead each module has a struct with it’s variables as fields. This struct is implemented once, with the name <code class="language-plaintext highlighter-rouge">my_module_</code>. With this method, the variables can be accessed with <code class="language-plaintext highlighter-rouge">my_module_.my_var</code>. For the label, the modules use child label, which are kinda like sublabels. The only issue here is that defines and struct names are not separated by modules.</p>
</li>
<li>
<p>Then I refactored, again, the pong game to find a good way to cut the code into small and modular files.</p>
</li>
<li>
<p>Now, the <code class="language-plaintext highlighter-rouge">module.var.s</code> contains the definition of the structs and the defines of the module.</p>
</li>
<li>
<p>The variables are declared in the main file, by implementing the main struct of the module (<code class="language-plaintext highlighter-rouge">my_module_</code>) in the enum.</p>
</li>
<li>
<p>During the initialization, the <code class="language-plaintext highlighter-rouge">.init.s</code> files are included. They contain the code of the module that need to be executed only one time.</p>
</li>
<li>
<p>During the VBlanck interruption, the files <code class="language-plaintext highlighter-rouge">display.s</code> and <code class="language-plaintext highlighter-rouge">body.s</code> are called. The other codes that need to be executed on each iteration are included in <code class="language-plaintext highlighter-rouge">body.s</code>. This is because the VBlank time when we can edit the screen is short, so we need to use it before doing a lot of computation.</p>
</li>
<li>
<p>Then we include, at the end of the file, the <code class="language-plaintext highlighter-rouge">.lib.s</code> files, which contains code that is not run directly, like function or sprites.</p>
</li>
</ul>
<p>After defining the structure of the code, I made a canvas for the <code class="language-plaintext highlighter-rouge">ŧesting</code> branch.</p>
<p>Next steep was defining the global variables (Thomas did the structs, I declared the variables). I haded <code class="language-plaintext highlighter-rouge">.stub</code> files to test the code. <code class="language-plaintext highlighter-rouge">.stub</code> are undocumented ugly code, hopefully short, that do stuff like moving the character, or displaying it. Stubs are inefficient and not modular. The main goal for now is to replace them with proper modules.</p>
<p>Virgile and Pascal quickly made a pull request with a display module. Now we can see Isaac on the screen, and a stub allow the buttons to update the isaac variable so we can move it.</p>
<p>Last update on <code class="language-plaintext highlighter-rouge">testing</code> yesterday: now Isaac plays animations when moving, and the buttons’ stub is replaced by the module <code class="language-plaintext highlighter-rouge">check_inputs</code>. And other stub was added to check if the direction variable is correctly update (yes, that’s why there is a half head in the middle of the nowhere :smile_cat:), and if the flags are correctly updated when A or B is pressed.</p>
<p>That’s it for now, see you late hour :crocodile:</p>
<p>JM</p>Jean-MarieHo dear! Oh dear! I shall be too late!,Graphics #2 - It’s alive !2020-06-26T00:00:00+02:002020-06-26T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/graphics2<p>Hi there,</p>
<p>It’s been a while since the last update but as you will see, we’ve been pretty busy !
Isaac now moves in all four directions and has a minimal walk animation. we had to sacrifice some of the aestetics for the sake of code efficiency.</p>
<p>Isaac’s sprite is too big to fit in only one 8x8px tile so we need 4 of them to display him correctly. We wanted him to have walking animation (4 frames) in every direction (x4) with the possibility to have an attack animation at the same time (that adds up to a lot).
If we used all 4 tiles for every possible frame of animation, we would have filled the memory of the gameboy. We needed an idea.</p>
<p><img src="../../assets/images/graphics1/isaac.gif" alt="isaac" /></p>
<p>In order to reduce memory space used and execution time, we exploited some particularities of isaac’s sprite.
As you can see <a href="../../assets/images/graphics1/isaac_frames.png">here</a>, isaac is very symetrical and turning him left and rigth is almost the same as making his eyes/tears disapear.</p>
<p>Comparing all of the frames individually, we noticed that we could re-use a lot of them and make combinations in order to reproduce every possible frame.
I’ll pass on the details but the main idea is to represent where isaac is facing with two bits; one for left, and one for rigth. If a bit is a “1”, it mean that the corresponding eye and tear will be displayed.
that way ‘00’ looks like the back of his head, ‘11’ looks like he is facing us and ‘10’ looks like the side of his face.</p>
<p><img src="../../assets/images/graphics1/direction_bit.png" alt="direction" /></p>
<p>This strategy allowed us to store Isaac in only 14 tiles (224 bytes of memory).</p>
<p><img src="../../assets/images/graphics1/spritesheet_logic.png" alt="logic" /></p>
<p>With a little more ingenuity and a few bit operations, this is the result.</p>
<p><img src="../../assets/images/graphics1/first_animation.gif" alt="direction" /></p>
<p><img src="../../assets/images/graphics1/logo_2.png" alt="logo 2" height="300px" width="300px" class="align-center" /></p>Pascal BérouleHi there,Day 42020-06-24T00:00:00+02:002020-06-24T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/daily%20update/log-day4<h2 id="day-summary">Day Summary</h2>
<ul>
<li>Virgile and Pascal
<ul>
<li>challenge : animate Isaac, while standing, walking and attacking in any direction, and with as few sprites as possible</li>
<li>optimized version of Isaac : only 14 sprites, reusing the sprites as much as possible</li>
<li>when Isaac turns, only his head rotates</li>
<li>the way sprites are positionned is crucial as Isaac is a superposition of several sprites</li>
</ul>
</li>
<li>Jean-Marie and Thomas
<ul>
<li>implementation of the collision functions</li>
<li>collisions can now be detected and resolved (movement canceled, damage applied, interactions called)</li>
<li>still a problem : no knowledge about the side of contact, should be implemented later</li>
</ul>
</li>
<li>Jean-Marie
<ul>
<li>creation of a structure for the code which allows anyone to add his bit of code easily</li>
<li>this structure has been approved by the rest of the team</li>
<li>documentation for this is currently being written</li>
</ul>
</li>
<li>Dorian
<ul>
<li>working on a code to convert a score into a custom music format</li>
</ul>
</li>
<li>Mélissa
<ul>
<li>Working on a programm which takes the custom music format file and plays it on the GameBoy</li>
<li>Use of time interrupts to play notes at a rather regular pace</li>
</ul>
</li>
</ul>
<h2 id="todo">TODO</h2>
<ul>
<li>have a first version of the programm in which Isaac can walk in a room</li>
</ul>Thomas GrenierDay Summary Virgile and Pascal challenge : animate Isaac, while standing, walking and attacking in any direction, and with as few sprites as possible optimized version of Isaac : only 14 sprites, reusing the sprites as much as possible when Isaac turns, only his head rotates the way sprites are positionned is crucial as Isaac is a superposition of several sprites Jean-Marie and Thomas implementation of the collision functions collisions can now be detected and resolved (movement canceled, damage applied, interactions called) still a problem : no knowledge about the side of contact, should be implemented later Jean-Marie creation of a structure for the code which allows anyone to add his bit of code easily this structure has been approved by the rest of the team documentation for this is currently being written Dorian working on a code to convert a score into a custom music format Mélissa Working on a programm which takes the custom music format file and plays it on the GameBoy Use of time interrupts to play notes at a rather regular pace TODO have a first version of the programm in which Isaac can walk in a roomSoftware engineering #1- A first function: collision2020-06-23T00:00:00+02:002020-06-23T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/SE1<p>н3110 ω0Я1δ,</p>
<p>This morning (well this morning, at 3 am…) I finished the first function (https://github.com/PainsPerdus/gboi-rocket/wiki/collision-doc). The collision function is a critical function of the game, which will be called a lot of times. Thus, this function is meant to evolve.</p>
<p>We debated yesterday and this morning (the real morning this time) about what this function should do, or what argument we should give it. For now this version takes a position and a size id for both element checked. We may implement another function for the bullets which takes only a point for the first element. Another optimization possible is to tell if the first hitbox is already loaded.</p>
<p>Dorian pointed out to me that using the RAM to store the variable is SLOOOOOOOWWWWWWW. Too bad for a critical function. The thing is that this function needs (at least) 8 variables (and even a little more), so there are not enough registers. We are thinking of using the HRAM as a cache for functions, and putting the stack in the WRAM.</p>
<p>For now, this function is tested with the pong game, and it works well. We will use it for the first milestone. Then we will consider our options to optimize this function if needed.</p>
<p>I also used this function to think about the documentation and used it for the first documentation page. (More about that in my next article :smirk_cat:)</p>
<p><strong>edit</strong>: Turns out HRAM and WRAM are the same speed</p>
<p>JM</p>Jean-Marieн3110 ω0Я1δ,Software engineering #2- Documentation2020-06-23T00:00:00+02:002020-06-23T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/SE2<p>RTFM,</p>
<p>With the first function written comes the issue of the documentation. ASM needs <strong>a lot</strong> of documentation. But after some try, it turns out that just commenting the code is not enough. There is not enough place to write all the informations needed.</p>
<p>So I decided to put the documentation in another file (See here for a copy of it https://github.com/PainsPerdus/gboi-rocket/wiki/collision-doc).</p>
<p>The documentation of a function first contains a label (useful if you want to call the function :smile_cat:), the parameters (with all informations needed like the names, size, struct, description…), the return value (how it is returned, the meaning, representation…).</p>
<p>After that come secondary informations (but I am ready to kick the ass of any slob who would make a pull request without documenting those) about the execution of the function. The values modified by the execution of this function (May I never find a callee saved register in this section…), the global variables used if there is any, the struct used, the memory locations, labels, etc used by this function.</p>
<p>And last but not least, the pseudo code of the function. Preferably written in C, with comments linking section of this code to sections of the assembly code. A high level explanation of the code has to be added if needed.</p>
<p>The assembly code has to be commented as well, but the comments aim to explain the transition from assembly to C. More informations are welcome but not mandatory as long as the link between the sections of assembly and the sections of pseudo code in the documentation is clear.</p>
<p>I can help but feel like I forgot something in the informations needed in the doc. Assembly leaves no place for imprecision… Well, for now that should do . The only comments I had with it was about the syntax I use to define sections in my code. We haven’t agreed yet btw…</p>
<p>JM</p>Jean-MarieRTFM,Sound #1- Defining the music format and driver outline2020-06-23T00:00:00+02:002020-06-23T00:00:00+02:00https://painsperdus.github.io/gboi-rocket/blog/Sound1<p>Hello world,</p>
<p>Melissa and me started working on the sound system. Before the project started, I had a rough idea of a format we might be able to use to gain space without much worry over performance and difficulty to generate.</p>
<p>Today, we worked out the last kinks and ridges and defined the format precisely. We also outlined the driver’s structure and behaviour.
Basically, a file will have N channels, each with their own scale and timings, The scale and timings will be described by a table associating a frequency/duration to a 4 bit index.</p>
<p>Each note will then be entirely described by a single byte.</p>
<p>The driver will then only have to keep in memory which note it is playing on each channel and when it has to go to the next note. To play a note, the driver has to read the byte of the note, read the descriptors to get the frequency, place it the the register corresponding to the channel, and set itself up to follow the timings.</p>
<p>We decided to use the timer interrupt to drive the timings, and, as the channels might not change notes at the same time, we make the timer fire the interrupt every 1/4096 s, and we manually keep track of when we have to change notes.</p>
<p>Silences are handled by a flag in the scale descriptor.</p>
<p>While Melissa is working on the implementation of the driver, I’m working on a converter from MIDI to this format in order to take already written music, and put them in the game.</p>
<p>Stay tuned for more !</p>
<p>Dorian</p>Dorian BourgeoisatHello world,