WIP: CPS 1.5 on CPS2 hardware

PCB problems and fixes
User avatar
emphatic
Breastfeeds when required
Posts: 6340
Joined: April 7th, 2009, 4:14 pm
Location: Alingsås, Sweden
eBay: jorgen_sjolander
Initials: JOR

Re: WIP: CPS 1.5 on CPS2 hardware

Post by emphatic » July 18th, 2015, 2:42 am

:-o

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 18th, 2015, 3:43 am

Amazing work, Asure.
Image

kuze
Posts: 89
Joined: September 29th, 2013, 5:09 pm
Location:

Re: WIP: CPS 1.5 on CPS2 hardware

Post by kuze » July 18th, 2015, 3:47 am

Very nice indeed. 8-)

Asure
Posts: 570
Joined: April 17th, 2013, 5:16 pm
Location: Netherlands
eBay: asure_nl

Re: WIP: CPS 1.5 on CPS2 hardware

Post by Asure » July 18th, 2015, 1:24 pm

Some more observations. I patched a bit of code to add 8000 to the first parameter of the sprite list. It didn't work out. Seems there might be something with the first 0x1f at 708000-70801f.
If i zero out the first 0x1f i already get partial sprites visible. If i leave the first 0x1f filled as it would have been on 900000 / 904000 + 1F the game hates me and wants to display no sprites.
I manually updated the first page of sprites , leaving the first 0x1f filled with zeroes. Sort of works:

Image

We can see there's an offset problem x/y. CPS1 does not use this, i guess some more mods to the sprite code are needed.

This is what charles tells us about sprites on CPS2:

Code: Select all

 +$00 : pp-- ---- ---- ---- : Priority bits (0=lowest(backmost), 3=highest(frontmost))
 +$00 : ---- --xx xxxx xxxx : X coordinate
 +$02 : e--- ---- ---- ---- : End of list flag (1= Hide this and all remaining sprites, 0= Show this sprite)
 +$02 : -nn- ---- ---- ---- : Tile number bits 17,16
 +$02 : ---- --yy yyyy yyyy : Y coordinate
 +$04 : nnnn nnnn nnnn nnnn : Tile number bits 15-0
 +$06 : hhhh ---- ---- ---- : Sprite height (1 to 16 rows of tiles)
 +$06 : ---- wwww ---- ---- : Sprite width (1 to 16 columns of tiles)
 +$06 : ---- ---- o--- ---- : Coordinate offset (0= Offset by X:-64,Y:-16, 1= No offset)
 +$06 : ---- ---- -yx- ---- : Y flip, X flip (1= enable, 0= disable)
 +$06 : ---- ---- ---p pppp : Palette number (0-31)
 Sprites are positioned in a virtual 1024x1024 space.
The main problem with the non-displaying sprites was in the first two bits.
Part of the Punisher sprite as seen in ram at 0x700000 on cps2.

Code: Select all

8106 005A 1011 0020 works
0106 005A 1011 0020 does not work.
From some old cps1 doc:

Code: Select all

Sprites:
    Sprites are represented by a number of 8 byte values
    xx xx yy yy nn nn aa aa
    where xxxx  = x position
    yyyy        = y position
    nnnn        = tile number
    aaaa        = attribute word
        $0001  colour
        $0002  colour
        $0004  colour
        $0008  colour
        $0010  colour
        $0020  X Flip
        $0040  Y Flip
        $0080  unknown
        $0100  X block size (in sprites)
        $0200  X block size
        $0400  X block size
        $0800  X block size
        $1000  Y block size (in sprites)
        $2000  Y block size
        $4000  Y block size
        $8000  Y block size

    The end of the table (may) be marked by an attribute value of $FF00.
    To use block sprites, the sprites must be layed out in 16 tile
    (256 pixel) wide blocks.
What i read in the old cps1 doc does not seem to match quite what i see with punisher, or i am looking at it the wrong way.

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 18th, 2015, 4:41 pm

Dude! You really nailed it:
Image


The instruction addi.w #$0040,D1 applies the properties mask at the to be written sprite index data after it's is read from a table in the ROM, so I changed the mask to $8040 and Arthur started to appear. He's at the right spot because I already have a bit of code inserted at the start of the game program which poke the sprite layer control registers correctly.

Edit:I believe the smartest way of doing this would perhaps be have a piece of added code in the video interrupt add 0x8000 to the first word on the sprite table for each sprite entity in the list, after copying the whole table from the originally alloted CPS1 sprite memory.
Image

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 18th, 2015, 8:34 pm


The sprites were actually blinking but the youtube video can't capture that properly due to difference of framerate with mame.

