Elbows Up: Board decision on how we host our services - CoSocial Community Cooperative
We have always prioritized data residency in Canada for the open social services we provide. To date we have made no distinction about the ownership of theCoSocial Community Cooperative (Cosocial.ca Canadian Mastodon Cooperative)
Festnahmen nach Krawallen bei Renten-Protest in Buenos Aires
Seit Wochen protestieren ältere Menschen in Argentinien wegen niedriger Renten. Nun eskalierte die Lage in Buenos Aires. Nach Krawallen, an denen Fußballfangruppen beteiligt waren, wurden mindestens 150 Menschen festgenommen.
Read about the best things to see and do here. How do you like Nikko? backpackandsnorkel.com/Nikko/
Travel Guide for Nikko - Japan Purple Travel Guide
Nikko is a popular tourist destination in the mountains north of Tokyo. We show you the best things to see in Nikko and, as always, we provide lots of photos so you can decide where you want to go.Backpack and Snorkel Travel Guides - The Home of the Purple Travel Guides
The good thing about not having an active security clearance is that there is no king that can take it away from you.
youtube.com/watch?v=B4YMdS2fPF…
Judiciary Goes NUCLEAR After Trump’s Savage Attack on Top Law Firm
Harry reports on outrage following Trump's intense attack on a top law firm–TALKING FEDS PODCAST is a roundtable discussion that brings together prominent fo...YouTube
Remember when the fascists running our government told us they would only go after "dangerous" people?
This 10 year old recovering from brain cancer, on their way to a medical appointment, wants a word.
nbcnews.com/news/latino/us-cit…
U.S. citizen child recovering from brain cancer deported to Mexico with undocumented parents
The Texas family was on their way to an emergency medical checkup, they said, when they were detained at an immigration checkpoint.Nicole Acevedo (NBC News)
I made a thing.
In deep into finishing up the survival guide for Adventure! The Quack of Dawn. In the manual I have included images of characters from the demo game for the tutorial, and other things.
I am not an artist. However, I can manipulate images. So, as I don’t have a budget for art, I’m rolling my own combining public domain images and filters in Gimp. I briefly considered using generated images but believe it’s an abuse of fair use.
Here’s an image I created. It’s a lot of effort.
As Mass Incarceration of Immigrants Rises, Detention Centers Eye New Contracts
One attorney warns of a “humanitarian crisis” in detention centers as a jail notorious for abuse reopens to ICE.Mike Ludwig (Truthout)
From that Times piece about the bromance between Gavin Newsom and the far Right:
"Their fast-paced, hourlong discussion was both good-natured and peppered with predictable disagreements. But the conversation revealed some curious policy overlap and potentially exposed each man’s views to supporters of the other."
WE ARE SO COOKED.
omg I'm about to turn into a crazy crank, I'm so mad.
When you invite a Nazi to be on your podcast, you host a Nazi podcast.
Hey did anybody hear anything yesterday to "remember" or "never forget" the day that we entered the global pandemic called #Covid?
It's been 23 years and we still get bombarded with insistence that we never forget 9/11!!
But not one rememberance of Covid.
DEATHS:
7,090,776 - Covid
2,996 - 9/11
ILLNESSES RELATED TO:
65,000,000 - #LongCovid
45,200 - 9/11
If we had a 9/11 every day since March 11, 2020, the total deaths would still not be as many as the deaths from Covid.
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Manga Teihen Boukensha da kedo Mahou wo Kiwamete Miru Koto ni Shita. Munou Skill kara Kami Skill ni Shinka Shita “Mahou Souzou” to “Item Sakusei” de Musou Suru - E-Komik Gallery
Manga Teihen Boukensha da kedo Mahou wo Kiwamete Miru Koto ni Shita. Munou Skill kara Kami Skill ni Shinka Shita “Mahou Souzou” to “Item Sakusei” de Musou Suru (Teihen Boukensha da kedo Mahou wo Kiwamete Miru Koto ni Shita.E-Komik (E-Komik Gallery)
Saudi Arabia Buys Pokémon Go, and Probably All of Your Location Data
404media.co/saudi-arabia-buys-…
Oh, comme c'est ballot.
Saudi Arabia Buys Pokémon Go, and Probably All of Your Location Data
A company founded by the Saudi Arabian Public Investment Fund just bought the most popular AR video game of all time.Jason Koebler (404 Media)
New York City. Four firms on 42nd Street in block east of Fifth Avenue were being picketed in this manner on this afternoon
#NewYorkCity #42ndStreet #FifthAvenue #NewYorkCitys #Nunn-Bush" #undefined #photography #DorotheaLange
A German national (Jessica Brösche), a British national (Becky Burke), and now a Canadian national (Jasmine Mooney) have all been detained at the border and placed in ICE custody under dubious pretenses.
It is time for other nations to issue a travel warning to tourists headed to the US.
10news.com/news/local-news/nev…
Canadian woman put in chains, detained by ICE after entering San Diego border
A Canadian entrepreneur detained by ICE is speaking out after she got arrested while trying to enter the San Diego border to obtain a visa last Monday.Austin Grabish (ABC 10 News San Diego KGTV)
reshared this
Aight, pain management says I'm done for the day. While I'm always happy to write for free, if you'd like to help me stop a bank that will happily kick an elderly woman who can't work, her husband stricken with terminal cancer, and their three little dogs out on the street by taking her house, I'm accepting donations again here: ko-fi.com/anarchoninawrites
I'm making ends meet as best I can in my life, but coming up with the money to pay their mortgage too while my mom cares for my stepdad and neither of them can work is getting difficult and I've run out of saved up money to keep doing so. If you can't afford to, or simply don't want to help, please don't worry about it. I'll figure something out; I always do.
See ya tomorrow folks.
Support AnarchoNinaWrites on Ko-fi! ❤️. ko-fi.com/anarchoninawrites
Support AnarchoNinaWrites On Ko-fi. Ko-fi lets you support the people and causes you love with small donationsKo-fi
If you received at least one telephone call from The Credit Wholesale Company, Inc. between October 22, 2014 and November 17, 2023, you or your business are eligible for a settlement payment if you sign and return a Claim Form or if you submit a claim on this website by clicking the "File Claim" button on the top right corner on or before April 11, 2025.
Aguilar Auto Repair et al. v. Wells Fargo Bank, N.A., et al. Settlement
This website has been established to provide general information related to the proposed settlement of the case referred to as Aguilar Auto Repair et al. v. Wells Fargo Bank, N.A., et al. Settlement.www.callrecordingclassaction.com
@fluffykittycat when the trusts bust you, they bust you.
weirdly, the best movie on this is Who Framed Roger Rabbit 😂
Microsoft Windows XP • Iconfactory Portfolio
We worked with Microsoft to create a fresh, new design style and produced over 100 icons to complete the makeover of the Windows XP look and feel.Iconfactory Portfolio
@admin The last thing one wants to do is become complacent.
But Canadians have been the victim of lack of respect from USA residents for months now, including an USA official crossing the border from side to side saying: “USA #1 / 51st state”.
montrealgazette.com/news/provi…
And it’s not only Canada, but also Greenland:
bbc.com/news/articles/cr4236e2…
And Panama:
theguardian.com/us-news/2025/m…
😀
Panama president says ‘Trump is lying’ about reclaiming canal
José Raúl Mulino calls Panama canal rhetoric ‘new affront’ to sovereignty amid tensions over Chinese involvementGuardian staff reporter (The Guardian)
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Funny fact: I was trying to get an online assembler to spit out the machine code for "int 1a" but couldn't get it to, so I just went "fuck it, I can probably just do that in my head!"
Turns out I can. My brain is weird.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •PRONOUNS DETECTED: THIS GAME IS WOKE
sadly they don't have they/them on here. What about the non-binary criminals, huh?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I think I might be able to do the hack I want by changing one byte.
I'm trying to change it so it has "daily challenges", and I think I can fix that by just switching a INT 1A from subfunction 00 to 04, making it seed the random function with the date instead of the ticks-since-midnight
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •NORMAL CODE
random(*(byte *)*(undefined2 *)
(*(int *)(*(int *)0x39a6 * 0xe + local_c * 2 + 0x1d02) * 2 +
*(int *)(local_c * 2 + 0x24b)) - 1);
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •male: 0
female: 4
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •why? because they have strings like:
char* HE="He\0\0She\0"
char* HIS="His\0Hers\0";
char* HIM="Him\0Her\0";
so they can do like:
printf("Follow %s to %s lair, and capture %s alive!", badguy->name, HIS+badguy->gender, HIM+badguy->gender);
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Player's don't have genders. Only thieves have genders.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •why does ghidra's "search by instruction pattern" default to BINARY?
what kind of a freak remembers the machine code for INT 21 on x86 in BINARY?
it's CD21h, not 1100110100100001!
what are you, some kind of nerd?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I love reversing a string and it's:
void printString(char* str, int length);
and I go look what calls it, reverse that function, and it's:
void printStringSimple(char *str){
printString(str, strlen(str));
}
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •it's like "aww, did someone have second thoughts about making PRINT always take a length, and got tired of having to manually calculate lengths so you just wrapped it?
and your compiler didn't inline SHIT?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •0-31: where the shit was stolen from
0-2: which item it is from that location
0-8: whodunnit
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •For the second one, it's:
0: mask of Priam
1: Achilles's heel
2: sibyl's secret.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •It's got 1 added to it so you won't get Carmen Sandiego, as a rookie at least.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so the game uses a pattern like this:
char * RANKS="Rookie\0Sleuth\0Private Eye\0Investigator\0Ace Detective\0"
and then latter they do:
char* your_rank = select_string(RANKS, player->rank);
and select_string is a confusing function to reverse engineer, but knowing the name I gave it gives it away: it advances through the list until it's on the nth string and returns it
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Ghidra is officially sexist. It'll automatically detect the word "Female" and mark it as a string, but not the word "Male"!
Why? SEXISM!
or the fact the default minimum length for strings is 5 characters, so "female" is long enough but "male" isn't.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •they have invented a Pronoun Markup Language.
It's \x80 for He/She
It's \x81 for he/she
It's \x82 for his/her
so a string will be "\x80 mentioned \x81 liked seafood and offered me a ride in \x82 motorcycle"
and it'll fill it out based on the pronouns of the suspect
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •in trying to hack myself into the game, it glitched and said I had "Hobby: Male"
no... I haven't done that in ages!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so in addition to the 5 listed attributes (and their name), the game tracks one hidden attribute:
food preference.
There are only two options:
00=Mexican
01=Seafood
what an odd binary
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •You could always do, like, "Where in Middle Earth is Carmen Sandiego?"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so when the game starts, it loads:
ACME.DAT
CARMEN.DAT
MIDISND.DAT
DIGISND.DAT
CITIES.DAT
Interestingly, it uses the same code to load the last three, suggesting they're some kind of basic container format
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •this blit function seems to take a useless first argument, a second argument that's the height, a third argument that's the width, and a fourth argument that doesn't seem to do anything.
notice anything missing? like... a lot of things?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •this game uses a fun text encoding method: both-ended null terminated!
It stores city names with a nul at the beginning because it reads them backwards. For some fucking reason.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •they seek to position X
read 1 byte
read 99 more bytes
then seek to position X+100
now if you know how both math and random access files work, you'll realize something the programmers of Where in the World is Carmen Sandiego? Enhanced (1990, DOS) did not:
THEY'RE SEEKING TO THE POSITION THEY'RE ALREADY AT
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the way this game does the investigations is interesting.
so the basic gameplay is that you're in location X, you get 3 hints, which lead you to location Y, where the whole process repeats.
But if you savescum to experience the same pursuit again, they'll always go through the same places... but if you don't get the hints, they won't be there.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •presumably it's each song and then some config info?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •hmm, reading a buffer and then summing all the values of the bytes in it.
suspicious behavior.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I can't make the math work but I'm reasonably sure that's what it is
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Sensitive content
there's also this code in the for-loop that steps through this array:
if index==8:
color=white
else:
color=black
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Sensitive content
@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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •oh it's because ghidra's near/far pointer support is shit.
I had param2 defined as a byte*32 and it was casting it to a byte* before using it
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •well I found the decompression method.
as always, I hate it. decompression routines are probably my least favorite thing to reverse engineer
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •aetonisrdlhugfcwypbmk,vSA.T'PMxBCIRGDWHqE-zNFKL0j:51YJ8\U?73Q;2!469
\r\nOVXZ()*+"#$%&<=>/@[]^_`
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •"\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"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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]
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •b'\x02asked questions about Shinto rituals\x00said\x81was researching an archipelago\x00'
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •That's odd, because it means it had to rewrite the image in memory, the image it's about to unload.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •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!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Strange!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •write the byte 04 every 69 bytes
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •oh sweet jesus, that's the left two pixels of the image.
it's loading the image vertically!
at least it's top to bottom.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •yeah, doom did that too, but Doom was a 2.5D image that had to do pseudo-raycasting.
THIS GAME DOES NOT
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •it allocates a 1024 byte buffer, then makes a pointer to the end of it, minus -0x42?
why would you need a link to the end of a new, freshly cleared buffer, minus 62?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •unless it's an odd number, in which case it's a free block. and pointer to the previous block, once you make it even again
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •You see this little About dialog box? Guess how many times the DrawText function is called?
Once! and just to draw "Where in the World is Carmen Sandiego?".
The rest of the text is draw elsewhere, and I have no idea why.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •The game loads the BoldFont first, then the SmallFont, then the NormalFont.
Annoyingly this isn't how they're laid out in memory:
It's SmallFont, then BoldFont, then NormalFont
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •font_alloc = malloc(local_a);
if (font_alloc == (void *)0x0) {
font_alloc = (void *)0x0;
}
Ahh yes. remember, if you get a null pointer back from malloc(), make sure to set that variable to NULL so it won't be left as... NULL?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •man, running on 4 hours of sleep is killing me.
I can't even remember the MS-DOS interrupt to open a file!
I know reading it is int 21 ah=3f, closing it is int 21 ah=3d, and I'll never forget that seeking is int 21 ah=42, but how do you open a file?
I mean, not the int 21 ax=6c00 way, that one is only for DOS 4.0+, and obviously a game released in 1990 isn't gonna use that.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ahh, now that I've looked it up, it seems I was wrong!
closing isn't 3D, that's 3E! 3D is open!
no wonder I couldn't remember it, I had it confused with another call
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •what the fuck do you mean that carmen.dat is opened on the first call to finish_draw_maybe()?
like, I know there's a "maybe" in that name, but it's not THAT big of a maybe.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •it actually LoadDatFile, which makes a HELL of a lot more sense
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •maybe do it for everything MS-DOS.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I think I failed to load the cursor, which caused it to corrupt the mouse cursor catastrophically
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I did a little looking into the contents of MIDISND.DAT
It's got 12 small tracks, and each of them is a valid MIDI file if you remove the first byte.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •heh. I was checking different near-death animations by overriding the randomness, so I had to tell my debugger to set AX to 0
guess which animation that is? The one with the AXe.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •why do they store the day of the week as a 16bit int?
future proofing in case the calendar gets updated and has more than 256 days in the week?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •They're in Rome and they've just slept through about two months of nothing
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I finally figured out how it calculates travel times.
It's the difference in X coordinate between the two cities, plus the difference between the Y coordinate, plus one.
that quantity divided by 40, then has 2 added. if the result is over 7, it's set to 7.
Weird! that's not how you measure distance, Carmen.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •also, it's the 90s, I can afford a sqrt().
I should fix it up for my version.
or use a squared lookup table. you could do this REAL easy by making it a table search: there's only 6 possible results: 2,3,4,5,6,7. each entry in the lookup table contains the maximum squared distance that can generate that number of hours
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •here's all 30 city locations:gist.github.com/foone/09925178…
it's currently way too 6am to do more calculations, though. I'll do that tomorrow
Carmen Sandiego city locations
GistFoone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Good news: @modulusshift did the calculations for me!
digipres.club/@modulusshift/11…
~ (@modulusshift@digipres.club)
digipres.clubFoone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •PUSH ES
PUSH AX
RETF
why must you hurt me, carmen sandiego?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •So the GraphicsMode enum goes:
0: MCGA
1: CGA
2: Hercules
3: EGA
4: Tandy
5: VGA
6: ???
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I find-replaced the background from palette entry 0 to palette entry C:
Now I can confirm how big this image is. Previously it was set into a black background, which made it harder
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •worst thing that could happen just happened:
I just realized the portable Where in the World is Carmen Sandiego? is based on the same version I'm hacking, meaning it's in-scope for me to get this, dump the ROM, and compare.
That just increased the cost and complexity of this project by bunch
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •WAIT HOLD ALL THE PHONES.
Here's a photo from a MS-DOS version. It does that thing some companies (like Sierra) did back in the day, and included both 3.5" and 5.25" disks in the package.
BUT WHY ARE THERE SO MANY DISKS?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ARG, they mislabeled this.
Admittedly, this isn't really their fault, this is confusing shit.
This is the 1992 Where in the World Is Carmen Sandiego? Deluxe, not the 1990 Where in the World Is Carmen Sandiego? Enhanced.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay I finally found a boxed copy of the Enhanced 1990 DOS edition. (confusingly labeled the 1993 edition)
It comes on two 5.25" disks: presumably double-density, so that's 720kb in total.
Floppy Disk Pop Quiz: What's weird about these floppies, specifically given that this is MS-DOS version?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I happened to look at mobygames, and noticed two interesting things.
First, the Mac version is very similar to the DOS version, other than the expected changes you'd get from it being on a monochrome system with a GUI.
But wow, that's a completely different font! Is that built into macs or something? (EDIT: @amr confirms it is)
(also, the dialogue box is top-aligned. DOS bottom-aligns them)
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •The PC has basically always been double-sided, so they only need one notch, on the top/a side.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Broderbund was releasing games on a bunch of other systems that DID have single-sided drives. For simplicity they just bought Xty-thousand double-notched disks
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •is it gonna matter? not in the slightest (assuming there's no format-mismatching, which their shouldn't be: these are all the same density of disks, I think).
The PC doesn't check for a notch there, so it won't notice either.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •It's just funny because this is, like, technically wrong?. These aren't PC disks, but the difference doesn't matter, so why not?
It probably saved them a decent amount of money because of bulk discounts and inventory simplicity.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I am currently, as in this very thread, reverse engineering Carmen Sandiego Enhanced (1990, DOS)!
I've seen the code that asks for you to put in the other disk! And it only asks for DISK1 and DISK2!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •just looking at the files, not the code (and not having seen original disk images yet that I can recall), I bet the answer is that they put CITIES.DAT on DISK2.
the whole game - cities.dat is ~300kb, with cities.dat being 168kb.
They could do the whole game - carmen.dat and cities.dat in only 200kb, which'd give them 160kb (luxury!) for a fancy installer.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I should just check. I'm sure disk images can be tracked down in places.
the video and audio detection seems to be excellent, by the way. it just silently figures it out, without asking questions or requiring special arguments or configuration.
Perfect for a game aimed at the little childrens.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I found two different copies of the disk images, in different places.
both are imaged off a 3.5" disk version, which of course comes on only one (double density, 720kb) disk!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •So I've got code at 17DA:08AA, which is E8 5D F7. DOSBox decodes that as CALL 000A.
Manually decoding it myself, it should be a relative jump, and it's a jump to $-0x8a3. following the jump it ends up at 17DA:000A.
BUT GHIDRA thinks this code is at 1fb7:08aa, and it decodes it as call SUB_2000_fb7a, which doesn't exist.
I'm not sure how (0x08aa+3)-0x8a3 = 2000:fb7a. Something weird is going on. Why is the number BIGGER?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •eww. They're using the NEAR version of CALL to call a FAR procedure.
You might say "wait, won't that break when it tries to do RETF?" and yes, it would, unless they manually do PUSH CS before they call it!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •a call FAR absolute would be 5 bytes for the call, whereas push CS + call NEAR is 3+1 bytes
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Anyway it seems it doesn't have a VideoDetect function, it's a DriverDetect function, since it's used for sound too.
First it goes through the video drivers in the following order:
VGA, TGA, EGA, HGA, HERC, and CGA.
Then it goes into the audio drivers:
stdsnd, adlib, covox, gblast, ibmg, sblast, tandy.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •stdsnd is pc speaker,
adlib is adlib, covox is the speech thing, gblast is game blaster, most likely, ibmg is... I'm not sure. The PS-1 Audio card?
sblash is soundblaster and tandy is tandy 3-voice
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I'm an idiot, this isn't a driver check... it's an argv check!
you can pass "ega" or "vga" or whatever to carmen.exe to select those types.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the other argument you can pass is ROSTER=$FILENAME
This lets you reset which file it uses for the list of registered players, setting it to something other than the default ACME.DAT
Not mentioned in the manual, but I can see how that might be useful for schools and such
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •The problem is that ghidra gets confused when the relative addresses are too big.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so the first one is at 1000:0000 and the second was at 1fb7:0009. I moved it to 5000:7000, and the second segment seems to be working fine now.
the problem is that I was only able to do that because the segment is only 82a7h long. the first segment, the 1000:0000 one, is FB79 long. So I can't just move it so it's in the middle of a segment, since it'll end up spanning into the next 64k chunk, which is where ghidra fucks up
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •9000:8006 9a d7 05 b7 1f CALLF SUB_2000_0147
Hey ghidra I can read the machine code. That's CALL FAR 1fb7:05d7, not CALL FAR 2000:0147! WHY ARE YOU CONFUSED BY THIS?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so now I can just manually thunk every cross-segment call, by creating the 2000:0000 segment that ghidra is imagining exists
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I was extracting the portraits of the people you talk to, and it turns out they're number 1-36. naturally I checked all 256 possible options.
but it turns out every thing above 37 either:
1. crashes
2. shows nothing
3. shows pixel gibberish.
EXCEPT 238. 238 renders a bellhop perfectly, just like 5 does
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •it has been zero days since Ghidra has done something I can't understand and seems to be obviously wrong.
I've got B8 B0 26: this decodes to mov ax, 0x26b0. a 16bit immediate, moving into a 16bit register.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ghidra disassembles this as:
b8 b0 26 MOV uVar1 ,0x26b0
uVar is defined as a ushort: a 16bit type.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •all makes sense, right? 16bit to 16bit!
so ghidra decompiles it as uVar1._0_1_ = 0xb0;
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the most annoying thing?
this is picking between two strings to display, and those strings are "he" and "she".
EVEN IN 35 YEAR OLD COMPUTER GAMES I CANNOT ESCAPE GENDER PROBLEMS!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •unfortunately due to an oversight it believes those 65536 genders are allocated as:
0: He/he/Him/him
1-65535: She/she/Her/her
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Since it's no longer 1990, I think I can safely bump that up a bit? I won't need more than another 64 KB, which means I'll just bump the game up to 496 KB memory required. Completely doable in any 640 KB or more machine!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the applyPronouns function lets you adjust how it's encoded dynamically. Fancy!
So how it works is you do something like this:
applyPronouns("\80 was bald", 0x80, "he\0him")
and it'll return "he was bald", right? But it's more than just a simple find-replace...
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Because you can do:
applyPronouns("I saw \81. \80 was bald!", 0x80, "he\0him")
and it'll return "I saw him. he was bald!".
See, you can specify multiple replacements at once, by using \x80, \x81, \x82 and so on.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I got my floppy copy in the mail, I just need to image it.
Fun fact from the box: It has a letter from the player character to their cousin, and I believe this is the only place in the game and associated media that they name your character.
It's Dale.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •They're laid out like this:
Disk 1:
CARMEN.EXE
CARMEN.DAT
Disk 2:
CITIES.DAT
MIDISND.DAT
DIGISND.DAT
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Finally, we know the answer to the age-old question of Where in the World is Carmen Sandiego?
The answer is "My floppy drive"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •well my "ignore the problem" solution of using bochscpu to embed a 16bit x86 emulator has failed. it's somehow broken and it's broken in the rust library or C core, not the python, and I really don't want to have to deal with debugging this.
time to switch to a completely different x86 emulator? PROBABLY!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •unicorn has great documentation.
at least I assume it would be great, if it existed
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •x86 16bit segmentation and regular expressions:
BECAUSE FUCK IT
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I'm implementing unicorn as an x86 emulator to do the decompression, but I'm single-stepping the processor and I'm aiding debugging by showing what instruction I'm on.
but instead of having to set up an x86 disassembly engine, I'm just parsing a plain text ghidra dump of the disassembly. I'm parsing it with regexes
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •my latest bad idea: DUMBPATCH.
to avoid the complexity of generating functions and mapping them into the address space of the emulated PC, I instead designed a simple syntax:
a 16bit segmented address plus a number. that function is emulated as if it returned that number in AX. There are no other options. I suspect I'll be able to emulate up to 80% of complex subfunctions with this one bit of functionality
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I need this because the decompression routine I'm emulating isn't entirely standalone: it calls malloc() at the beginning and free() at the end
so I'm replacing malloc() with a static value and free() with a return value no one will check
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ideally I should be able to patch arbitrary python in there and do some kind of interop to return values to python
but that's hard. and way easier unflexible thing this is 80% of what I need that for
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •back on hacking Enhanced, DOS, 1990.
My best guess is that this game has between 4-6 compression algorithms, depending on how you count them. Possibly more are hidden in the bowels of this program.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •This code mallocs 65516 bytes in a loop until malloc returns zero.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •totally normal part of starting program: allocate all the RAM in the system.
I mean, it's DOS. There's nothing else running that could possibly call malloc. So why not?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •There's just not that much memory in the system that this can touch, since it's not supporting any of the endless varieties of breaking the 640k barrier
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •there's a story on Old New Thing somewhere about Windows 95 accidentally breaking a DOS game, because it did this same trick of allocating all the memory, but since Win95 was running as the DPMS, it meant it had access to all of windows 95's virtual memory. including the swap.
So instead of mallocing all 8mb or whatever your 486 had, it malloced all that and then tried to use up YOUR ENTIRE HARD DRIVE, slowly.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •this game runs mostly in a 16 color mode, with some high-end modes being basically 16-colors within 64 or 256 colors, right?
SO WHY DOES IT USE 16-BIT INTEGERS FOR COLOR INDICES?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •note to self: patch out the Romani slur in one of the hints for Budapest
EDIT: both of them
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •The description of Hungary says it's bordered by Czechoslovakia, Austria, Yugoslavia, Romania, and the Soviet Union.
Two of those are still right!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so I fly into Reykjavík, and immediately sleep for 8 hours. In the morning, I can go to either the airport or the hotel, but it'll take 3 hours to get to either.
Question: where am I right now, if I'm not at the hotel or the airport?
Z̈oé ⛵
in reply to Foone🏳️⚧️ • • •yomimono, still on earth
in reply to Foone🏳️⚧️ • • •Crystal Huff (they/them)
in reply to Foone🏳️⚧️ • • •Aatheus
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Aatheus • • •Aatheus
in reply to Foone🏳️⚧️ • • •Graham Sutherland / Polynomial
in reply to Foone🏳️⚧️ • • •Large Print Edition (Delia~!)
in reply to Foone🏳️⚧️ • • •Kevin Boyd (he/him) 🇨🇦
in reply to Foone🏳️⚧️ • • •~
in reply to Foone🏳️⚧️ • • •Pxl Phile
in reply to Foone🏳️⚧️ • • •Ben A L Jemmett
in reply to Foone🏳️⚧️ • • •C.
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to C. • • •Spindel
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •They initialized the SoundBlaster DSP backwards.
You're supposed to send a 0 to the reset port, wait 3 microseconds, send a 1, then wait up to 100 microseconds for an 0xAA to show up on the data port.
They instead send a 1, then a 0, then immediately start trying to read the data port.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •tekhedd
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to tekhedd • • •tekhedd
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •they're sending a... internal soundblaster test command?
(DSP 0xF0)
I dunno why this code is like this.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I suspect there may be an issue here: I identified a variable as containing the Soundblaster IO port, right? and I'm assuming everything that uses it is Soundblaster code.
But it may just be "soundcard IO port" and there's other sound device code mixed in here. So that's why some of it doesn't make sense as soundblaster, it's actually tandy 3voice or something
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •it's a loop that runs 256 times!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Tom Forsyth
in reply to Foone🏳️⚧️ • • •Joel Michael
in reply to Foone🏳️⚧️ • • •@jbqueru@floss.social
in reply to Foone🏳️⚧️ • • •Coreworlder 🎲
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •there's code in here specifically to detect if it's running on an IBM PS/1 by looking at the CMOS area?
WHAT THE
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the menu system limits menus to having a maximum of 32 items.
which is weird because ONLY 17 WILL FIT ON SCREEN
Otte Homan - remember Geordie
in reply to Foone🏳️⚧️ • • •cerement
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I did some experimenting with MSVC 5.1, and it's weird. I get the same strings in the exe as carmen.exe has, but the code itself looks completely different.
either I set up my compiler wrong, or this game is full of assembly even for very simple functions
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I don't know exactly what this function does (I know it sets some flags based on something in the graphics context) but I DO know one important thing about it:
they included it in the final binary FOUR TIMES.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •byte-identical.
this is a compiler & linker from 1988, it doesn't understand how to merge identical copies of functions apparently
Clark Breyman (he/him)
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Clark Breyman (he/him) • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I found another function which has 4 copies.
I'm starting to suspect this program originally had 4 C source files and the linker wasn't optimizing this
anparker
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •wait I bet it's drivers!
like, one version of this function is called by VGA_DrawFuncUnknown and nothing else.
Another one? CGA/Hercules.
the third? EGA
The last? Tandy.
They compiled the 4 video drivers separately, and then linked them into the EXE, with no deduplication across compile units
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •yeah. Found another: VGAMalloc is the same as CGAMalloc (and Hercules doesn't have it's own HerculesMalloc, because it's in the same code unit as CGA: So it just uses CGAMalloc)
Tandy has TandyMalloc.
But not EGAMalloc. That one is completely different.
Walter van Holst
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Walter van Holst • • •@whvholst the function just mallocs the param passed in, so it doesn't care about layout.
except for EGA. which I don't understand yet
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the DrawLine API is weird.
To draw the horizontal underline for the hotkeys in the menu, it calls DrawLine(0, -width).
It's DrawLine(int y, int x), and yeah you pass negative numbers
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •because 0,0 is silly, you're always drawing at least one pixel. So DrawLine(0, -5) draws a six pixel wide horizontal line to the left
Klairi Flurry
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •PUSH BX
PUSH ES
PUSH SI
CALL StartPlayingSound
POP BX
POP ES
POP SI
since when has the x86 stack been FIFO instead of LIFO?
KeyJ
in reply to Foone🏳️⚧️ • • •Dentaku (Thomas Renger)
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •LoadAndPlaySoundChunk is called with a chunk name from digisnd.dat, but you can also pass -1 or 0. I'm not sure what -1 does yet (maybe silence a currently playing sound?) but 0 means "wait until the sound finishes"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I'm not really sure why it works that way, especially because calling LoadAndPlaySoundChunk(0) is equivalent to calling WaitUntilSoundFinishes().
So why not just do that instead?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •uh oh. the computer noise is triggered with:
LoadAndPlaySoundChunk(217)
but I look in the DIGISND.DAT file and it has chunks 200-216.
So either my DAT file parsing is wrong or it's loading sounds from elsewhere, somehow? because the sound DOES play, so it's not just an error
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I thought it might just be playing from MIDISND.DAT instead (since the computer noise is very beepy, maybe it's just a synth sound?) but MIDISND.DAT starts at chunk id 218 and goes up.
WHERE IS 217?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •huh. weird. when you try to backspace too far in the name entry screen, it goes "duh-nuh" at you, but that isn't connected to a LoadAndPlaySoundChunk call.
So it's using a different function for this ONE NOISE?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •YEP. muted my soundblaster (MIXER SB 0:0) and it's still duh-nuhing at me.
why would you do this to me, brøderbund?
Olivier Galibert
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Olivier Galibert • • •Olivier Galibert
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ah-ha! I found 217.
DIGISND.DAT has PCM sound effects for 200-216.
But there's also chunks in CARMEN.DAT for 200-229.
I didn't think the ones in CARMEN.DAT were sound files because they're so small... but they're just the right size to be PC speaker sound effects!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •they hardcoded two sound effects into the EXE and the rest are loaded from the DAT files.
eww. Someone hacked something in at the last moment!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Adriano
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •there's 729 functions in the EXE.
I've named (in some way, counting placeholders) 355 of them, or 49%
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •by placeholders I mean things like "pcjr_sound_related" or "VGAFunc8"
and 13 of those function names include the word "maybe"
Briala
in reply to Foone🏳️⚧️ • • •Andrew Zonenberg
in reply to Foone🏳️⚧️ • • •Sounds like most of my IDBs.
"UART_func4", "Socket_func2"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I think they generated their hints wrong.
The *22 chunk for a city says something like "$SUSPECT was going to an opera with the president" or "$SUSPECT would be having tea with the Emperor", right?
but it's also got "drove away in a vehicle flying a green, blue, and yellow flag". which'd be fine, except that hint is also in *19!
I think they accidentally duplicated it when they generated the cities.dat file
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ugh. ghidra really doesn't understand that you can call far functions using near calls.
and the compiler for this LOVES using them.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I might have explained this before, but normally a near call to a far function will break, because it'll pop 4 bytes off the stack for the return address, when the near call only pushed 2.
So you fix this by doing push CS first, so it'll pop the 2 from the call, and then the 2 you placed before.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so you'll see, for example, it decompiles a strlen as:
uint1 = strlen(0x1000, some_String);
which is less than useful
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •in 32bit we do 32bit calls and 32bit returns.
in 64bit we do 64bit calls and 64bit returns.
in 16bit we can do 16bit calls and 16 bits returns, 32bit calls and 32bit returns, and sometimes we do a 16bit call to a 32bit return because it's slightly fewer bytes
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •one of my favorite stupid methods of reversing is "break it"
what's this function do? well, lemme disable it, and see what breaks.
Apparently this is the "restore the image under the cursor" function.
reshared this
myrmepropagandist and Mother Bones reshared this.
Kit Bashir
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •gloriouscow
in reply to Foone🏳️⚧️ • • •i will convert you someday. mark my words
just as soon as i implement, like twenty years of hardware
Foone🏳️⚧️
in reply to gloriouscow • • •gloriouscow
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to gloriouscow • • •@gloriouscow I think so, yeah.
Actually, it supports EGA/CGA/Hercules/MCGA as well, so I could definitely try running Carmen in MartyPC.
Maybe next session, I'm already halfway through a lot of nasty stuff
gloriouscow
in reply to Foone🏳️⚧️ • • •i can add breakpoint logging for you definitely tho
what do you imagine that looking like, a timestamp with cs:ip and breakpoint name when hit?
Foone🏳️⚧️
in reply to gloriouscow • • •gloriouscow
in reply to Foone🏳️⚧️ • • •yeah i've got something similar planned when i add Rhai scripting. you'll be able to attach a script that is evaluated when the breakpoint is hit
the script interpreter will have access to logging output facilities and the entire machine state
but that's a little ways off still
Foone🏳️⚧️
in reply to gloriouscow • • •gloriouscow
in reply to Foone🏳️⚧️ • • •it'll really kick things up a notch.
i'm still waffling about using lua instead but i wrinkle my nose when i look at lua code
Foone🏳️⚧️
in reply to gloriouscow • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •2. the world doesn't wrap. This path is longer than "just" crossing the pacific, which is how this flight actually goes.
Mother Bones reshared this.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Troldann Arothin
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Troldann Arothin • • •@troldann of course!
(there's only 435 routes, I can precalculate them offline and just embed the answers in the code)
Joel Michael
in reply to Foone🏳️⚧️ • • •Bill Ricker
in reply to Foone🏳️⚧️ • • •@troldann
Only 30 destinations? I guess that was just enough to keep each play through somewhat different without switching floppies 💾
30×(30−1)÷2
Foone🏳️⚧️
in reply to Bill Ricker • • •@BRicker @troldann
yeah, there's only 30. They had room for more, but I guess they had to stop somewhere.
The second disk has the CITIES.DAT file, which is 168kb. There's still 102kb free on that disk, so it would be doable to add another 20 or so cities
Bill Ricker
in reply to Foone🏳️⚧️ • • •gkrnours
in reply to Foone🏳️⚧️ • • •Tim 🎮
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Tim 🎮 • • •Tom Forsyth
in reply to Foone🏳️⚧️ • • •instagram.com/cobrakaiseries/r…
Cobra Kai on Instagram: "Johnny’s a point A to point B type of sensei. 👊 Never let a "curvature" slow you down."
InstagramOneironaut
in reply to Foone🏳️⚧️ • • •Bill Ricker
in reply to Foone🏳️⚧️ • • •(Otoh for intending to run on home PCs with 8088, 386, 486sx (emulated floating point only), that might be excusable? CORDIC integer trig is amazing but avoiding it might be forgivable.)
s0 Traingirl Era
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to s0 Traingirl Era • • •cyberlyra
in reply to Foone🏳️⚧️ • • •best game ever tho
@trochee
MontyOnTheRun
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to MontyOnTheRun • • •MontyOnTheRun
in reply to Foone🏳️⚧️ • • •well, given that it is not graphically intensive, it makes sense. I just assumed people went the ASM way by default.
Thanks for the clarification!
Gabe
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Gabe • • •BetaRays
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to BetaRays • • •Oliver Sampson
in reply to Foone🏳️⚧️ • • •Rue Mohr
in reply to Foone🏳️⚧️ • • •StartPlayingSound:
POP AX
POP BX
POP ES
POP SI
CALL EnableSound
PUSH BX
PUSH ES
PUSH SI
PUSH AX
🤣
Timo J
in reply to Foone🏳️⚧️ • • •Datawuppi
in reply to Foone🏳️⚧️ • • •that reminds ne of my Amiga BASIC days. As it had no sleep or somesuch, it actually required:
FOR I 1 TO 1000; NEXT
IIRC that where ~3s or something.
And yes, that thing was in the manual for some of the example programs.
Ian Scott 🐙
in reply to Foone🏳️⚧️ • • •@jbqueru@floss.social
in reply to Foone🏳️⚧️ • • •Jeremy Visser
in reply to Foone🏳️⚧️ • • •I had a client that used the computer mouse inverted.
But not in software. I mean physically turning the mouse around 180° and having the cord come out where, uh, the tail would be, I guess.
(Now that I put it like that, it makes sense why someone might do that.)
The end result being both X/Y axes are inverted, and the buttons are in the wrong place.
But it *worked*. That's the way the brain learnt it. It's like spending your whole career in ETAOIN SHRDLU only to discover the rest of the world is on QWERTY. You'd probably just stick with what works.
Foone🏳️⚧️
in reply to Jeremy Visser • • •I knew a kid back in the 90s who played NES games with the controller backwards
Krutonium://
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Krutonium:// • • •Ingo
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Ingo • • •