I need a comparative DOS CPU tracer.
Like, load two copies of the same EXE, and run until the execution diverges
okay, so, the copy protection:
1. It checks for a sector that should not exist: Track 38, sector 113.
It's on a single-sided double density floppy (160kb), so there's supposed to be 8 sectors per track. But as we saw in this post:https://digipres.club/@foone/115011910054706753
this disk DOES have a sector 113.
Attached: 1 image oh hello copy protection, fancy meeting you here
so step one to bypassing the copy protection is hack that function to return "yes the sector exists".
EXCEPT THAT WON'T WORK. For two reasons. The first I'll get to later. The second is that the actual value of that sector matters, it gets read into memory and the bytes at 0x7-0x8 are checked later.
so I make sure those 2 bytes in memory are set. Easy!
the next phase of copy protection checks another sector: track 39, sector #25.
Another sector that doesn't exist, but it does, and it's 128 bytes long, and... they're doing evil things to DOS to make this readable. They switch the DOS format in memory, reset the disk IO system, and try to successfully read a 128byte sector. Somehow, apparently, this works?
trying to figure out this possible third layer of protection before I continue.
today's scores- emulators crashed:
1. DOSBOX: 2 times
2. MartyPC 1 time
3. 86Box: 0 times
but if you apply these two patches, it'll STILL not work!
But it won't work silently. It'll pretend to work.
But at the end of the game, it'll change your tombstone, and not save your score:
It'll call you "Software Pirate" and say you were killed by the "Copy Protection Mafia"
fun fact: this code is self modifying! not for copy-protection reasons, but for generic-interrupt reasons.
x86 doesn't have an INT r8 instruction, only INT imm8. So to generically call an interrupt, you have to either:
1. do a lookup to a bunch of INT 00h, INT 01h, INT 02h, INT 03h instructions, OR...
2. just rewrite your own code at runtime. overwrite the second byte of the "INT 00" instruction and bam, dynamic interrupts
so, step 3: The checksums.
I hack out the checksum function so that when it's called, it just writes the "correct" answer into the return value.
I do it at the point where checksum_memory() is implemented, not where it's called, as there's two visible calls to the checksumming function, there may be more. this way it'll always return the right value.
(assuming they always checksum the same part of memory! a fun trick would be doing different chunks of RAM... but not here)
so I have a hack that works: I don't think I trust it though. I'm going to change it so the right memory gets into RAM at the right places, just to make sure there's no additional side effects.
There's random values in this sector, after all: what if the game is using them to multiple enemy damage or something?
rather than hack my way into having a disk that'll work when mounted in DOSBox, I'm just going to make it work properly if the files are copied to DOS? I'll stick the information from those sectors into a file, and swap the raw-sector interrupts out for a simple DOS read-file-data routine.
in fact, I might be able to steal one from elsewhere in the EXE
btw, the game (Rogue, if I didn't mention that before) is written in C, and uses Lattice C 2.00.
Ghidra mostly decompiles it properly. The function arguments sometimes confuse it: Lattice seems to add some padding between arguments sometimes? I'm not sure why exactly.
okay I understand enough of the IO system to write this code, but I haven't done it yet.
but I have been working on this for, uh, 10 hours? so I should probably take a break.