Originally, when recording that video I used a add instruction to change the sprite list. I changed that to a logical OR instruction and the sprites stopped blinking. Still need to improve the logic as I am not "catching" all the sprite writes yet.
Image

User avatar
frsj8112
Posts: 62
Joined: April 11th, 2012, 6:06 pm
Location: Sweden
eBay: frsj8112

Re: WIP: CPS 1.5 on CPS2 hardware

Post by frsj8112 » July 18th, 2015, 8:43 pm

Wow! :clap: :clap: :clap:

Asure
Posts: 570
Joined: April 17th, 2013, 5:16 pm
Location: Netherlands
eBay: asure_nl

Re: WIP: CPS 1.5 on CPS2 hardware

Post by Asure » July 18th, 2015, 10:31 pm

Leo, did you patch all the writes with the 8000?
In Punisher I found a few places to addi the 8000, the first one i did, not all sprites were patched. As a result the sprite list is not parsed fully.
The screenshot i posted with items, it's a single frame written to 700000. I manually added the 8000 to _all_ the sprites.

As for going about the 'way to do it', an extra rom with some routines to jmp to might be a good idea, but i'm not sure if the additional cycles will mess up timing.
We need at least a
- 'fffffx register fix' routine (7000 807D and friends into fffff0- range)
- Generic sprite list fixer

Also i'm not sure how the sprite priority works, as i've not seen enough of a game running. Some sprites should appear below/above others for example, punisher can stand behind/in front of others.
Maybe it's already fixed by the order of the sprites in the list. (first entry is the lowest, others draw on top of it?)

In punisher, there is a bunch of odd sprites at the first 0x1F as well.
These have parameters like "012E FEEC 4F32 0115". The first F causes a problem, the sprite is not drawn and the list is not parsed further. If i kill those two entrys, i can get the rest of the sprites.

Also, the register to draw the frames.. it works 'the other way around. E.g. you write a list into 708000 when 700000 is visible, then flip the regiser, and draw into the invisible range.
Megaman has a proper mechanic for doing this which i borrowed partly: It uses ff8060 to hold 0/1 which it pushes to the latch register, and ff8061 to hold ff or 00. It flips these each cycle :)
When some cps1 games turn off sprites, they just write 0 into 800100. But we need a consistent mechanic to clear the screen, as not all games seem to clean up the sprite list.
Right now i have my code set up so it writes into 7080 by default, but i can poke stuff into 700000 to test.

