• entries
177
531
• views
164054

Emulation goodness inside

## Last Post

Well apparently my GDNet+ stuff still works, I canceled it since I don't post much any more, maybe there's some grace period or something.

I haven't done much over the summer since I'm so tired after work. My only real progress has been separating GameKnight into two projects, the Windows executable and an API independent library. I did this because back in May someone e-mailed me about porting it to XNA to run on the Zune, and was having trouble separating the emulation and Windows code.

The new release(0.21) in on the CodePlex page, but it's pretty much the same as the 0.2 one except for the way the code is organized. Hopefully I'll get around to adding sound support soon.

Also news of the project has somehow reached several emulation sites. I don't know how as I've only posted about it here, but GameKnight 0.2 got 158 downloads versus 0.1s measly 14.

This will likely be my last post here, so I'd like to thank everyone that stopped by, even though some of you(Hopedagger, Rob Loach) seem to have disappeared from GD. Since I don't have any new screenshots and since every post has to have a picture, Jon Arbuckle will once again have to fill in:

## Look! It's another crappy Beta!

Wow, not a single post in April. My focus on school did pay off though, four A's and one D(I was expecting an F so this is good). Anyway my burn out is wearing off and I've started to work on GameKnight again.

This release(0.2) adds save states and a crappy dialog window to change keys.

Unfortunately save states currently only work original GameBoy games, when loading the color ones, a portion of the VRAM seems to get screwed up.

Here's the hastily made dialog box, I'll add mouse and joystick/gamepad support later. Hopefully my old Gravis GamePad(it looks like an SNES controller) with its ancient DB15 connector will work.

## Laugh at my source codes!

I've setup a CodePlex page for GameKnight(yes we're back to GameKnight, no more GreatNES). The binaries and source are in separate zips since CodePlex doesn't have an option to label a file as both. I was also planning on going with the zlib/libpng license, but CodePlex limits the licenses you can select and I went with the MIT license instead, oh well.

Go give it a whirl so I know if works or doesn't work on your system(system specs would be nice). You should get around 60 FPS, anything else and it means either your computer sucks or my timing code sucks, probably both. Actually I've been having problems with GameBoy Color games that run in double speed mode, seems my 2Ghz machine can't handle an 8Mhz Z80. If you'll looking for some ROMs, Mr. Zophar has a couple you can use.

Still haven't gotten around to adding anything thanks to heaps of school work. School ends in three weeks and I plan to take a one week break(I'll need it) before starting my summer job, so hopefully I can add sound and save states then.

I'm blaming Ravuya and so should you.

## Total Lack of Progress

It's been over two weeks since the last update, so I thought I should update this thing. Unfortunately I haven't been able to get much done in that time, it's the last couple weeks of school and I'm buried in tests, assignments and projects. There's some sound code, but not enough to actually make any sounds and I've been able to get the other GameBoy Color games to run, although most of them are unplayable.

Here's Mega Man Xtreme 2:

X looks like he just teleported into some demented Tetris game.

The Zelda Oracle games now just generate a black screen [sad].

I'll probably get back into it soon. I wanted to finish this before the summer break, but it doesn't look like it's going to happen, hell I thought it would be finished back in October(what's the saying, "the last ten percent"?).

After all this is sorted out I plan on going back to either Doom.Net or adding in the GBA to the emulator, I think I'll save the NES for later.

## In Living Color Part 2

Well I fixed the rather trivial bugs, most of which where a pain to find due to all the changes I made.

The first one was pretty embarrassing, basically I was using windows calculator to find a the right shift amount for 0x2000 and used 1
The palette issues where simply because I was doing the 15bpp to 32bpp conversion at the wrong time. My code uses A8R8G8B8 for everything, but the GameBoy Color uses X1B5G5R5. I could use the same format, but someday I'd like to implement a tile editor/viewer and have it work for all systems so it's easier just to stick with 32bpp.

Finally the problem with the old GameBoy games, was that I forgot about the changes in RAM size between systems. The GameBoy Color has 8 4KB banks of internal RAM, but the older version only has 8KB. With the older games I was only accessing the first 4KB.

Anyway, enough talk. Here's what you came here for:

I can't get the damn Oracle series to work. Seems it still thinks it's running on an old system.

I've also broken Kirby's Dream Land 2 again and the star in Super Mario Land doesn't work. I've dealt with that bug numerous times though and it has to do with the timer interrupt. Damn interrupts and their finicky timing!

