Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Quasar

Chocolate Strife Beta 1 now available

Recommended Posts

Quasar said:

One difficulty with adding code to DOS programs is the relocation table - there must be an entry in it for every absolute address in the code.

Not really a problem. If you want to address some own data or get access for internal variables without adding fixup you can use call $ pop eax (e8 00 00 00 00 58) for getting real address. See doom2-plus.crk "saves" section:

00086F94: 00 E8 ;call        000061D85
00086F99: 00 59 ;pop         ecx
00086F9A: 00 83 ;sub         ecx,9

Share this post


Link to post
Graf Zahl said:

Even for DOS-extended 32bit programs? I always thought that the DOS extender was taking care of this by properly mapping the memory.

I have no idea what the technical reason for the requirement is, but even 32-bit DOS programs have to be relocatable >_> entryway's method is intriguing, although I'm not entirely sure how it works ;)

Share this post


Link to post
Quasar said:

entryway's method is intriguing, although I'm not entirely sure how it works ;)



It does a call to the address right behind the call. Since the call is address relative it can be done without relocation. So then you got the current address on the stack and can use it to reference your code/data relatively to that address.

Share this post


Link to post
Graf Zahl said:

It does a call to the address right behind the call. Since the call is address relative it can be done without relocation. So then you got the current address on the stack and can use it to reference your code/data relatively to that address.

Yes. Just because there is no opcode for "mov eax, eip"

I can record small video how to get / to change value of some variable with this trick if Quasar wants.

Share this post


Link to post

Entryway is on the right path. Tricky parts are:
1. Finding a place to put the original P_Random routine.
2. Getting the data
3. Getting it out to a file. The most tricky.

I think maybe you could dump the data into the save buffer, and then trick the save code to dump the file - might be easier than trying to write your own routine. Even if the program then crashed, as long as you actually got valid data into the file, you'd be set.

I'd love to mess with this myself, and am not unwilling, but I am not set up very well for this kind of thing anymore - it's been a long time since my exe hacking days. Also, I have very little time.

Quasar, if you could provide the following, I think I can try to write the strife exe stub code. I need text files of each of the following areas of your IdaPro disassembly, complete with offsets:

. The P_Random() function
. The SaveGame function (the one that actually writes the file)
. A large contiguous string (at least 64 bytes or so). Does Strife have finale texts??
. The line of code that references that string.

I can try to use that information to create a stub that you'll need to patch into a copy of Strife.exe.

Share this post


Link to post

I'd expect the screenshot writer would be easier to hijack considering you know the output size a priori (and it provides a relatively safe buffer to inject).

Share this post


Link to post
DaniJ said:

I'd expect the screenshot writer would be easier to hijack considering you know the output size a priori (and it provides a relatively safe buffer to inject).

I totally agree. Quasar, please modify my request to include the Screenshot routine, and the call to it.

Share this post


Link to post
kb1 said:

I totally agree. Quasar, please modify my request to include the Screenshot routine, and the call to it.

I take it you don't happen to have IDA Pro, because if you did, the .idb is available...

But assuming not, I'll get you that info. However, what format are you looking for it in? Assembly listing with addresses on the side?

EDIT: If so, http://eternity.pastebin.com/S8UYvykF

Share this post


Link to post

I need the machine code too!! (The hex bytes that assembly is generated from, usually listed to the left of the mnemonics).

Well, I've got IdaPro 5.0 - freeware version, but some post back I think you mentioned that I'd need at least 5.2 IIRC for the other half that does the conversion attempt to C, which was interesting.

I priced the latest - around $2,800 for what I wanted - damn.

Of course, I *gazed upon* another version - as of yet, I've been afraid to install...

I can try to get it all up and running, but, again, I have about 100 years of projects lined up, and, will probably be feeble before I get half way through...

Sorry to be a pain in the ass - if you could resend it with the hex, I'll see if I can whip something up.

Share this post


