Home
Development
OpCodes
Technical
Screen Shots
Downloads
JavaDocs
NES Specs
Links
Help
Feedback
Admin


monkeycoder();
MonkeyNES Development

This page is in reverse chronological order, if you are new to this site please start reading from the bottom.

2005-04-16 19:34

Added a cycle cap to the HighResolutionTimer. This effectively prevents the timer from running away. Running away is where the amount of time needed to complete a cycle batch results in the next batch being larger, and this process tends to run away into larger and larger batches. The cycle cap is the maximum number of cycles that can be returned by the timer regardless of how many cycles should have actually happened. This will keep the system responsive to user input but will reduce the effective clock speed.

Started to design a component for picking colors. Failed for now to come up with a control that suits me for that purpose however, so the ability to adjust the master palette is not ready yet.


2005-04-13 11:26

Updated the MemoryMapper interface to include a method that can be called by main memory to indicate that a write was performed. The mapper can do whatever it wants with that information and then returns whether or not the write to memory should actually take place. Since most values the mappers care about are writes into ROM they needed that ability to prevent ROM (usually program data) from getting all messed up.

The other side effect of that however is that memory write functions needed to be created to allow the mapper to do its initial load of memory and ignore the mapper's own ability to veto writes. It was a catch 22 really. The mapper is responsible for the initial load of the ROM into memory, the mapper has the ability to veto writes to memory, in general the only writes that are vetoed are the ones to the section of memory that is ROM, thus the mapper was vetoing its own attempt to load the ROM into memory.


2005-04-12 23:13

Corrected an off by one error in the pixel color that only occurred at the right-most edge of the sprite (assuming the sprite was not flipped). It was being cuased by an inaccurate bit shift. Added correct transparency to sprites so color value 0 is not drawn. Added code that will properly flip the sprite in either the horizontal or vertical directions (or both) correctly.


2005-04-12 14:29

Spent a little time today upgrading the pattern table viewer. When I wanted to draw a sprite with a script last time, I had to scale a screenshot of a pattern table up 400% and draw lines on it by hand and do a lot of counting to make sure I was looking at the tile I wanted. This process seemed like a huge waste to me so I added a red box as a cursor for the pattern tables and convenient labels at the bottom for identifying which pattern table you are in, and also which tile you are over. While I was in there I greatly reduced how often the pattern table image needed to be regenerated. It was a good thing in general and was also very helpful for displaying the red box cursor quickly as the mouse moves around.


2005-04-11 22:07

After some work on the PPU today, I finally got the sprite rendering PPU internal function working to the point where a test script designed to display one of the helmet guys from Super Mario Brothers actually showed him. He is built out of four 8x8 sprites positioned carefully next to each other and the colors he's made out of are simply colors hand picked by me. The screen shot has been posted in the screen shots page.


2005-04-11 15:02

In continued efforts to work on the guts of the PPU, I created a sprite test script for the OpCode Test Shell. This script included new commands that didn't exist at the time. Now inspired by that script the ppu command has been written granting you more or less direct control over the internals of the PPU.

Also in the desire to make information validation even easier, I spent some time creating additional tool windows. Now, similar to the PrgRomHexViewerGui, I have created both SpriteRamHexViewerGui and VideoRamHexViewerGui. Then realizing that a visual way of validating the palette would be a good idea I also created the PaletteViewerGui coupled with the PaletteView component. Screenshots have been updated with the new tools.


2005-04-11 01:27

Wired the PPU to the video screen with the Observable/Observer system. This is one place that will work perfectly. In an effort to test the PPU/Video interaction I created a test pattern tied it into the main hardware loop and had it cycle internally while sending update messages to the screen. The result was quite fun to watch, and while the cycle counts were higher per update than the CPU running on its own, they were actually keeping up.


2005-04-10 16:02

A very long time ago I wrote the NesController interface and the class NesJoypad. At the time I felt I was doing it correctly based on the specs I had, but since I had virtually nothing else in the system coded to wire the controllers into, I had no real way of knowing. Today, while working on the DmaManager I wired the joystick ports into the system through DMA's, and I must say, the task was completely painless. The interface turned out to be well designed and easy to use. I've also written the various video memory DMA channels as well, but they have not yet been tested.

One thing I've realized I need to figure out is how to implement the appropriate delays caused by DMA's. For example, while the DMA to write a full page of main memory into sprite memory takes place nearly instantly in my code, the CPU needs to be prevented from doing anything for a rather incredible 512 cycles. Related to this is the thought that my Memory Mapper interface will both need to be updated (as I expected it would) but also that the use of the mappers will need to be moved from the upper hardware level down to the main memory level. More research is needed before I can prove that, but for now I have a rather strong hunch based on things I've read.