Edit: Nevermind, fixed that as well.

## In Living Color

I've given up trying to track down every little bug for now, and have started working on sound and GameBoy Color features. Unfortunately information on both is extremely scarce so this may take a while.

I have color support kind of working. The extra memory and color palettes are in, but some of the tiles seem to reference the wrong palette.

Maps I'm not surprised don't work, I didn't expect them to. However the sprites should be correct.

Also I've been making some heavy changes to the design, nothing that's required a rewrite, however all this new color stuff seems to have completely broken all the old games. I can't play a single one and the few that at least start mess up after a few seconds. [sad]

## Synchronization hell

I've squished a few more bugs and have almost all the games working now. Most still have some graphical problems, likely due to timing. There are also two games I continue to have trouble with, Mortal Kombat which refuses to pass the "presented by Midway" screen and Super Mario Land 2, which won't go past the title screen. Yes I know it was working last entry, but it's a finicky bastard.

The first bug and the one that has been causing all the games to flicker, was that I wasn't copying enough bytes for the sprite DMA. Part of the problem here is the documentation:

Got all that? Well basically each sprite is 4 bytes, but you only need the first 28 bits. When I first read this I though it just copied the first 0x8C bytes. Maybe the hardware does only transfer 28 bits per sprite for speed, but I can get away with just transferring 0xA0 bytes. Why they couldn't just say 0xA0, I have no idea.

Next bug was some fixing the interrupt timing. See the GameBoy has an instruction called HALT which justs halts the processor until an interrupt occurs. I've been ignoring it since most games just check the LCD registers after and if nothing happened jump back to the HALT. However there are some games that don't and seem to be built around it. Damn programming was a lot harder back then, I swear these guys where counting clock cycles.

Finally a bug that caused some of the games to flicker their title screens. Problem was that I was only checking if the LCD was enabled when I did the actual rendering of the whole screen during VBlank. Some games though would turn the screen on right when the VBlank occurred so now I check it every scan line.

I don't know why I wrote all that, so here's what you're really here for:

Kirby's Dreamland 2 and Gargoyle's Quest, I haven't tested them throughly, but at least they start.

## Damn you and your integers C#!

Guess what? It's time to play "spot the bug" again!

public static int RRCA( Processor Processor, Opcode Opcode )
{
int Carry = ( Processor.A 7 );
Processor.A = (byte)( ( Processor.A >> 1 ) | Carry );
Processor.NegativeFlag = false;
Processor.HalfCarryFlag = false;
Processor.CarryFlag = ( Carry != 0 );
return 0;
}

Yep thanks to C#'s "lets make everything an integer" policy, Carry isn't just limited to 0 or 128. Well part of this is of course my fault for making Carry an integer or forgetting that shifting a byte doesn't return a byte.

New version:

public static int RRCA( Processor Processor, Opcode Opcode )
{
Processor.A = (byte)( ( Processor.A >> 1 ) | ( Processor.A 7 ) );
Processor.NegativeFlag = false;
Processor.HalfCarryFlag = false;
Processor.CarryFlag = ( ( Processor.A & 0x80 ) != 0 );
return 0;
}

This fixes the "platform bug" in Mega Man 2 that I showed a couple entries ago. Unfortunately it hasn't fixed much else [sad].

## What Mega Man would look like on LSD

I fixed a bug in the TIMA(timer) register and have been able to get Super Mario Land and Kirby's Dream Land working again.

The problem was that both games re-enabled interrupts right near the start of their interrupt routines and the timer interrupt was occurring too often.

Sadly Kirby's Dream Land 2 doesn't even start [sad]. There are also plenty of bugs in the games, even if they work. I figure there's a bad opcode someplace, but I've gone over them like a billion times and it's really getting tedious.

I've also been trying to combat the sprite flickering technique a lot of games use(the Mega Man series being the worst offender) by blurring the last frame with the current one. Here's what the first attempt yielded.

I actually tried playing through the level like this, I don't recommend it.

## Almost there

When I said almost all the games worked last time what I really meant was that only half of them worked, the other half started but where buggy as all hell. I've squashed quite a few bugs and now there really is only a couple games that don't work. For example Mega Man V(my favorite Mega Man on the GB) just restarts when you select the level. There are also some other bugs like this in Mega Man 2:

If you don't see it, take a look at the platform in the upper-left.

I did finally get Super Mario Land 2 to work right. I've never been able to get it past the title screen, even in the old emulator.

