Articles Index
Front Page

VeNES Update #2
Jeremy Chadwick - October 28, 1996

Issue #1: Speed

Recently, many changes have occured to VeNES; the biggest modification being speed. In our previous updates, we were ranting and raving about how our 3500 opcodes a second was efficient and fast. We were dead wrong.

After a small conference with one of Mr. Snazz's co-workers, we were informed that CPUs work on a per-cycle basis -- therefore, a 1MHz 6502 CPU, such as the one inside of the NES, executes 1,000,000 (one million) cycles a second. In a 6502, (on average) each instruction (opcode) uses 3 to 4 cycles. The result of some simple math says that a 1MHz 6502 CPU executes somewhere between 250,000 and 350,000 opcodes a second.

All this meant to Mr. Snazz and I was that our code was slow -- beyond slow. "But why?" we asked one another. Our code, in some cases, was horrendous, and very unoptimized -- as all code is in the beginning stages of any major project. Mr. Snazz and I both agreed that our code was "evil," but not as evil as to only emulate a 0.1MHz CPU -- 1/10th the speed of the real NES.

So, Mr. Snazz and I sat down one evening to figure out what was causing the slowdown. Was it my unoptimized PutPixel() routine? Was it our 6502 emulation? Just what *WAS* it? We had no idea, so we began debugging.

We continued debugging all night long, drinking nearly 6 litres of soda in the process, until Mr. Snazz stumbled upon the answer. The slowdown had nothing to do with our graphics routines, our CPU emulation, nor our implemen- tation structure.

The slowdown was due to Borland Pascal's "KeyPressed()" function. As an assembly coder, I knew the solution almost immediatly -- stop using the stupid function, and start using an interrupt-based keyboard handler.

And that's exactly what we did.

In nearly 10 minutes, I implemented a replacement, totally interrupt based. I also disabled INT $16 (keyboard handler interrupt used by the BIOS in all PCs) -- why waste internal CPU time when we're not using it?

The speed increase was phenominal.

We jumped from our previous 3500 opcodes/sec to nearly 350,000 -- all on a 486 DX4/120 w/ 512k cache, still running under a Windows 95 MS-DOS Prompt! On a Pentium? I'm sure you can imagine.

Issue #2: Graphics

As I mentioned above, VeNES's code is far from optimized; the only assembly being used is for memory addressing, and graphics routines.

Previously, VeNES used the famous (infamous?) MODE-X, which many highend demo coders use to produce demos under "tweaked" video modes, such as the famous 320x240x256 mode.

As the NES screen is 256x256x16, I could not use the linear MODE $13, which consists of 65536 bytes in segment $A000 of the PC's memory. Very easy to address, and a PutPixel() routine would've been pretty fast, consisting of something this simple:

mov ax, 0A000h mov es, ax mov ax, 320 mul YCoordinate add ax, XCoordinate mov di, ax mov al, Colour mov es:[di], al We needed MODE-X to provide us with the extra 40 pixels for height, as in NTSC mode, you lose 16 pixels off of the top and bottom of the screen, resulting in a 256x224 resolution. In PAL mode, you lose 8 instead, resulting in 256x240.

"Then why not use 320x240?" you might ask. Well, you have to do small calculations to compensate for the extra pixels being gone -- calculations per pixel which Mr. Snazz nor I really wanted to deal with. Just more overhead and a waste of CPU time.

So, I did try MODE-X's 320x240 mode -- only to find out you cannot address it directly like MODE $13's $A000 segment. MODE-X works in bitplanes, therefore a simple PutPixel() routine ends up looking something like this evil son-of-a-bitch:

mov ax, 0A000h mov es, ax mov cx, XCoordinate and cx, 3 mov ax, 1 shl ax, cl mov ah, al mov dx, $3C4 mov al, 2 out dx, ax mov ax, 80 mul YCoordinate mov di, ax mov ax, XCoordinate shr ax, 2 add di, ax mov al, byte ptr col mov es:[di], al Now, if you're a programmer, you *KNOW* the speed difference between the two PutPixel() routines is phenominal, especially when it comes to having to use instructions like "out", communicating with PC I/O ports.

I was sad about this -- very sad. There was no real way around the problem, as I had never heard of a linear 320x240 mode before -- such can't exist (to my knowledge), as you'd need to address 128K in a linear fashion, and since PC segments are only 64K.... well, you can understand the problem.

