Thursday 25 February 2016

Blog Merge

I've decided to merge my blog with the new personal website that I am developing. I don't think many people read my blog anyway, and it's not like I post that often so I'm not too worried about the transition. :P

You can find my current website at Michael.Kafarowski.com and when my new site is complete that will be hosted there as well.

For now here is a preview screenshot.


Sunday 22 November 2015

Creating an NES Emulator From Scratch Part 3: CPU Complete!

We have completed the CPU portion of our emulator. Yay! :D
Well, it was completed a while ago, but I've been so busy with school I haven't had time to write about it. I still don't really, but I'm going to update anyway. Here is what I've been up to.

Finishing and Testing Opcodes
Since my last update I was working on building the instructions for the various opcodes. After writing them I decided to try out nestest.nes - a rom designed to help programmers of emulators debug their code. Conveniently, this was possible even without any PPU - By comparing my output to a known-good log from another emulator called Nintendulator, I was able to correct some glitches in how I was addressing memory as well as fixing some instructions to work properly.

Implementing Details
Before the CPU was ready to be called 'done', I needed to implement some final touches so that it would be accurate and ready for a PPU. These details included memory mirroring (which for some reason I had neglected until now), cycle counting (making sure each instruction took as long or as short as it was supposed to) as well as a few smaller things

Added a Configuration File
Do you like recompiling every time you want to change games? Me neither! Cartridge path, number of cycles to perform, as well as execution start address override (mostly for nestest.nes which required 0xc000 rather than whatever was stored at the reset vector) have been placed into a nice config file.

I also reworked the output screens a bit and cleaned up and documented a lot of the code.

Further Improvements.
With that the CPU is "complete". I say it with quotes because there is so much that can be improved. While cleaning up the code I stuck in probably a dozen different //TODO notes. The most significant improvement I believe is to remove ALL string operations. There are A LOT of string operations in the code - Opcodes and addressmodes get assigned a string, and is compared in several dozen if statements every single cycle. Changing these strings to enums or structs would probably result in a massive performance boost. However, I want to move on to the PPU first to see how it performs, then come back to this.

Next Step: PPU
I said I would write a post about the CPU before I started on the PPU, but I lied. I actually did quite a lot of research on the PPU and started the code in a new github branch. The graphics of ALIAneS will be powered by SDL. I've successfully created a window and drawn random pixels to it each cycle, and I estimate I'm 5 hours of coding away from displaying the first graphics from the screen - as primitive as they may be. I'll talk more about the PPU in another post.

My exams are in 2 weeks, and I'm done the school term in about 3-4 weeks. After that point I'll get back into this project more full-time.
 

Thursday 13 August 2015

Creating an NES Emulator From Scratch Part 2.5: CPU Code: Another Progress Update

(I changed my blogger name from Skyline_ to Aliasmk)

Hi again!
Its been a year and a week since I first posted about this project, and though its slow going, we are making progress.


Now, I know I said I'd be teaching as I go, but I found that I'm kinda learning on the fly here.. so I don't feel too qualified to teach. That said, I definitely will post research logs soon, once I know that things are going to work out.

I've implemented a shell so that testing can be done in a sandbox of sorts... you are given an instance of the CPU with a blank memory space, and you can write memory to the space and execute at an address as you would any cartridge. This will make it way easier to make sure addressing modes and opcodes are working correctly for the next stage of the project, which is actually creating the opcode instructions. The shell can also start the emulator as normal. Below is a screenshot comparing ALIAneS with Macifom's Debugger - note that (with a few exceptions) both report the same Opcodes and report the same addressing modes and operands.



You are free to build and try it yourself as always! Currently it works out of the box with OS X, probably works out of the box on Ubuntu and linux etc, and might work if you build it from the source on Windows.

Next steps:
  1. Ensure that all opcodes are being read with their correct addressmodes. There is no point continuing until this is complete.
  2. Code the instructions for each opcode. For example, LDA (load accumulator with memory) would be
    if(operation = "LDA"){
     setA(operand); //Where operand is found using relevant addressing techniques
    }
 Thats all for now. I'm still actively developing, its just real life gets in the way sometimes. See you again soon.



Friday 27 March 2015

Creating a NES Emulator From Scratch Part 2.25: CPU Code: Actual Progress Update


This is a project update, not a research log. I will be posting a blog entry explaining everything I have learned in detail in coming weeks. I don't have time right now (due to school) to study for exams, write the emulator, and summarize, edit and post all my research at the same time. But it will be up, and if you don't understand everything on this post, you will once you read that one. Stay tuned!

