Wed Dec 25 00:00:33 UTC 2019

Presents for NMK

Been a long ol' time since I updated this. I've released a formalized version of my Gunnail alarm hack; it's no different from the version I laid out in a post on shmupsforum, but should be simpler to apply. But that's not all.

I'm also releasing a hack of P-47 Aces, which fixes the sound engine to play sound effects on time. You can get that here: http://daifukkat.su/hacks/p47aces_sfx/. The original behavior is pretty deficient in my opinion, and the fix ended up rather interesting and helping emulation, so I'm glad I went and did it. Though it was amusing to see the end stage screens with constant explosions, I'm hoping having properly timed sound effects will make the game even more enjoyable.

I'm hoping to start posting on this blog again more, some fun stuff coming ahead. For now, happy end of year festivities, whatever they may be. To a pleasant 2020~

Update 2019/12/28: I fixed the P-47 Aces fix, so now it works everywhere.


Posted by trap15 | Permanent link | File under: arcade, reverse_engineering

Sun Jan 24 23:07:34 UTC 2016

Thus Endth The Story

Completely out of left field, this one. I was at a friend's place the other day, and he had Mitchell Corporation's The Karate Tournament running. I'd never played the game but thought it looked interesting so I gave it a few rounds and thought it was pretty damn interesting.

Then I was told that the dumped version doesn't have English voice acting and has much slower "cutscenes". Of course, this means it's time to break out the ROM reader.

Another friend dumped the ROMs and I added it to MAME, and now it's coming your way. The driver that emulates this isn't in the best shape, so I intend to go fix it up at some point, but for now it seems to work fine, I noticed no significant problems.

Credits to The Dumping Union and Anonymous for this one. Get it while it's hot: http://daifukkat.su/files/karatour.zip, and a compiled MAME that can play it: http://daifukkat.su/files/karatemame.7z


Posted by trap15 | Permanent link

Wed Aug 19 03:44:08 UTC 2015

Restructuring

As you maybe noticed, I've removed dodonpachi.daifukkat.su. It was something I'd been thinking about doing for a while, finally bothered to follow through with it. Please excuse the mess as I re-link everything for the new placement, but all old links should still work and redirect to the new URLs.

EDIT: All done now!


Posted by trap15 | Permanent link

Sat Jul 11 09:00:08 UTC 2015

WonderSwan Hardware Tests

A few weeks ago I was working on my WonderSwan game project, Fire Lancer, and was trying to optimize further for speed to try to remove the lingering slowdown. I noticed I was very often copying large chunks of memory around, and figured that'd be an easy win if I could optimize it. Unfortunately, the V30MZ CPU lacks many opportunities to optimize memory copy. Luckily, the WonderSwan Color has a DMA engine which I felt could be put to great use in this case. While this sounded great, I was also skeptical that it could work on hardware, as I'm using on-cart SRAM for all of my RAM, only using the IRAM for tasks it's required for (sprite list, tiles, BG tilemap, palette), and I wasn't entirely sure if the DMA engine could access SRAM. For the time being, I implemented the DMA as Mednafen supported DMA from and to anywhere, intending to later test on hardware if I could indeed perform such a DMA.

A few nights ago I decided to start testing that, but as usual my scope exploded and woops now I'm checking instruction cycle timings and DMA intricacies. I wrote a test harness and log parsing tool that I can now use to test the timings of anything and easily get data and specifics off of a real WonderSwan. Naturally, I used my WonderWitch for this task, as it provides a very easy way for me to write code and get it running on a real console, and has a very small iteration overhead, allowing me to test many versions very quickly.

I'd like to explain my method of getting precise cycle timings, but I'm afraid I need to give a bit of back story first. Over the past few weeks at work I've been implementing a libc for our platform to get rid of the pile of garbage known as newlib. In the process of this, I had to implement rand(), which I decided to temporarily implement as a simple LFSR. With LFSRs on the brain, and being very mindful that any seed produces the same series of outputs that never have duplicates until the entire period has been exhausted, I devised a plan for getting precise timings from the WonderSwan.

Now, the WonderSwan has a noise mode for one sound channel on its sound chip. It's implemented as a 15-bit LFSR with 2 taps, one configurable and one fixed. The default tap configuration has a period of 32767 cycles, which is maximal length for a 15-bit LFSR. There are two properties of this LFSR that make it particularly interesting: the update speed is controlled by the channel's frequency register, and the current value of the LFSR can be read by the CPU. The first property is even more interesting when one considers the range of frequencies allowed by the register. The output frequency is f = MCLK / (2048 - reg), where the register can range from 0 to 2047. This means we can have the LFSR update at a rate of one update per master clock.