2005-04-09 17:35

I stumbled across a rather vast collection of PPU related research documentation in my very own collection. Part of the problem was that many of the documents actually refer to the PPU as the 2C02. I actually knew that from all my research, but it had completely skipped my mind when I went looking for something on which to base my PPU development.

Wrote an OpCode Test Shell script to validate the write to sprite memory DMA I had written. Testing it identified a bug in the OpCode Test Shell where address 0 was not accurately testable for any of the memory banks. Once that was fixed the DMA was proven to work accurately. There are several others to write still, but so far my game plan for DMA's seems to work quite well.


2005-04-08 10:13

As it turns out the JMP bug wasn't terribly difficult to code it just took a little bit of mental gymnastics to come up with a way that reliably produces the desired effect. It now works in the correctly "bugged" way. The various Zero Page indexed addressing modes now remain in the zero page of memory as they are supposed to. The theory that it would be a centralized fix turned out to be correct.

Since I'm ignoring the task of OpCode Test Scripts for now in lieu of coding things that are more interesting, I will be working on a DmaManager. The way I see it, memory being observable is only truely helpful for the timely updating of various GUI tool windows, and not for the core activity of the emulator. After thinking about it for a bit, the observer would end up doing things in a seperate thread and would likely result in obnoxious race conditions from time to time that would be nearly impossible to trace down.

Speaking of memory access, my NesMainMemory does not do proper shadowing for a couple of spots, and may need to be the home for the above mentioned DmaManager. We shall see as I learn more about the sneaky little things the NES did that were not directly part of any of the main chips. Information I have on the CPU totals in the thousands of pages, while what I have on the PPU stacks up to less than one hundred pages and it all seems to contradict itself or not provide any real information. So much research still appears to be required.


2005-04-05 19:15

Remembered a "bug" in the Indirect JMP OpCode that was in the real processor but has not yet been implemented in my CPU. This one may be a little tricky to code, and due to the confusing nature of the result, probably equally tricky to test.

Also realized the Zero Page, X and Zero Page, Y addressing mode instructions must all be tested for address wrap conditions because all zero page instructions are designed to stay in the zero page. Fortunately that should be a centralized fix in the code.

As a distraction from OpCode Test Scripts I have started to research the PPU. It turns out there is a 3rd bank of RAM in the NES. Clocking in at a whopping 256 bytes in size, the SPR-RAM (or Sprite RAM) is an independent memory bank accessible through DMA Channels. I added a NesSpriteMemory class to the system to accommodate.


2005-04-05 19:15

I found a good explanation of page boundry crossing by indexed addressing modes and corrected the code used for determining when it has happened. Now all 152 OpCodes are written, and all the addressing modes appear to work correctly. All OpCodes previously colored blue on the OpCode Page are no longer blue. All that's left is to validate all OpCodes that haven't been validated yet and the CPU will be done. I hope to finish that tonight or at least make a lot of progress.

Ok, for the record, it's extremely difficult to remain motivated while working on OpCode Test Scripts. Especially because many of the OpCodes I'm now building scripts for now have several conditions that must all be validated. This includes things as simple as setting flags accurately, and as complicated as chewing up the right number of cycles.


2005-04-05 11:56

All OpCodes are now coded in the CPU core. The remaining ROL and ROR proved to be quite a pain due to just how different Accumulator and memory based addressing modes really are. SBC wasn't so bad as it's almost exactly the same as ADC except for the use of the carry flag and the obvious replacement of a minus sign in a few places.

All that remains is to either locate a document that better explains what page boundry crossing is or at the very least to read it again and again until it clicks. That will be part of the validation process for 17 of the remaining 60 OpCodes.


2005-04-04 13:55

Continued efforts on developing OpCodes in the CPU have finally resulted in a working ADC OpCode. This is extremely exciting and it took a programmers manual from 1976 before I felt I had enough information to accurately code it. For good measure I've already tested ADC in immediate addressing mode through the OpCode Test Shell. Subtraction and the missing modes of ROL and ROR are next on my list, and are the only remaining OpCodes not yet written.


2005-04-02 14:46

With so many OpCodes now successfully verified I decided to spend a little time actually coding the guts of the ones that are still missing. Coded several ASL OpCodes and a couple ROL and ROR's as well.


2005-04-02 10:07

