25 Jul 2018

Capcom 85H001 (sound module) reproduction - part 2

After routing a small PCB for SMD parts I realised my supplier didn't have the targeted Z80 QFP chip I was planning to use... Boring.
So I had a look for an alternative and discovered SMD Z80s come with (too) many different pinouts.
Now I have to update my schematic and reroute a board...

Meantime I've routed a board for through hole parts (at least pinout is consistent). I'm quite happy with the result as the newly designed board is just slightly bigger than the plastic module:

The replacement module tested on Trojan:

The replacement module tested on Ghosts'n Goblins:

That's great to have a solution now for those evil modules!

18 Jul 2018

Street Fighter EX 2 - Arika/Capcom 1998 (repair log)

Game was working, sound effects were there but music was absent (in fact Q-Sound was missing).
I first swapped the CPU board with a known working one and problem followed the romboard.
It didn't take long before I noticed one tiny SMD part had been ripped off the romboard near the Q-Sound chip after a shock. Comparing with an other romboard I learned it was simply a 10k resistor bringing the clock signal to the Q-Sound chip from the nearby crystal.
I installed a new one and Q-sound was fully back.

Game fixed.

11 Jul 2018

Irem M72 multi kit - part 2

I've finally received the PCBs, assembled them and already made a small correction (2 yellow wires for the double size sprites ROMs of X-Multiply):

As you may have seen my projects are always a mix of software hack and hardware design, I repeated the process once again.

There are 10 known games on this hardware:
- Air Duel (Japanese version)
- Battle Chopper/Mr.Heli
- Dragon Breed (Japanese version)
- Gallop (a.k.a. Cosmic Cop)
- Daiku No Gensan (Japanese version of Hammerin' Harry)
- Image Fight
- Legend Of Hero Tonma
- Ninja Spirit/ Saigo No Nindou
- R-Type
- X-Multiply (Japanese version)

Hardware is identical between games except for R-Type which uses a simpler romboard with no samples capability.

Also the top board contains a different PAL chip between games and a protection chip (again, except R-Type which has no protection).
This PAL has 2 functions:
- work RAM offset
- program ROMs mapping
I probed it and discovered it was very simple in the way it works: address lines on one side, multiplexed /CE lines on the other side.
I chose to handcraft an "universal" PAL mapping RAM @ 0xA0000 (7 games out of 10 use that) and 4 consecutive banks of 128kB for program ROMs.
Then I patched the 3 games not using RAM @ 0xA0000: Dragon Breed, R-Type and X-Multiply.
And by arranging program ROMs correctly I could run all the games BUT...

There comes the protection: the MCU (i8751) used for protection does 2 things:
- boot up protection (prevent the game from running by throwing a RAM error on boot up)
- samples playing
I patched all games to boot without any MCU installed. This was a good start but games played without any sample now.
Thing is the sample playing mechanism isn't understood in MAME and instead is simulated.
I spent a good Saturday afternoon trying to fully figuring it out. It's not that often I can find so much time to work on my projects (i.e. 3 or 4 hours consecutively) so I had to succeed.
In fact when the game wants to play a sample it sends a command to the MCU which in turn sends a command to the sound CPU. I thought I could simply fork data to be sent directly to the sound CPU, bypassing the MCU, but on real hardware the needed port isn't accessible by the main CPU. It also thought of writing directly to the sound RAM but I was worried about synchronisation (were samples going to be played fully and at the right pitch without any cuts?) and it was probably a lot of work patching all games. Digging deeper I found the real problem: only the MCU has access to the samples ROMs so it had to be kept anyway.
I ended up handcrafting an universal MCU for samples playing! Yes the same MCU code supporting all the games for the sample part.
Anyway, this means a lot of great things:
- games with a faulty MCU can now be revived
- any game (except R-Type due to the specific romboard) can be converted to any other game (including R-Type)
So now you're asking yourself "Why not making a universal MCU for the protection part too?". Because internal ROM of the MCU is 4kB only. Of course I could use external ROM but:
- then my code would be visible
- I would have to design an additional daughter board for the MCU, external ROM and at least one LS373 in between to latch lower address lines as the 8751/8951 MCUs use the same port for lower address lines (A0~7) and data lines (D0~7).

So now that I have found a solution for each problem it was time for testing:

I was super excited to see games were playing fine: controls, graphics, sound effects, music and samples!

Now you think this is the end of this article? NOT! I was suggested to have a look if R-Type II could be ported from M84 to M72. And:

So not only the multi kit supports all M72 games but also R-Type II from M84 (with samples of course)!
I'm now thinking of adding an other M84 game to the list: Lightning Swords/Kengo. Not a great game to say the least, but it's an other challenge as it uses an encrypted V35 CPU (I have already decrypted it) with embedded IRQ controller when it's external on M72.

4 Jul 2018

Pound for Pound (Irem M85) to R-Type II (Irem M84 ) conversion

Pound for Pound is the only know game on Irem M85 hardware.
It's extremely close to M84 hardware except it has trackball inputs only.

There are 3 hurdles in the conversion.

1st hurdle:
Pound for Pound use has only 4 sockets for background graphics chips when R-Type II uses 8.

Merge R-Type II files 2 by 2 to obtain 4 * 2Mb files. Install them on the P4P board and move jumper J4 from position OT to 2MM and jumper J5 from position 1MM to OT.
This is the only hardware modification needed for the whole conversion!

=> Tested working on real hardware.

2nd hurdle:
Sound hardware is slightly different from hardware point of view but identical from a software point of view. Only ports are different between P4P and RT2.

MAME wrote:

static ADDRESS_MAP_START( rtype2_sound_portmap, AS_IO, 8, m72_state )
AM_RANGE(0x00, 0x01) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write)
AM_RANGE(0x80, 0x80) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0x80, 0x81) AM_DEVWRITE("m72", m72_audio_device, rtype2_sample_addr_w)
AM_RANGE(0x82, 0x82) AM_DEVWRITE("m72", m72_audio_device, sample_w)
AM_RANGE(0x83, 0x83) AM_DEVWRITE("m72", m72_audio_device, sound_irq_ack_w)
AM_RANGE(0x84, 0x84) AM_DEVREAD("m72", m72_audio_device, sample_r)
// AM_RANGE(0x87, 0x87) AM_WRITENOP /* ??? */