I'll put out the first real release after I fix the remaining (hopefully few) bugs and create a dialog to switch keys.

Also I've decided to make the project open source, but it'll be after I'm sure this thing is 100% correct. Not sure what license I'll use, but it sure as hell won't have "GPL" in it.

Edit: Fixed the bug in Mega Man V.

## Lots of progress

NES Progress

The NES portion of the emulator is coming along. The processor, memory(including VRAM) and a few mappers are implemented. I can actually run and trace programs, but nothing shows up because I haven't implemented the PPU. I'm waiting till the GameBoy portion works to make sure my timing is right.

GameBoy Progress

Have you ever looked at code only a few months old and wondered how you where able to program something that looks like an ungodly abomination that begs for apocalypse? Well that's what happened when I opened up GameKnight again. I'm warning you about the next piece of code.

public static int DEC8( Processor Processor, Opcode Opcode )
{
byte* Pointer = Processor.GetRegisterPointer( ( ( Opcode.Value >> 3 ) & 0x07 ) );
*Pointer = (byte)( *Pointer - 1 );
Processor.SetFlags( Processor.GetFlags( Flags.Carry ) );
Processor.AddFlags( Flags.HalfCarry, ( ( *Pointer & 0x0F ) == 0x0F ) );
Processor.AddFlags( Flags.Zero, ( *Pointer == 0 ) );
return 0;
}

Yes pointers in C# and they where everywhere.

Here's the new version for comparison:

public static int DEC8( Processor Processor, Opcode Opcode )
{
int RegisterIndex = ( ( Opcode.Value >> 3 ) & 0x07 );
byte Value = (byte)( Processor.GetRegisterValue( RegisterIndex ) - 1 );
Processor.NegativeFlag = true;
Processor.HalfCarryFlag = ( ( Value & 0x0F ) == 0x0F );
Processor.ZeroFlag = ( Value == 0 );
Processor.SetRegisterValue( RegisterIndex, Value );
return 0;
}

much better, no pointers or that "SetFlags/AddFlags" nonsense.

While rewriting the opcodes I stumbled upon one bug so bad, I'm blaming it for all my lost progress in October. That is I'm pretty sure that this bug wasted a month of my life as after fixing it almost every single game works.

Here's the unfixed version:

public static int RES( Processor Processor, Opcode Opcode )
{
int RegisterIndex = ( Opcode.Value & 0x07 );
byte Value = Processor.GetRegisterValue( RegisterIndex );
Value &= (byte)( 1 > 3 ) & 0x07 ) );
Processor.SetRegisterValue( RegisterIndex, Value );
return 0;
}

I'll let you guys figure it out. If you don't know the Z80, the RES instruction is supposed to reset a bit(set it to 0).

Unfortunately while most games now work, a few don't, oddly they're all ones that do work in GameKnight.

Anyway here's what everyone came here to see, screenshots!

I haven't implemented windowing or sprite priorities yet, so if it looks like something is missing, it is.

Name my emulator!

As you can see from the screenshots the emulator is named "GreatNES". This worked when it was just supposed to be for the NES, but now that it works for multiple systems, it seems weird.

So any suggestions are welcome for a new name.

## Two thousand and seven

