News:

Herr Otto Partz says you're all nothing but pipsqueaks!

Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - llm

#31
Quote from: Daniel3D on October 11, 2022, 10:47:13 AMseg000 Line 1060:     mov     ax, 0AC74h 
    mov     ax, offset aGsta; "gsta"
    push    ax
    push    [bp+var_38]
    push    [bp+var_3A]
    call    locate_shape_alt
    add     sp, 6
    push    dx
    push    ax
    mov     ax, 0AC74h
    push    ax
    call    copy_string
    add     sp, 6
    push    word_407D6
    push    word_407D4
    mov     ax, 4Ch ; 'L'
if this is one there are 13 other hits on "ax, 0AC74h"


0AC74h is very likely an offset into the data segment, to some string or something
you need to analyse copy_string - in IDA you would annotate the parameter of copy_string so IDA can infere further
#32
Quote from: Daniel3D on October 11, 2022, 10:42:57 AMFirst line of interest..  8)
seg000 Line  607:     mov     ax, 0FFFFh 
_ask_dos:
    sub     ax, ax
    push    ax
    push    ax
    push    dialogarg2
    mov     ax, 0FFFFh
    push    ax
    push    ax
    mov     ax, offset aDos ; "dos"
    push    ax
if this is one there are 85 other hits on "ax, 0FFFFh"

that is very likly just -1, in assembler everything is unsiged, but that does not
mean that a value IS unsigned, -1 isn't very likely an offset :)

see online-conversion:
https://cryptii.com/pipes/integer-converter
https://imgur.com/BiCqyoI
#33
Quote from: Daniel3D on October 11, 2022, 08:15:07 AMI only intend to catalogue them.

this regex finds most of magic-values numbers, that could be offsets, and only global offsets are relevant

(\,|\-|\+)\s*((0[a-fA-F0-9]*|[1-9][a-fA-F0-9]*)h|[0-9])

im using that with Notepad++ (but other editors with regex support should also work)
searching all asmorig asm-files

removing all "add or sub sp,VALUE" + defines reduces the list to ~13.000, but most of the findings
are value-sets or something