static ADDRESS_MAP_START( poundfor_sound_portmap, AS_IO, 8, m72_state )
AM_RANGE(0x10, 0x13) AM_DEVWRITE("m72", m72_audio_device, poundfor_sample_addr_w)
AM_RANGE(0x40, 0x41) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write)
AM_RANGE(0x42, 0x42) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0x42, 0x42) AM_DEVWRITE("m72", m72_audio_device, sound_irq_ack_w)
Giving the following equivalents:

rtype2 ------- poundfor
0x00, 0x01 -- 0x40, 0x41
0x80, 0x80 -- 0x42, 0x42
0x80, 0x81 -- 0x10, 0x13
0x83, 0x83 -- 0x42, 0x42
0x87, 0x87 -- 0x43, 0x43

Patch R-Type II sound program ROM to use P4P ports.

 => Tested working on real hardware.

3rd hurdle:
Pound for pound is a trackball game using two µPD4701AC chips to read data from the trackballs.

Despite what MAME says all inputs are wired and available on the JAMMA edge in parallel of the specific trackball connectors.
However they can't be accessed the same way so I had to study a bit the hardware and how the µPD4701AC works.

Here's the wiring for player 1 (identical for player 2 on the second µPD4107AC chip):
- UP => YA
- DOWN => YB
- LEFT => XB
- BUTTON 1 => R
- BUTTON 2 => L
- BUTTON 3 => M

Instead of reading from port 0x00 I patched the program to read form ports 0x0A (buttons), 0x08 (X), 0x0C (Y).
For the buttons it's only a matter of masking and writing correct bits (button order doesn't matter for R-Type II as they have the same function but I plan to reuse the subroutine for other games so wrote it right the first time).
For the direction it's a bit more tricky.
As we send pure digital signals to a chip requiring phase shifted signals here's what happens (example given for UP button):
- first frame, button not pressed => value read = 0x000000
- second frame, button pressed => XA = 1, XB = 0, value read = 0x000001
- third frame, button pressed => XA = 1, XB = 0, value read = 0x000000
- xxx frame, button not pressed => XA = 0, XB = 0, value read = 0xFFFFFF
- xxx+1 frame, button not pressed => XA = 0, XB = 0, value read = 0x000000
For button DOWN values are reversed due to the signals phase (0x000000 => 0xFFFFFF => 0x000000 => 0x000001 => 0x000000).
Same applies for right/left.
I made a small subroutines to detect rising/falling edges.
There's no input lag as we can detect which button is pressed and process it in the same frame.

=> Tested working on real hardware.