Saudi Arabia Buys Pokémon Go, and Probably All of Your Location Data
404media.co/saudi-arabia-buys-…
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)
journa.host/@anneapplebaum/114…
Anne Applebaum (@anneapplebaum@journa.host)
Read my former colleague Ruth Marcus, explaining why she left the Washington Post https://www.newyorker.com/news/essay/why-ruth-marcus-left-the-washington-postJourna.host
unironically just repartition based on indigenous territories with all that implies
might take a while to sort out
gothamist.com/news/tsa-agents-…
TSA agents at Newark Airport find live turtle hidden in man's pants
The 5-inch reptile, which was wrapped in a towel, was discovered "in the area of the man's groin" on March 7.Giulia Heyward (Gothamist)
"A cutting-edge project to test “fusion blanket” technologies is taking shape, with the Idaho National Laboratory (INL) leading the charge to create a critical component of a fusion reactor."
Segera baca di e-komik.org/komik/220775
#EKomik #Komik #Comic #Manga #Action #Fantasy #Harem #Seinen #SliceOfLife #Supernatural
Chapter terbaru dari Isekai Kaeri no Daikenja-sama wa Sore Demo Kossori Kurashite Iru Tsumori desu (Chapter 42) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/220775
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Fantasy #Harem #Seinen #SliceOfLife #Supernatural
Chapter terbaru dari Isekai Kaeri no Daikenja-sama wa Sore Demo Kossori Kurashite Iru Tsumori desu (Chapter 43) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/220775
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Fantasy #Harem #Seinen #SliceOfLife #Supernatural
Driftless Area, Dane County, WI, USA
#butterfly #insects #lepidoptera #nature #naturephotography
_F2A0675aaap2 copy.jpg
"Black guys counting my money! I hate it. The only kind of people I want counting my money are short guys wearing yarmulkes every day. Those are the kind of people I want counting my money. No one else." = Donald Trump
Watch Lawrence spell it out.
youtube.com/watch?v=n804BwrNwQ…
Lawrence on Trump's 'vile, antisemitic' attack on Schumer: Trump's mind is gone. It is shattered.
In the Oval Office today, Donald Trump used “Palestinian” as a slur and said the highest-ranking Jewish elected official, Chuck Schumer, is “not Jewish.” Tho...YouTube
Ahh the relationship between Cisco and Jadzia Dax is quite a thing.
Cisco: “She’s a married woman”
Dax: “That would have never stopped Kurzon”
There’s a comfort with the previous hosts that… I have a… difficulty of making my own. But the comfort with her previous… nay still present masculinity is something I have much less difficulty with. While I always claim I have no insight into the male mind, it was just a disguise, I am quite comfortable and open about the masculinity I have, and Jadzia & Ciscos relationship feels very comfortable and natural, and mirroring my own relationship with many of the men I’m friends with from before. Even many I’ve met since.
I tell people I’m she/her, my birth certificate has an F, but I do consciously avoid the term “woman”, preferring “transfemme”. To the cis that push, I’ll pull out “trans woman”. But that’s all an unwillingness to describe my thoughts to cis folks.
My actual feelings, much murkier. I’m devoting a lot of energy to exploring the femme side, it’s so very overdue. The masc side is coming out a lot more, curiously concomitant with my wearing exclusively dresses. But “side” isn’t the right word. It’s a very homogeneous blend… the word blend is one I’m troubled by, as they’re not separate ingredients mixed, they’re an inseparable medium, uniform, uncuttable. And there is another thing in there, that is neither, both. The programmer that hid from the world, that tried to understand, using tools that are unable to parse many of these concepts. The love for a flower, or a stick insect, or a trigonometric ratio.
My non-binary-ness is not a thing I’ve really got around to understanding. I know there’s a me, and there’s aspects of the femme and the masc, and I’m not sure where the borders are, and I’m leaning towards not wanting to draw borders. I know I lean femme, even as the mirror leans quite masc. The me that is… of these 3 things, finds describing them as 3 things offensive. The will to dissect and understand is dwarfed by the will to… be me. A whole.
I don't really count calories but try to stick to one meal a day
I went to target today to get some suncream and bought this packet of cookies but I ate them all and it's like 840 calories total and now i don't feel hungry so no like dinner, just cookies today
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
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.
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
NORMAL CODE
random(*(byte *)*(undefined2 *)
(*(int *)(*(int *)0x39a6 * 0xe + local_c * 2 + 0x1d02) * 2 +
*(int *)(local_c * 2 + 0x24b)) - 1);
male: 0
female: 4
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);
Player's don't have genders. Only thieves have genders.
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?
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));
}
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?
0-31: where the shit was stolen from
0-2: which item it is from that location
0-8: whodunnit
For the second one, it's:
0: mask of Priam
1: Achilles's heel
2: sibyl's secret.
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
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.
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
in trying to hack myself into the game, it glitched and said I had "Hobby: Male"
no... I haven't done that in ages!
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
You could always do, like, "Where in Middle Earth is Carmen Sandiego?"
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
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?
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.
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
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.
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.
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!
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
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
presumably it's each song and then some config info?
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?
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?
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.
hmm, reading a buffer and then summing all the values of the bytes in it.
suspicious behavior.
I can't make the math work but I'm reasonably sure that's what it is
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
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?
Sensitive content
there's also this code in the for-loop that steps through this array:
if index==8:
color=white
else:
color=black
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.
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
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?
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
well I found the decompression method.
as always, I hate it. decompression routines are probably my least favorite thing to reverse engineer
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.
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
aetonisrdlhugfcwypbmk,vSA.T'PMxBCIRGDWHqE-zNFKL0j:51YJ8\U?73Q;2!469
\r\nOVXZ()*+"#$%&<=>/@[]^_`
"\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"
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]
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"
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
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
b'\x02asked questions about Shinto rituals\x00said\x81was researching an archipelago\x00'
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.
That's odd, because it means it had to rewrite the image in memory, the image it's about to unload.
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.
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!
write the byte 04 every 69 bytes
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.
yeah, doom did that too, but Doom was a 2.5D image that had to do pseudo-raycasting.
THIS GAME DOES NOT
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?
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
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
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?
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.
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
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.
it actually LoadDatFile, which makes a HELL of a lot more sense
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.
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.
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?
They're in Rome and they've just slept through about two months of nothing
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.
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
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
Good news: @modulusshift did the calculations for me!
digipres.club/@modulusshift/11…
~ (@modulusshift@digipres.club)
@foone I did it lol https://docs.google.com/spreadsheets/d/e/2PACX-1vTr5GBfUNkxzVN7RoAiMg081ihERAFs93oE_m_1dPj67IxG-pkMQ41zoVVDlK0DJQepfeRe3NcA-9z8/pubhtml hope this answered any questions you haddigipres.club
So the GraphicsMode enum goes:
0: MCGA
1: CGA
2: Hercules
3: EGA
4: Tandy
5: VGA
6: ???
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.
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)
The PC has basically always been double-sided, so they only need one notch, on the top/a side.
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
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.
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.
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!
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.
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.
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!
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?
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!
a call FAR absolute would be 5 bytes for the call, whereas push CS + call NEAR is 3+1 bytes
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.
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
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.
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
The problem is that ghidra gets confused when the relative addresses are too big.
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
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?
so now I can just manually thunk every cross-segment call, by creating the 2000:0000 segment that ghidra is imagining exists
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
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.
ghidra disassembles this as:
b8 b0 26 MOV uVar1 ,0x26b0
uVar is defined as a ushort: a 16bit type.
all makes sense, right? 16bit to 16bit!
so ghidra decompiles it as uVar1._0_1_ = 0xb0;
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!
unfortunately due to an oversight it believes those 65536 genders are allocated as:
0: He/he/Him/him
1-65535: She/she/Her/her
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!
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...
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.
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.
They're laid out like this:
Disk 1:
CARMEN.EXE
CARMEN.DAT
Disk 2:
CITIES.DAT
MIDISND.DAT
DIGISND.DAT
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!
unicorn has great documentation.
at least I assume it would be great, if it existed
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
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
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
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
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.
This code mallocs 65516 bytes in a loop until malloc returns zero.
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?
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
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.
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?
note to self: patch out the Romani slur in one of the hints for Budapest
EDIT: both of them
The description of Hungary says it's bordered by Czechoslovakia, Austria, Yugoslavia, Romania, and the Soviet Union.
Two of those are still right!
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?
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.
they're sending a... internal soundblaster test command?
(DSP 0xF0)
I dunno why this code is like this.
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
it's a loop that runs 256 times!
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
the menu system limits menus to having a maximum of 32 items.
which is weird because ONLY 17 WILL FIT ON SCREEN
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
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.
byte-identical.
this is a compiler & linker from 1988, it doesn't understand how to merge identical copies of functions apparently
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
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
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.
@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
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
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
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?
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"
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?
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
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?
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?
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?
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!
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!
there's 729 functions in the EXE.
I've named (in some way, counting placeholders) 355 of them, or 49%
by placeholders I mean things like "pcjr_sound_related" or "VGAFunc8"
and 13 of those function names include the word "maybe"
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
ugh. ghidra really doesn't understand that you can call far functions using near calls.
and the compiler for this LOVES using them.
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.
so you'll see, for example, it decompiles a strlen as:
uint1 = strlen(0x1000, some_String);
which is less than useful
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
i will convert you someday. mark my words
just as soon as i implement, like twenty years of hardware
@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
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?
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
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
@troldann of course!
(there's only 435 routes, I can precalculate them offline and just embed the answers in the code)
@troldann
Only 30 destinations? I guess that was just enough to keep each play through somewhat different without switching floppies 💾
30×(30−1)÷2
arg, this function is saving and storing part of it's own return address.
It's a farcall (in 16bit mode), and it is looking at the stack to read the segment portion of the address, so it can save it away in a struct.
this is a SaveRegisters function, which also saves the cs:ip of the calling function.
but there's also a RestoreRegisters function, which ALSO restores the cs:ip of the calling function.
and then it returns.
to the restored cs:ip
THIS FUNCTION IS A DYNAMIC GOTO
gonna have to dig out the appropriate compiler and check if setjmp/longjmp compiles the same.
then cry
okay so, the way main works is like this:
it calls initGame(), then setjmp.
if setjmp returns 0, it initializes the game.
if it returns 2, it goes into the main game loop.
except it's not really a loop? because the functions longjmp back to main(). it's a distributed dynamic goto loop
like if you do File->New, it longjmps(&env, 1).
which causes the game to reload from the beginning.
*smacks forehead*
of course this compiler doesn't take ANSI C. it's from three years BEFORE ANSI C
I only have Small installed. lemme find the floppy disk to install Compact/Medium/Large
it's not large... because large saves DX.
uh-oh. was MSC5 right all along, I just had the wrong model?
yeah. msc5 matches as well, if I set it to the right model.
WELL THAT WAS A WASTE OF TIME
I have a sneaky suspicion it was build with MSC5.1, not 5.0.
it's going to take an annoyingly long amount of time to verify that theory
it turns out what I thought was my MSC5.0 install WAS 5.1
so I need to install MSC5.0, not MSC5.1
yeah it's definitely not 5.0.
ugh. it's not 5.1 either. there may be some minor patch that I don't have access to
after extensive cross-referencing with the msc5.0 manual and the msc5.1 libraries being opened in a parallel copy of ghidra, I have finally been able to determine that the function I named sprintf_maybe is, in fact, _sprintf.
my hard work, as always, pays amazing dividends
I'm currently figuring out functions through the amazing insight of "the linker is simple and linear"
which means when I have _memmove, FUNC_1fb7_6db0, and _strcmp in the EXE, FUNC_1fb7_6db0 is probably not going to be an adlib sound driver. it's going to be something from the libc.
Cassandrich reshared this.
I've done this a lot especially in embedded stuff where you have an open source peripheral library or RTOS bolted onto closed source application code.
Find one xref to a SFR, match to the corresponding vendor HAL function, then you probably get 30 functions with minimal effort that are right before/after in the same order as the .c
Cassandrich reshared this.
okay I've got all the libc stuff named, other than some internal functions (which I don't have names for), and one weird memmove-ish function that I just named "memmoveish"
it looks very similar to memmove, but with an extra check or two, but I can't match it to anything in the library
Total funcs: 758
Unnamed funcs: 332
% named: 56.2%
pretty good for a day's work: nearly 4% done
made a discovery:
Galleons of Glory: The Secret Voyage of Magellan, released by Brøderbund in 1990, uses the same DAT format for its game files.
I haven't looked into the EXE yet, but that definitely sounds like they're sharing code
oh wow, it looks like Prince of Persia (DOS) also uses this DAT format!
Sadly, while the source for Prince of Persia is available... it's for the Apple II version. The DOS version is a complete reimplementation
SDLPoP is based on reverse engineering of the DOS PoP, maybe I can see how they implement DAT file reading.
GitHub - NagyD/SDLPoP: An open-source port of Prince of Persia, based on the disassembly of the DOS version.
An open-source port of Prince of Persia, based on the disassembly of the DOS version. - NagyD/SDLPoPGitHub
hey look, Prince of Persia uses the same setjmp/longjmp mainloop design!
github.com/NagyD/SDLPoP/blob/7…
SDLPoP/src/seg000.c at 7bd3bb85d8f7d4cb8ef72557ea0e65d80ba0906d · NagyD/SDLPoP
An open-source port of Prince of Persia, based on the disassembly of the DOS version. - NagyD/SDLPoPGitHub
the compression has a fun quirk: images can be compressed either top to bottom or left to right.
and the game switches between the two compression formats on a per-image basis.
So the developers just compressed each image both ways and used the smaller one. clever.
I've now got a boolean that has three values (true, false, and 'image')
but it's okay, I have a permit: I'm non-binary.
I have successfully extracted the first image from the game, using the ported SDLPoP compression code!
1 compression method down, 3 to go.
@gloriouscow everyone* knows canada only has one city, and it's Montreal.
* the 1990 game Where in the World is Carmen Sandiego? Enhanced
Sydney: fine.
Singapore: fine.
San Marino: fine.
Rome: PYTHON CRASHED
working on a full dat exporter, to build a JSON of all the hints.
and I'm running into pronoun issues. Story of my fucking life.
yeah looks good.
gist.github.com/foone/82de72a0…
The misplaced entries (like Cairo having a leader hint of "left in a vehicle flying a red, white and black flag") are like that in the original data files. Brøderbund just got their hints miscategorized sometimes.
if you are in New Delhi and need to go to the USSR, but misclick on Oslo instead of Moscow, you can't just fly to Moscow from Oslo. You have to go back to New Delhi first
fun fact about Prince of Persia (which I am doing research on because of how it reuses code from Carmen or vice versa):
A copy of it leaked with symbols included, but it's not the most normal version you can imagine... it's the mac port recompiled for MIPS.
press a button, then for the next X seonds, all modifications to the display memory are recorded along with the backtrace of what code changed it. So you could see a button get drawn, and check what code did that.
the original PC ran an 8088 at 4.77mhz, which DOSBox emulates as 240 cycles.
so this is approximately equivalent to a half-megahertz PC
PUSH DS
PUSH peel_ptr
PUSH DS
PUSH peel_ptr
the pointer so great they pushed it twice!
running this software at 15 cycles/second, I can confirm that the creators of it definitely didn't do that.
their general approach is "I KNOW PROGRAMMERS WHO TRY TO AVOID OVERDRAW AND THEY'RE ALL COWARDS
then white.
then it starts redrawing the background.
this only happens with movable dialogs. unmovable dialogs don't flash black+white.
which makes me think it's a bug rather than an intentional decision
b8 13 29 MOV AX ,0x2913
50 PUSH AX
b8 00 00 MOV AX ,0x0
50 PUSH AX
POP QUIX: The usual way to zero out a register on x86 is XOR AX,AX. This'd be only 2 bytes (31 C0). The compiler knows this. Why didn't it use XOR AX, AX here, instead of the bigger MOV AX, 0x0?
(It's not because optimizations were off!)
here's a hint: that disassembly is from the EXE, not from the memory of a running program.
(why would that matter?)
Total funcs: 762
Unnamed funcs: 293
% named: 61.5%
118 of those named functions have been marked as identical to ones from Prince Of Persia (or vice versa... I have no idea which game had this code first)
my initial theory of how the code sharing went:
Prince of Persia ->
Where in the World is Carmen Sandiego (enhanced) ->
Where in the USA is Carmen Sandiego (enhanced) ->
Galleons of Glory: The Secret Voyage of Magellan
1000:700b MOV CX,0x20
TimingLoop:
1000:700e LOOP TimingLoop
ahh, the good ol' days when "32 instructions" was a meaningful unit of time.
2. WHY DID I HAVE TO READ THE DOSBOX-X SOURCE CODE TO FIND THIS OUT?
the game picks between "they flew off to X" and "they drove off to X" and "they rowed off to X" and "they sailed off to X" but it doesn't seem to do this with any smarts.
or if it does, the database is incorrect.
carmen apparently drove off to nepal from canada
another way in which this game shows that it's from 1990 is that the librarians will tell you anything about their patrons.
that shit stopped after 2001
I'm experimenting with a way to show how DOS games render themselves.
Basically I'm recording a lossless video of the game running on a very slow CPU, then removing all the frames where nothing happens, and I'm playing it back sped up a lot.
The highlight of this video is how terrible the handling of the mouse cursor is! it's getting peeled and restored constantly
the mouse cursor appearing and disappearing is because they don't have multiple frame buffers: they have to hide the mouse cursor before they can draw anything, or the cursor would corrupt the newly drawn stuff if it happened to be over it.
so they solve this by hiding the cursor before every drawing command and showing it afterwards.
but instead of doing it once per screen, they're doing it once per command.
the GUI system they're using (I'm just calling it the broderbund UI in my reverse engineering work) DOES support avoiding this mess: you can tell it to hide the cursor, then when each sub-command tries to hide/restore it, it stays hidden, but they're not using it here.
which is of course equivalent, but it means you get this code:
offset2_rect(-y - param_3->bottom,-x - param_3->right,
(Rect *)CONCAT22((char *)ds,¶m_3->bottom),
(Rect *)CONCAT22((char *)ds,¶m_3->bottom));
instead of:
offset2_rect(-y - param_3->bottom,-x - param_3->right, param_3, param_3);
broderbund::hide_cursor();
broderbund::show_cursor();
WERE YOU PUNKS GETTING PAID BY THE CYCLE?
right after this it checks if the mouse is even enabled (hey, it's 1990, not everyone has a mouse!)
I'd think that you would check that before you try to hide and redraw the cursor, but maybe this is exactly why I'm not employed writing educational games in 1990?
MousePos is a struct with 2 shorts, x & y. they need MousePos.x & MousePos.y into CX and DX. BUT HOW?
LES DX, [MousePos.x]
MOV CX, ES
okay on an original 8086, LDS + MOV REG,REG is 29+2=31 cycles.
MOV REG, MEM*2 is 18*2=36 cycles.
I GUESS?
compilers are programs. programs are predictable (with enough effort. if it was easy, we wouldn't need people like me)
humans are not predictable. reverse engineering what a human is doing is much, much harder.
so I think digipres.club/@foone/114611650… does make some sense: it's hiding and redrawing the cursor because it already moved the mouse position, and wants the on-screen cursor to match up .
broderbund::hide_cursor();
broderbund::show_cursor();WERE YOU PUNKS GETTING PAID BY THE CYCLE?
it's just you'd think this would be like:
hide_cursor();
cursor.pos=newpos;
show_cursor();
but apparently the way the cursor hiding/showing works, hiding uses a saved position, while show_cursor uses the new global position.
so the code that uses the soundblaster auto-detects the IRQ in use by simply setting up a handler for every possible SB interrupt, then asking the SB to fire an interrupt. then it sees which one triggered.
Makes sense, but I wonder why this wasn't universal? why were programs always asking me which IRQ to use? maybe this isn't compatible with less-accurate SB clones?
at a guess, in case something else was using one of the “regular” SB IRQs that happened to fire at the same time?
I do not miss assigning non-conflicting IRQs from usually one of 3 options on every card.
currently in destructive-debugging mode.
I've a bunch of functions I tagged as "draw_relatedNN". Currently I'm down to 1, 2, 7, 9, 11, and 20.
So I'm running the game with them disabled (one at a time, natch) to see what doesn't render properly.
for example, when the first instruction of draw_related1 is a RET, suddenly animations don't play
the menu items 1-indexed, sort of. it treats 0 as "the whole menu itself"
so like:
set_menu_enabled(TRUE, 1, Menu_Game);
sets the first item in Game to enabled, but
set_menu_enabled(TRUE, 0, Menu_Game);
sets the whole Game menu to enabled.
the second thing the main() does (after setjmp) is try to unload the game.
this is a side-effect of how they're using setjmp to make main() a sort of event handler, so when they need to load the game's resources they don't know they're not already loaded, so it first tries to unload them, fails because they're not loaded, and THEN loads them
Probably the other way round - it was likely too prone to false positives.
Printing something in the background (one of the few multi-tasking things DOS could do)? Instant IRQ7 misdetection.
Receiving a packet from a network card that's configured to an IRQ line which is also typical for a sound card? Well ...
I remember mouse cursors flickering a ton back in the day.
I was just happy to have a mouse at the time
ohh I wonder if I could do this for my research for my video on blobbers 🤔 there's actually very little information out there on how to optimize the drawing
Are you just setting the emulator to very low cycles?
😮
well i know one of the big ones is lands of lore, because it doesn't just draw the scene but it also intersperses critters into it
i spent hours looking at the source for the scummvm engine but it's almost entirely uncommented and they do stuff like bitwise ops using raw numbers everywhere so it was just too hard to follow and figure out what was going on :/
@eniko Is the back buffer of double buffered rendering code always in the same place?
I would've presumed it would depend on the given software's compilation or freed memory, though I'm more of a higher level programmer in that it's kind of hidden from the drawing cycles I've dealt with.
@AT1ST @eniko yeah it depends on the game and what graphics hardware it targets. but it's usually easy to figure out where it is:
set a write breakpoint on the visible screen, and when it's hit, you now know what code writes to the screen. probably that's just a memcpy from main ram or vram, depending
bmeia.gv.at/oeb-peking
Reading the German Wikipedia etyomolgy section, that follows a
Chinese postal romanization, which, apparently, fell out of use between 1980s and early 2000s.
en.wikipedia.org/wiki/Names_of… suggests that, yes, mid-80s would be a typical swich time.
Maybe the editor was German?
All's well!
fuck yeah, that was specs of my first PC. A Siemens telewriter that came with an onboard Hercules gfx card.
For a wild reason when I added a CGA card it jumped to 4.78 MHz. I still miss that old box
@astraleureka digipres.club/@foone/114565324…
@Devourer_ITA It's from a PS2 port! PoP Sands of Time included the original PoP as a bonus, and an early leaked version included the symbols
TBQF, some decades that's true IRL too.*
When m-i-l & darling went to see the Schlieman Gold of Troy during Glasnost, flights to Moscow were change planes in Finland or Poland.
*(for that SPECIFIC example. I do realize you gave an example of a rigid game mechanic. I just find it a peculiarly interesting example.)
compiler-explorer/docs/AddingACompiler.md at main · compiler-explorer/compiler-explorer
Run compilers interactively from your web browser and interact with the assembly - compiler-explorer/compiler-explorerGitHub
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."
479K likes, 2,997 comments - cobrakaiseries on November 28, 2024: "Johnny’s a point A to point B type of sensei. 👊 Never let a "curvature" slow you down.".Instagram
(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.)
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!
StartPlayingSound:
POP AX
POP BX
POP ES
POP SI
CALL EnableSound
PUSH BX
PUSH ES
PUSH SI
PUSH AX
🤣
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.
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.
I knew a kid back in the 90s who played NES games with the controller backwards
@onfy They did make the RS/6000, including that one weird PowerPC ThinkPad, so there's that…
All the RISC computer manufacturers just couldn't get rid of the idea that *their* workstation will sell despite being so expensive and they'll get rich despite lacking any plan for Step 2 in their 3-step scheme. Shame.
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.
I'm posting this infographic as an excuse to (briefly) talk to people who, despite all the evidence, are having a hard time believing that a bunch of rich politicians and billionaire donors really are just hateful fascists willing to spend infinite monies on policing, persecuting, and even eliminating people they don't like for wholly arbitrary (white supremacy, xenophobia, anti-LGBTQ animus, ableism, misogyny, etc), irrational, or conspiratorial reasons.
First of all, let me assure you that they really are just a bunch of fundamentalists, hatemongers, and fascists. This isn't some sort of secret, the larger establishment right in America and the fascist Trump political machine have been caught saying the quiet parts out loud repeatedly when they think nobody is listening or has the courage to hold them to account; this is documented heavily in even mainstream media sources and then instantly memory-holed by the Very Serious PeopleTM in American public discourse. If you're struggling to comprehend how hate could be such a powerful motivating factor even for a class of people with enough "fuck you" money to last for generations, it's probably because you're not a hateful little nazi, and that's objectively a good thing.
Setting that aside however, I need you to understand that operating a militarized fascist police state is a highly-lucrative endeavor - for *some* people. Naturally, I don't mean its profitable for you, or the larger society you live in; in fact you'll effectively be billed for all this fascist repression in the form of taxes. But someone gets paid to install and operate the mass surveillance panopticon. Someone gets paid to violently disrupt legally-protected protests. Someone gets paid to arm and train the murderpigs. Someone gets paid to build the prisons and guard the incarcerated. Hell a bunch of besuited minions even get paid to catalogue all of this and write glowing reports about what an effective expenditure it is. There's so much money flowing through the U.S. carceral state that the larger industry that exists to serve it is a whole plank in the modern capitalist economy. Furthermore, the people getting rich off a fascist police state have more than enough money and power to bribe politicians to expand that fascist police state; which is why doing so has largely been a bipartisan position in American politics for decades and decades now. Even though he's using it in horrifying ways, it's important to remember that Trump did not build the already massive fascist police state he inherited when he became president; it was built by generations of American politicians before him, both Republican and Democrat; many of whom were trying to secure donor money, or make a quick buck regardless of who that ultimately harmed.
All of which brings us to Trump and the rapid expansion of the carceral complex necessary to enact his fascist agenda. When Downmarket Mussolini moves to conduct the mass deportation of millions of people, that creates an *enormous* pot of money that can be looted by his rich donors in various ways. Are these folks motivated by white supremacy? Yes, definitely, but even if they weren't we're talking about billions, if not trillions of dollars worth of government contracts at stake here - a whole lot of people are going to get very rich off Trump's ethno-nationalist policies, regardless of what they believe in their hearts. To varying degrees, the same holds true of surveilling, suppressing, and hunting down anti-genocide protestors, conducting a pogrom against trans people as part of a made up "war on gender ideology," spying on every woman in America to make sure she's not trying to get an abortion, and so forth. Maybe I won't ever be able to convince you that the establishment fascists, doing fascism, have hate in their hearts, but surely you're already familiar with some of the awful, inhumane, and tyrannical shit rich people and the politicians they own are already willing to do for fuckpiles of money in our society, right? As far as the donors behind Trump are concerned, a rapid expansion in the number of state "enemies" and targets for repression, along with the corresponding expansion of the apparatus necessary to conduct that repression, is potentially one of the most profitable business opportunities in American history.
Quite frankly, we *could* take this discussion a lot further; for example, I could point out that capitalism itself is dependent on the marginalization, otherization, and dehumanization of minority or out groups in our society to create whole classes of people it's legally acceptable to ruthlessly exploit. For now however, just keep in mind that there's potentially trillions of dollars available for folks who want to help transform Trump's fascist vision for America into reality, and for that reason (among many others), it doesn't actually matter what's in their hearts.
And just what does that rapid expansion of the fascist police state look like even in the infancy of the Trump administration? As this March 9th piece published on Truthout notes, it's already a fascist nightmare where migrants are kept in inhumane conditions and their human rights are routinely violated in violent, even lethal ways - and Downmarket Mussolini's regime is only getting started:
truthout.org/articles/as-mass-…
As Mass Incarceration of Immigrants Rises, Detention Centers Eye New Contracts
"That crisis is set to grow as detention expansion continues. Last week, ICE signed a $1 billion, 15-year contract with the private prison company GEO Group to reopen an empty jailhouse in Newark to incarcerate up to 1,000 immigration prisoners at a time, the first large detention expansion under Trump’s crackdown.
GEO Group pushed hard for the contract and sued New Jersey in 2024 to successfully overturn a state law originally supported by racial justice activists that banned private companies from contracting with ICE to house immigrants. Now, GEO Group reportedly has plans to increase the facility’s capacity to incarcerate people and potentially generate an additional $500 to $600 million in annual profit. The company has faced multiple lawsuits after immigrants were subjected to what attorneys describe as underpaid and forced labor. Most recently, a federal court upheld a ruling requiring GEO Group to pay $23 million in damages after the company paid ICE detainees $1 a day for labor at a detention center in Tacoma, Washington."
Like most honest reporting about America's horrifying migrant carceral complex, this is a hard story to read for folks who aren't already familiar with the cruelty, depravity, and casual disregard for human life with which Americans conduct their one-sided war on migrants. The testimony from formerly-incarcerated individuals provided in just this single story should be enough for most people to understand that this has nothing to do with so-called responsible policing, or keeping anyone safe, while the dollar figures involved make it clear that broadly speaking the US government is heavily-funding a whole lot of odious people in the business of torturing migrants for profit. Furthermore, as Trump works to expand the hunting, detention, and deportation of migrants, the piles of money, flow of human rights violations, and atrocities committed in the name of protecting Americans from the lady who works at your local nail salon, will only expand correspondingly.
#Fascism #PoliceState #Trump #MigrantRights #MassDeportations #ICE #PrivatePrisons #MigrantCarceralComplex
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)
🔥 Pecinta Komik, Ini yang Kamu Tunggu! 🔥
Chapter terbaru dari 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 (Chapter 21.2) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/240177
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Baca komik 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 Bahasa Indonesia!!!
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #FantasyManga 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)
🔥 Pecinta Komik, Ini yang Kamu Tunggu! 🔥
Chapter terbaru dari 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 (Chapter 21.1) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/240177
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Baca komik 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 Bahasa Indonesia!!!
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #FantasyManga 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)
🔥 Pecinta Komik, Ini yang Kamu Tunggu! 🔥
Chapter terbaru dari 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 (Chapter 22.1) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/240177
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Baca komik 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 Bahasa Indonesia!!!
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #FantasyManga 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)
🔥 Pecinta Komik, Ini yang Kamu Tunggu! 🔥
Chapter terbaru dari 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 (Chapter 23.2) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/240177
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Baca komik 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 Bahasa Indonesia!!!
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #FantasyManga 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)
🔥 Pecinta Komik, Ini yang Kamu Tunggu! 🔥
Chapter terbaru dari 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 (Chapter 23.1) sudah hadir dalam Bahasa Indonesia! 🎉
📖 Gabung bersama ribuan pembaca lainnya dan nikmati kisah serunya.
✨ Jangan biarkan orang lain tahu kisah ini lebih dulu, baca sekarang dan rasakan sendiri keseruannya!
👉 Klik di sini untuk mulai membaca sekarang: e-komik.org/komik/240177
⏳ Jadilah yang pertama tahu apa yang terjadi selanjutnya!
#EKomik #Komik #Comic #Manga #Action #Comedy #Fantasy
Baca komik 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 Bahasa Indonesia!!!
Segera baca di e-komik.org/komik/240177
#EKomik #Komik #Comic #Manga #Action #Comedy #FantasyManga 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)
Eleanor Rees
in reply to Dgar • • •