I came across a small little utility called "TWEAK" by Robert Schmidt, which allowed you to make your own custom VGA modes, or to use some pre-set ones the author had already created for you.

To my surprise, "TWEAK" came with a "256x256x256" mode -- I just about shit my pants, as I knew this is EXACTLY what I wanted. But wait! Was it linear? I sure as hell hoped so.

Sadly enough, it wasn't -- but, I quickly found out that there *WAS* a linear 256x256x256 mode, titled MODE-Q. Rumour had it you could address the memory even simpler than in MODE $13, but that the aspect ratio was 1:1, not 4:3 like in MODE $13. Personally, I didn't care about the aspect ratio, as it makes no difference in this instance. Anyways, this MODE-Q did come with "TWEAK" as well, the pre-set file titled "256x256c.256" (the "c" stood for chained, which is what MODE $13 is as well; MODE-X is unchained).

I spent nearly 72 hours trying to figure out how "TWEAK" handled this "MODE-Q," as it was *EXACTLY* what I wanted...

I failed during the entire 72 hours; "TWEAK" does some of it's own shit in conjunction with the pre-set file -- the author doesn't tell you this, however. And since I don't know C... well, I was basically fucked.

A few hours later, I met a guy with the nickname "Bolt" on IRC, who had actually had experience using MODE-Q. With his help, I was able to correctly initialize the VGA CRT to handle MODE-Q.

"What about PutPixel()!" you may be asking. Well, PutPixel() became this simple:

mov ax, 0A000h mov es, ax mov ah, YCoordinate mov al, XCoordinate mov di, ax mov al, Colour mov es:[di], al Beyond simple, makes sense, and is *HELLISHLY* fast.

As of today, VeNES is now using MODE-Q, and the results are definitly faster than MODE-X (visually faster).

Issue #3: Colours

It seems many people are referring to VeNES as "the NES emulator with fucked up colours."

Rest assured, the colour/palette problem has been fixed thanks to the help of Alex Krasivsky.

Please, before stating misstatements about any software, make sure you have the most recent information by calling the producer, or by contacting the authors, or (gasp), by looking at the home page for the software again! Thanks.

Issue #4: Backgrounds and Sprites

Awhile ago, Mr. Snazz and I implemented background tile support, there- fore procuding the glamourous title screens you see on VeNES's home page today. We found a few bugs over time, such as some problems with VRAM addressing, and fixed the immediatly.

Sprites are another issue -- but just to inform you all ahead of time, yes, they are implemented, and yes they do work.

Sprites on the NES are very strange, and with our limited document- ation, we are unsure of what some of the sprite control bits do.

However, you can sucessfully control the sprites; we do have horizontal and vertical flipping enabled, therefore, the following games are playable to their full capabilities:

  • Donkey Kong
  • Donkey Kong Jr.
  • Mario Brothers
  • Pinball
  • Popeye
  • Tennis
Alas, there are sprite drawing problems; sprites aren't being masked with the background, and do leave traces of their previous frames laying around. These will definitely be fixed as Mr. Snazz and I devise a way to quickly mask sprites over the background.
Issue #5: Joypad emulation and Sound

I am constantly harassed in regards to sound in VeNES; it seems the two most desired things in an emulator are speed and sound. This doesn't come as a surprise.

I will lay down the truth here and now: Yes, VeNES *WILL* support NES sound (all 5 channels), but it is *NOT* a concern of Mr. Snazz nor I's at this present time. Sound is the LAST THING on our minds -- decent and fast emulation are our concerns. For more concerns of ours, please check the VeNES home page.

When sound is implemented, we will be supporting the Gravis Ultrasound first, and then slowly implementing SoundBlaster (original, Pro, 16, and AWE32) support later on.

Issue #6: Memory Mappers

Memory mappers... yes, the evil things which allow a NES game to be greater than 24K (including VRAM).

Currently, VeNES does not support any memory mappers. It loads a very limited amount of games.

Yes, VeNES in the near future will support all memory mappers, but do not ask Mr. Snazz nor I about supporting the MMC3 memory mapper/chip, as it's something I have no documentation on. We will be supporting all memory mappers covered by the NES documentation provided with the shareware version of "iNES" by Marat Fayzullin.

Archaic Ruins is not connected or affiliated with any mentioned company in any way. The opinions of Archaic Ruins do not reflect the views of the various companies mentioned here. Companies and all products pertaining to that company are trademarks of that company. Please contact that company for trademark and copyright information.
© 1997/1998 Archaic Ruins