I've been working for many hours now (tonight and this morning) on getting the cycle counts correct for branch instructions. So far they still aren't correct and are proving to be extremely tricky to fix. Most of the problem is accurate detection of a page boundry crossing for relative addressing mode.

Relative addressing mode page boundry detection now works perfectly. The branch instrustions are no longer blue on the OpCode Page because of this fix. Now comes the tedious process of testing all of the branch instructions. The scripts have to test all 5 uses of each branch instruction and validate resulting PC value and the number of cycles the branch took. Fortunately there are only 8 of them for which to write scripts.


2005-04-01 11:29

Validated OpCode count is now up to an amazing 82. That puts me well over half done with the CPU by OpCode count. There are still several more OpCodes I can write test scripts for, but I think I'm going to actually spend a little time writing new OpCodes today for a change of pace. Also added JavaDocs to the file that was missing them.

The regs OpCode Test Shell Command now supports display of individual register values or flag values by name. The new regset command allows for directly setting register values and works in the same way as the memset and vidset commands.

Put the output from help for each OpCode Test Shell command up on the Help Page.

MemoryAccessMessage now supports an access type of TYPE_CLEAR for use by the clear() functions of both NesMainMemory and NesVideoMemory.


2005-04-01 00:13

The step command was not returning any information besides how many cycles it took to execute the next step. The output of how many cycles an operation took does little good for accurately identifying what was done. A new data transport class called ExecutedInstructionInfo was created for the purpose of providing more information back to the OpCode Test Shell.

Plans for tomorrow (well, later today I guess at this point) include filling in the JavaDocs for GameGenieTableModel which was thrown together in haste and didn't get them as it should have. I've been tossing around the idea of adding a command to the OpCode Test Shell that allows direct manipulation of CPU register values. And naturally, more OpCode Test Scripts and maybe even some work on correcting the "blue" OpCodes or writing code for unimplemented OpCodes.


2005-03-31 11:25

Working on OpCode Test Scripts again. I've corrected a problem that universally affected all CMP, CPX, and CPY OpCodes. The problem was caused by a misinterpretation of a description on how the OpCodes work. After referencing another document and rereading the original description again, I pinned down how it should be working and set out fixing the 14 OpCodes that were broken because of this. Now finished validating INC, DEC, CPX, and CPY for all addressing modes.

Added memclear, vidclear, step, and rom commands to the OpCode Test Shell. The power on command no longer clears memory. The step command runs the next instruction in memory as though the CPU were just granted enough cycles to do it. The rom command loads a ROM file and inserts it into the hardware.

Corrected the power up sequence the hardware was using. The old way resulted in the program counter being stuck at the default of $0000 which is inaccurate in all sorts of ways. The power on order of events was powering on the CPU before powering on the mapper and for that reason the CPU was loading the Reset Vector before any memory was loaded from the ROM.


2005-03-29 23:29

After a bit of work on the news/development note admin tools for this site, I have resumed working on OpCode Test Scripts. I'm expanding my script creation into addressing modes that are more complicated since they obviously need to be tested too, and likely more than the easier ones for which it is easier to write scripts. It makes me happy to be working on the core emulator again on some level after a break for Game Genie related things and a spot of web development.

Added the clear() method for resetting memory to all zeros to both main and video memory banks and also made the power on OpCode Test Shell command do this to both banks. This will help eliminate false successes on OpCode Test Scripts caused by values that exist in memory before the test.

Verified and corrected as needed 7 OpCodes tonight. These included advanced addressing mode versions of STA, STX, STY, INC, and DEC OpCodes. Many more will likely be verified tomorrow, and if I can work up the motivation, I will even code some OpCodes that haven't been implemented yet.


2005-03-28 15:14

I've finally gotten around to actually working on the Game Genie GUI. It's been a while since I've used a JTable so I'm a little rusty and it took a little longer than I would have liked as I relearn how to use them. The GUI window does very little in the way of validating the codes or values entered by the user, but it does work. You can add or remove codes with relative ease. There is a screenshot of the new GUI on the Screen Shots page.


2005-03-26 19:10

Today I fixed how the indirect addressing mode functioned. It was not returning the target address, it was instead returning the value at that address. For this reason the JMP OpCode in indirect mode was broken. Also, the JMP instruction in absolute mode was doing more of an inaccurate indirect jump instead. Both have been corrected and function properly now.


2005-03-19 17:23

Coded the GameGenie hardware and incorporated the use of a MemoryFilter into NesMainMemory. The Game Genie I have created is not limited to 3 active codes as the original Game Genie was, but due to processing overhead, I can't recommend the use of excessive numbers of codes. Every time memory is read the Game Genie code must check to see if it needs to return a modified value for every active code. How much overhead this adds is unknown, but considering the frequency of memory reads, I can only assume it adds up pretty quickly.

