Ancestors

Written by Foone🏳️‍⚧️ on 2025-01-24 at 02:27

Hah! the game apparently calculates some info ahead of time, but only a few steps. I changed who the suspect was by memory editing, and it didn't take effect... until I got to the third location.

Since I went from a robbery by Fast Eddie B to one by Merey LaRoc, it means the pronouns changed when I got to London.

Congrats on coming out as a trans woman, Merey.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 03:57

ok I ran my dosspin tool to gibberish every byte of the save game file (it's only 102 bytes, so this is easy!) and none of them change where you start. very interesting... I'm guessing either the values are spread out too much for my gibberishing to reach, or you need to modify multiple bytes at once

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 04:43

huh, I found a hidden(?) key: if you hold down either shift, it skips all the pauses in the printing. so it goes at MAX CPU SPEED

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 04:46

ahh good. it's always fun to find code that looks like:

do{

while(variable!=0);

some one has a custom tick handler that's permutating a global!

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 04:46

can't be threading, this is 16-bit DOS. There is no threading.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 05:21

looking at interrupts, and I think I found a bug.

they set handlers for various CPU errors, but they accidentally set 10 (COPROCESSOR ERROR) twice, instead of the 05 (BOUND check)/10 (COPRPOCESSOR) interrupts they save

someone copy-pasted and missed a bit

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 06:08

I finally found the two helper functions they use to get and set vectors!

all the 30 other places I've seen them set/get vectors, they do it manually, but hey, maybe they use the helpers too

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 06:08

could also be that this is a compiler-provided bit of code, which is left in because the runtime needs it, or they just didn't eliminate dead code

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:11

okay I've figured out there's a shared format they're using here. it chunks the file into chunks, which have a 16-bit ID (unique per file, but not globally), an offset, and 16-bit length

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:13

so like, midisnd.dat will have 12 entries, and the first 11 are 200-500 bytes each, and then the last is 3k.

presumably it's each song and then some config info?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:15

cities.dat is very interesting. There's 30 cities in total, but 491 entries in it!

So they must be doing something odd there, that doesn't divide equally. Maybe one city-chunk gives IDs of the others?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:17

idea for a test: it's easy to spot which chunk in a city is the image, because it's the biggest. Here's a way to determine if it's looking up by IDs or offsets/indices: swap the IDs of two images

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:23

darn. turns out you can't just renumber the chunks, because they have to be in increasing order.

so maybe I just need to leave the chunk indexes as is, and instead of moving the entries around, I move where they're pointing?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:28

Bingo! I'm in Athens, but I'm seeing the image for Baghdad, and apparently with the Baghdad palette?

So one of these other chunks must be the palette for a city. Or it selects from a selection of palettes? Maybe they've just got a couple defined.

=> View attached media

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 07:34

okay I figured out the cities.dat IDs:

They're all 1XXYY (in decimal):

XX is the city number (0-29), YY is the sub-chunk-id.

So like:

YY=0: City name

YY=2: City image.

They go between 00 and 22, and not all numbers need to be present.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 08:26

hmm, reading a buffer and then summing all the values of the bytes in it.

suspicious behavior.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 08:40

okay I think it has a very simple 1-byte CRC check on the chunks, which are optionally not run.

I can't make the math work but I'm reasonably sure that's what it is

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 09:26

okay they're using a blit that's UI-aware, so it starts the coordinate system at (1,13). Fun!

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 09:39

looking into the blitting code I managed to steal the world map out of RAM

=> View attached media

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 09:55

ugh. TODO for my eventual Good DOS Debugger:

Instant Video display.

I don't know exactly how DOSBox-X is doing it, but while single-stepping the debugger, the display never updates. I can dump the ram at A000:0000 and see what updated, but not on the screen in DOSBox

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 10:19

found a suspicious array, which goes:

[

(-1,0),

(-1,1),

(0,1),

(1,1),

(1,0),

(1,-1),

(0, -1),

(-1,-1),

(0,0)

]

POP QUIZ: why does the font renderer need this array? how are they being "lazy" with this array?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 10:20

there's also this code in the for-loop that steps through this array:

if index==8:

color=white

else:

color=black

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-24 at 10:30

@dividuum got it:

they're drawing the font 9 times, offset in each of the 8 directions, and in black. then they draw it in white, with no offset.

It's a pixel-outliner! By drawing their pixel font offset in each direction, they get a black outline on their font.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-25 at 09:36

The Answer to the DRM questions for Where in the world is Carmen Sandiego? Enhanced (DOS, 1990) are, in no particular order:

23

Kent

dragon

calcium

1796

Warren

revenue

1792

Willard

1937

Crater

Tanzania

Hartford

Duluth

London

Gem

Silent

squeaker

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 16:46

if ((0x80 >> ((byte)local_4 & 7) &

        (int)(char)*(byte *)((int)((int *)param_1 + 1) + (local_4 >> 3))) != 0) {

COULD YOU USE SOME MORE CASTS MAYBE?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 16:52

oh it's because ghidra's near/far pointer support is shit.

I had param2 defined as a byte32 and it was casting it to a byte before using it

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 16:53

if I define it as byte* and let the calling convention implicitly define it as 32bit, it doesn't do the cast

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:03

well I found the decompression method.

as always, I hate it. decompression routines are probably my least favorite thing to reverse engineer

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:09

I think this compression is specifically designed for ASCII text, which is annoying because they've also got compressed images... which probably use a DIFFERENT COMPRESSION!

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:17

it looks like this chunk has length 256, which means 253 usable bytes, and it expands to 374 bytes.

Not the greatest compression. a little better than just doing 6-bit ASCII.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:29

it's some kind of shifting bit mask but it starts at encoding values in 4 bits, then it can increase (or decrease, I guess) based on the input stream.

then it has an output filter, where if the number specified wasn't 8 bits, it's actually an index into a predefined text table

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:30

the predefined table starts with NUL, space, then:

aetonisrdlhugfcwypbmk,vSA.T'PMxBCIRGDWHqE-zNFKL0j:51YJ8\U?73Q;2!469

\r\nOVXZ()*+"#$%&<=>/@[]^_`

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:47

given that the most comment symbols are near the beginning, this is presumably a sort of lazy huffman coding

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 17:47

but I've got the predefined table, an input file, an output file, and now I need to write some python code to replicate this, hopefully without crying

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 18:07

"vs ses oa is isgit's tc eital and largest t u anhtA ttggh os nnotosnhrdsmarosogdn ss drte tishoth's isdhsceohtsnthminder of isgit's t nuorhdhtpast\x00 geru is slightltsn oaller than ndhd na and is o nnsgtgstbtst oa dotlalssaaolootbiaoht Sal gh, sonuhvia and sl ghh\x00isgit, ontvdn ss nhsiaalgarsnadlfnaatawlarst oadrlhrs i is a rugged land dooousr'casrbhe nrdsgs fountainsnht iah"

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 18:07

I mean, it's not 100% wrong, but it's not right either

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 18:09

that's supposed to read:

"\x03Lima is Peru's capital and largest city. A well-known landmark is the Archbishop's Palace, a reminder of Peru's colonial past\x00Peru is slightly smaller than Alaska and is bordered by Ecuador, Colombia, Brazil, Bolivia and Chile\x00Peru, once the center of the mighty Incan Empire, is a rugged land dominated by the Andes Mountains. Forests and jungles cover half its land area\x00"

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 18:35

I somehow confused the dosbox-x debugger into not accepting letters anymore

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 18:49

it was a trivial off-by-one error.

I was doing saved_byte=input[3]

but while I needed the 3rd byte, that's at input[2]

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:12

yess!

C:\DOSBox-X\drive_c\carmen\py>python datfile.py cities.dat --dump=12803 --decompress

"\x03Sydney, with a population of more than 3.3 million people, is Australia's largest city. A well-known sight is Sydney's distinctively designed Opera House\x00An island continent, Australia is nearly as large as the United States but has only one-fifteenth the population\x00The capital of Australia is Canberra, located in the southeast corner of the country between Sydney and Melbourne\x00"

=> More informations about this toot | More toots from foone@digipres.club

Toot

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:15

It starts with \x03 to indicate there's three strings: then it describes the city three times. at runtime it uses select_string function with a random input to select one of the three strings

=> More informations about this toot | More toots from foone@digipres.club

Descendants

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:22

okay now that I can decode the chunks (well, most of them) I can identify a lot more of them:

00 Name and (some other info)

01 ???

02 Image

03 City descriptions

04 Items to steal

10 ???

11&up: Hints leading here

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:23

So like, the 12 chunk for Tokyo says:

b'\x05asked about the exchange rate for yen\x00was practicing Japanese characters\x00said\x81planned to take photographs of Mount Fuji\x00asked about tours of the Imperial Palace\x00was interested in visiting Shinto shrines\x00'

So it picks from one of those 5 options

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:23

and then 13 will be:

b'\x02asked questions about Shinto rituals\x00said\x81was researching an archipelago\x00'

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-27 at 19:24

so when it sets up a city that has hints to lead to Tokyo, it picks 3 of these sets of questions, then picks a question in each set.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:22

tool that'd really be handy right now:

a "live" version of binxelview, so I can step through the DOSBox-x debugger and see how memory is changing in real time, as an image.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:22

that might not be TOO hard to hack in, hmm.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:23

I'm stepping through a high-level loading routine I don't understand yet, trying to figure out when it decompresses an image by watching the RAM it uses for file loading and decompression and spotting when the image appears

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:27

sadly DOSBox-X's memory breakpoints don't let you set up a breakpoint that covers a whole 64k. you only get one byte. A shame.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:33

ooh, I'd also need to be able to watch multiple address ranges at once. that'd be sweet, multiple windows of visibility into RAM

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:35

I'm in Paris, I look at work ram, I see the image of the Eiffel. I head to Rome, and before I load the next image, I can see that the Eiffle tower in workram now has the wrong stride.

That's odd, because it means it had to rewrite the image in memory, the image it's about to unload.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:36

I think this might be the GUI system doing a screenshot of the image under a window, so it can restore it at the end. And it still does that here, even though we'll never need to restore that image: we're about to overwrite it

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:49

Here's what I want a tool to do:

I hit a breakpoint in the debugger, I turn it on, set another breakpoint, and hit go.

between those two breakpoints, every time a CALL instruction is hit, it dumps my selected memory region. If it's identical to the last dump, it's ignored.

At the end, each dump is rendered as an image, and the combined set are an animation I can scroll through.

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:51

I need a higher order debugger. I'm doing too much shit manually

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:55

GOT YOU, YOU SON OF A BITCH! I FOUND YOU.

=> View attached media

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:56

it's in a function I already found, temporarily named "blit_related".

I guess they don't decode the image until RIGHT before it needs to go up on the screen!

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:01

if definitely decompresses and then blits the image as two parts, which aren't evenly sized, and it starts from the bottom

=> View attached media

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:05

I think they're just trying to keep their RAM usage down by not having both halves in memory at once

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:17

wait is this image format vertically interlaced!?

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:23

It loads the half-width version, then a few functions later, it's been replaced with a full-width version.

Strange!

=> View attached media | View attached media

=> More informations about this toot | More toots from foone@digipres.club

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:24

wait no, the colors are wrong... I bet I'm seeing it decompress the binary, but that's using the full width of the bytes. it then gets expanded out to a 16-color image.

=> More informations about this toot | More toots from foone@digipres.club

Written by a kilo of saucepans (rakslice) on 2025-01-28 at 06:05

@foone this sounds like a job for whatever scripting the debugger supports?

=> More informations about this toot | More toots from rakslice@mastodon.social

Written by Foone🏳️‍⚧️ on 2025-01-28 at 06:09

@rakslice

new side project: add scripting to this debugger

=> More informations about this toot | More toots from foone@digipres.club

Written by Ongion 🥚🐞 on 2025-01-28 at 05:51

@foone not sure if you could use it for older programs, but have you ever used Time Travel Debugging?

=> More informations about this toot | More toots from Ongion@mendeddrum.org

Written by Foone🏳️‍⚧️ on 2025-01-28 at 05:55

@Ongion I've not, no. It sounds awesome, but sadly it doesn't seem it's usable for my usual ancient-software-reversing tasks

=> More informations about this toot | More toots from foone@digipres.club

Written by Cassandrich on 2025-01-28 at 05:42

@foone Visualizations of memory contents is a vastly unexplored area. I suspect you could do automated statistical analysis of patterns with some way to display the output and seriously accelerate reverse engineering.

=> More informations about this toot | More toots from dalias@hachyderm.io

Written by Andrew Zonenberg on 2025-01-28 at 05:47

@dalias @foone This is something I'd love to see more exploration of. Especially with changes over time. Scanlime had that "temporal hex dump" tool but that's only scratching the surface of what could be done UI wise.

I would love a tool integrating with ngscopeclient that lets you look at e.g. QSPI bus activity in a graphical manner to somehow visualize access patterns and understand how a boot image is constructed by dynamic analysis.

=> More informations about this toot | More toots from azonenberg@ioc.exchange

Proxy Information
Original URL
gemini://mastogem.picasoft.net/thread/113901918374275304
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
592.918165 milliseconds
Gemini-to-HTML Time
40.202941 milliseconds

This content has been proxied by September (3851b).