as usual - a huge mess of assembler code :(
#34
Quote from: Daniel3D on October 10, 2022, 07:22:24 PMThere will be false positives.

if you change a non-symbolic offset to an symbolic one and compare the exe before/after no bit should have changed - then could it be still wrong but still does not can harm the gameplay because the exe is not changed, doing such changes without checking before/after is like playing roulett for earning bugs without any need
#35
for example

mov    di, 55CAh
is

mov    di, offset word_40D3A
should produce the very same executable (binary equal)

from IDA-Editor:
dseg:55C8                 db 0FFh
dseg:55C9                 db    0
dseg:55CA word_40D3A      dw 0                    ; DATA XREF: end_hiscore+638␘w
dseg:55CA                                         ; end_hiscore+656␘r start+6A␘o
dseg:55CC word_40D3C      dw 0                    ; DATA XREF: end_hiscore+63E␘w
dseg:55CC                                         ; end_hiscore+6C1␘r
dseg:55CE word_40D3E      dw 0                    ; DATA XREF: end_hiscore+644␘w

more or less easy in IDA Pro - but first you need to know that this is really a offset value
and which segment the offset targets - in this case seeable by looking at the code above
seems to be dseg - so its a offset to a variable in the data segment (some copy/init operation is done)

IDA always shows the binary information (offsets, opcodes) in parallel to the disassembly: https://imgur.com/fsUvtVI
thats the primary reason for using a professional tool for reverse engineering, thats also the reason for using a IDA script
to produce the asm code - any finding can result in multiple changes over the asm files - for example you finding a common type
and start using it in IDA - IDA will use that information to extend other parts of the disassembly, resolving more and more
that is not easy with dead end assembler code - and a huge part of the reversing process

IDA Pro is not an assembler editor (you can't change anything in the assembler-code) is just a tool to help reverse engineering - so
cross references, graphs, deep analysis etc., you can add types, structs and annotated the found functions, giving IDA more infos
how to disassemble stuff he didn't understand by itself
#36
Quote from: Daniel3D on October 10, 2022, 01:43:11 PMSo to make a symbolic offset out of it you must first find the correct byte offset and locate it in the assembly code?

thats why people using IDA or Ghidra for reversing - they keep the assembler source view and and the binary code in sync - so you can easier see what an offset could target

Quote from: Daniel3D on October 10, 2022, 01:43:11 PMLooking at your example i guess it is not very difficult for you. But i understand why they are not all done.

it could be difficul because sometimes offsets are calculated using serveral lines of assembler code
which could be also some sort of 3d point calculation - its not always easy to differ

Quote from: Daniel3D on October 10, 2022, 01:43:11 PMIf i find more (i now have an idea of what they look like) and they are not commented as such I'll make a note of it.

great
#37
Quote from: Daniel3D on October 10, 2022, 12:55:19 PMAssuming that the hex value is a number that corresponds to the line it seems to be a little off.
But i guess that the start of the file should be excluded from the line count as that is compiler info.

the hex value does NOT coresponds to a line number, NEVER - the hex-value is an byte-offset from the image start (behind the exe header), it depends on the size of code that sits before and every asm command is of different size in binary

for example: this is a assembler routine (not from stunts) - on the left is the binary-offset, then the binary code and the corespondig asm source

IDA-Offset  | Binary code | Assembler source
            |             |
seg000:BDF4 |             |  sub_1BDF4  proc near
seg000:BDF4 |             |                                   
seg000:BDF4 | 06          |            push    es
seg000:BDF5 | 1E          |            push    ds
seg000:BDF6 | 56          |            push    si
seg000:BDF7 | 57          |            push    di
seg000:BDF8 | 8D 36 76 BC |            lea    si, ds:0BC76h
seg000:BDFC | B9 06 00    |            mov    cx, 6
seg000:BDFF |            |
seg000:BDFF |            |  loc_1BDFF:                       
seg000:BDFF | 83 C6 04    |            add    si, 4
seg000:BE02 | 2E 8B 04    |            mov    ax, cs:[si]
seg000:BE05 | 2E 0B 44 02 |            or      ax, cs:[si+2]
seg000:BE09 | 74 02      |            jz      short loc_1BE0D
seg000:BE0B | E2 F2      |            loop    loc_1BDFF
seg000:BE0D |            |
seg000:BE0D |            |  loc_1BE0D:                       
seg000:BE0D | 2E 89 1C    |            mov    cs:[si], bx
seg000:BE10 | 2E 89 7C 02 |            mov    cs:[si+2], di
seg000:BE14 | 5F          |            pop    di
seg000:BE15 | 5E          |            pop    si
seg000:BE16 | 1F          |            pop    ds
seg000:BE17 | 07          |            pop    es
seg000:BE18 | C3          |            retn
seg000:BE18 |            |  sub_1BDF4  endp

Shellstorm disassembly of the same Binary code without symbolic offsets

0x0000000000000000:  06            push es
0x0000000000000001:  1E            push ds
0x0000000000000002:  56            push si
0x0000000000000003:  57            push di
0x0000000000000004:  8D 36 76 BC    lea  si, [0xbc76]
0x0000000000000008:  B9 06 00      mov  cx, 6
0x000000000000000b:  83 C6 04      add  si, 4
0x000000000000000e:  2E 8B 04      mov  ax, word ptr cs:[si]
0x0000000000000011:  2E 0B 44 02    or  ax, word ptr cs:[si + 2]
0x0000000000000015:  74 02          je  0x19 <-- jmp offset
0x0000000000000017:  E2 F2          loop 0xb <-- jmp offset
0x0000000000000019:  2E 89 1C      mov  word ptr cs:[si], bx
0x000000000000001c:  2E 89 7C 02    mov  word ptr cs:[si + 2], di
0x0000000000000020:  5F            pop  di
0x0000000000000021:  5E            pop  si
0x0000000000000022:  1F            pop  ds
0x0000000000000023:  07            pop  es
0x0000000000000024:  C3            ret 

so "lea si, ds:0BC76h" is encoded in the exe as {8D 36 76 BC}
#38
Quote from: Daniel3D on October 10, 2022, 10:37:39 AM"non-symbolic offset" Like these lines?
    mov     di, 55CAh       ; offset in dseg where uninitialized data starts
    mov     cx, 0AD20h      ; original size/end of dseg

yes stuff like that - could be that there are many of these - or just a few - but every of these in-ables the code moveablitity - or could make it harder

so more or less every magic value that is a offset - but not

add sp,some-value

that is for stack-cleanup
#39
Quote from: Daniel3D on October 05, 2022, 08:30:30 PMI also assumed that multi-player would not be possible. But that kind of seems to be possible without much effort.
What can ww make of that with more effort?

there is much possible for a full blown developer with time :)

the multiplay-stunts(https://github.com/kurtis2222/stuntsmp) by kurtis2221 is using the CheatEngine (or direct memory read/write) to look through the dosbox-exe into Stunts memory - its technically like my extension of the dosbox source (the code hooking, variable watching) working with a specific version of dosbox+stunts, and then he adds TCP/IP from outside to control the keys and set variables of the opponents, i don't think he is patching or changing the game size at all (but the project source is very small and readable - so work yourselfe through it), but his
solution only works because of the 32/64bit dosbox environment, doing that in pure DOS would be much more harder, im not to deep into it but i can technically explain what and how he is doing it on a very deep level :)

im also using dosbox for doing different stuff - because the 16bit environment is so limited that i better work in the 32bit code of dosbox to "help" stunts doing the stuff i want (first win: even if the game is in segmented-memory, my own 32bit code works in pure linear style, i can do things that are not possible in the pure stunts code, like writing data with size over 64k in a for loop, copy memory of that size etc., trace data from every point in code into a textfile ...) - but that is also only doable with a good background of coding skills which kurtis2221 obviously got

BUT don't get me wrong here extending dosbox eases SOME modifications/ideas but no per default - extending game features
that are usable/seeable in game are still not easy because dosbox will not help changing the code of the game - its only easier to overwrite
behavior (sometimes) - but i don't know how you can do it without software development knowledge
working on a disassembled C based game of that size without any deep knowledge about how programming works is just very hard

look at my super-simple: dosbox/stunts branch: https://github.com/LowLevelMahn/dosbox-staging/tree/main_stunts_tests/src/_stunts
im using that code for tracing all data that gets outputed to the sound driver - its super easy code and all knowledge one need
is the very-same as kurtis2221 uses - know the offsets of functions/variables + how to hook stuff

or my also simple AlphaWaves branch of dosbox: https://github.com/LowLevelMahn/dosbox-staging/tree/main_alpha_waves_tests/src/_alpha_waves
which uses my tiny "emulator" in the uncompress function: https://github.com/LowLevelMahn/dosbox-staging/blob/b89837740a5ab65fc28548440b8de3d7c3516a49/src/_alpha_waves/_alpha_waves.cpp#L773
and this is the C-Port of that routine: https://github.com/LowLevelMahn/dosbox-staging/blob/b89837740a5ab65fc28548440b8de3d7c3516a49/src/_alpha_waves/_alpha_waves.cpp#L495

most of the time these reverse engineering projects use serveral strategies combined to reach the ultimate goal - that is totaly
different to real C/C++ source based projects were this type of cumulated strategies just not needed at all
#40
QuoteAnd stunts does not have a separate graphics, physics and collision engine but has those jumbled into one pile of code.

it isn't called a "engine" because of physical separation, and no developer mixing up such code
they could be still very separated in the assembler code (never analysed them)

QuoteThat tangle will be difficult to unravel even if the code is ported to c.

the C code amount would be 5 to 8 times fewer lines - that would help alot

the problem is: you've never built something like that/or even the simplest form of that (according to your posts) on your own
so you've got nearly no background to estimate anything, you're just assuming on a very very high level

QuoteMy question therefore was that, if we plug in external code (by whatever means we can do effectively)
are we still restricted to the memory allocation and graphics limitations of STUNTS?

this is also a very strange question - nothing in a computer will just enhanced the capatility of a program - only if the constraints are memory, hard disk space or cpu-power hunger like for example a database system got

yes we will still be restricted - because the code itself limits it to this constraints, someone wrote code that is constraint that way and the compile generated cpu-code based on that constraints to make it small and fast, its like a house build of concrete where every dependcy (offset) is fixed, there are dynamic parts in there that could be changed easier - but not because its a standard but how this specific thing in the game was implemented

but i don't know if it makes sense to explain stuff like that to you because even a senior-level C application developer (without hardware or assembler background) couldn't follow easily - could be that you getting it all wrong or in a different way as intended :( - not your fault

QuoteFor example. One thing I would like to change on short-term is increasing the 32 car limit.

This is not easily changed in the source. I know what part of the code handles this. There is a load function that loads 32 cars. Setting a lower number works as expected. Setting a higher number creates an error when trying to load a car beyond 32.
That would imply that the memory allocated for this is fixed at 32 times the 4 characters of the car. Whatever space that takes is a multitude of 8 so it makes sense. And going beyond that the game tries to read data that is reserved for other things.

Changing what memory is used is not possible in its current state. So increasing it is not possible within the current source.

that means the needed change isn't at one point but spreaded over several functions
you need to expand the space for the cars - that will move data and code - therefor moving of data, code should be
safe, which means segments should para aligned and all non-symbolic offsets should be found, every change will always come
back to that point

QuoteCan you make a hack for this?

i can possibly technicaly do it, but i have no time lurking through the code for maybe weeks (and i want to work more on stunts)


#41
QuoteAnd I am very much aware of things i don't know. I am also terribly exited and inpatient..

me too, started this project with others over 10 years ago :)

QuoteOne question before I shut up about it for a while..

you don't need to shut up :)

QuoteIf one would redirect to code outside the source, could we then use memory outside the 640K?
Like high memory or even ram?

you mean extended-ram? because everything is ram - we are currently in "conventional" ram

here is a memory-map: https://www.phatcode.net/res/155/images/fig1-1.png

QuoteAnd could that code run in a higher resolution than 320x200?

your question is confusing:

code does not "run" in a resolution and the position and size were code gets loaded is unrelevant for the resolution

video-modes uses different "memory-layouts" for displaying pixels, some of them are easy some of them
needs you to splitt the color of a pixel over multiple planes by switching using grafics card registers for each draw, some needs banking - so parts of the video-ram needs to be transfered between grafics card and conventional ram - due to its size

stunts in MCGA/VGA mode is more or less easy Mode 13h, 320x200x256 colors, so every byte starting
at 0xA000:0 is a pixel with one of the 256 palett-colors

drawing a pixel in C in Mode 13h is this

//y = 0..199
//x = 0..320
uint8_t far* video_ram = MK_FPT(0xA000,0);
video_ram[y*200+x] = palett-color

the problem is now that somewhere in the code are these 320 and 200 values hidden
sometimes even not as the values itself but as 4*80 or something - everything is possible
linear block operations for moving texture etc. - so its not just looking for put-pixel, its just to slow for the video-output doing it like that

switching to a different video-mode is possible but you need to change the drawing routines
and their local buffers, and what else is resolution dependend, for pre-drawing etc. its never just put-pixel but also the algorithm data behind

for example VESA mode 640x480x256 seems to fit (it just doubles resolution) - but this mode needs that much ram (~300kb)
that you need to switch the banks (because stunts isn't a protected mode program that would alllow linear accessing) while drawing, the bank switch is a super-super-slow BIOS call in real-mode - so every pixel drawing, polygons drawing/filling routine needs to be fixed, and every trick based on "it will be ever 320x200" is now a problem and without - its a mess

and all graphics needs to be doubled or else they will not be drawn tiny but (due to x doubling) distorted

and the resulting grafic can contain holes, due to the current low-resolution line drawing and polygon filling can be a little unprecise
which getting more and more a problem when the resolution gets bigger

and also the collision detection code could be resolution dependend ....

it could be simple like everything is always drawn on polygons then not everything needs to get changed - but a analysis of the gfx engine is
needed for that, maybe only the driving in higher resolution could be possible first

its way more complex than switching the segment from byte to para alignment :)

Quoteit's a learning experience. I learn by doing best. And that includes breaking it over and over again..

you need to understand that there is stuff that can eventually break (that is also hard to test stuff) and stuff , when done right cannot break - not everything is trial&error, there are some part of this workload that can be done in a uncluttered fashion - and these are the parts we should not also break due to misunderstanding, for example changing segment alignment from byte to para is one of these clean things


and all that would be much more doable when having C code (still not super easy) so the biggest workload gives us the biggest win - as usual in the reversing world :/

FYI: someone does that with Duke Nukem 2: https://github.com/lethal-guitar/Duke2Reconstructed - a full C reverse to 100% binary compatiblity - im am so envious :)
The "War-Story" on Twitter with all the dirty details: https://twitter.com/lethal_guitar/status/1575123187360227335 - read the follow up posts
#42
Quote from: Daniel3D on October 04, 2022, 07:20:41 PMI know little about this subject. But it seems to me that reverse engineering the entire code will not happen anytime soon.

TSR+runtime patching are a complete different story than reversing the entire code - completely unrelated comment

Quote from: Daniel3D on October 04, 2022, 07:20:41 PMBut knowing what we do about the code , we are able to make pretty good TSR's or runtime patches.
It is probably a better choice than changing the half understood source.
It may be a quick and dirty solution but it might increase the playability of the game.

the fixes you install with the TSR can be easier and safe be done in the source itself, the TSR does not help to prevent ANY of the technical problems (anything thats wrong in source-time is also wrong at runtime)
and the changes to the main source should be already separated by IFDEFs to keep it clean

a TSR isn't something that can magical changes the nature of the executable in
a way that modifications are more trival/easier to do, a runtime-approach makes it even more complex
in can do the very same inside of the source but much safer without playing around with non-symbolic offsets to patch etc.

but that is all based on missing knowledge about how assembling or executables work - too much guessing and assuming, it is absolutely clear whats needed and how time consuming it is, for every case we talked about (and porting to C is just one of 8 possible further steps) - but you have currently no chance (but your knowledge is already growing) to take the right decision, because that needs a deeper level of understanding, without trick and trial&error

im telling you the best approach, but you aren't able to understand it, you want to go further, ignoring my tips because they also fail very quick (due to missing konwledge etc. on your side) - as i told you before - reverse engineering is the prime class of development - all problems at one point combined :)

i hope to find more time in the future to help "finishing" the project
#43
Quote from: Daniel3D on October 04, 2022, 01:31:09 PM
Quote from: llm on October 04, 2022, 08:37:17 AMa TSR will not change the problem of moving code around
(which is solveable by link-virus style programming)

it makes not real sense staying away from the source by adding a patch-systems with mods that still can't be created without
decent knowledege about the code and positions
That is where my idea for a replacement main menu came from. We only need to know how it stores global variables (player car, opponent and car, track and graphics settings).
Then we can use the new menu as tsr.
We could add a simple redirect in the code and compile it. It would make further messing with the code unnecessary for menu related changes.

i don't see anything better in using a TSR (when NOT only changing variable values like a game-cheater, which is currently the easiest change in source)
patching the code at runtime is equaly error prone then doing it in source - because there is no difference
as long as you cleanly check what you code-change changes - that goes for the sourc-code as for the TSR changes, a TSR isn't some sort of magical working isolation - and yes im developed some TSRs and runtime patchers - but only because i did not got the source around
#44
Quote from: Cas on October 04, 2022, 03:21:56 AMThat is really interesting to see!  Inline assembly emulation. That would help solve lots of things!

what things do you think about, different than my things?

Quote from: Cas on October 04, 2022, 03:21:56 AMI had already thought in the past about the possibility of just inserting a call instead of the direct code and putting the main code somewhere else, but what I don't know is if the new segment will end up at the end of the whole program code, because if it's somewhere in the middle, still some program code would be moved done. I don't know much about Turbo Assembler and how it does its thing. If I were sure about it, I could use that.

the order of the re-states segments in the inc file is the order of segments in the executable
new code (with segment-realtions) will change the relocation-table but that isn't a problem

Quote from: Cas on October 04, 2022, 03:21:56 AMOn the other hand, there's another idea I'm having right now which could simplify all this. Instead of inserting new code within the compiled program... this is DOS!  No memory protection, no difference between data and code. And while this is bad for many things, it has its advantages. How about I create a TSR that hooks up a custom interrupt and have Stunts call this interrupt as an API. The hooking would be small and I could do it virus-like, but then, every other bigger mod would just be part of the TSR, not the main program, so nothing would be moved down!  What's more, I could make the TSR be a mod hub where other mods can be plugged in. When I have a moment, I'll start working on that.

a TSR will not change the problem of moving code around
(which is solveable by link-virus style programming)

it makes not real sense staying away from the source by adding a patch-systems with mods that still can't be created without
decent knowledege about the code and positions

#45
from my VS2019 IDE - uncompress is started - the 16bit DOS game Alpha Waves is waiting for the uncompressed data - based on my 32bit C++ code :)
so i change dosbox in a way that calls inside of the emulated code are hooked and replaced by my own C++ code, this way i can partially replace code

https://imgur.com/a/vwhrMzY (use this link for a larger image)