Next on the list of things to work on is a GUI for dealing with active codes. I will likely allow codes to be entered as either original Game Genie formatted codes, or as raw data for the 3 fields (or 2 fields for 6-character codes.) I figure I will resume working on OpCodes soon, but I needed this break from them.


2005-03-18 18:26

Corrected a small problem where 8-character Game Genie codes were not being properly recreated from stored data all the time. Had the wrong bit mask in one place. If that bit happened to be a 1, the index of the resulting value was way out of translation range. Otherwise it worked fine.

Revised the MemoryFilter interface. Didn't seem right that a filter would need a reference to a memory bank to function, so now both the read and write functions expect a value. To work correctly, it is expected that you read a value from memory and pass it through the read filter to get the byte that should be returned. For writes, you pass in the value you expect to write, and it returns the value that should actually be written. Makes much more sense this way as it also means that the MemoryFilter interface can be used on any type of memory where before it was being inadvertently restricted to work with main memory only.


2005-03-17 02:21

Completed the GameGenieCode class. This class acts as a data transport and translation system. This particular file may have more bit shifting and masking than any other file I've ever written. The designers of the Game Genie were clearly trying to make it difficult to make your own codes. Perhaps they were planning on selling you new codes, and if my memory serves me, they did just that for a short time. Their efforts to obfuscate their code system did little beyond making it more of a pain to emulate in the end, but my tests of the code translation functions seem to prove my efforts victorious none-the-less.


2005-03-15 23:49

Very little development today due to socioeconomic forces beyond my control. (Forces that will likely continue to affect me for the next couple of months.) I still have some things to talk about however. In web site development related news, the display and input form portions of the feedback system were written today, the submit and form validation parts will probably be written tomorrow.

On the Game Genie front, I put together a skeleton of the actual hardware code today and prompty realized I would not be able to do anything effectively the way I was planning on doing it. My thought was to have a GameGenie object that was a main memory observer. It seemed right until I started writing it. Then I quickly realized that an observer would be unable to jump in and supply an altered value since the unaltered value was just read (and thus why the GameGenie code was getting the access message about it.) The correct way to do it is actually to create a generic MemoryFilter interface that provides the rules for altering values read from or written to memory. Then to revise the NesMainMemory to allow the use of one of them. And finally to make the GameGenie hardware code implement the MemoryFilter interface. A clean and simple solution that provides the ability to support Game Genie codes, and any number of other interesting filters that someone may come up with later on.


2005-03-15 02:46

Started working on a database backend for the Monkey Coder sites (which obviously includes this site.) This system is small and only designed to handle news (like development notes) and feedback (like bug reports and other end-user comments.)

In news actually directly related to MonkeyNES I can say only that as a small break from working on OpCode test scripts I started to think about a GUI for Game Genie related activity. To make everyone's lives easiest it will support a code box for original Game Genie codes and boxes for the translated hex values. The boxes will be connected in both directions so you can fill out one set or the other and the other set will be filled out for you. This should give you the ability to create Game Genie codes in the simplified broken down way (the way the system will handle them internally) and it will produce for you the scrambled codes the original Game Genie used. So, if you own one, you should be able to try out the codes on your real system. I will code the Game Genie system when I have time, and hopefully soon while it is still fresh in my mind.


2005-03-12 13:27

FreeBSD has historically weak Java support. I believe the last "official" release of Java for FreeBSD was version 1.1.8. Recently there has been talks between FreeBSD people and Sun people to try to get a more recent version of Java onto FreeBSD. From that effort a port has become available for Java as recent at 1.4.2. Technically 1.5 is also available, but they don't reccomend its use. This is exciting news for FreeBSD users. It took my FreeBSD machine (P4/1.7ghz) a little more than 4 hours to compile Java and it used almost 1.7GB of hard drive space in the process. MonkeyNES does in fact run under FreeBSD which was cool to see. Due to these efforts a monkeynes.sh file is now also included in the package to start the emulator. This also means that the minimum version of Java required to run the emulator will not be 1.5 as was previously indicated. That way I have the potential to reach the most people on the most operating systems.

And once again... back to test scripts for OpCodes. Several OpCodes have been corrected (more address/value mismatching) and several have been proven to work correctly. The total for validated OpCodes is now up to an impressive 52.


2005-03-10 17:42

