| << Newer | Articles under MAME | Older >> |
Monkey
What you may have deduced from the whatsnew in MAME 0.106u1 (assuming you read it) is that some work on the video system was under way. I've been claiming "video system rewrite!" for so long that I can barely remember when I first started discussing it. It was at least a year ago, if not longer.
Ever since I first mentioned it, it has been a monkey on my back -- a giant "everything's gonna break" rewrite that I've been both itching to do and dreading at the same time. It's been clear for years that MAME has needed far more fleixibility in handling things like multiple screens. It's also been clear that my original attempt at a system to incorporate artwork was only partly successful. And there has been way too much interference with game-drawn graphics by external entities like the user interface, which has created a lot of grossness about the way video is handled.
All this was to be fixed with the video rewrite. And if you know me, you know that fixing all those problems is something that I really, really wanted to do. But at the same time, I was dreading it. Why? Well, the biggest reason is probably the fact that it would mean delving back into DirectX programming once again, which is always fraught with pain. Ever since the original port to Windows a number of years back, I haven't had to deal with the DirectX side of things much.
Plus, it's a hard problem, and not the sort of problem that I can easily solve in one-hour sessions over the course of a number of weeks. It's really the sort of problem that requires me to sit down with several days' worth of completely dedicated time ahead of me so I can get "over the hump" of the initial programming work and then spend the more normal one-hour sessions debugging/fixing the remaining problems.
Well, this past weekend, I'm happy to say, it finally happened. Bye bye,
monkey. :)
A number of factors came together to get most of the work done, but the
most important one (and the one that I have been planning around) is that
the missus was out of town from Thursday noon to Sunday evening. Couple
that with some vacation time, a bunch of junk food, some musical inspiration,
limited sleep, and you end up with a solid 78 hours of geekdom. I think
I ended up programming for 55-60 of those. It's all a blur now anyway.
The practical upshot of this is that the core work for the new video system is now written. I had the software-only version up and running by the wee hours of Friday morning, and the Direct3D-based version running about the same time Saturday morning. Artwork of all forms -- bezels, overlays, backdrops -- is working, including more flexible state-based control over the pieces. Vector games use the hardware to render the vectors. Multiple screen support works in the core, and most of the code is written to allow it to actually render to multiple screens/windows on the Windows-specific side, though I'm still at a loss for how to expose the new gamut of options in the limited form of the command line.
In subsequent days, I hope to provide more information about the rewrite, including details on the new layout file format and some of the internals of the new system. For now, I'm just going to list out a few interesting tidbits/side effects that you should be aware of. Keep in mind that although the basic system works, there are still a lot of things left to do.
- There is now a new layout file format (.lay), which is XML-based, and which replaces the old .art files. Converting a .art file to a new .lay file is a little tricky, but not too difficult. I've done it for invaders and turbo.
- XML-based layouts are also now used internally to describe how screens are oriented and positioned. For example, dual-screen games have a layout that positions the two screens relative to each other.
- Multiple layouts can be loaded and ready, and can be switched between at runtime. This means you can have a layout which only has the first screen of a dual-screen game, as well as a layout with both screens visible, and can switch between them. Eventually I hope to save this information in the .cfg file. Rotation of the UI and game screens will also eventually be able to be dynamically changed.
- There are no plans to support DirectDraw with the new system. It will be Direct3D or GDI only. DirectDraw has been deprecated for several years now. The Direct3D support will require Direct3D 8 or later, since I based the code on the work I did for the Radikal Bikers emulator.
- Even if you use software rendering, you still get stretching to the correct aspect ratio now (no filtering, just point-sampled stretching). You can turn this off by selecting a "native" layout, which is based on the pixel resolution of the screen rather than on the aspect ratio of the screen.
- A number of existing Direct3D and DirectDraw options will be going away in the first incarnation. Some of the options don't really make sense in the new world, and I doubt they will make a reappearance. For example, "cleanstretch" would only stretch the screen by integer ratios, but now each element in a layout can be stretched by arbitrary amounts, so there is no single item to use as a gauge for cleanstretch. A lot of the other options need some serious thinking in order to make a reapperance.
- In general, it seems that the use of video in MAME falls into one of two categories: either you are running it with a regular VGA monitor and want all the bells and whistles; or you are running it with an arcade monitor and want just the screen with no adornments and just the raw bits. I am considering making this a command-line switch, because choices about how to handle different behaviors can be more sensibly made if your intentions are clear.
- The UI font is now configurable. In the short term, this is more just for fun, but now you can provide any .BDF font (including proportional fonts) and use it for the GUI. I took one of the FreeFont TTFs and imaged it at 40pt to produce a nice, crisp font at high resolutions. Since the new rendering system is unicode-aware, we can eventually support displaying proper Unicode names of Japanese titles.
That's it for now. I'll post some screenshots later, and discuss more details
over the next week or two. Again, remember this is all still very much
a WIP, but the remaining issues can all be tackled one at a time. The big
deal was getting the core work done, and thankfully, that's finished!
Programmable Logic Devices in MAME
One of the best uses of MAME is the identification of random video game parts. Thanks to the -romident feature, you can dump a ROM or PROM from a game and pretty quickly identify what game you have. Believe me, as someone who owns a giant pile of PCBs, it is not always easy to tell. :)
In theory, MAME should catalog all the programmable parts on an arcade PCB. This is useful not only because of the -romident feature, but also because if a part fails due to bit rot or corrosion or some other kind of damage (or is just missing), you can identify it, track down the data, and program yourself a new one. Up until now, we have only been really cataloging ROM-based devices, in spite of the fact that another class of device -- the Programmable Logic Device (PLD) -- is often found on PCBs, especially those dating from the mid-80's onward. PLDs are a class of device that includes PALs, GALs, and other related devices, which are programmable in much the same way that ROMs and EPROMs are.
One of the big reasons why we haven't been including PLDs is because they are generally not stored in raw binary format, like ROM data. Rather, they are stored in a format known as the JEDEC file format (.JED), which is basically a text file containing all the data, with lots of room for programmer-inserted comments and many optional fields. This is not really a big problem in and of itself, except for the fact that every single programmer out there, when reading a PLD, will produce slightly different output. This in turn makes tools such as the -romident feature useless for such devices because -romident works by comparing the CRCs and SHA1s of the files, which would be different even for the same PLD read by different programmers.
I finally took a close look at the .JED file format over the past week,
and came up with several strategies for how MAME can finally begin cataloging
these parts. After a bit of discussion, I finally settled on one that will
be implemented in the 0.105u4 release which should be coming up shortly.
Here is how it works.
At the creamy center of a .JED file is what is known as the "fuse map".
This is the raw set of binary 1s and 0s that get programmed into the PLD.
In fact, the rest of the .JED file beyond that is mostly filler: some checksums,
default states for unspecified fuses, etc. The final fuse map is really
the important data, along with the type of device that was used (was it
a GAL16V8A or a PAL16L8?)
So the basic premise for logic devices in MAME works like this: the fuse map is stored in raw binary form, preceded by a single 32-bit (big-endian) value that specifies the total number of fuses. Each bit of the fuse map is packed into a byte from LSB to MSB. This, it turns out, is the exact format that is used for the internal fuse map checksum, so it is a natural arrangement. I decided not to try and encode the device type into the file because (a) there are way too many devices to be concerned with, and (b) many devices with similar but not identical names are equivalent. Rather, PLDs that are added to MAME should specify the device type in the filename. (Also keep in mind that if the device type were encoded into the file itself, then if person A reads a GAL16V8 and person B reads a GAL16V8A that contain identical data, they would not match.)
How do you get data in and out of this format? Well, starting with 0.105u4, the default build of MAME will build a new utility called jedutil, which can convert a .JED file into its binary form, and vice-versa. This means that you can find the binary form of a PLD, run jedutil on it, and extract a .JED which can be programmed into a real life PLD using any standard programmer.
So how does this help -romident? Well, if you read a PLD from a board and want to see if it matches anything we've cataloged, you can do one of two things. You can take the resulting .JED and run jedutil on it to convert it to binary form. Or, you can just point -romident to the .JED file directly, because I've added code to the romident feature that recognizes .JED files and automatically parses them into binary form on the fly.
The first experiments in using this will be the mid-80's and later Atari
games, which I've been working on cleaning up the names on, and which I've
already read the GALs from.
I know there are several other games out there that we already have good
PAL/GAL dumps from as well. Hopefully we can produce an even more complete
catalog of arcade game devices as a result.
A Tale of Two Kickstarts
When the Amiga came out, I have to admit I had serious computer envy. Here was a machine that had no text mode, up to 32 color graphics, tons of RAM, and the best port of Marble Madness ever! Not to mention lots of other games. In fact, the Amiga seemed to be specially tailored for games.
I did get my chance, briefly, to play on an Amiga when I was in high school, but sadly it wasn't my own. The teacher who ran the Computer Science department at my school was into Amigas, and had purchased a few for the school, using them for early desktop publishing of the school paper among other things. When I was a senior, I decided to take AP Computer Science, not so much for the challenge, but because I knew it would be an easy A. There weren't many AP CompSci people in the school (I was 1 of 2), so we pretty much got to pick our own "curriculum", as long as by the end of it we knew Pascal well enough to pass the AP exam. Since I already knew Pascal inside and out from my Turbo Pascal programming on the PC, I wanted to learn something knew. Well, wouldn't you know it, there was this Amiga, and they had Modula-2 for it which was technically a new language to me (barely ;)).
In the end, I managed to work it out so that I spent my AP Computer Science time each week writing games on the Amiga in Modula-2. I seem to remember writing a Gauntlet-style bow & arrow style game, and another Qix-ish like game before the semester was over. But I never really got to understand the full system.
So it was with this background that I decided to take a look at why the
Arcadia system games had no sound.
Turns out, the Amiga has a pretty basic 4-channel DMA driven 8-bit sample
playing set of DACs, and it only took a couple of days to get the sound
going. But by this time, I was intrigued. I had managed to track down a
used copy of the Amiga Hardware Reference Manual and as I read more
about the Copper and the Blitter and the custom registers, it sounded like
more and more of an interesting emulation challenge. Most of the Arcadia
games already worked pretty well, but there were still glitches in a few
of them, and Up Scope and Moonquake were two other Amiga-based
games that weren't yet in MAME.
With that incentive, I started delving into the existing implementation of the system. Although the Amiga implementation in MAME hasn't been around that long officially, I knew that Ernesto Corvi had worked on it on and off for a few years even before it made its debut. At the time, the original driver was written to be fairly low-impact, meaning it was reasonably optimized and made fairly poor documentation of how the system worked in exchange for speed (though by comparison to the UAE code, it was clear as a bell). I set out to change that.
The first thing that needed an overhaul was the video renderer. I noticed that Moonquake ran in extra half-bright mode, which wasn't supported, so I first tried to fix that. Along the way, I discovered that a lot of assumptions were being made in the code which would ensure that features such as dual playfield scolling and collision detection would not work without a substantial rewrite. A substantal rewrite ensued.
Of course, rendering on the Amiga is driven to a large extent by the Copper chip, and as I started to look into that, I realized that Magic Johnson's Fast Break (a)bused the Copper to jam multiple sprites and scrolling displays along the top and bottom of the screen. Which meant I needed to overhaul how sprite drawing worked in order to support these "manually drawn" sprites, and I also needed to tweak with the timing in the Copper code so that it changed the sprites at just the right instant within a given scanline. I'm still not convinced I have the sprite rendering and Copper timing just right, but it's good enough for the games we've got.
Then I wanted to understand this Autoconfig thing. There were some references to Autoconfig in the Arcadia driver, which is how expansion cards were plug & played on the Amiga. Taking the existing implementation at face value, I abstracted out the Autoconfig system so that MESS could eventually use it to plug in peripheral cards, and then I reconnected the expansion card in the Arcadia so that it worked via the Autoconfig mechanism.
Of course, after doing that work, I am now convinced that it is wrong. :) First off, it doesn't make sense that a custom piece of hardware like the Arcadia would bother to implement anything as elaborate as the Autoconfig protocol. Second, the first word of the Arcadia BIOS ROM is a standard Amiga "ROMtag", and if you map the BIOS up into the Fxxxxx space it boots fine without any Autoconfig mumbo-jumbo. And third, the docs say that the Arcadia systems ran off the Kickstart 1.2 boot ROM. But when you boot an Autoconfig device with the Kickstart 1.2 boot ROM, you run into a bug in the 1.2 code that causes a crash on startup if the device has a boot ROM (you can tell it's a bug because it is very clearly fixed in the 1.3 version of the ROM). I suppose the documentation about the 1.2 boot ROM could be wrong -- after all, up until now the Arcadia systems all ran fine with the Kickstart 1.3 boot ROM, right?
Well, actually, no. I now have proof that the original system couldn't have run off the 1.3 boot ROM. Sidewinder, a vertical shooter, always had particularly odd problems. The background bitmap would wrap strangely, and when you shot, you would hit random targets in the middle of nowhere. I tracked this down yesterday to code that would attempt to blit data from one bitmap to another, but which would somtimes specify the destination to be a location outside of RAM somewhere. Until recently, there had been a hack in the blitter that would throw away accesses outside of chip RAM, but I knew that was wrong because the documentation is very clear that outside accesses would wrap around and clobber important bits of program code.
Looking into this problem more closely, it turns out that the blitting code was doing a bunch of careful 16-bit calculations in the low half of the 68000's D1 register, and then at the end, adding the full 32-bit D1 value to the address. Which means it was assuming that the upper half of the register was 0. Tracing backwards, it was clear that this code was called as part of the VBLANK interrupt routine, and the code which put the non-zero data in the upper half of D1 was the part of the Amiga Kickstart ROM which actually handled the first part of the interrupt. Comparing that same section of code between the 1.2 and 1.3 Kickstart ROMs revealed very different register usage patterns, and sure enough, booting the system under the 1.2 Kickstart ROM produces no invalid blitter accesses and yes, all the graphics problems are fixed.
Of course, prior to discovering the Kickstart problem, I thought for sure it was a bug in the blitter. So yes, I ended up rewriting the blitter routines as well, attempting to document them moreso than optimize them. Which in the end was a good thing as I managed to somehow fix the blitting problems in SportTime Bowling. By this time, I'd rewritten 80% of the emulation, so finishing it off by rewriting the 8520 CIA I/O routines and cleaning up the rest of the driver goes without saying.
If I had the time, I'd probably play around with the Amiga emulation in MESS, now that I've made a number of fixes and improvements to the system, but there are more pressing matters, as always. Oh, and what about Up Scope and Moonquake? More later.
It’s About Friggin’ Time!
A while back, I emulated a couple of the early Gaelco 3D games, Radikal Bikers and Surf Planet. I knew at the time that there was a third game on almost identical hardware, which was the racing game Speed Up, but unfortunately the dump of that game we had was incomplete. Over the past couple of years, I've managed to acquire two different board sets for Speed Up, yet getting a good dump of the 42-pin mask ROMs on the board has been challenging to say the least. Guru and I even manually mapped the address and data lines back to the ADSP-2105 that runs the sound, and confirmed that they matched the standard pinout of an ST 27C160/27C322, yet my programmer would always end up with garbage.
A couple weeks ago, I was given a tip that sometimes these mask ROMs have either the /CE or /OE signals inverted. Last night I finally got around to trying it out, and sure enough, if I tied the /OE signal to Vcc during the dump, I got a good read of the sound and polygon data ROMs. Seemingly victorious, I also dumped the texture ROMs in the same way, but discovered that I had another obstacle in my way in reading those.
With the texture ROMs, my programmer complained that pins 15, 17, 19, 21, 23, 25 and 27 weren't providing good connections. Curious, I looked at the pinout and discovered that these were the D8-D14 lines on the chip. This is a good indication that these ROMs are intended to be read in BYTE mode, not WORD mode. Of course, my programmer only handles WORD mode, which makes things tricky but not impossible. I simply had to read the ROM twice, tying the A"-1" pin alternately to GND and Vcc, and then merge the results, removing the bogus upper byte of each word.
And so, at last, we have Speed Up. It pretty much worked straight
away, apart from some input port problems, and looks pretty nice. Reminds
me a bit of Cruisin' USA, except a bit smoother since the Gaelco
hardware supports bilinear filtering.






