[Solved] Hatsune Miku Project DIVA [PSP] - Change Control Scheme

Started by flame, December 03, 2016, 11:26:57 AM

Previous topic - Next topic

flame

Hatsune Miku Project DIVA is a rhythm game; it looks like this:

In this image, the note icons are each moving toward their respective targets. The goal is to "hit" notes by pushing the correct face button with the correct timing.
On to the goal of this hack. In every later Hatsune Miku Project DIVA game, you can hit an "O" note either by pushing the O face button or pushing right on the D-pad, or more generally the corresponding D-pad button. To goal here is to port that function to Hatsune Miku Project DIVA.

I did some stuff and couldn't solve it. I think my main problem is either I'm misreading the asm, or I'm failing to find where note timing is assessed.
On to what I did find:

0884B0E8 - has something to do with input. I tried changing this and it didn't do much / I couldn't get it to work.
It goes like this: 0x1 start, 0x4 up, 0x8 right, 0x10 down, 0x20 left, 0x400 L, 0x800 R, 0x40 △, 0x80 ○, 0x100 X, 0x200 □
These get OR'd together to made the control status halfword.

0884B680 - this routine is looking for control input matches. It gets passed a parameter a1. It also gets parameter a0 but this is always 08C2C234, an address for the control input buffer. At offset 0x18 within this buffer is the currently pressed buttons (halfword). At offset 0x1C is any "newly pressed" buttons. Anyway, the function returns 1 on v0 if the button was newly pressed, or 0 otherwise. It always returns 0 on v1 as far as I can tell.
6, 7, 8, and 9 are the a1 parameter values looking for input on the face buttons.

0886AB00 - this routine is active only during the rhythm game. It calls the 0884B680 function multiple times to find out about control input.
I did some simple asm that basically does:
1) Is a D-pad being pressed? (if not, exit)
2) Make it look as if, instead, a face button was just pressed
And I did this at the start of the 0886AB00 routine. What happened was pressing the D-pad made "button sounds" but couldn't hit the rhythm game targets. The face buttons preserved all functionality (made sounds and hit the rhythm game targets), this was as expected.

I stepped out one level from the 0886AB00 function. I think this is the routine that makes the rhythm game work. It looks complicated and I'm not sure techniques that can help me ID the right routine I need to change. Maybe I could try, instead of at 0886AB00 doing the input modification, doing it instead at the top of this routine.

I also tried doing it at a very low level but what ends up happening is the X function gets executed when you push down and this will not work for the game's menus.

Can anyone help?

STARWIN

I'm sure you can do it pretty soon if you think like this.

Basically your task is to isolate the iteration of the game loop where you happen to hit with correct timing. Following keystate progression during this loop iteration is bound to solve it.

Perhaps make a savestate a short moment before a correct timing moment. Then, set a read breakpoint at keystate storage. My assumption is that there is another spot that checks the keystate during the correct timing, and hopefully the keystate is read only a few times each iteration. Load state before interesting moment, break, run, break, run.. until you see an extra read.

Or, yeah, could look at the nearby code. If you think a keystate check involves a certain routine call, look for that call instead of reading all the nearby code. Or does this routine cache the keystate and just check from that? I haven't used PPSSPP so I could be missing something.

flame

That was right. Still not solved yet; the problem seems quite tough.

I tried one more thing, the 0884B0E8 that's checking input, I tried fusing the buttons so D-pad right is 〇 and so on. This worked, but it doesn't work like the later games do. If you hold down 〇 and press right, it doesn't register. Because that button is already down, it doesn't register as a new press.

I found this.
088582F0 This routine is active only during the rhythm game and only when there are any targets on screen. This will branch if outside of the timing window and won't branch if inside the timing window.
08858A50 This part is recording your press during a timing window. It doesn't get hit until you press something.
08858A68 sb zero,0x0(s6) - It's storing in stack memory a zero (the default value is 1). This gets checked later. Different actions are taken inside the timing window vs outside of it.

Just need to figure out where in here control input is being read.

NoOneee

Quote from: flame on December 03, 2016, 11:26:57 AM
I also tried doing it at a very low level but what ends up happening is the X function gets executed when you push down and this will not work for the game's menus.
If you know that during gameplay(or during menus) a certain memory address always contains a certain value, you can it do the "low level way". Just check if it is on gameplay before changing the pressed buttons value. If you can't find such memory value, you can make it yourself (when the user starts playing, set some value in memory. when the user stops playing, unset that value).

flame

Fully solved.
http://www.mediafire.com/file/iln2kotnzudaqqi/HMPD_D-Pad_Control_Fix.7z

I did basically as NoOnee said to.

The solution was 4 parts:
A routine that copies D-pad inputs to face button inputs (this was the big one)
Three smaller routines:
A routine that sets a flag on the rhythm game main loop. The big routine won't copy inputs if the flag is not set.
A routine that resets the flag when you access the pause menu.
A routine that resets the flag when you finish the song.

This setup won't work for the first frame of a song, or for the first frame after unpausing. Some songs have notes on the first measure, but none of the songs have a notes on the first note of the first measure, so that's not an issue. As for the pausing thing, rhythm game targets can still be hit using the face buttons on the first frame after unpausing, so I'll suggest that as a work-around. I really think most players won't notice this.

There's a patcher too, so feel free to try it out.

Would someone like to submit this for me?

The only piece missing is motivation, so let me explain briefly what it was:
1) I like this game. I did like J-Pop, but I did not think I liked rhythm games before I tried playing this one.
2) On the HMPD page at TV Tropes wiki, a contributor wrote:
QuotePlayers who played later games going back to the first game will likely get a few "Worst" notes because they were trying to use the D-Pad to hit them. You can't do that, here.
And to me, it sounded like an idea for a romhack.

I am not an expert player. I might ask at a Project DIVA community site for an expert player to test it out. The patched version, to me, feels just like the later games in its series.