I've been working on OpCode test scripts all day. Several of the OpCodes that I had already validated I had to revisit because I was not properly verifying conditions that are supposed to change processor status flags. I am being much more careful to write the scripts completely now.

Several OpCodes that had already been verified incorrectly have now been fixed. One example is the TSX OpCode was not correctly setting status flags S or Z. The reason for this was simply because the code wasn't even there. The document on which I've been basing most of my OpCode development said nothing about affected flags for any of the "Stack Instructions." As it turns out, all the other documents I have do say something. TSX and TXS are not quite opposites as I had previously assumed. Transferring from IX to SP affects no flags because the SP register simply doesn't care. Transferring from SP to IX however can affect either the S or Z flags because the IX register does care.

The NesCpu now correctly treats all unknown OpCodes as NOP's. INX, INY, DEX and DEY all now correctly set the S flag. STA, STX and STY now work correctly in absolute addressing mode.


2005-03-09 01:15

I thought of a feature that would make the OpCode Test Shell even better. The ability to verify values automatically seemed like a good thing to add. That way when looking over the output of a complicated script you can see right off the bat whether a value is what you expected it to be or not. Now using the test command you get a clean and easy to read true or false value from a comparison.

The test command gives you direct access to all CPU registers, all CPU flags, and both main and video memory banks at any address. You can compare them using =, !=, <, >, <=, or >= to any hex value you wish. As with all other commands in the test shell, full help is given both at parse time and through the help command.

Back to writing OpCode test scripts...


2005-03-05 22:18

After 2 extremely long feeling days of updating JavaDocs for source files that truely should have had them all along, I am done. All current source files now have full JavaDocs. Go check them out from the JavaDocs page if you like.


2005-03-04 23:00

After what has seemed like an eternity of doing JavaDocs, and if not an eternity certainly all day, I have caught up on fleshing out the JavaDocs for 30 of the 44 java files. If this isn't an extremely strong case for doing JavaDocs as you develop instead of all at once I don't know what is. Not a whole lot to report on the development front because of all that JavaDoc'ing. Check back tomorrow for what I hope to be the report claiming I am done with JavaDocs and have resumed my efforts on OpCode validation.


2005-03-04 11:41

The opx parser now works! It successfully translates 6502 assembly statements into op commands for you. Now the real JavaDoc effort can begin.


2005-03-04 08:27

Added into the OpCode Test Shell the ability to detect recursive or cyclic nested file loads. It allows nested files to be loaded up to 10 layers deep. I cannot imagine anything that would require a depth more than about 3 deep, so I figured this wouldn't be limiting, but would help prevent trouble. The count of 10 does not include the original load command typed in by the user. Started working on the opx parser as well.

Added the CpuRegister16 class to prevent confusion between the 8-bit registers and the program counter (PC) register which is a 16-bit register. Also added the cage() function to CpuRegister to provide a centralized function for restricting the bits that are in use by the rregister.

Began fleshing out the JavaDocs for this project. This may take several days to complete, but I feel it will improve the overall quality of the project tremendiously.


2005-03-03 07:56

Ok, the supposedly broken addressing mode was not actually broken, the use of it was however. I inaccurately assumed the addressing mode was broken when "fixing it" also fixed the OpCode I was testing at the time. The flaw there is that all the other OpCodes that use that addressing mode need to go back into the test bucket. I have reverted that change and created a master test bucket script. OpCodes are no longer fully validated until they are ALL validated at the same time by the master script.

This also presented an interesting problem where using the clear command in files loaded by a script would effectively destroy the output for that script instead of simply cleaning up the output buffer which is desired when scripts are being executed one at a time. The load command now disables the use of the clear command in nested scripts.


2005-03-02 12:46

The OpCode Test Shell is just about the best piece of code I've ever written. It's like installing a bug zapper into your code and hooking it up to a 20,000v power source. I've found broken OpCodes, broken addressing modes, even memory writes that weren't being contained properly within their 8 bits per address, all made visible in crisp detail with small scripts.


2005-03-02 08:51

Ok, lots of new features added to the OpCode Test Shell. There are now quite a few things the it is capable of doing. You can run ops, clear the output, turn the power on and off, set values to or get values from either main or video memory, add comments, view the CPU registers, load scripts from a file, and save the shell output to a file. It even reports how many cycles the instruction took to complete so you can validate branch taken and page boundry conditions. And how about the added pleasure of a command history you can navigate with the up and down arrows. All that and all the help for each command you could ever want built right in.