The more adept of you may already see where I'm going with this. Essentially what I can do is start the LFSR at maximum frequency, save the LFSR value, perform some operation, then save the LFSR value after that. From these saved LFSR values, I can convert them back to a cycle index using the property of LFSRs that causes all outputs to be unique. Now that I have a cycle index for before and after the operation, I can subtract the latter index from the former, and get a 100% accurate time delta with complete precision between the two sample points. With a small test, I can also check the cycle overhead of sampling the LFSR, and discard that overhead from real test results. This gives me perfect timings of any operation I wish to perform.

From here, I can simply schedule a series of DMA transfers of varying lengths and retrieve the timings of each, then correlate the data to get a final algorithm. From my tests, a DMA transfer takes 5 + 2n cycles, with n being the number of words to transfer. I discovered a few other things in the process, but those will be put up into a new version of WSMan soon enough.

I've open-sourced my hardware testing infrastructure and tools on my bitbucket at https://bitbucket.org/trap15/wswan_hwtest.


Posted by trap15 | Permanent link | File under: emulation, reverse_engineering, wonderswan

Mon Mar 30 00:21:06 UTC 2015

It's Turbo Time

A few things to say today. I've released two new hacks in the past few days, and did a fairly quick commission hack that was released recently as well.

Metal Slug 2 Turbo

I made a hack for system11 that makes Metal Slug 2 not a laggy piece of garbage. In the end, the old rumor that it was caused by "updating the game logic twice per video update" was incorrect. The real issue was much more dumb, and much more puzzling. The way they wrote their code to lock to 30 FPS is something like this:

void vblank_callback(void)
{
  if(vblank_counter != 0xFF)
    vblank_counter++;
  if(vblank_counter != 2)
    return;
  vblank_occurred = 0xFF;
  // do things...
}
void game_update(void)
{
  // do things...
  for(;;) {
    if(vblank_occurred & 0x80) {
      vblank_occurred &= ~0x80;
      break;
    }
    vblank_occurred &= ~0x80;
  }
  vblank_counter = 0;
  // do things...
}

At first, this code seems reasonable, and not particularly odd or troublesome. But now think of the problem case: what happens if the game update misses the 'every odd frame' update window? Now the game is waiting two entire frames to get back on sync. Because of this, instead of a drop from 30 FPS to 20 FPS, it is now effectively a drop to 15 FPS. If it drops to 15 FPS, it's not affected, but if it would drop to 10 FPS, it drops to 7.5 FPS. This is very very significant, and is what makes the game run at a snail's pace. Most of the time the game is not even dropping to 15, it's only displaying as such because of the poor frame limiter code. Yes, this is actually why it runs so poorly.

Now that I've discussed the problem, let's discuss how I fixed it. Essentially, I replaced their code with the code listed below. This new code is faster to execute, simpler to understand, and works better than the original. This is what I implemented in my hacked version:

void vblank_callback(void)
{
  vblank_counter = 2; // this needs to be done for other functions to update properly
  vblank_occurred++;
  // do things...
}
void game_update(void)
{
  // do things...
  while(vblank_occurred < 2); // wait for 2 frames to have elapsed
  vblank_occurred = 0;
  // do things...
}

You may look at system11's post on the release at http://blog.system11.org/?p=1442, including a very enlightening comparison video and instructions on how to replace the ROM on a physical cartridge.

Same!Same!Same! NEW VER!

I've made a more subtle hack this time around, opting to merely fix problems in the original game, rather than turn it into something entirely different. With NEW VER!, I have added built-in 30Hz autofire that doesn't break the flamethrower, rebalanced the powerup order, changed how long items last on screen, and rebalanced difficulty, in a way that I think makes the game both more fun, and more recoverable. That said, it's still an extremely difficult game, and that was one thing I actively tried to keep with these changes. In the end, I think this makes the game much more fair, and much more playable and approachable.

You can get it here: http://dodonpachi.daifukkat.su/hacks/samenew/.

Ketsui Arrange 1.7

I've released one last version of Ketsui Arrange, which removes the suicide bullets added in 1.5, and tweaks various parameters and colorations. This is the definitive version of Ketsui Arrange, and it will be the last.

I don't have much else to say about this, you can get it here: http://dodonpachi.daifukkat.su/hacks/ketarr/.


Posted by trap15 | Permanent link | File under: arcade, reverse_engineering