Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Changing the Stage ID System
#1
I was dreaming about this years ago, but impossible as a then-purely-DCer. While after only just several days hanging around here, it seems the green light is out. Not only possible (of course), but I guess it is quite practical. A guess only. Although it only involves some changes in numbers, I seldom find mods that done with the similar things.

Still haven't say what I want exactly... it is

GOAL: To change the stage id: system such that 20 is recognized as Stage 2, up to 100 as the Survival Stage. Besides, only 19, 39, 59, 79 and 99 are definite finals, so now there will be 20 acts (sub-stages) available for every stage.

I hope it is possible to really change it successfully. I've found some related instructions and variables, but not all, because I don't know how to find the rest...
I've brainstormed and listed below what the existing system is and what to change to realize my plan. (This is what this thread mainly set up for.)
I've thought of 6 elements and listed below, but there might be more.

Besides, the address stores the stage id is 450B94.



1. Stage choosing in the menu [CERTAIN]
After choosing the characters, players can choose the starting stage - 1, 2, 3, 4, 5 or Survival.
It is confirmed that at this moment, no such values 1, 2, 3... exist in the storage, but rather, the stage id 0, 10, 20, ... 50.
I've found the related instructions:
    ASM-Code:
0042DEE4   83C0 0A          ADD EAX,0A      ;Add 10 [when Attack is hit.]
0042DEE7   83F8 3C          CMP EAX,3C      ;If it is 60, [set it back to 0.]
0042DEEA   A3 940B4500      MOV DWORD PTR DS:[450B94],EAX
0042DEEF   75 06            JNZ SHORT lf2hexed.0042DEF7
SOLUTION for my plan: I guess change them to 14 (20) and 78 (120) would be fine for this part.



2. Always set to the starting sub-stage in the menu [UNSOLVED]
If I change the 0A at 42DEE4 (shown above) to something else, like 0B, the stage id would still be divisible by 10 finally. However, when it comes to the boundary of 60 (see 42DEE7, above), it fails to limit it. Therefore this process is done after the above one.
On the other hand, if I change 0A into 14 instead, which is 20, divisible by 10, the Stage would be 1, 3, 5, 1, 3, 5 ... with pressing Attack.
Here's my finding: once I change the stage id using Cheat Engine, on the menu, it immediately changed back to something divisible by 10, and 42CCF5 is reported for writing to stage id.
    ASM-Code:
0042CCE0   F7E9             IMUL ECX
0042CCE2   C1FA 02          SAR EDX,2
0042CCE5   8BC2             MOV EAX,EDX
0042CCE7   C1E8 1F          SHR EAX,1F
0042CCEA   03C2             ADD EAX,EDX
0042CCEC   8D0480           LEA EAX,DWORD PTR DS:[EAX+EAX*4]
0042CCEF   03C0             ADD EAX,EAX
0042CCF1   2BC8             SUB ECX,EAX
0042CCF3   74 05            JE SHORT lf2hexed.0042CCFA
0042CCF5   A3 940B4500      MOV DWORD PTR DS:[450B94],EAX
0042CCFA   8B0D 78114500    MOV ECX,DWORD PTR DS:[451178]
I need to change "... divisible by 10" into "20", but I can't see anything looks like 10. What should I do?
SOLUTION for my plan: Currently none.



3. Set backgrounds at stage starts [CERTAIN]
I found the instruction set for defining the backgrounds to be loaded at stage starts.
    ASM-Code:
0042CF90   893D B40B4500    MOV DWORD PTR DS:[450BB4],EDI
0042CF96   833E 01          CMP DWORD PTR DS:[ESI],1
0042CF99   0F85 A9000000    JNZ lf2hexed.0042D048
0042CF9F   A1 940B4500      MOV EAX,DWORD PTR DS:[450B94]
0042CFA4   3BC7             CMP EAX,EDI      ;<stage> id: 0
0042CFA6   C705 9C0B4500 46>MOV DWORD PTR DS:[450B9C],46
0042CFB0   893D A80B4500    MOV DWORD PTR DS:[450BA8],EDI
0042CFB6   893D AC0B4500    MOV DWORD PTR DS:[450BAC],EDI
0042CFBC   893D A40B4500    MOV DWORD PTR DS:[450BA4],EDI
0042CFC2   893D 28D04400    MOV DWORD PTR DS:[44D028],EDI
0042CFC8   75 0C            JNZ SHORT lf2hexed.0042CFD6
0042CFCA   C705 24D04400 01>MOV DWORD PTR DS:[44D024],1      ;Load background 1 listed in data\data.txt. (Lee On Road doesn't count; background 0 = HKC)
0042CFD4   EB 53            JMP SHORT lf2hexed.0042D029
0042CFD6   83F8 0A          CMP EAX,0A      ;<stage> id: 10
0042CFD9   75 0C            JNZ SHORT lf2hexed.0042CFE7
0042CFDB   C705 24D04400 02>MOV DWORD PTR DS:[44D024],2      ;Load background 2 listed in data\data.txt.
0042CFE5   EB 42            JMP SHORT lf2hexed.0042D029
0042CFE7   83F8 14          CMP EAX,14      ;<stage> id: 20
0042CFEA   75 0C            JNZ SHORT lf2hexed.0042CFF8
0042CFEC   C705 24D04400 03>MOV DWORD PTR DS:[44D024],3      ;Load background 3 listed in data\data.txt.
0042CFF6   EB 31            JMP SHORT lf2hexed.0042D029
0042CFF8   83F8 1E          CMP EAX,1E      ;<stage> id: 30
0042CFFB   75 0C            JNZ SHORT lf2hexed.0042D009
0042CFFD   C705 24D04400 04>MOV DWORD PTR DS:[44D024],4      ;Load background 4 listed in data\data.txt.
0042D007   EB 20            JMP SHORT lf2hexed.0042D029
0042D009   83F8 28          CMP EAX,28      ;<stage> id: 40
0042D00C   75 0C            JNZ SHORT lf2hexed.0042D01A
0042D00E   C705 24D04400 05>MOV DWORD PTR DS:[44D024],5      ;Load background 5 listed in data\data.txt.
0042D018   EB 0F            JMP SHORT lf2hexed.0042D029
0042D01A   83F8 32          CMP EAX,32      ;<stage> id: 50
0042D01D   75 0A            JNZ SHORT lf2hexed.0042D029
0042D01F   C705 24D04400 06>MOV DWORD PTR DS:[44D024],6      ;Load background 6 listed in data\data.txt.
0042D029   83C8 FF          OR EAX,FFFFFFFF
SOLUTION for my plan: Change the parameters found in 42CFD6, 42CFE7, 42CFF8, 42D009 and 42D01A.



4. Change the stage IDs that are recognized as final acts [UNCERTAIN]
This is uncertain because I don't know is this process included somewhere else.
I'm not really sure what the actual criteria for a stage end. There may be at least two versions I could come up:
If all of the current sub-stage's phases are clear, AND either (1) or (2) is met. // (1) The id after the current one is absent.
Version 1: (2) The current stage id is 9, 19, 29, 39 or 49, (or 59).
Version 2: (2) The next stage id is out of the range of the current stage (eg. 0-9/10-19/...)
It is annoying that they mean the same, but the codes would look quite different... I don't even confirm is the real process one of these, and if yes, which one.
SOLUTION for my plan: None.



5. Enable the use of the extra stage id: 60-100 (or -119) [UNCERTAIN]
This is uncertain because I don't know is there actually a limit set like this.
I just tried using a stage id: 60, found that it would make LF2 crash while loading the stage file. This limit requires more observations, just as basic as why this would occur...



6. Change the calculation of the tag "STAGE %d-%d" [CERTAIN] [UNSOLVED]
It is certain that they are calculated based on the stage id. I just don't understand how it calculates the stage and act number in assembly code. By math it would be
STAGE = ID div 10 + 1
ACT = ID mod 10 + 1
The related code would probably be:
    ASM-Code:
0043871C   8B0D 940B4500    MOV ECX,DWORD PTR DS:[450B94]
00438722   83F9 32          CMP ECX,32      ;Stage IDs below 50 would take this method, else Survival.
00438725   8B35 74714400    MOV ESI,DWORD PTR DS:[<&MSVCR80.sprintf>]   ; MSVCR80.sprintf
0043872B   7D 52            JGE SHORT lf2hexed.0043877F
0043872D   B8 67666666      MOV EAX,66666667
00438732   F7E9             IMUL ECX
00438734   C1FA 02          SAR EDX,2      ;EDX here,
00438737   8BC2             MOV EAX,EDX      ;... and here making EAX, are the stage number, 1-5 (0-4 here actually, without the process of 438749).
00438739   C1E8 1F          SHR EAX,1F      ;To clear EAX. Basically, SHR EAX,03 would be suffice in fact.
0043873C   03C2             ADD EAX,EDX      ;= MOV EAX,EDX (in this case SHR EAX,1F is also not needed)
0043873E   8D1480           LEA EDX,DWORD PTR DS:[EAX+EAX*4]      ;This, and the next instruction, is for "times 10". ...
00438741   03D2             ADD EDX,EDX      ;... EAX is the stage number here, so the result of EDX would be 0 for Stage 1, ... 40 for Stage 5. These stimulate the "10" of "mod 10".
00438743   2BCA             SUB ECX,EDX      ;After EDX is in 10 folds, subtract it and ECX would be the act number. Before this ECX is exactly the Stage ID. This stimulates the "mod" of "mod 10".
00438745   83C1 01          ADD ECX,1      ;+1 at the very last moment; before it is 0-9 instead of 1-10. This is for the act number.
00438748   51               PUSH ECX
00438749   83C0 01          ADD EAX,1      ;+1 at the very last moment; before it is 0-4 instead of 1-5. This is for the stage number. For instance, if anyone wants the stages to be 7-11 instead of 1-5, just put this 1 into 7.
0043874C   50               PUSH EAX
0043874D   68 849D4400      PUSH lf2hexed.00449D84                      ; ASCII "STAGE %d-%d"
00438752   68 18144500      PUSH lf2hexed.00451418
00438757   FFD6             CALL ESI
00438759   A1 08564500      MOV EAX,DWORD PTR DS:[455608]
0043875E   6A 6E            PUSH 6E      ;x-coord.
00438760   68 68010000      PUSH 168      ;y-coord.
00438765   68 C8C8C800      PUSH 0C8C8C8      ;Color.
0043876A   6A 00            PUSH 0
0043876C   68 18144500      PUSH lf2hexed.00451418
00438771   50               PUSH EAX
00438772   E8 198BFCFF      CALL lf2hexed.00401290
And I don't know what the instruction is for loading values into those "%d". // (Edit) ANSWER: PUSH (roughly).
SOLUTION for my plan: By math change the "10" to "20" would be fine, just don't know the corresponding part in assembly code. Another thing is the 32 at 438722.
(Edit) SOLUTION: 438734 SAR EDX,3 // 438741 CALL ??? / ??? ADD EDX,EDX / (???+2) ADD EDX,EDX / (???+4) RET



7. Array size [UNSOLVED]
(05-28-2014, 03:03 PM)Blue Phoenix Wrote:  I am most definitely sure that in the original code, the stage-array has been allocated as an array with 60 elements (counting from 0 to 59). This means you'll have to enlarge that array (oh boy!). [...]
1. Where is it? I know in programming variables need to be defined or declared before being used. This includes arrays, about the data type and its size, but where is it?
2. How to change its size then? ...



May 28 edit:
For Element 6, I've added some descriptions to the code according to my findings.
On the other hand, I see the system makes stage id: 0-19 recognized as Stage 1, 20-39 as 2 etc. if I change 438734 into SAR EDX,3. To tackle the remaining problem, just repeat 438741 once more, making the "10" into "20" would be fine. (Now it is (1+4)*2, I need it (1+4)*2*2.)
Element 6 SOLUTION: 438734 SAR EDX,3 // 438741 CALL ??? / ??? ADD EDX,EDX / (???+2) ADD EDX,EDX / (???+4) RET

May 29 edit:
Added Element 7 as Blue Phoenix has raised.
Reply
Thanks given by: A-Man , darkfiren
#2
Whenever I put a Stage ID >= 60 in Stage mode, LF2 crashes. I've no idea where this limit from and I need help most on this... Please help...!
If I can't solve this, all the other effort would be useless.
Reply
Thanks given by:
#3
(05-26-2014, 01:56 PM)Ikran Ahiyìk Wrote:  2. Always set to the starting sub-stage in the menu [UNSOLVED]
If I change the 0A at 42DEE4 (shown above) to something else, like 0B, the stage id would still be divisible by 10 finally. However, when it comes to the boundary of 60 (see 42DEE7, above), it fails to limit it. Therefore this process is done after the above one.
On the other hand, if I change 0A into 14 instead, which is 20, divisible by 10, the Stage would be 1, 3, 5, 1, 3, 5 ... with pressing Attack.
Here's my finding: once I change the stage id using Cheat Engine, on the menu, it immediately changed back to something divisible by 10, and 42CCF5 is reported for writing to stage id.
    ASM-Code:
0042CCE0   F7E9             IMUL ECX
0042CCE2   C1FA 02          SAR EDX,2
0042CCE5   8BC2             MOV EAX,EDX
0042CCE7   C1E8 1F          SHR EAX,1F
0042CCEA   03C2             ADD EAX,EDX
0042CCEC   8D0480           LEA EAX,DWORD PTR DS:[EAX+EAX*4]
0042CCEF   03C0             ADD EAX,EAX
0042CCF1   2BC8             SUB ECX,EAX
0042CCF3   74 05            JE SHORT lf2hexed.0042CCFA
0042CCF5   A3 940B4500      MOV DWORD PTR DS:[450B94],EAX
0042CCFA   8B0D 78114500    MOV ECX,DWORD PTR DS:[451178]
I need to change "... divisible by 10" into "20", but I can't see anything looks like 10. What should I do?
In terms of CPU-cycles, division is one of the most gruesome basic operations there are. It's likely that the compiler simply "optimized" the code by replacing "divide by 10" by some brainwrecking commands. I actually tried to understand what happens in the code posted above but eventually gave up :p
This thread shows what can be done to optimize exactly this problem, so as you can see, things get messy really fast. My suggestion would be to just JMP out of there, do your own calculations for "division by 20" and JMP back to the end of this block.



(05-28-2014, 08:17 AM)Ikran Ahiyìk Wrote:  Whenever I put a Stage ID >= 60 in Stage mode, LF2 crashes. I've no idea where this limit from and I need help most on this... Please help...!
If I can't solve this, all the other effort would be useless.
I am most definitely sure that in the original code, the stage-array has been allocated as an array with 60 elements (counting from 0 to 59). This means you'll have to enlarge that array (oh boy!). As chances are low that it's right in front of some empty space, you'll probably have to redefine the pointer to the stages-array. I expect that to be some terribly nasty work, similar to enlarging the frame-limit of characters or object-limit of data.txt. Somebody that has more experience in hex than me (so basically, everybody :p) rate the level of effort for this.
Silverthorn / Blue Phoenix
~ Breaking LFE since 2008 ~

"Freeze, you're under vrest!" - Mark, probably.

» Gallery | » Sprites | » DeviantArt
Reply
Thanks given by: Ikran Ahiyìk , darkfiren
#4
(05-28-2014, 03:03 PM)Blue Phoenix Wrote:  In terms of CPU-cycles, division is one of the most gruesome basic operations there are. It's likely that the compiler simply "optimized" the code by replacing "divide by 10" by some brainwrecking commands. I actually tried to understand what happens in the code posted above but eventually gave up :p
This thread shows what can be done to optimize exactly this problem, so as you can see, things get messy really fast. My suggestion would be to just JMP out of there, do your own calculations for "division by 20" and JMP back to the end of this block.
I guess I've got something when investigating element 6, that's similar to this one... Maybe I could solve it later, but jumping to a blank area for own calculations is a good suggestion as last resort through. :p

(05-28-2014, 03:03 PM)Blue Phoenix Wrote:  I am most definitely sure that in the original code, the stage-array has been allocated as an array with 60 elements (counting from 0 to 59). This means you'll have to enlarge that array (oh boy!). As chances are low that it's right in front of some empty space, you'll probably have to redefine the pointer to the stages-array. I expect that to be some terribly nasty work, similar to enlarging the frame-limit of characters or object-limit of data.txt. Somebody that has more experience in hex than me (so basically, everybody :p) rate the level of effort for this.
Ah yeah! Never thought of this and thanks for bringing this out!
But... I've no idea how to implement this. First off I don't know where the array is defined, and how exactly to enlarge it for the second. Those people who change the frame-limit simply just throw their exe out with little explanation, or did I recalled wrongly? ... Anyway this is the biggest problem now, at least right now I see this has nothing to do with all elements 1-6 I listed above, and I have to add one more.

Thanks for insights ;)
Reply
Thanks given by:




Users browsing this thread: 1 Guest(s)