Now comes the fun, read horrible, part. Now I have to sit down and write 152 test scripts that literally beat the heck out of each OpCode and confirm how it handles both base and border conditions and make sure they all work. And let's not forget that I'll need to fix the ones that I find to be broken. On the bright side, most of these scripts don't need to be very long and many will be able to borrow code from each other as they test similar things. On the not-so-bright side however... did I mention that I have to write 152 of them? Many of which are for OpCodes that haven't even been developed yet.


2005-03-01 15:34

Everything except opx is written now for the test shell. New things may be added as I use it to test OpCodes and determine that new features would be nice to have.

The process of verifying all the OpCodes will be documented on the OpCode table page with the use of colored backgrounds behind verified OpCodes.


2005-03-01 08:34

Created the basic layout for the OpCode Test Shell and tied it into the Tools menu. More information to follow as I work on it throughout the day.

The function for getting a specific bit from a register still wasn't working correctly and should be fixed now. The OpCode Test Shell has come very far considering it didn't exist at all this morning. It now has an extensive help system and can execute instructions. Next on the platter of things to add to the shell are setter and getter functions for main and video memory. The help system already knows about them, but the code isn't actually done yet for them. After that the opx command for executing 6502 assembly instructions instead of the raw hex support of the op command will be written.


2005-03-01 01:04

Cleaned up the CPU State Viewer in the ways mentioned below. Everything is in convenient to read hex values, the status register has been split into the individual flags and a bug was located in the CpuRegister.getBitValue(int) function. The function was supposed to return an int with a 1 or a 0 depending on the value of the bit at the requested position, but the value was not being properly shifted and the value was of the mask not the bit.

Tomorrow I begin the insane process of creating an OpCode test shell. A system through which each OpCode can be executed with different values and the CPU/memory state before and after can be viewed and checked for accuracy. I'll be honost here, I'm really not looking forward to this, even if I know I need to do it.


2005-02-28 00:21

The CPU State dialog is done for now. It's ugly, it should problably have the information presented in a cleaner way, and it's not real-time, but it does appear to work. On the fact that it's not real-time I did that on purpose. The last thing the poor overworked CPU code needs right now is the added overhead of sending out state update messages. Breaking apart the processor status (PS) register and converting the other values into hex prior to display would probably be nice so I'll keep that in mind for the next version.

On the bright side this new tool has hinted at a couple of potential bugs. That makes it worth the effort already. Now granted the CPU isn't done yet, but the ACC and PC registers either aren't ever being updated, or they aren't being reporting correctly to the state viewer, but something about their values seems wrong.


2005-02-27 16:28

I remembered that I was working on this project once upon a time and started looking at it again. Most of today was spent digging through the code and even these development notes to figure out what I may have been doing when I stopped coding last time. Cleaned up this site a little bit too. Specifically I pulled the OpCode table out of the development news page and enhanced it to include ALL OpCode information (accessed by mouse over of the table.)

Since at some point in the last 6 months version 1.5 of Java was released by Sun, the project will likely be written to require it from this point on. This may also involve revisions to existing code to use new features. Hopefully the new version of Java will be a little faster.

In regards to my complaining about the speed of the project in previous posts, I would like to mention that a wise friend of mine reminded me of a very important rule of development. "Get it to work, then make it faster." So for that advice I send my thanks to Org, as without that simple thought I may never have resumed development on this project.

First I plan to work on is a CPU status GUI. It will undoubtedly be an overcrowded and hard to read window full of register values and status flags and program counters and everything else, but I think it will be very handy to have in the near future as I attempt to debug my OpCodes.


2004-09-06 22:32

I've stumbled across some serious doubts about how I'm doing things within my NesCpu class. Questioning things as simple as "Am I properly restricting the values to 8 bits or 16 bits for addresses?" up to things as complicated as "Am I setting register values and flags correctly for any of my instructions?" and let's not forget the one that can spell doom for the whole project "Why is my CPU running so slowly considering how simple the things it does are?"

I think before I can go much further on the NesCpu class I will need to create an op code test driver and build the hooks I need to support it. That way at least I can see exactly what I'm doing and whether or not it's wrong and if it's wrong, how exactly it's wrong.

After that I will need to start thinking of ways to speed everything up. The current speed of things internal to the CPU isn't able to keep up with the clock speed of the system, and that's without the added overhead of the PPU, the pAPU or cycle counting in mappers. I only hope I can figure out how to make it faster. I think in this case I may be fighting a battle against the inherent speed issues of Java.


2004-09-04 20:01