Long Time Coming…
And so another month and a half without a post. So what's been keeping me busy recently?
Well, the MAME 0.105 release for one thing. When I started out doing some initial cleanup work, I did not expect to stretch the dev cycle for that release into two months! But I just kept finding more and more ways of getting the core system into better shape, and decided it was best to get as much of it done at once while I still had the interest. And then there was the usual cycle of bugs. But in the end, I'm much happier with the way the system is initialized and cleaned up. It all makes much more sense now, and is much better documented.
Near the end of 0.105, I started getting the itch to actually emulate some stuff again instead of breaking a bunch of already-working things some more (imagine that!) Sega's Universal Sound Board is something I've been meaning to dive into for quite some time. Only two games were known to use it: Star Trek and Tac/Scan. As Sega vector games, they were also on my list to fix for another reason ... MAME was far too accurate at emulating the vector generator.
Wait, what do you mean, "too accurate?" you might be asking. Well, I couldn't help but notice when I was at California Extreme last year, playing Zektor, that after the big face taunts you at the start of the level and it begins to shrink down, the arcade game was very jerky -- it wasn't a nice, smooth scaling like I had always seen it in MAME. I looked into it a bit then, and found that the vector generation code in MAME used real double precision floating point sine and cosine values to accuracies that were not likely for 1981.
So I decided to completely rewrite the Sega vector generator according to the schematics. Turns out I was right. The Sega vector generator lets you specify an angle and length for each vector in a shape, and an overall angle and size for each shape as a whole. This is done by adding the vector and shape angles, computing the sine/cosine, and multiplying them by the vector length and shape size. In MAME, this was done to high precision, using a sine/cosine lookup table with full accuracy, and 32-bit math. On the actual hardware, the sine/cosine lookup table was sigificantly smaller with less resolution, and only the top 9 bits were used out of the multiplcation result. So now if you play any of the Sega vector games, you may notice some jerkiness that wasn't there before. It's most noticeable in the lower window in Star Trek and during the previously mentioned shrinking effect in Zektor.
But back to the Universal Sound Board. I figured this wouldn't be too difficult because it had some similarities to the Exidy sound board (used in Venture-era games), and I had already conquered that one many years ago. But the Sega board had its own share of interesting surprises. It is really a hybrid digital/analog system, so I ended up having to emulate a number of RC and CR filters along the various paths. It also used a digital noise source which produced white noise, but then ran it through an interesting series of filters that I just couldn't figure out. Luckily Frank Palazzolo had the insight that it was filtering the white noise into pink noise, and from there I was able to generate a pretty reasonable facsimile of the correct effect. In fact, if I run the sound self-test in Star Trek using the old samples and the new emulation, they are very close to identical apart from volume (maybe not as good as Derrick's stuff, but pretty good). Unfortunately Tac/Scan doesn't quite match up as well as I'd like, but it's actually pretty close. Hopefully with some more advice from the analog experts, I can nail that one soon.
After I did that, someone pointed out to me that Pig Newton also used the Universal Sound Board. Sweet! Plugging that it did indeed confirm that the main CPU uploads the sound code to the USB and plays some sound effects at the appropriate time. I love it when a plan comes together. :)
With all that work behind me, and most of the bugs caused by my core shuffling quashed, it was finally time to get 0.105 out the door. And then on to something new. I've been curious for a long time why the Arcadia games -- which are based off the Amiga hardware -- didn't have sound. Turns out it's just that it hadn't been implemented yet. So I started (re-)learning about the Amiga. But that's for another post.