(Tips) How to Code a Video Game/Computer Emulator: Part 2

Tips : How to Code a Video Game/Computer Emulator: Part 2

Today, I will be coding an emulator for a fake minimalistic CPU I have made, called the Gypsy 15. Let's create a fake ad from 1975, introducing the Gypsy-15 to the world.

Behold! The new Gypsy-15 4-bit central processing unit, capable of storing and manipulating binary numbers from 0 to 15! With 4 data registers (R0, R1, R2, and R3), you can add values together with a number of instructions, including STOR, ADD, and SUB! Be the first kid on your block to own a home computer with the new Gypsy-15! Buy one today! (Only $55.75!)

There you have it. An extremely simple CPU that I just made up. Oh, and if you're wondering, the syntaxes for the instructions are:


STOR [REGISTER] [VALUE] (Places the binary [VALUE] into register [REGISTER].)
ADD [REGISTER] [VALUE] (Adds [VALUE] to register [REGISTER].)
SUB [REGISTER] [VALUE] (Subtracts [VALUE] from register [REGISTER].)

Sure, they are pretty basic functions, but they're fictional. Now, let's begin. Say a user has written this code for our 1975 4-bit CPU:


STOR R0 0011
ADD R0 0001
SUB R0 0010

This program stores the binary-equivalent of the number 3 into Register 0, adds 1 to the register, and subtracts two, leaving us with a final value of 2. Now, before these instructions are executed by the CPU, they are changed to binary instructions by an assembler. Their binary equivalent might be:


0000 0000 0011
0001 0000 0001
0010 0000 0010

When the CPU reads each binary value, it manipulates the registers based on what the user has specified. Now let's imagine I am a Gypsy-15 fanatic living in the present day, and I would like to write a Gypsy-15 emulator. This would be an extremely simple emulator to write. Now, let's begin.

First, I select C++ as my programming language to write the emulator in because of its versatility and wide range of functions. I declare some variables to emulate some of the CPU's internals, including four specific variables to emulate the contents of the CPU's registers (R0, R1, R2, R3).

I must now code the area of my program that executes when it loads. I insert code to show a dialog that allows a user to select a file, and when I have the full file name, I must open that file as a binary file, and not a text file. Why? Because it is not a text file. It is a data file. A simple way to do this in C++ is to use iostream.h, along with io::binary, to read a file and store its contents in a buffer. Once this section is coded, I must now move into the processing of the code.

My program now has the contents of the file stored in a variable, and can read from it and act accordingly. I would do this using string manipulation, and I would initiate a loop that analyzes every four digits it comes across in the file. This part basically defines an emulator. A good definition of an emulator would be a program that analyzes binary opcodes and reacts accordingly. In most cases, you will be using a loop to analyze these values.

Inside the loop, my program acts accordingly based upon what four digits it is processing. For example, if the current instruction being analyzed is 0000, my program would know it is going to store a value in a register. It would look to the binary value next to it (which in this case is also 0000), and would know that we are dealing with R0. Then, it would look right once more, and see it will store binary value 0011. So, my program knows to store 0011 in R0. This is how an emulator will process all of the instructions it is given.

Now, since my program knows exactly what to do, it will react. It takes the binary value 0011 and stores it in its variable that emulates register R0. After this, it would skip two values in the list of instructions (because these values were used as arguments in the instruction just processed), and the program will move onto the processing of the next instruction. This should occur until every instruction entered has been processed. Your emulator will have to be able to process (almost) every instruction a CPU can process, but luckily, your life might be a bit easier.

A lot of CPUs group similar process together using a particular digit of the instruction's binary counterpart. For example, all instructions that will perform mathematical processes on registers will begin with the digit 1. This means that on a CPU, addition might be identified as “1000”, subtraction as “1001”, and multiplication as “1010”.

Since CPUs and their emulations deal with binary values, there will be a lot of mathematical functions that you might have never heard of before, including bitwise operations, which deal with changing individual bits of binary values based on another value, and bit shifting, which will change the position individual bits. C++ includes many functions that help to accomplish these processes.

Emulator programming is a complex subject. Just a little warning to you: although it is possible, programming an emulator using a simplistic programming language will make your life even harder. C and C++ can handle complex mathematic processes, so they are good to use. Visual Basic can handle programming simple emulators, like CHIP-8 and Game Boy, but I would not recommend it for creating next-gen emulators. And I would not recommend using Javascript to program an emulator at all. Basically, the more sophisticated the programming language, the easier it will be to program an emulator in (to a certain extent! I would not program an emulator in assembly language!).

Another thing: if you plan to emulate next-gen consoles (PS3, Xbox 360, and even the Wii), you may have an extremely hard time, even if you use a programming language like C++. Because these consoles handle such complex mathematical processes, it will be hard for a common computer to recreate all of the parts necessary to accomplish a decent emulation. Think about it: you don't see an average computer emulating a super computer!

(Just a little bit of information that may help some of you. The Zilog Z80 CPU is emulated all the time, and has been used in a variety of video game consoles and 8-bit computers of the past. A document can be found here that will help you along with decoding Z80 opcodes if you ever have to emulate this CPU.)

Many beginners like to code emulators for computers that processed CHIP-8. CHIP-8 was a programming language used to simplify the creation of video games, and includes only 35 opcodes. Technically, you would be writing a programming language interpreter if you created an emulator for CHIP-8, but the way CHIP-8 works is so close to the way a CPU processes instructions that it is a good experience to write one!

Now you know exactly how to code an emulator. Remember, all computers are different, so all emulators will be different. Some will be harder to code than others, but it will be worth it when you can relive the memory of playing that old Pong game on your black-and-white television.

I am debating whether or not to write a third part to this series. It would cover the emulation of specific parts of the computer, including memory, the call stack, and graphics. Please tell me if you would like to see a new addition!

Would you like to be a Community Voices blogger? If so, please send a letter of interest and a sample blog entry (what you would post here if you were already a blogger for us) to forums@pcworld.com. We'd love to hear your perspective.

  Part - 1  

Courtesy : blogs.pcworld.com

Google