Added a PRG-ROM Hex Viewer so that I can look at the bytes in the PRG-ROM to verify things. Sounds so simple, but it's actually easier to use than a hex viewer on the .nes file because of the fact that it only shows what's currently in PRG-ROM (and with the correct offsets) and not other things like the INES header and CHR-ROM and the like.


2004-09-04 13:36

Finished coding all the addressing modes. Now I can really start laying into the op code development. For progress on the op code development please see the table on this page.


2004-09-04 02:07

Found a decent document on how the addressing modes work, it's not quite perfectly clear on a couple because I have to match them up to information in other documents due to differences in names but it should be good enough to go on. In the mean time I can code many of the implied mode instructions.

I also needed to stop development to chase down some conclusive data on how exactly the stack works in the 6502. I knew that it lives in page one of main memory, and I knew that the stack pointer points at the first available empty spot on the stack... but I needed to know which way the stack worked in terms of addresses. I'm glad I looked because I would have assumed that the stack pointer starts on $0100 and increments toward $01FF with new pushes. I would have been completely wrong however. As it turns out the stack pointer starts on $01FF and decrements with new pushes. This is very important for roms that do any sort of stack short cutting.


2004-09-03 00:36

Began working on the NesCpu and NesOpCodeTable classes. This is obviously one of the largest pieces of this project and between the two around 2500 lines of code have been added so far, and that is without even a single op code actually working in the CPU. Tomorrow will be spent coding individual op codes and researching addressing modes and that sort of thing.


2004-09-02 11:23

My research on how to render things faster turns out to have been a very good use of my time. I added a little bit of code to time the rendering of the Pattern Table View so I could easily see if my research was producing any speed advantage. Below is the results of my optimization:

  Initial CPU On
Old 3437ms 3547ms
New 62ms 6ms
Improvement 55.44x 591.17x

I didn't change anything about my PatternTableTile as I had originally planned to do. I started instead with the alternate rendering method. Instead of using the Graphics class to literally draw every pixel into the view, I now blast the raw pixels into a buffer, dump that into a MemoryImageSource, dump that into an image, and use the Graphics class to draw that image for me. It sounds like much more work, but when you consider the virtually non-existant overhead of blasting pixel values into a buffer it becomes quite obvious that time will be saved.

Today I bit the bullet and purchased some parts for a replacement machine for TrollServer. It'll be a couple of weeks before they come in and I can set up the server again, but the process is at least underway.


2004-09-01 17:55

Both memory banks (main and video) are observable now. To make this feature a bit faster for situations that truely don't need observation there is a second copy of each of the access functions now with NoMessage stuck on the end, these versions as indicated by their name don't send an access message to observers. This was added to make supporting mappers with features such as IRQ timing counters and virtual register access possible. As a test bed for this capability the Pattern Table Viewer now observes video memory and updates the tiles as needed.

I will likely be modifying the internal structure of the PatternTableTile class to (hopefully) speed it up a bit on the rendering end. While I'm at it, I will probably explore other methods of rendering to speed things up (because if the speed found in my Pattern Table Viewer is all that I have, I'll be seriously hurting for a good frame rate while emulating for real.)

In the near future I'll probably add a Technical page for more detailed descriptions of how things work within this system. Or at the very least, how I am planning for them to work.

TrollServer is still down and out, I have no replacement hardware yet. Anyone with a quad Itanium2 or Opteron system sitting around that wants to donate it?


2004-08-27 19:53

Began the rather brutal process of managing the NesController's interaction with the user and with the NesHardware. Ironed out a couple of issues with my timing loop too. The system I have so far seems to be pretty clean, there are undoubtedly a few issues that would come up if a Joypad was not "plugged in" to the Hardware, but I'll let those slide for now since with the simple system of a drop box to choose the type of controller plugged into each port, they should never come up.

Still no TrollServer... Keeping my code for the project and this site on my USB JumpDrive in the mean time.


2004-08-27 19:53

Built the main timing loop which locks the system to a specific clock speed while keeping it synchronized. Created the NesController interface and NesJoypad class for user input. Put the NesHardware in its own thread. Fixed the disabling of the menus to have the right things enabled or disabled at the right times. All in all it was a busy night of development.

In other news, the TrollServer machine is on its very last legs. There was an ongoing battle between the power supply and the motherboard and it would appear that battle is drawing to a close. There are no survivors expected. The frantic process of trying to find another cheap machine to turn into the reincarnated TrollServer has begun, but with my luck on ebay, it won't end up working out for me in the end.


2004-08-27 19:53

Tonight's focus is mostly non-NES related. I've fixed the StateLight class up a bit. It now draws correctly. I also created a logging singleton called DebugLog. It supports output to standard out, to standard error, to a file, and into the void (not logged.)

