Friday, March 6, 2009

Zaxxon Sets dissected

stephh from The Ultimate Patchers earns 1000 points!

Determined set one of Zaxxon corrected a near imperceptible defect in the way Zaxxon set two (zaxxon2) handled fractions of a credit, only seen when earning free credits through game play when the credits-per-token is set to a fraction.

The details he posted at MAMEWorld.info:

SPOT THE DIFFERENCE : 'zaxxon' and 'zaxxon2'
Version 1.0 - Copyright Steph from The Ultimate Patchers, 2009.06.03


There are only 3 (THREE) bytes of difference !

Z:\>fc /B zaxxon1.u29 zaxxon1a.u29
Comparing files ZAXXON1.U29 and ZAXXON1A.U29
00000FFE: 21 79
00000FFF: DD DC

These 2 bytes are for checksum (LSB first), so they are of not much interest ...

Z:\>fc /B zaxxon3.u27 zaxxon3a.u27
Comparing files ZAXXON3.U27 and ZAXXON3A.U27
00000C71: C9 21

Here is the byte that does everything ... Let's now compare the Z80 code :

Z:\>diff zaxxon.asm zaxxon2.asm
1874,1876c1874
< 0C71: C9 ret
< 0C72: 12 ---
< 0C73: 60 ---
---
> 0C71: 21 12 60 ld hl,$6012
0C74: 7E ld a,(hl)
0C75: A7 and a
0C76: C0 ret nz
0C77: 2B dec hl
0C78: 77 ld (hl),a
0C79: C9 ret

To sum up the routine in Z2 sets contents of 0x6011 to 0 if contents of 0x6012 = 0 ...

So what do we have at these addresses ? 0x6012 is the number of credits (BCD coded, range 0x00-0x90)
and 0x6011 is a value for partial credits ... WTF is that ? To make it short, let's see the
useful values :

. 0x00 : no partial credit
. 0x40 : 1/4 credit
. 0x56 : 1/3 credit
. 0x80 : 1/2 credit
. 0xab : 2/3 credit
. 0xc0 : 3/4 credit

Now let's go back to the routine in Z2 and imagine this situation : you set "Coin A" to 2/1 3/2 4/3,
you insert 2 coins, you play a one player game, and you insert another coin ...

When 1st coin is inserted, contents of 0x6011 = 0xc0 and contents of 0x6012 = 0x00 ...
You still have 0 credit, so you need to insert another coin to start a one player game ...
When 2nd coin is inserted, contents of 0x6011 = 0x80 and contents of 0x6012 = 0x01 ...
You now have 1 credit, you start a one player game, and number of credits is back to 0 ...
When the game is over, the routine is called, and contents of 0x6011 is ALSO turned to 0x00 !
So when 3rd coin is inserted, contents of 0x6011 = 0xc0, contents of 0x6012 = 0x00,
you still have 0 credit, so you need AGAIN to insert another coin to start a one player game !

In Z1, the behaviour is different because the routine is NOT called due to the 'ret' instruction ...
Let's simulate the previous situation with this new behaviour ...

When 1st coin is inserted, contents of 0x6011 = 0xc0 and contents of 0x6012 = 0x00 ...
You still have 0 credit, so you need to insert another coin to start a one player game (same as in Z2) ...
When 2nd coin is inserted, contents of 0x6011 = 0x80 and contents of 0x6012 = 0x01 ...
You now have 1 credit, you start a one player game, and number of credits is back to 0 (same as in Z2) ...
When the game is over, the routine is NOT called, so NOTHING happens ...
So when 3rd coin is inserted, contents of 0x6011 = 0x40, contents of 0x6012 = 0x01,
you have 1 credit, so you DON'T need to insert another coin to start a one player game !


Z2 is the original first revision of the game, but what about Z1 ? The way the code is patched
(one opcode of difference and code is NOT shifted - leaving 2 unused bytes at 0x0c72 and 0x0c73)
tells this was done on purpose ... It could be a bug fix to avoid partial credits being lost
(who could have complained about that as I doubt someone would have found the "trick" ?),
but what is the interest as players would require to insert less coins in the machine ?
Unfortunately, code doesn't help here, and only an old Sega coder or project coordonator
could answer such weird question ... If you ever find the answer, please let me know ...

No comments:

Post a Comment