I posted a few weeks ago saying that I had rebooted the project and in fact I have. I'm close to having CPU emulation working. Here is a rundown of what I have done over the last few weeks:
 
  • I'm calling the project "ALIAneS" because emulator names are weird and have strange capitalization like that
  • I had to re-research everything again because I hadn't made any real notes the first time that I looked into the project way back in August. Focusing mostly on CPU I learned a lot more about the NES file format and CPU memory addressing methods than I remember learning about before. So taking notes would have been good, but looking at it again with more knowledge of programming helped.
  • Began coding basic frameworks for the CPU. I'm splitting the class files into System, CPU, Cartridge, PPU, and APU, as well as having headers for all of those of course. Only the first three of these are actually written as PPU and APU are secondary goals of mine for this project.
  • Wrote functions for setting and getting all values of registers as well as memory, given a location.
  • Coded the startup sequence of actions outlined on NesDev into the emulator init function
  • Got the cartridge loading methods done: right now this emulator will load a 8K or 16K PRG-ROM cartridge only; I have not (and will not for a while) support any mappers, as they are a tertiary goal.
  • Working currently on opcode decoding..

That last one, opcode decoding is taking the longest time. Luckily the binary of the byte that makes up an opcode can be parsed to more efficiently determine the operation and the addressing mode.
This is the last step in CPU emulation as far as I know, other than to implement memory mirroring functions for the RAM, which I haven't done yet for some reason.

That’s it for now. All source code on GitHub! See you again after exams are done!

Wednesday 11 March 2015

Creating a NES Emulator From Scratch Part 2: CPU Code

I figure it's high time to update this project, and this blog.
After dropping this project for quite a long time, I've picked it up again, armed with new C++ knowledge developed through my first and current school terms. Even though I knew Java before, these classes really helped develop my programming skills in both languages.
Anyway, I have officially started the CPU programming. At the time of writing, here is what it does so far:
  • Initializes CPU registers
  • Writes to memory
  • Reads a cartridge, and writes it to memory
  • Framework set up for future functions.
I don't have time to write too much now, but if you want to take a look at the program so far, it is available on my Github located at https://github.com/Aliasmk/ALIAneS-Emulator
Talk soon! :)

Tuesday 21 October 2014

Creating an NES Emulator From Scratch Part 1: CPU Basics

My first task was to read up a little bit on how emulation actually works. In our case, Emulation is when you design a software program to act as a hardware component such as a Microprocessor.

Before going further, I needed to understand how a CPU works as well as some history. So here we go. I’ll put a TL;DR at the bottom if you don’t understand… it’s a lot of stuff to try to understand , though not all the history or small details are all that important.

A CPU is a type of Microprocessor, and a Microprocessor is a chip that contains a logic center, as well as small areas of memory, called Registers. Registers are used to store numbers, states, or memory addresses pointers temporarily, until a program interacts with them. Registers are used because it is much faster for a CPU to use a register value than to fetch the same value from RAM.

Programs executed by CPUs are written in Binary, aka Machine Code. This type of language is formed by a string of 1’s and 0’s. Each 1 or 0 is called a bit, and if you have 8 bits, you have 1 byte. If you have 1000 bytes, you have a kilobyte. If you have 1000 kilobytes, you have a megabyte, and so on. Just think, every photo you have ever taken or any digital music track you have ever listened to is actually millions of 1’s or 0’s.

You may now be thinking “Hmm, I understand how data could be stored in 1’s and 0’s, but how can programs possibly be made up of them, since they aren’t physical data in the same sense as a picture?”

The gritty details are out of the scope of this first post, but CPUs (and most microchips) assign various internal instructions to correspond with a pattern of 1’s and 0’s, fed to it by a stream of data. Imagine it like Morse Code, where letters are spelled using either long (written as dashes - ) or short (written as dots . ) bursts of Light, Sound, hand signals, etc. If you were in danger, you would signal SOS to a plane with . . . - - - . . .
SOS is an instruction, and it is relayed by morse code. Binary can be thought of in a similar manner, where each instruction corresponds to a different stream of 1’s or 0’s. Instructions are referred to as OpCodes.



Back to programming. If you are familiar with programming, you may not realize that although you write your program in Java or C++, when you compile, your program is converted into this machine code, to later be used by the processor. But before there were ‘high level’ languages such as those, programmers would of had to write all their programs in binary… had it not been for a few other “Inventions”.

If you look at a page full of 1’s and 0’s eventually you are going to get dizzy and the whole lot is just going to be unreadable. To make binary more human readable, we use a numbering system called Hexadecimal. By the time this is posted I would have posted an explanation of Hex, so I’m not going to cover it again here.


Okay, so at least now we aren’t looking at a page full of 1’s and 0’s but hexadecimal isn’t much better. That’s why the next step was to program in Assembly. Assembly was created to assign “words” and “syntax” to hexadecimal (and thus, binary) commands. I use quotation marks around those two words because as you will see, Assembly kinda sucks to read as well. However, things began to look much more structured.

However, apart from straight-up binary or Hex, Assembly is one of the most painful languages to program in especially for beginners (like me!), because it appears to be so abstract, yet readable at the same time. Interestingly, at this point the only reasons assembly is worth understanding are if you are really interested in how CPU’s work, have lots of spare time and want to learn a low level language, or if you are writing an Emulator, Compiler, among other niche programs. Don’t be afraid though, we wont write our emulator in assembly.