I am also planning to build several of the options GUI windows and the Help About window. I'm getting to the point where having some knowledge of what options I intend to offer is a good idea. Tweaked the NesPalette class so that the int versions of all the colors are available as well as the Color versions.


2004-08-26 23:17

Tonight I came up with a design for the timing system that I think I like. It should be able to keep the system to roughly the correct clock speed while at the same time keeping things properly synchronized. That way when I eventually support games that do PPU timing hacks, the rusults should be correct.

The basic plan is to time everything backwards. Effectively timing everything based on how much could have gotten done in a certain time frame and then doing that much stuff. 'Stuff' in this case is running a cycle at a time on each of the chips that is affected by the clock. (CPU, PPU, pAPU, etc.) If a single cycle isn't enough time to do something, the cycle is stored by each chip individually until enough are available to do the next operation.

Began the process of encapsulating all the systems of the NES into a single container class called NesHardware. It contains things such as the CPU, PPU, pAPU, Main Memory, Video Memory, the Game Rom, the Memory Mapper and the High Resolution Timer. With them all together under one roof the interactions between them should be fairly straightforward to design.

The sloppy coding of hard wiring the Pattern Table Viewer to the Power menu has been fixed. It is now accessible as it should be through the Tools menu. Also added to the GUI are the ROM loaded (green) and power on (red) lights in the status bar at the bottom.


2004-08-26 09:27

I haven't been able to work on this project for a few days due to schedule conflicts. Busted alternator in my car that I needed to replace, various social obligations, and countless other distractions have kept me occupied. I've glanced at my research stuff a handful of times and I organized my NES ROM collection into directories for each individual letter so the directories wouldn't take so long to load. More development is coming very soon.

To appease the masses that flock to this site every day for updates and screen shots and new versions and all that other fun stuff, I have added several screen shots of the Pattern Table viewer to the screen shots page. Now showing 16x Mapper 0 games that you might recognize.


2004-08-20 18:36

Aparently I was very tired last night, because my mathematical acrobatics were producing incorrect numbers for how big the pattern tables actually are. Today I decided to give it a go anyway and load the CHR-ROM as though it were simply the Pattern Tables. Then I made a Pattern Table Viewer and sloppily hard wired it to the Power On menu. I loaded up a Mapper 0 ROM, turned on the system, and amazingly the very recognizable graphics from Super Mario Bros. showed up in the Patter Table Viewer box.

The next step is to correct the sloppiness mentioned above and to correctly wire the Pattern Table Viewer to its proper place in the Tools menu. To do that I will also need to build a class for orchestrating all of my hardware related classes.

Also fixed a problem in my GenericFileFilter where it wasn't matching odd capitalizations of the .nes file extension.


2004-08-19 17:42

Due to the sheer number of mappers there are, the mappers have been moved from the com.monkeycoder.monkeynes.hardware to the com.monkeycoder.monkeynes.hardware.mapper package.

Also still trying to figure out exactly how the CHR-ROM is laid out. It doesn't seem to be simply the Pattern Tables as I had at first figured it might be. While it does fit perfectly in the Pattern Table space in the PPU Video RAM area, the info I have about the Pattern Tables seems to make them far smaller than the amount of data typically found in a page of CHR-ROM. Back to square one on that research I guess. For good measure I'll likely craft a Pattern Table Viewer before I move on just so I can see what IS in there.


2004-08-19 13:15

MonkeyNES Site Launched. After a couple of days of development and a couple of days of research before that, I figured I should make decent web site detailing the process. Eventually I may make this page database powered, but for now I'd like to stay focused on MonkeyNES.


2004-08-17 15:40

Working on many "under the covers" systems that do large amounts of work but don't really get much credit in the end. These include the code for loading a *.NES file into memory, the access functions for dealing with the main and video memory banks, and things like that.


2004-08-16 23:56

MonkeyNES development has begun. Trying to get around several limitations of the Java language already. Specifically, the NES is an 8-bit system so nearly everything involving numbers is based on the numbers 0 to 255. Java doesn't have unsigned types (either primitive or objects) which was messing me up with opcodes at first because the numbers were ranging from -128 to 127 which is obviously not going to work. My rather simple solution was to treat every 8 bits as 32 bits instead. This allowed plenty of space for numbers while probably speeding up the system as a whole due to the 32-bit machines it would likly be running on.

In most cases this change doesn't even require masking to make it work which is nice. The "wasted" memory involved is still nothing to worry about because of the simple fact of how little memory the NES actually had.