Edit: My theory is right, we cannot just add 8000, at least punisher will have issues. I patched a few more routines to add 8000 (punisher uses several writes for id's to the list, for player chars(odd/even block), enemies(odd/even block), objects etc.). You can see in the shot below, the 'bar chair leg' is 'in front' of the punisher's leg, it should be behind it.
For Ghouls, 8000 may work in most cases, but there may be parts where sprites (doors, destroyable objects etc.) should be drawn in front/back of other sprites.

Image

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 18th, 2015, 11:40 pm

I don't want to change the game code. I want something that "translates" the sprite list to the format CPS2 uses. So a routine slapped into the interrupt code is a pretty fair bet.

I let the game render the sprite list at it's original memory position (Daimakaimura does it at 0x920000) then I have a routine copy it to the CPS2 sprite memory (the 2 8KB SRAMs on the B board).

To make the sprites appear I just changed the code we borrowed from SSFX2 slightly from:

Code: Select all

0001A0: 41F9 0070 8020             lea     $708000.l, A0    ; destination address
0001A6: 43F9 0092 0000             lea     $920000.l, A1    ; source address
0001AC: 3E3C 01F5                  move.w  #$1f5, D7        ; size of copy divided by 2 (in long words)
0001B0: 20D9                       move.l  (A1)+, (A0)+         ; copy first longword to CPS2 sprite table
0001B2: 20D9                       move.l  (A1)+, (A0)+         ; copy second longword to CPS2 sprite table
... (lots of NOPs so I can stuff code easily in the middle for testing)
...
0001D4: 51CF FFDA                  dbra    D7, $1b0           ; if we're not done yet, let's loop
0001D8: 33FC 9000 0080 0102        move.w  #$9000, $800102.l   ; instruction I borrowed the spot for jumping here
0001E0: 0A6D FFFF 760E             eori.w  #$ffff, ($760e,A5)        ; toggle CPS2 sprite list flag
0001E6: 4E71                       nop
0001E8: 33ED 760E 0080 40E0        move.w  ($760e,A5), $8040e0.l  ; write CPS2 sprite list flag
0001F0: 4EF9 0000 04D2             jmp     $4d2.l                   ; go back to where we came from
To:

Code: Select all

0001A0: 41F9 0070 8020             lea     $708000.l, A0    ; destination address
0001A6: 43F9 0092 0000             lea     $920000.l, A1    ; source address
0001AC: 3E3C 01F5                  move.w  #$1f5, D7        ; size of copy divided by 2 (in long words)
0001B0: 3A19                       move.w  (A1)+, D5           ; copy first word into D5
0001B2: 0045 8000                  ori.w   #$8000, D5         ; set highest priority bit to "1"
0001B6: 30C5                       move.w  D5, (A0)+           ; push first word into CPS2 sprite ram
0001B8: 3A19                       move.w  (A1)+, D5           ; copy second word into D5
0001BA: 0045 2000                  andi.w   #$03ff, D5        ; mask sprite list end bit out
0001BE: 30C5                       move.w  D5, (A0)+           ; push second word into CPS2 sprite ram
...
0001D2: 20D9                       move.l  (A1)+, (A0)+        ; copy second long word to CPS2 sprite ram
0001D4: 51CF FFDA                  dbra    D7, $1b0           ; if we're not done yet, let's loop
0001D8: 33FC 9000 0080 0102        move.w  #$9000, $800102.l   ; instruction I borrowed the spot for jumping here
0001E0: 0A6D FFFF 760E             eori.w  #$ffff, ($760e,A5)        ; toggle CPS2 sprite list flag
0001E6: 4E71                       nop
0001E8: 33ED 760E 0080 40E0        move.w  ($760e,A5), $8040e0.l  ; write CPS2 sprite list flag
0001F0: 4EF9 0000 04D2             jmp     $4d2.l                  ; go back to where we came from
This of course is experimental code... lol
Image

User avatar
undamned
Posts: 91
Joined: September 3rd, 2009, 9:24 pm
Location: Phoenix
eBay: undamned
Initials: UND

Re: WIP: CPS 1.5 on CPS2 hardware

Post by undamned » July 19th, 2015, 9:29 am

Nice work, guys! :D
-ud
"Sin and death's got the whole world gettin' illa, but I praise God for the Blood Spilla."

Asure
Posts: 570
Joined: April 17th, 2013, 5:16 pm
Location: Netherlands
eBay: asure_nl

Re: WIP: CPS 1.5 on CPS2 hardware

Post by Asure » July 19th, 2015, 2:55 pm

I think we need to take the info from ram and merge it with the sprite list for cps2 properly. My 'fix' for the first bit is dirty. At 800100+ $66-$67 that register has an offset for a page in 900000 ram with "Priority mask Sprites". If we use a "generic" fixer routine, I think we can merge/translate the priority bits from there into a cps2-compatible sprite list with correct prio for the sprites included.

Problem now is I'm not at home so no way to look at the ram page and prio bits for cps1 with mame memory viewer :). I hope they are just two bits for each tile which we can stick into the first byte for entries on the sprite list at 708000..

@leo: Alternative option for your suggestion would be to patch the list writes to 708000 and correct the invisible frame with the sprite prios just before the latch toggle, this saves some cpu cycles as we skip the copy action.

What I don't understand is why capcom decided to do sprites this way for cps2, the cps-a chip seems to get a lot less action.

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 19th, 2015, 3:54 pm

The real hardware has no need for the latch toggle write to display sprites... lol
I had the write to 8040E0 removed on that to test if it was required and it is not (for the real hardware at least).

By what I understood from the docs and from the circuit, write to 8040E0 causes the sprite RAM to swap the bank so you can write on the second half.

Image
Image
Image
Image
Image

Thanks to Charles MacDonald's documentation I was able to properly setup chores like reset the sound CPU and fix the I/O init for the CPS2 so the game even boot on the real thing...

The wrong tiles display also happen in MAME.
But unlike how it runs in MAME, there are palette problems everywhere but at least sprite priorities seem right.
Image

Asure
Posts: 570
Joined: April 17th, 2013, 5:16 pm
Location: Netherlands
eBay: asure_nl

Re: WIP: CPS 1.5 on CPS2 hardware

Post by Asure » July 20th, 2015, 11:47 am

leonardoliveira wrote:The real hardware has no need for the latch toggle write to display sprites... lol
I had the write to 8040E0 removed on that to test if it was required and it is not (for the real hardware at least).

By what I understood from the docs and from the circuit, write to 8040E0 causes the sprite RAM to swap the bank so you can write on the second half.
If you do it like that, you miss the double buffering effect. You can see sprites and items dragging along the screen. (at least i see that in Megaman)
Megaman starts out with this set to 0 (zero)
Set to 0 = Render sprite list from 700000. Game code writes sprite list to 708000
Set to 1 = Render sprite list from 708000. Game code writes sprite list to 708000, but writes end up at 700000

Again, on cps1 megaman this is done different. The list is drawn into 900000 and 904000. While the list is written into 900000, the active frame on screen is from 904000. (800100, 9040 is written here.). When the game reaches the next frame, the list at 9040 is used, and 800100 register is then set to 9000)