Link to post

Oh, also, please include one instance of code calling P_Random.

Edit: Preferrably one that is not in the same module. Thanks!
I'm just guessing what I might need. Working blind kinda sucks, you know? Might have to do something about that, come to think of it.

Share this post


Link to post

Ah hell, man, sorry about that - I should have said "opcodes" with the assembly. Anyway, it's all good now, as I'm now reading the .idb. Yay! Thanks anyway for the help...

I've made significant progress, and I have a couple questions.

The biggest question: Should I be using strife1.exe v1.3.1??? In other words, do strife 1.2 demos work on strife 1.3.1 and vice-versa?

If not, I'll need a copy of 1.2 - I only have 1.3.1.

Ok, here's some preliminary pseudocode for the capturing portion: (Not sure if this should be discussed to this length in this forum, or not...but here goes.)

-----------------------------[Buffer]-------------------------------------------------------------------------------------------
The buffer is comprised of an 8-byte header, followed by records of 6 bytes each. Currently it is being written to the same location
used to hold the save game buffer. Unfortunately that's 16K into the screens[1] buffer, which is probably written to every other frame.
I'll need to think of somewhere else to put it.

Header format:
00-03: Signature "kb1\0", used to make sure the buffer header has been initialized.
04-07: Offset from buffer start - the next location to be written. Can also be interpretted as the size of the buffer, including the header.

Record format:
00-03: Caller return address, indicating who called the random function
04:    Random type. 00=P_Random, 01=M_Random
05:    The actual pseudo-random number generated
 
-----------------------[Pseudocode/Assembly]-------------------------------------------------------------------------------------------

const byte DO_P_RANDOM = 0x00;
const byte DO_M_RANDOM = 0x01;

byte P_Random(void)
{
  				MOV 	AL, DO_P_RANDOM
  				JMP 	X_Random
}

byte M_Random(void)
{
  				MOV 	AL, DO_M_RANDOM
  				JMP 	X_Random
}

byte X_Random(byte AL = RecType)
{

6B 62 31 00		Sig:	DD	0031626Bh			; Buffer signature "kb1\0"
08 00 00 00		HdrSiz:	DD	00000008h			; Header size
06 00 00 00		RecSiz:	DD	00000006h			; Sync record size
		
00			RType:	DB	00h				; Random type: P_Random = 0, M_Random = 1
?? ?? ?? ??		Caller: DD	??				; Caller return address

  				MOV 	[RType], AL			; Temporarily store random type
	  			POP 	EAX				; Get caller address
	  			MOV 	[Caller], EAX			; save it
	  			PUSH 	EAX				; put it back so we can RETurn to caller
	  			PUSH 	EBX				; preserve EBX
  
A1 B8 C5 0D 00			MOV	EAX, SCREENS+4			; this is where the original savebuffer is placed.
05 00 40 00 00			ADD	EAX, 04000h			; I sure hope the buffer doesn't normally get overwritten...

  				MOV	EBX, EAX			; ebx = savebuffer
  				MOV	EAX, dword ptr [EBX]		; read signature
  				CP	Sig				; is it "kb1\0"?
  				JR	Z, Ready			; if so, buffer header has already been initialized
  				MOV	EAX, Sig			; otherwise, initialize it
  				MOV	dword ptr [EBX], EAX		; store signature
  				MOV	EAX, HdrSiz			; data starts at offset 08h
  				MOV	dword ptr [EBX+04h], EAX	; store initial offset

  			Ready:	MOV	EAX, dword ptr [EBX+04h]	; get buffer offset
  				PUSH 	EAX				; temp = eax
05 06 00 00 00			ADD 	EAX, RecSiz			; eax += 6
  				MOV 	dword ptr [EBX+04h], EAX	; store it in buffer header
  				POP 	EAX				; eax = temp
  				ADD 	EBX				; eax += savebuffer: add offset to buffer start: 
  				MOV 	EBX, EAX			; ebx = eax: finally, EBX points to next byte to write
  			
  				MOV 	EAX, [caller]
  				MOV 	dword ptr [EBX], EAX		; store caller address in buffer


  				MOV 	AL, [RType]
  				MOV 	byte ptr [EBX+04h], AL		; store random type in buffer

				OR 	AL				; Is it P_Random?
				JR 	NZ, MRand			; If not, do M_Random instead

A1 98 68 08 00		PRand:	MOV     EAX, prndindex			; Original P_Random()
40				INC     EAX
25 FF 00 00 00			AND     EAX, 0FFh
A3 98 68 08 00			MOV     prndindex, EAX
8A 80 94 67 08 00		MOV     AL, rndtable[EAX]
25 FF 00 00 00			AND     EAX, 0FFh

  				MOV	byte ptr [EBX+05h], AL		; store the random number
  				POP 	EBX				; done with EBX
C3  				RET					; return to caller of P_Random()

A1 94 68 08 00		MRand:	MOV	EAX, rndindex			; Original M_Random()
40				INC     EAX
25 FF 00 00 00			AND	EAX, 0FFh
A3 94 68 08 00			MOV     rndindex, EAX
8A 80 94 67 08 00		MOV	AL, rndtable[EAX]
25 FF 00 00 00			AND	EAX, 0FFh

  				MOV	byte ptr [EBX+05h], AL		; store the random number
  				POP 	EBX				; done with EBX
C3  				RET					; return to caller of M_Random()

}
Note that I don't yet have the gametic variable, which is required. Also missing is the code to write the file, but, I'm in luck - it looks like I can call M_WriteFile() to do the job. You can see the opcodes I was trying to get you include in some of the lines - I'll need to hand-assemble the rest, and manually patch it into strife1.exe.