First, happy new year! (Yeah I know I'm a little late)

Second, I thought I'd do a recap of 2007 as I enjoy reading the other ones people have put up. Plus it helps that I change projects every couple weeks [grin]. So here it goes:

January - Various Doom and Quake related projects which would eventually provide the base for Escalation.

February - Spent the whole month working on Escalation.

March - Pretty much finished the programming portion of Escalation and began looking for artists.

April - Had a couple "new" artists apply, but by then I'd already realized that Escalation was less fun to play then Pong on the Atari. Tried working on a "true 3D" game, but it didn't last long.

May - Wow, sure got a lot done in May. First there was VoxelSharp, a program for making voxel models. Second was VAtlas, someday I'll get around to changing its output to XML and including a .Net assembly to help use it. Next was the software raycasting project, and lastly I decided to learn shaders by applying them to Doom.Net.

June - Attempted to make an isometric editor for X-COM like games, didn't get very far.

July - It was too damn hot.

August - Started working on a new GBA emulator, but got bored with it.

September - Spent every possible second working on GameKnight, my GameBoy emulator.

October - Tried to iron out various bugs in GameKnight. Eventually got fed up with it after not really getting anywhere over the month(fixing something would just break something else).

November - Tried to write an assembler, failed.

December - Not a whole lot, but it was exam time. Just a simple CHIP8 emulator and porting over my TileStudio stuff to XNA.

What does the future hold? I plan to start working on a new emulator for the NES along with finally finishing GameKnight. Plus more Doom.Net goodness as it just won't die, although this time I think it'll be a port of the original source and not another "from scratch" version.

Thanks for reading all this dribble.

## Drawing.Bitmap makes me want to kill myself

I've been planning on making a GUI version of VAtlas for awhile and have finally gotten around to it. The plan is to fix several problems with VAtlas like being able to handle image formats other than 24 and 32 bit, editing previously made atlases, XML output and maybe sometime in the distant future an image, animation and map editor, basically a modern version of TileStudio. Unfortunately even the basic atlas portion of the program is proving difficult.

Here's an old screenshot, not that the latest one looks very different.

The main problem is that I'm trying to make it cross platform and am using the Drawing.Bitmap class everywhere(see title). The Drawing.Bitmap class sucks, first it takes up a shit ton of memory(and Dispose does absolutely nothing) and that while it'll allow you to load or create an indexed image, good luck finding an easy way to draw it or convert it.

I then tried making my own DDS Surface class to deal with everything. The problem then came with actually drawing it to the damn window. I took the easy way out and just copied the surfaces data to a bitmap with the same bit count. This ended up taking up even more memory and being a bigger pain in the ass then just using bitmaps.

Last thing I tried was SDL.Net. Well loading and conversion were easier this time, but now the damned SurfacePanel control won't draw anything but 24 and 32 bit images, shit!

Anyway, I've pretty much had it. This would be easier if I could just use DirectDraw or Direct3D, but I want it to be cross-platform and also I'm still pissed, and will always be pissed at MS for killing MDX.

So does anyone knows of an image library for .Net that will handle this kind of thing and doesn't suck?

## More TileStudio Stuff

If anyone's interested, I've ported one of my old TileStudio demos to XNA. Be aware though that I've only been using XNA for a few days, so there's probably plenty of room of improvement. It likely won't work on a 360, it lacks any of this "content pipeline" stuff and I doubt it works with the "click and place" IDE as I prefer to just code everything myself. If someone wants to fix it up to work with all that stuff, that be great.

Included in the download is the source and binaries for both the DLL and the demo program and the new TileStudio definition file.

Controls are left and right arrows to move, space bar to jump.

I know I'm not the first to use TileStudio in XNA, I found a couple other sites using it. However they either left things out like animations/sequences or where coded with that god awful Hungarian notation, why the hell do people still use that?

## Burn Out

Wow it's been over a month since I last posted. Unfortunately I haven't gotten much of anything done in that time. I started working on a NES emulator, but got tried of it after coding the 6502 portion. I also wrote a small(two source files) CHIP8/SCHIP interpretor call Chipmunk using SDL.Net:

I've been having problems getting the SCHIP portion to work right though. For example in U-Boat it says game over as soon as I press anything and in Joust the enemies kill themselves by colliding with the platforms.

I'm not really sure what to do now. After finding out that MDX won't work on 64-bit OS's, I've given XNA a try. It's not too bad, it delivers what is promises, but I'd still like a new version of MDX. I've thought about making one myself, but I have no idea what's involved. I've also given up hope on a decent cross-platform API, everyone is either too slow(SDL) or a complete mess(Tao), at least in comparison to MDX.

I'd like to actually make a game, but that damn art requirement always gets me. Plus everything I think of is just a cheap rip-off of some NES/SNES game.

## Actual development news

Unfortunately I haven't really felt motivated to work on GameKnight for the past two weeks. However since it's decent enough that I could actually show it off should I choose to try to get a programming job, I don't think I'll be releasing the source. Oh well, it's not like there's a shortage of GameBoy emulators.

Anyway right now I'm working on an assembler called TNT. Basically the assembler takes care of all the parsing and preprocessor crap and then passes it to the desired plug-in for whatever CPU the user wants. I'll probably have to write the plug-ins as well, starting with the Z80 and 6502.

Here's a screen shot of the current output(still working on the preprocessor part), not exactly breath taking:

There is a reason for all this, it has to do with my final project for school, but I'll save posting about it until I have more, it's still in the design phase.

Also I finally nabbed a used TI-83+ off eBay for $40(plus$10 shipping). It was really close too, some asshole bid in the last 20 seconds, but was a dollar under my maximum bid [smile]. So expect some calculator goodness after the assembler is finished.

## BEWARE I LIVE

Yeah sorry, I'll post some actual development stuff tomorrow. I needed something to post of Halloween and unfortunately I didn't have time to do another Doom inspired pumpkin like last year, plus I had to show off [smile].

## Demo #2

Well here it is. This version improves the interface(no more command line) and features better LCD timing. Almost all games now start up, although most are only playable for a few seconds before they go all screwy [sad]. I've included a few PD ROMs in the demo, however for some reason "They came from outer space" works when I run the emulator from the IDE, but is buggy when run normally.

Edit: Forgot to list the keys AGAIN

Enter = Start
Select = Space

Sample screenshots:

I finished rewriting the code a few days ago, but unfortunately there where a few bugs that stopped anything from running properly.

After days of stepping through numerous games code with the disassembler, the problem turned out to be that I placed Memory.WriteUInt16 instead of Memory.WriteByte in the LD (HL), A instruction.

Everything's back to normal now, expect a new demo sometime this weekend.

As you can the interface hasn't really changed. I opted to stick with just doing a simple GameBoy emulator instead of the plug-in MDI based system I talked about in the last entry.

Also I'm becoming fed up with the GDNet+ service as I've had to resort to using my old PhotoBucket account to host images. The bloody GDNet+ web space isn't working and hasn't been working for me for two days now. This isn't the first time this has happened either.

It's no mystery why people are moving their journals to other sites. If this bullshit continues, this will be my last year as GDNet+.

## The new and improved Apex

I've started working on a new emulator application, named Apex just like the GBA emulator I was working on. Basically it's a MDI application with a plug-in based system that loads various game systems via .NET DLLs with reflection. The first system to be added will of course be the GameBoy.

It's going to take a while though before I have any fancy screenshots. Unlike the previous emulator this one is meant to work with a number of different systems. Because of this I'm building a Z80 core first, which I will then inherit off of to build the GameBoys processor(a smaller version of the Z80).

The opcode class also makes use of inheritance to eliminate the amount of repetitive code, for example here are the 8-bit versions of SUB, SBC and CP:

SUB:

using System;

namespace Apex
{

public partial class Z80
{

protected partial class Opcode
{

public unsafe abstract partial class Arithmetic8bit : Opcode
{

public class SUB : Arithmetic8bit
{

protected int Carry = 0;

protected bool WriteResult = true;

public SUB( int Value ) : base( Value )
{
return;
}

public override int Execute( Z80 Processor )
{
base.Execute( Processor );
Pair Temp = new Pair( Processor.A.Value - *Pointer - Carry );
Processor.SetFlags( Flags.Negative );
Processor.AddFlags( Flags.Parity, ( ( Processor.A.Value ^ *Pointer ) & ( Processor.A.Value ^ Temp.LowerByte.Value ) & 0x80 ) );
Processor.AddFlags( Flags.HalfCarry, ( ( Processor.A.Value ^ *Pointer ^ Temp.LowerByte.Value ) & 0x10 ) );
if( WriteResult )
{
Processor.A.Value = Temp.LowerByte.Value;
}
return Cycles;
}

}

}

}

}

}

SBC:

using System;

namespace Apex
{

public partial class Z80
{

protected partial class Opcode
{

public unsafe abstract partial class Arithmetic8bit : Opcode
{

public class SBC : SUB
{

public SBC( int Value ) : base( Value )
{
return;
}

public override int Execute( Z80 Processor )
{
Carry = ( Processor.GetFlag( Flags.Carry ) ? 1 : 0 );
return base.Execute( Processor );
}

}

}

}

}

}

CP:

using System;

namespace Apex
{

public partial class Z80
{

protected partial class Opcode
{

public unsafe abstract partial class Arithmetic8bit : Opcode
{

public class CP : SUB
{

public CP( int Value ) : base( Value )
{
WriteResult = false;
return;
}

}

}

}

}

}

Basically if there's a problem with one of the opcodes, fixing it also fixes the others based on it. All the different address modes are also covered by the same function. Here is the Arithmetic8 class that all the 8-bit math operations inherit of off:

using System;

namespace Apex
{

public partial class Z80
{

protected partial class Opcode
{

public unsafe abstract partial class Arithmetic8bit : Opcode
{

protected byte* Pointer = null;

public Arithmetic8bit( int Value ) : base( Value )
{
switch( Value >> 8 )
{
case 0xDD:
Cycles = 19;
break;
case 0xFD:
Cycles = 19;
break;
default:
if( ( Value & 0x07 ) != 0x06 )
{
Cycles = 4;
}
else
{
if( ( Value & 0x40 ) == 0 )
{
}
else
{
}
Cycles = 7;
}
break;
}
return;
}

public override int Execute( Z80 Processor )
{
{
if( ( Value & 0xC0 ) != 0 )
{
Pointer = Processor.GetRegisterPointer( Value & 0x07 );
}
else
{
Pointer = Processor.GetRegisterPointer( ( Value >> 3 ) & 0x07 );
}
break;
Pointer = Processor.Memory.GetPointer( Processor.HL.Value );
break;
Pointer = Processor.Memory.GetPointer( Processor.PC.Value++ );
break;
Pointer = Processor.Memory.GetPointer( Processor.IX.Value + Processor.Memory.ReadSignedByte( Processor.PC.Value++ ) );
break;
Pointer = Processor.Memory.GetPointer( Processor.IY.Value + Processor.Memory.ReadSignedByte( Processor.PC.Value++ ) );
break;
}
return 0;
}

}

}

}

}

In GameKnight each opcode had different classes for each address mode, so there where hundreds of files just for the opcodes, most of which had exactly the same code except for a couple lines. The goal of the emulator this time isn't speed, but to be easy to debug and maintain.

## Demo Time!

I've implement mapper 3 and 5 so the only mappers left are the special Hudson and Bandai ones. With these two mappers all the Pokemon games along with Ghosts 'N Goblins now work, although Ghosts 'N Goblins suffers from seizure inducing sprite flickering.

Sprite multiplexing may work on the GameBoys LCD, but it doesn't work on a computer [sad]

Demo:

I'm releasing what I have now because the whole thing needs to be rewritten. It's not that it doesn't work, but I'd rather do it now then later. Basically the design is horrible, the code is full of public statics, classes can access things that they shouldn't be able to.

Anyway download the program here. It's a command line program right now, if you don't know what that means just drag the files into the executable. You'll need .Net 2.0 and Managed DirectX installed, although I plan on trying to switch over to SlimDX during the rewrite.

You can get public domain ROMs over at Zophar's. I tested "GB Lander", "The Horrible Demon 3" and "They Came From Outer Space" and they all worked.

Edit: Sorry I forgot to include what the keys are.

Enter = Start
Select = Space
A = A
S = B

Yeah I don't know how it'll work on non-QWERTY keyboards.

## Almost there

Small update today. I've implemented windowing so status bars now work along with finally fixing the palette issues. Still need to work on sprite priority.

Should have a demo ready sometime this weekend.

## ARM CANNON FTW

I've gotten more games to run and a few are now completely playable thanks to squashing a retarded bitwise bug in one of the jump opcodes. This is the problem with making an emulator, all it takes is one little mistake in one opcode hidden away and nothing will work right. It doesn't just crash either, it just executes garbage, making it a pain in the ass to debug.

Anyway the first game to actually run without any game play errors was Super Mario Land.

Zelda is also playable:

Unfortunately the only playable Mega Man game is Mega Man 2. Mega Man 1 will get past the title screen now, but freezes when the screen scrolls vertically.

Yeah he thought he was all that, but I beat him without even having the health bars.

As you can see there are still plenty of graphical issues to work out. I need windowing support to get the status bars to work and obviously the palettes are still all screwy.

## Le Progress

After implementing mappers 1 and 2 along with all the interrupts I've been able to run a few more games. Unfortunately "run" doesn't mean "play", most games fail to get past the title screen.

I can play a couple games though:

Every game seems to have sprite issues though. Mega Man seems to load sprite RAM with garbage and doesn't display anything, the pacman demo requires a bunch of palette hacks and in asteroids the ship sprite gets all messed up on some of the rotations.

## HOLY SHIT IT WORKS!!!!!!1

Yep I've actually been able to emulate something. Not much really, just a simple 32KB public domain ROM, but it's a good start. I'll be implementing the memory mappers over the weekend and trying to run something bigger.

I've also been working on the various debugging tools for the emulator. The only one that's finished is the disassembler, which I finished about an hour ago and helped in fixing a few broken opcodes to get the above program running.

Edit: Just did a speed test. Around 18000000 instructions per second before it drops below 60FPS at 3x resolution, more than enough.