![[chip8.webp]] I always found emulators amazing pieces of software. The first I used was a SNES one, that I use to play some classic games I never was able to get when I was a kid. I thought those _beasts_ were _black magic_, something I will never be able to grasp. # Motivations I basically wanted to improve my OpenGL (and C++) skills through a fun project. I always wanted to make an emulator, and the Chip8 is a fairly easy one to start with. So why not making the rendering 3D to be able to move “inside” the game. Here is a small video of what it looks like: [youtube](https://www.youtube.com/watch?v=h3pDNioWFzI) ![](https://www.youtube.com/watch?v=h3pDNioWFzI) # About Chip8 The Chip 8 is actually a virtual machine developed in the 70s by [Joseph Weisbecker](https://en.wikipedia.org/wiki/Joseph_Weisbecker). So it was never a real console to begin with but we still can emulate it. There have been plenty of games written for it so we can run them later in our emulator. This is probably the easiest emulator you can start with, since it has a very small number of opcodes and they are pretty simple to implement. You can find easily on the internet the specifications needed to be implemented. For instance on this [website](http://devernay.free.fr/hacks/chip8/C8TECH10.HTM). ![](https://www.youtube.com/watch?v=R1K5NIyvHFk) # C++ data modeling ```cpp struct Cpu { uint16_t opcode; Memory & memory; std::array<uint8_t, 16> registers; uint16_t index; uint16_t pc; std::array<uint8_t, 64 * 32> pixels; uint8_t timerDelay; uint8_t timerSound; std::array<uint16_t, 16> stack; uint16_t sp; } struct Memory { std::array<uint8_t, 4096> storage; } ``` So as we can see that machine is very simple. We've got 4Kb memory to work with, 16 registers and then some variables where we are storing the current opcode, the current index and the value of the program counter (pc). There is two timers that are clocked at 60Hz. Each one of them should be decremented 60 times per second. If the `timerSound` is above 0, we should play a sound. If you are interested in knowing more about it, you should check this [guide](https://tobiasvl.github.io/blog/write-a-chip-8-emulator/) which explains a lot more things than me. # Rendering Usually the games are rendered in a `64 * 32` framebuffer. To make mine a bit different from the others I decided to treat each pixels as a _cube_. Each single pixel is treated as an entity to be drawn, this is definitively not the most efficient way of doing it, but for such a small number of pixels it went well with an average of 200 fps on a machine without a dedicated graphic card. ![[chip8_1_a9afb7f689.png]] The 3D engine is a simple basic **OpenGL** renderer with a few shaders for the shadows and lights and a very basic _free fly camera_. The most important part is to render those array of pixels into cubes and translating it into 3D using matrices. ```cpp auto view = camera.getViewMatrix(); auto projection = glm::perspective(camera.getZoom(), 2.0f, 0.1f, 500.0f); auto cameraPosition = camera.getPosition(); int i = 0; for (const auto & pixel : pixels) { if (pixel > 0) { auto pos = glm::vec3(i % WIDTH, -i / WIDTH, -40); glm::mat4 model; model = glm::translate(model, pos); draw(model, view, projection, cameraPosition); } i ++; } ``` You can find the source for everything [here](https://github.com/Rydgel/chip8). A NES emulator should be a fun next exercise.