The idea is you run the program in DOSBox, with something like this:
strife1.exe -devparm -playdemo demo1
The program immediately starts filling a buffer. Just before the demo finishes, you press F12 which, instead of producing a screenshot, will dump the buffer to a file.

Ok, issues and questions:

1. The savegame buffer is really a re-use of the screens[] array, specifically starting at screens[1]+04000h. I'm not sure, but if I remember, the page flip, the status bar refresh, and the screen wipe code use that buffer as well. Any ideas where I can relocate my buffer? I am also considering getting the program to allocate more screens[], but I would rather not change the memory layout if possible.

2. Can anyone think of a file write scenario in strife that does append mode vs overwrite mode? If I could append to a file, I can avoid the buffer altogether. I think the code calls _open and _write. Does anyone know what flags I should pass to these to get them to do a file append?

3. Quasar, have you thought about your portion within chocolate-strife? Basically, it needs to work like this:

. At the start of the game, open a file for append: "sync.dat"
. For each of P_Random() and M_Random()
. Change function to accept an int: P_Random(int caller), etc
. write a line to the file:
 00 caller rndval (For P_Random)
 01 caller rndval (For M_Random)
. Close the file upon exit
. In each call to either function within the entire source, add a unique caller value.

It may even be possible to go back and update your unique numbers with the actual addresses from strife1.exe, for a one-to-one correspondence. Not strictly necessary, but it would make analysis much easier. I have a feeling that we'll get demo1 working quickly, but more work will be required to make other demos sync.

Maybe, I can mock that code up after I get the original stub working, but I think you get my drift. I intend to write a small VB6 app that will assist in comparing the two files. We'll see.

Please let me know if it's more appropriate to discuss this offline.

Share this post


Link to post

Sry double-post, different subject:

Ok, now I'm convinced that the supplied .idb file is for a different .exe than what I have. It's similar, but the addresses don't quite match, and the source appears to be slightly different. I have come to the conclusion that Strife1.exe v1.3.1 was not the program disassembled.

Version 1.2 perhaps?


Can you:

1. Verify your version against this v1.2 I just acquired:

Strife1.exe
CRC32: A4498079
MD5: F32F0EEB8EC3ED8E3ADB21F5D85D290F
SHA-1: DB32393B4082184B0BD419A68711A89E995E9317

2. If that's not it, send me the strife1.exe (full size), and the strife1.le (DOS extender stripped) that you used?

Considering being able to use the right damn .exe, it's conceivable (no promises) that I have it working by Monday afternoon.

Share this post


Link to post

We are currently working on Strife 1.2, yes. 1.31 has also been disassembled, though not in as full detail. Instead I ran a special kind of difference process between them and found everywhere they differ (there is a thread detailing these differences in this forum a few pages back...).

The intention is to support both 1.2 and 1.31 behavior in Chocolate Strife, since there are so few differences. And for what it's worth, the 1.2 and 1.31 IWADs are identical, including the demo, which, for what THAT'S worth, states it is for v1.1 (101).

There were more than likely no changes to the gameplay code in any released commercial version of Strife. All the changes and fixes were to stuff such as the menu system and the finale sequence.

Share this post


Link to post

Ok, good to know. Any chance you can verify the MD5 I supplied? I'm screwed if I happen to be working on the wrong one.

At least please verify the file size: 752,691 bytes.

Share this post


Link to post
kb1 said:

Ok, good to know. Any chance you can verify the MD5 I supplied? I'm screwed if I happen to be working on the wrong one.

At least please verify the file size: 752,691 bytes.

Now that I am at home I can send you the files.

http://eternity.mancubus.net/stuff/strife12-exe-le.zip

Also, you realize that M_Random is not sync-critical right? That's its only purpose. We found nowhere in the engine where it was being abused to do game-sync-critical work. P_Random, on the other hand, is sometimes used for things which should *not* be sync-critical, as it was in DOOM, such as for selecting Acolyte wake-up sounds. Very silly.

Share this post


Link to post
Quasar said:

Now that I am at home I can send you the files.

I've got the same problem in reverse: At work, I can check the forums. At home, I can work on Doom stuff.

Quasar said:

Also, you realize that M_Random is not sync-critical right? That's its only purpose. We found nowhere in the engine where it was being abused to do game-sync-critical work. P_Random, on the other hand, is sometimes used for things which should *not* be sync-critical, as it was in DOOM, such as for selecting Acolyte wake-up sounds. Very silly.

Yeah, it's not supposed to be. Problem is, I'm not as familiar with Strife as I could be, so I may be talking out my ass. But, I wouldn't want something like a random sound with random timing affecting the player's ability to, for example, close a dialog at a specific time. I get that, some of Strife's code is very good, and some is kinda wonky (huge player structure, etc.)

As you know, demo sync is tricky stuff. I'll probably continue capturing M_Random for the time being. Good to know you didn't find it being used directly for gameplay.

Share this post


Link to post
kb1 said:

I've got the same problem in reverse: At work, I can check the forums. At home, I can work on Doom stuff.


Yeah, it's not supposed to be. Problem is, I'm not as familiar with Strife as I could be, so I may be talking out my ass. But, I wouldn't want something like a random sound with random timing affecting the player's ability to, for example, close a dialog at a specific time. I get that, some of Strife's code is very good, and some is kinda wonky (huge player structure, etc.)

As you know, demo sync is tricky stuff. I'll probably continue capturing M_Random for the time being. Good to know you didn't find it being used directly for gameplay.

No. And the dialogue engine is disabled during demo recording anyway. DOOM demos don't depend on realtime execution to stay in sync. You can run them at any realtime speed you want. If this were not the case, demo sync in any port would be utterly impossible.

Share this post


Link to post
Quasar said:

...DOOM demos don't depend on realtime execution to stay in sync...

Right, not suggesting otherwise. However, it's conceivable that another company COULD have gotten it wrong - it's easy to do. Of course, you'd know better than me :)