So, back to the list, we have sprites now anyway, who cares how it's done 8-)
I checked out a bunch of other games on CPS2, they use the priority bit for sprites a bit more. I can see variations like 8000 and 6000 being used.
For games like Punisher and C&D we really need to figure out how they decide on the sprite prio and where the bits are stored.

Btw, hidden object test for Punisher: (does not show 'prio') like SF2:ww/ce/hf do :(

Code: Select all

<cheat desc="Enable Hidden OBJECT CHECK and SCROLL TEST">
<script state="run">
<action>maincpu.pb@FF0893=01</action>
</script>
</cheat>

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 20th, 2015, 11:38 pm



Still need work, but hey, the sound driver is now 100% decrypted.
Image

kuze
Posts: 89
Joined: September 29th, 2013, 5:09 pm
Location:

Re: WIP: CPS 1.5 on CPS2 hardware

Post by kuze » July 20th, 2015, 11:45 pm

That's awesome, keep up the great work!

User avatar
emphatic
Breastfeeds when required
Posts: 6340
Joined: April 7th, 2009, 4:14 pm
Location: Alingsås, Sweden
eBay: jorgen_sjolander
Initials: JOR

Re: WIP: CPS 1.5 on CPS2 hardware

Post by emphatic » July 21st, 2015, 12:29 am

Nice progress, guys!

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 30th, 2015, 7:04 am

I understand that this thread has slowed down slightly recently... But I've been still working at this.

I spent the whole day today trying to improve the sprite tables handling code and I changed the way my controllers change code work.

Now, I have the player(s) inputs tied directly to the CPS2 player inputs. But for the special control buttons (start, coin, service, test) I process them on the vblank interrupt and store the output already converted into CPS1 format at a empty spot of the RAM (using A5 as pointer, just like Capcom do). Then on every reference to 0x80001E which relate to the buttons (some games use that address to enable hidden features, like the advanced OBJ test on Punisher) I redirect the reads to my value on RAM.

It's super effective!


Now, about the sprite copy code, I added code to detect and convert CPS1 style mark for end of sprite tables (0000 0100 0000 00ff) into the CPS2 equivalent ( 0000 8000 0000 0000)

Image

I have this one working 100% inputs now. Still need to fix the coin locks and EEPROM.

But we still need a fix for the priority problem:

Image

I'll only bother with EEPROM fixes after figuring out the last piece of the puzzle (sprite priority).
Image

darksoft
Posts: 124
Joined: July 8th, 2011, 10:04 pm
Location:
eBay: greenberetfan
Initials: PFG

Re: WIP: CPS 1.5 on CPS2 hardware

Post by darksoft » July 30th, 2015, 7:23 am

AWESOME! You can see the work behind that. It's not just a couple of byte change :)
Arcade Project Master at www.arcade-projects.com

fluxcore
Posts: 40
Joined: January 13th, 2014, 9:18 am
Location: New Zealand

Re: WIP: CPS 1.5 on CPS2 hardware

Post by fluxcore » July 30th, 2015, 8:33 pm

Brilliant! I'm glad this is still being worked on :)

User avatar
leonardoliveira
Posts: 689
Joined: August 30th, 2012, 5:53 am
Location: Brazil
Initials: leo

Re: WIP: CPS 1.5 on CPS2 hardware

Post by leonardoliveira » July 31st, 2015, 7:19 am

After reading this whole thread several times again, jedpossum's comment on Super Street Fighter2 Turbo about it being designed to play identical as possible to the original Street Fighter 2 CE/Turbo, I looked how it draws it's sprites and it WAS ACTUALLY DRAWING it's sprites backwards. Because it has a CPS1 engine, that game might be a real source of information for this project.

As everyone can see on the pictures Asure's idea of drawing the sprites list upside down kind of almost work.

But for that to work I had to disable the code which detects the sprite list end. Also there's some issues with the data copy. I am not sure if it's due to my algorithm being crap or if it's because I have the sprite list end check disabled.

Image


Image

Another thing I just implemented was use the data the game writes to the CPS-A register 0x800100 as the toggle of odd/even for the sprites double buffer. Currently I only copy the sprite data from 0x900000 but I plan on implementing another branch of code to copy from 0x904000. I am not sure if that's really important

Well, at least I have some progress... :roll:
Image

Post Reply