|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
Magical Puzzle Popils GG hack help?
Posted: Sun Jul 09, 2017 7:01 pm Last edited by matt on Mon Jul 10, 2017 11:51 am; edited 1 time in total |
Hi,
I'm trying to 100% Magical Puzzle Popils. To do so I need to match/beat the target number of steps/moves for each level. Steps are increased every 16 pixels moved by the player. Left or Right along platforms, or Up and Down ladder. In order to beat some level goals it's necessary to literally count the pixels being moved. Walking one pixel too far along a platform and I'll finish the level with 9 steps rather than 8. And then I have to redo it. Step count is only displayed on the pause screen. Pixel count is not displayed at all. So I had an idea. Why not hack the ROM to have step count displayed at all times? And if I'm going to do that, why not hack it so that it displays the hidden pixel counter? I've hacked some ROMS before, so I know how to debug and watch memory addresses. But I don't know assembler for the GG. I'll be happy to find out the memory addresses of the counters. Can anybody help me with the rest of the hack? |
|
|
Posted: Sun Jul 09, 2017 7:37 pm |
Helllo, ummm I think it would be possible.
I'll try to help you when possible |
|
|
Posted: Sun Jul 09, 2017 10:23 pm |
Great, thanks! I'll find the memory addresses. |
|
|
Posted: Mon Jul 10, 2017 11:33 am |
OK! some addresses:
C313 level C320 lives C334 steps C335 sub-step count (seems to count in half pixels?) the pause information is on the bottom two rows of characters: IQ, ROUND, LIVES JUST NOW, PPP STEPS (if round has not been cleared) MPR=TTT/YOU=PPPSTEPS (if round has been cleared) Really I would like the bottom row during gameplay to show: MPR=TTT/YOU=PPP+XX.X MPR= initials of mapper who set target step count for that level. TTT= target steps PPP= player step count XX.X= sub-step count Mock-up image shows: MTN=017/YOU=016/12.5 in EDIT MODE, bottom row is: TESTING R=NN XXSTEPS so it might be easier to branch to that code? During gameplay the bottom row displays "IQ IS NOT ADDED." if you have already cleared the round. I do not care to see this information so it can be overwritten. |
|
|
Posted: Tue Jul 11, 2017 6:38 pm |
This actually counts in increments of 8 from 0x00 to 0xF8 Divided by 16 gives the pixel count in half pixels. |
|
|
Posted: Thu Jul 13, 2017 9:41 am |
Making progress.
My friend Jamie and I have got the whole number part of the sub-step count displaying in the pause status text. Proof of concept. I've been brushing up on my Z80 opcodes! More work needed! |
|
|
Posted: Sun Jul 16, 2017 2:46 pm |
Current findings are here: https://tcrf.net/Magical_Puzzle_Popils
including
Here's my work-in-progress symbol file: https://www.dropbox.com/s/y6el2dtfg3ot611/popils.sym?dl=0 |
|
|
Posted: Sun Jul 16, 2017 3:04 pm |
You're welcome to dump any info in http://www.smspower.org/Development/MagicalPuzzlePopils-GG too. | |
|
Posted: Sun Jul 16, 2017 6:52 pm |
Thanks, I will do so. |
|
|
Posted: Mon Jul 17, 2017 11:07 am |
Done! Hints for efficient debugging and reverse engineering would be appreciated X) |
|
|
Posted: Mon Jul 17, 2017 12:01 pm |
I tend to assemble with WLA DX and then label and comment the code, to generate symbols. Others seem to write the symbol file themselves which seems harder to me. | |
|
Posted: Mon Jul 17, 2017 10:19 pm |
I'd not considered doing it your way, I'll give it a try. |
|
|
Posted: Tue Jul 18, 2017 8:15 am |
Hello matt
I tested Debug Mode option and implemented it putting new code to unused PAUSE button, changing value RAM $D3F3 from 00 to FF At $66 PUSH AF LD A, ($D3F3) CPL LD ($D3F3), A POP AF RETN Hex code at $66: $F5 $3A $F3 $D3 $2F $32 $F3 $D3 $F1 $ED $45 It loads actual value from $D3F3 and reverse all data 00 to FF or FF to 00 You can activate or deactivate DEBUG MODE everytime in game, and save it in option menu |
|
|
Posted: Tue Jul 18, 2017 11:56 am |
Thanks! I'll try that later.
Did you see debug mode do anything? |
|
|
Posted: Tue Jul 18, 2017 3:37 pm |
It loads a preview Steps Counter before entering round
For now, I don't see anymore |
|
|
Posted: Tue Jul 18, 2017 4:22 pm |
That counter usually appears after completing the level once. Interesting that it is appearing before completing a level with debug on.
I couldn't get the hex patch to work, and I'm not sure the pause button is working in Emulicious? |
|
|
Posted: Tue Jul 18, 2017 4:53 pm |
Yes, it is working fine.
I tested it |
|
|
Posted: Tue Jul 18, 2017 5:54 pm |
It would be good to confirm if there's a way to enable it without modifications, and also what other effects it might have. | |
|
Posted: Tue Jul 18, 2017 6:45 pm |
I'll try again when I get back to my Mac. |
|
|
Posted: Wed Jul 19, 2017 5:39 am |
Is there anything I could be doing wrong when applying the patch? I'm running Emulicious on Mac OS and still can't get the patch to do anything. $66 is never accessed. I'm running the .gg ROM in Game Gear mode. Pause. Open memory editor Enter HEX at $66 Unpause Press pause key Apologies, I'm new to this :) |
|
|
Posted: Wed Jul 19, 2017 5:52 am |
Does the Pause button work in Game Gear mode? | |
|
Posted: Wed Jul 19, 2017 7:22 am |
No. | |
|
Posted: Wed Jul 19, 2017 8:37 am |
Hello, Pause button is only access for Master System, and I was refering to master system hack.
For implement it in game gear rom may be you can do a call routine to this code where Start button is allocated, and copy stripped bytes. Then everytime you push Start Button you change $D3F3 value $00-FF I test it before when I'll arrive at home. |
|
|
Posted: Wed Jul 19, 2017 10:54 am |
OK thanks! Glad I'm not going crazy. | |
|
Posted: Wed Jul 19, 2017 5:53 pm Last edited by Junosix on Wed Jul 19, 2017 8:02 pm; edited 1 time in total |
Okay - Matt and I have sussed the substeps part and have got that working. (Can't add a screenshot as I've only just signed up).
Spent some time together over the weekend picking through and finding useful addresses and routines, with the original thought being to take the test mode in the map editor and merge it with the status panel in the pause screen of normal mode but that wasn't quite working out. Had some time today to work on it some more and had a breakthrough finding some code that wrote to the VDP that could be hugely space-optimised using loops, doubly-useful because the routine updates every frame. After collapsing a mass of OUTI instructions into a couple of OTIRs I had a couple of hundred bytes to stick some extra code in. Updated routine with new code starts at $059F. ; space-optimised version of the routine already present here 059F AF XOR A ; low byte of VRAM address to write to 05A0 D3 BF OUT ($BF),A ; port VDP Address 05A2 3E 7F LD A, $7F ; high byte of VRAM address to write to 05A4 D3 BF OUT ($BF),A ; port VDP Address 05A6 0E BE LD C,$BE ; port VDP data 05A8 21 00 DE LD HL,$DE00 ; start of data 05AB 06 40 LD B,$40 ; loop counter 05AD ED B3 OTIR ; copy data to VDP RAM 05AF 3C INC A 05B0 D3 BF OUT ($BF),A ; port VDP Address 05B2 3D DEC A 05B3 D3 BF OUT ($BF),A ; port VDP Address 05B5 2E 80 LD L,$80 05B7 06 80 LD B,$80 ; loop counter 05B9 ED B3 OTIR ; copy data to VDP RAM ; new code begins here 05BB 3A 03 C3 LD A,($C303) ; check state machine main value 05BE FE 01 CP $01 ; is it "level" state? 05C0 C2 45 06 JP NZ,level_state_false ; if not then exit subroutine 05C3 3A 04 C3 LD A,($C304) ; check state machine sub value 05C6 FE 03 CP $03 ; is it "level start ok" state 05C8 C2 45 06 JP NZ,level_state_false ; if not then exit subroutine 05CB 01 03 00 LD BC,$0003 ; loop counter 05CE 11 1A DC LD DE,$DC1A ; address to write mapper's initials as ASCII string 05D1 21 92 D8 LD HL,$D892 ; get mapper's initials 05D4 ED B0 LDIR ; write ASCII string 05D6 3E 3D LD A,$3D ; ASCII "=" 05D8 12 LD (DE),A ; write "=" 05D9 13 INC DE ; move to next position in string 05DA 3E 20 LD A,$20 ; ASCII " " 05DC 12 LD (DE),A ; write " " 05DD 13 INC DE ; move to next position in string 05DE 3E 20 LD A,$20 ; ASCII " " 05E0 12 LD (DE),A ; write " " 05E1 3A 95 D8 LD A,($D895) ; take mapper's steps par 05E4 FD 21 1E DC LD IY,$DC1E ; address to write mapper's steps par as ASCII string 05E8 CD 96 4C CALL $4C96 ; convert hex value to ASCII 05EB 01 0D 00 LD BC,$000D ; loop counter 05EE 11 21 DC LD DE,$DC21 ; address to write rest of status panel as ASCII string 05F1 21 DF B6 LD HL,$B6DF ; start address of rest of status panel ASCII string 05F4 ED B0 LDIR ; loop until rest of status panel is drawn 05F6 3A 34 C3 LD A,($C334) ; take player's whole steps 05F9 FD 21 26 DC LD IY,$DC26 ; address to write player whole steps 05FD CD 96 4C CALL $4C96 ; convert hex value to ASCII 0600 3A 35 C3 LD A,($C335) ; take player's substeps 0603 0E 0F LD C,$0F ; only check lower nibble (0-15) to use as fraction... 0605 A1 AND C ; ... by using a bitmask 0606 FE 08 CP $08 ; what is the substeps' fraction? 0608 28 04 JR Z,fraction_is_set ; if result is $08 then the fraction is .5 decimal 060A 3E 00 LD A,$00 ; set fraction to .0 decimal 060C 18 02 JR fraction_not_set fraction_is_set 060E 3E 05 LD A,$05 ; set fraction to .5 decimal fraction_not_set 0610 FD 21 2B DC LD IY,$DC2B ; address to write substeps fraction as ASCII string 0614 CD 96 4C CALL $4C96 ; convert hex value to ASCII 0617 3A 35 C3 LD A,($C335) ; now take the player's substeps again 061A CB 1F RR A ; rotate... 061C CB 1F RR A ; ... upper... 061E CB 1F RR A ; ... nibble... 0620 CB 1F RR A ; ... to get substeps integer 0622 FD 21 29 DC LD IY,$DC29 ; address to write substeps integer as ASCII string 0626 CD 96 4C CALL $4C96 ; convert hex value to ASCII 0629 3E 0C LD A,$0C ; lower byte of VRAM write address 062B D3 BF OUT ($BF),A ; write that to VRAM 062D 3E 7D LD A,$7D ; upper byte of VRAM write address OR'd with $40 ($3D|$40) 062F D3 BF OUT ($BF),A ; write that to VRAM 0631 21 1A DC LD HL,$DC1A ; start address of status panel tile string 0634 01 14 00 LD BC,$0014 ; loop counter write_VDP 0637 7E LD A,(HL) ; get tile data 0638 D3 BE OUT ($BE),A ; output it to VRAM 063A 3E 01 LD A,$01 ; tile property 063C D3 BE OUT ($BE),A ; output it to VRAM 063E 23 INC HL ; move to next tile data byte 063F 0B DEC BC ; decrement counter 0640 78 LD A,B ; check to see... 0641 B1 OR C ; ... if counter is zero 0642 C2 37 06 JP NZ,write_VDP ; keep writing data until counter is zero level_state_false 0645 C9 RET ; return from subroutine Hex dump of same code: AF D3 BF 3E 7F D3 BF 0E BE 21 00 DE 06 40 ED B3 3C D3 BF 3D D3 BF 2E 80 06 80 ED B3 3A 03 C3 FE 01 C2 45 06 3A 04 C3 FE 03 C2 45 06 01 03 00 11 1A DC 21 92 D8 ED B0 3E 3D 12 13 3E 20 12 13 3E 20 12 3A 95 D8 FD 21 1E DC CD 96 4C 01 0D 00 11 21 DC 21 DF B6 ED B0 3A 34 C3 FD 21 26 DC CD 96 4C 3A 35 C3 0E 0F A1 FE 08 28 04 3E 00 18 02 3E 05 FD 21 2B DC CD 96 4C 3A 35 C3 CB 1F CB 1F CB 1F CB 1F FD 21 29 DC CD 96 4C 3E 0C D3 BF 3E 7D D3 BF 21 1A DC 01 14 00 7E D3 BE 3E 01 D3 BE 23 0B 78 B1 C2 37 06 C9 Some bytes need to be changed starting at $B6E7 to accommodate for the altered status panel text: 2F 20 30 2E 30 Got some more figuring out to do re: debug and occasional credits screen, but I'm chuffed to get the constant substeps display working! |
|
|
Posted: Wed Jul 19, 2017 6:48 pm |
Here’s a screenshot.
We had so much fun doing this hack. |
|
|
Posted: Wed Jul 19, 2017 6:57 pm |
Hello,
Can you upload ips patch? Finally do you need debug mode hack???? ;) |
|
|
Posted: Wed Jul 19, 2017 7:12 pm |
Yeah, loved chewing into this, great fun!
BcnAbel76 - I'll do an IPS patch in a bit and will put your pause code into the same routine as the new status panel stuff. |
|
|
Posted: Wed Jul 19, 2017 9:25 pm Last edited by Junosix on Wed Jul 19, 2017 9:55 pm; edited 2 times in total |
Here's an IPS file. Have optimised things a bit more to give room for extra code if required, and have added ability to turn debug mode on: to do this, go to the options menu then initialise the game. When the game restarts debug mode is available in the options menu and is on by default. There are a few instances where $D3F3 is read throughout the code so I'm going to check what happens with that later on.
|
|
|
Posted: Wed Jul 19, 2017 9:53 pm |
Note that the outi block you replaced was there for speed reasons, your changes may have some side effects on a real system. | |
|
Posted: Wed Jul 19, 2017 10:00 pm |
Yep, I'd considered that but it doesn't seem to have any detrimental effects in the three emulators I've tried it in - so fingers crossed it should play okay. Anyone got a flash cart they can give it a go on? | |
|
Posted: Wed Jul 19, 2017 10:17 pm Last edited by matt on Wed Jul 19, 2017 10:33 pm; edited 1 time in total |
We wondered why the OUTI block was there and supposed that there had to be a reason. What's the history of that technique? And why isn't a more succinct OTIR the same? OK I found this: http://www.smspower.org/forums/14941-HowToKnowThatYourVBlankRoutineIsTooSlow |
|
|
Posted: Wed Jul 19, 2017 10:32 pm |
Hello, thanks for the hack !
Writting VDP ports with OTIR may cause too fast writting and corrupted data is causing game, palette or glitches bugs It is an electronics hardware limitation. |
|
|
Posted: Wed Jul 19, 2017 10:50 pm |
BcnAbel76 - what conditions cause OTIR to execute VDP port writes more quickly than OUTI?
I'm working on the basis that the code doesn't seem to run over vblank and in that case things are alright, perhaps they used unrolled OUTI because that's standard/best practice, though as this is a simple game you can get away with it. There's space for a good few OUTI commands if it turns out I need to mix some in to keep the speed up in case there are problems. It would be great to get it running on a Game Gear to see. |
|
|
Posted: Wed Jul 19, 2017 10:59 pm |
Emulicious in break on invalid VDP access mode is a pretty good indicator of any issues.
A block of outis is faster than otir because there's no counter decrement and check for zero. The speed gain may not be necessary though. |
|
|
Posted: Wed Jul 19, 2017 11:11 pm |
I understand the decrement-and-check would slow things up but there was a suggestion a couple of posts back that OTIR would write too quickly for the Game Gear hardware to register the port writes correctly which confused me as OTIR takes more T-states.
Will check the break on invalid access with Emulicious, thanks for the tip. |
|
|
Posted: Thu Jul 20, 2017 12:47 am |
Had a quick go with invalid VDP breakpoints enabled and didn't have issues but I was able to whittle things down even further which gave me space to go back and unroll one of the OTIR loops to OUTI, so here's a patch for that in case anyone has problems with the other one.
|
|
|
Posted: Sun Jul 30, 2017 8:44 pm |
Debug mode also allows access to levels 1-100 before you've played enough to unlock them. | |
|
Posted: Tue Aug 01, 2017 1:22 pm Last edited by matt on Thu Aug 03, 2017 12:12 pm; edited 1 time in total |
The code that governs the appearance of these credits asks for the following conditions to be satisfied:
0. Region is Japan 1. we are about to view the main menu 2. the Start Button is being held down 3. the number of times the main menu has been viewed is a multiple of 8 If all of these conditions are met, the state machine is set to $0B to show the alt credits (more on the state machine soon) The credits will not trigger if any of these conditions are false. For example if you press the Start Button to exit the Options Screen rather than holding it down the alternative credits will not appear. disassembly F_CHECK_ALT_CREDITS:
01CBB: ld hl, VAR_COUNT_MAIN_MENU_VIEWS ; VAR_COUNT_MAIN_MENU_VIEWS = $C338 01CBE: inc (hl) 01CBF: in a, (Port_StartButton) 01CC1: and $40 01CC3: jr nz, + 01CC5: ld a, (hl) 01CB6: and $07 01CB8: jr z, F_SET_STATE_ALT_CREDITS ... F_SET_STATE_ALT_CREDITS: 01D36: ld a, $0B 01D38: jp F_SET_STATE_MACHINE |
|
|
Posted: Wed Aug 02, 2017 7:40 pm |
Interestingly, I tried my copy of the game on a friend's GG and I wasn't able to get the Alt Credits to appear.
edit: the alt credits will only appear when running on a Japanese GG. |
|