Note that assembly, though a human readable representation of Machine Code, couldn’t be fed to the processor itself. It has to be compiled into binary before that could happen.

Eventually people got tired of Assembly and invented higher level programming languages (like C), that are much easier to read and program in, but that could be compiled (aka translated) by a computer, [back into Assembly], then finally into Binary, where a computer was ready to run the program.
 
My fingers are hurting so TL;DR:

- Emulation is where you use one computer to run a program with instructions designed for another… translation needs to be done.
- A CPU is a chip that has a logic center and small areas of memory called Registers
- Registers are temporary storage areas used in programs
- Programs are a series of 1’s and 0’s that a CPU reads as instructions. Different variations of 1’s and 0’s mean different things.
- Instructions (defined streams of 0’s and 1’s) are called OpCodes
- Hexadecimal is used to make data easier to read than if it were in Binary
- Assembly is used to make program data easier to read than if it were in Hex.
- High Level programming languages are used to make program data easier to read (and write!) than if it were in Assembly.

Tuesday 19 August 2014

How Hexidecimal Works

Below is a post I wrote a while back somewhere else about how Hexidecimal works. This will become important for when I post the next part of my NES emulator series.




Decimals to Hex and Binary

The numbers we use everyday work on a base ten system. That is we count from 0 to 9, then add a 1 in front of the 9 then return the 9 back to 0 ( 09 becomes 10 ). At 99, a 1 gets added in front of the 99, and the 99 loops back to 00 ( 099 becomes 100 ). This way of looking at it is very important to understand other base systems.

Now imagine a system that works on base sixteen instead of base ten. You would essentially be counting up to 15, then adding a 1 in front and setting 15 to zero. So, like 8, 9, 10, 11, 12… you would have (0)(13), (0)(14), (0)(15), (1)(0), (1)(1)…. and so on. ( (0)(15) becomes (1)(0) )

I used brackets to separate each 'digit' but we need a way to represent 10-15 as a one digit character. Lets replace 10, 11, 12, 13, 14 and 15 with A,B,C,D,E,F. So 9 in decimal would still be 9, but 10 in decimal would be A. 15 in decimal would be F, and 16 in decimal would be 10, because if you go one higher, you set F to zero and add 1 at the beginning (0F becomes 10). Congratulations, you have learned the essentials of Hexadecimal.

Converting Dec to Hex

An easy way to convert to Hex is by looking at the number of digits and the values each represent. As an example, we will look a couple of examples in decimal. The number 300. It has three digits, and can be rewritten as 3x10^2. The number 50 can be rewritten as 5x10^1. Finally, 8 can be rewritten as 8x10^0. Because 300 + 50 + 8 = 358, you could say that (3x10^2)+(5x10^1)+(8x10^0) = 358.

That in mind, lets do the same for Hex. We will decode, or find the decimal value that is associated with the hex value 0x166. The "0x" will now be added to distinguish Hex from decimal. We can rewrite this number as (1x16^2)+(6x16^1)+(6x16^0) to give us 358.

Finally, lets encode a Hex value given a decimal number. Starting small, this number will be 39.
- To start, we want to see how many powers of 16 the number has. So grab a calculator, unless you are good with exponents. See how many times you can multiply 16 by its self without going over your decimal number. In this example, we can only go as far as 16^1, because 16^2 is 256, way over.
- Now we need to see how close we can get to our number by multiplying 16, again without going over. The most we can go is 2x16^1 = 32.
- We need to find what is left after this multiplication, so subtracting 32 from 39 leaves us with 7.
- Because this is inside the base 16, we leave this at 7.
- Therefore, the hex value for 39 is 0x27

Converting Hex to Binary

Binary is simply another system of numbering. Remember that while decimal is base-10 (0-9), and hexidecimal is base-16 (0-F), binary is base-2 (0-1)! 

To count up in binary, you start at zero. Then you count up until the number reaches 1. Then, on the next count, you set that digit back to zero and add a 1 in front of it, like so:

0 -> 1 -> 10 -> 11 -> 100 -> 101 -> 110 -> 111-> 1000 -> 1001 -> 1010 -> 1011 -> 1100 -> 1101 -> 1110 -> 1111

Now, here is where it gets interesting. Check this table out:

 

1111 corresponds to F... So, the last one digit hexidecimal number fits in four digits of binary. In computer science, each 1 or a 0 of binary is called a bit. Because one digit of Hex is 4 bits, you can fit 2 digits of Hex in a byte (which is 8 bits).

11111111 is equal to 0xFF, and equal to 255. In one byte, you can store a number up to 0xFF (255 in decimal).

Infographic

Here is the infographic that really helped me learn this. Credits to the original owner... I just found it on Google Images :)