I wrestled with IP last night til about 6:00am, trying to get it to relocate the dseg03 segment, and fix up all the labels, to no avail. My goal was to get it to STOP CHANGING THE ADDRESSES in the opcode and in the hex dump, to match the exe. Any reference to data is 0x60000 too high in IP, compared with the original file. Yes, it even changes the bytes in the hex dump. I'm at a loss to understand this behavior. The help file mentions "virtual vs. linear" addressing wery briefly, but leaves a lot to be desired.
On a positive note, it's helped me learn to navigate it better (there must always be a positive note, right?)

Anyway, I can work around it, by offsetting everything - yikes.

Share this post


Link to post

This has probably been pointed out already, but with the default settings, the enter key doesn't work as an "inventory use" key, as the heads-up code to redisplay the last message overrides it (key_message_refresh, hu_stuff.c). Any plans to remove that?

Share this post


Link to post
fraggle said:

This has probably been pointed out already, but with the default settings, the enter key doesn't work as an "inventory use" key, as the heads-up code to redisplay the last message overrides it (key_message_refresh, hu_stuff.c). Any plans to remove that?

Message refresh function needs to be moved to the ? key actually. The HUD code is dense as all crap and is one area we have not made a lot of inroads into understanding. I've gotten into it only as far as I needed to make the dialogue system and statbar work properly, so there's plenty of TODO's in there.

Share this post


Link to post

Well, I'm about 2/3 done with the patch. I re-discovered the cold hard truth about .exe address relocation fix-ups.

EDIT: Aw hell, just noticed this...in this very thread:

Quasar said:

One difficulty with adding code to DOS programs is the relocation table - there must be an entry in it for every absolute address in the code. xttl came up with a way to overcome this for the Prebeta EXE when we were hacking on it (and I'd still love to release something based on that effort as well...) but I do not know if the same approach would work on Strife or not - probably so, actually.

And, also noticed entryway's response. By the way, nice, informative video, entryway!

One thing you must still do, is invalidate those table entries that want to modify addresses that fall within your replaced code. This caused me quite a lot of grief last night, as I was replacing a memory read containing a relocatable address, with very different code.

Anyway, considering I've lost quite a bit of sleep last weekend, I'll just say "When It's Done", but it'll be soon.

Did anyone notice that, sometimes the screenshot key for Strife 1.2 is F9, and sometimes it's F12?? What's up with that?

Share this post


Link to post

Ok, my demo data-capturing patch of Strife is partially working. Quasar, I PM'd you the details.

Share this post


Link to post

Just a note to say that the IWAD demo is now in sync with some fixes to P_NewRandomDir, P_CheckMissileRange, P_XYMovement, and P_ZMovement. Of course this is no reason to stop working on that tweak, kb1 - we still have a lot of work to do.

The project has made significant progress toward completion. I have finished the cheat codes as of last night. Unfortunately I cannot release a new beta at this time because my internet connection is completely trashed - my DSL modem is on the fritz and I need to find a new one, as well as have my outdoor wiring replaced. I'm going to be very scarce for a while now.

Share this post


Link to post
fraggle said:

Awesome!

Yeah, that is awesome. Incredible, actually! Nice.

Quasar said:

...Of course this is no reason to stop working on that tweak, kb1 - we still have a lot of work to do.

I'm a little late, huh? I've just got the patch working. I would love to host the files somewhere more relevant than just a file hosting service. Any takers/ideas?

Here is an excerpt from it's output, detailing the random calls made by strife1.exe during tic #86 (about 2 seconds in) of the IWAD demo:

TIC #86:
  A_Punch1()                 rndtable[0x73] = 0x32
  A_Punch2()                 rndtable[0x74] = 0xEF
  A_Punch3()                 rndtable[0x75] = 0x31
  P_DamageMobj()             rndtable[0x76] = 0x6F
  P_SpawnBlood1()            rndtable[0x77] = 0xA4
  P_SpawnBlood2()            rndtable[0x78] = 0x46
  P_SpawnMobj()              rndtable[0x79] = 0x3C
  A_FriendLook1()            rndtable[0x7A] = 0x02
  A_FriendLook1()            rndtable[0x7B] = 0x25
  A_FriendLook3()            rndtable[0x7C] = 0xAB
  ...
The numbers at the end of the function names represent multiple calls from the listed function.
If requested, I'll consider adding SpawnMobj, and P_XYMovement hooks in as well. These things combined would make finding future demo/net desyncs an order of magnitude easier.
Unfortunately, in it's current state, it would have only indirectly pointed to the need for the type of fixes Quasar mentions, with the exception of P_NewRandomDir.
So, let me know what you need - I'm in business now, and would like to feel like I contributed something more than inspiration!

Share this post


Link to post
kb1 said:

Unfortunately, in it's current state, it would have only indirectly pointed to the need for the type of fixes Quasar mentions, with the exception of P_NewRandomDir.
So, let me know what you need - I'm in business now, and would like to feel like I contributed something more than inspiration!

Yeah that's the essence of the problem really. It's easy to see if your number & order of P_Random calls match in the code but difficult to tell when they are bad because of an algorithmic issue. In this case, the desync during the second Acolyte battle was caused by Peasants elsewhere walking in the wrong direction(s) due to some translation errors (all my own fault mind you :P) in P_NewRandomDir, which is like P_NewChaseDir except for random meandering actors instead of walking monsters.

The P_Randoms getting off caused the Acolyte to try to attack instead of walk, and so the player would stop slightly short of where he should have been, running into the wall.

Then after that was fixed, it started getting just slightly out of sync after he jumped the railing. I found out this was due to some completely missed code to apply air resistance (ie friction) to players while they're in the air, in P_XYMovement. >_> Also, the code to snap the player's pitch angle to 0 when he hit the ground was inside the wrong if() statement, and only ran if you actually took falling damage, whereas it should always run (P_ZMovement).

What you've come up with sounds very cool though. What we may want to do is record some more interactive demos such as runs through the pure "combat" levels of Strife like the Security Complex or Programmer's Lair. They'd be bound to find more problems.

Share this post


Link to post
Quasar said:

Yeah that's the essence of the problem really. It's easy to see if your number & order of P_Random calls match in the code but difficult to tell when they are bad because of an algorithmic issue.

Yes, but it probably would have pointed you to the right tic :) I'll add the P_XYMovement and the SpawnMobj stuff - in my Doom port, those are included, and, thinking about it, I used the combination of all of these extensively for both network and demo sync. You almost need all of those to be able to tell what's going on.

Wow, how did you find what was wrong?? :O Checking all functions again? Quite impressive!

Quasar said:

What you've come up with sounds very cool though.

Thanks, man. It's actually is kinda interesting having a window into the inner workings, so to speak. Actually, I'm just happy to get the damn thing working - it took a lot longer than it should have.

Quasar said:

What we may want to do is record some more interactive demos such as runs through the pure "combat" levels of Strife like the Security Complex or Programmer's Lair. They'd be bound to find more problems.

Yes, we need some more demos, especially ones that use a lot of the more esoteric A_ functions, where a desync could be lurking...

Now: Not to be rude, but no one responded, so I have to ask again: Can anyone host a few of these files, and maybe a html page for me? I'm not only excited to finally be able to contribute something back to the community, but this stuff's just kinda interesting - I'd like to share what I've come up with. Yes, I can dump it to Fileshack, or something, but that doesn't seem to make sense. The 'online-presence' thing is sorta new to me, and I don't really have enough stuff to justify my own domain or anything like that.
Come on, hook a brother up... :)

Share this post


Link to post

I'm probably going to set this aside for now. Let me know if there's any more need for it, or need to modify it. I need to get back to more pressing things.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×