well I can confirm that if you break the directory names for CHARAL and CHARAS in Robot Alchemic Drive, it gets to the first scene where it's supposed to display them and just softlocks forever
so I know which function it is that loads data from a VFS, if I can figure out how to extract the file directory from the VFS (either from the file or the in-ram representation), I can automate calling it for each file and saving the result, so I can extract the whole filesystem
okay I can decode most of a directory listing. now I gotta figure out how different directories are linked together, since this VFS format doesn't have one big index, it's a bunch of hierarchical directories
okay it's not 100% alright (it's clipping in some places) but using Tenacy and importing with VOX ADPCM, offset of 2080, and sample rate of 22050 gives me reasonable-sounding audio
so I can find and extract all the dialogue (not compressed, I have a close enough code that works), and I can find all the other datafiles but not decompress them yet
maybe I can procrastinate on the decompression routine by extracting all the audio, converting it to WAV, and then running it through a voice recognition model
I think my problem with compression is that my ADHD means I am not good at holding a bunch of small numbers in mind. I can work around this limitation in most of my programming/reversing, but compression is inevitably a bunch of small numbers getting masked and bitshifted and indexed
okays so broad strokes of the compression: it has a 4k scratchpad circular buffer, which it seems to keep updated on each iteration. it maintains two key variables, which I've named (somewhat arbitrarily) sliding_mask and control.
each iteration through the loop, control is set to sliding mask, and at the end of the loop sliding mask is shifted right by 1.
in the loop, there's a first check: if sliding mask & 256 == 0, we set control to the 4 bytes off the input pointer (which I call "main pointer" for reasons). then the sliding mask is set to control OR'd with 0xFF00, and we advance the main pointer one byte
in the RLE logic, control is set to the 4 bytes at the main pointer, OR'd with the second byte anded with 0xF0 and shifted left 4 bits. then we set write_len to the second byte of main_ptr ANDed with 0xF, and advance the main pointer by 2.
yeah and if they didn't compress anything, they'd have wasted about 98 megabytes.
Load speed, maybe? I'm playing on an emulator off an SSD but this might have been a nightmare on a real PS2, especially since they load a lot of files in no particular order and at CD speeds
anyway the main complication in the RLE branch is that it tries to do 8 bytes at a time. I don't know if this was done manually or if it was a compiler trying to inline a memcpy
I changed the type of scratchpad to a byte* instead of a void*, which removed all the int casts but did cause ghidra to unroll setting 64 bytes at once
remaining stuff to do: 1. extract the scripts from the mission briefings / other text files? 2. decode all the voicelines into WAVs 2b. optionally autotranscribe them 3. decode the font? I'm looking at the files and it's mostly obvious, but it may be WAY easier to use my Automatic Visual Font Extraction scheme on it 4. find all the character portraits and extract those 5. find a .JP ISO and re-run all this to see if there's more left in that version
the game also definitely has the ability to load a USB keyboard driver (they stuffed the driver inside CONTROL.DY for some reason) but I don't know if that means it actually responds to any keyboard keys.
ah-ha! so Robot Alchemic Drive was made by Sandlot in 2002. In 2003 they released the first of the Earth Defense Force series, Simple 2000 Series Vol. 31: The Chikyū Bōeigun/Monster Attack.
and I just checked: that game uses the same VFS format for its datafiles!
okay so extracting the script is going to be hard. they are stored inside IEX files, which I think contain binary code as well. So I can't easily statically figure out where the shift-JIS script is, even if it's mostly identical between missions
oh interesting! there's a prototype, which uses a different naming scheme for the two VFS files: it calls them RAD.EE and RAD.IOP
That's Emotion Engine (CPU/GPU) and I/O Processor.
And that split makes sense for the CONTROL.DY/REMOTE.DAN too: CONTROL is files the CPU/GPU needs, like levels and textures and subtitles, while REMOTE is sound files
which might explain why they're not compressing the REMOTE/IOP files: without a CPU to decompress it, they're just DMAing straight from the DVD into IOP memory
my kingdom for debuggers that let me set them to logging only and define what gets logged. I'm so tired of stepping through a bunch of OpenFile breakpoints, and having to click three times on each one to look up what file its trying to read
I finally got the emulator in the right place to inject a different character name, typed in the 40-digit hex number, and hit resume, and waited... and the whole emulator crashed
don't get me wrong, I totally understand why my hex editor doesn't understand shift-jis. it'd be a terrible feature to support such an insane text encoding that no one should use
also I keep having to retype manually 36-character hex filenames. and not only is that boring and error prone, but remember, I'm me: I immediately start ADHDing off onto the idea of building a keyboard to automate this somehow
if you ask a foone to type in a 36-character string, she'll start thinking about building a keyboard by digit 8, open an IDE at digit 16, and by digit 24 she's got a microcontroller connected over USB
ugh. this is just an artifact of how I'm generating the indexes in program A and printing filenames in program B and there's too much normalization between them
either I need to encode an intermediate file in shift-jis, or refactor program A to output json
the latter is unfun work compared to the ease of the former... but the former should be considered a crime in many countries. for the good of the internet, do not create more shift-jis files
okay look I don't want everyone to think I took an hour and a half to add CSV export to my scripts and import it into google sheets and make it translate them all
there was some Life Events that took me away from video game hacking for an hour. I don't want you to think I'm losing my touch here
so now I've got a list of every original filename's shift-jis encoded filename (for injection into the game at runtime, to make it load different images), the original kanji, and the translated version. cool.
hmm. I can't replace files on the disk (yet) because I don't have ability to rebuild the archives. and I can't just hex edit the ISO because they're compressed. ugh. I think I'm going to have to do everything in-ram, which is a pain
It's one of the more fun moods to be in when writing fiction, too! (Unless you're straitjacketed by the need to write an MFA-respectable Literary Novel for a publisher you conned into paying you a seven digit advance two years ago and who are now waiting on your doorstep with a baseball bat, tapping their toes impatiently.)
THE ORION EXPERIENCE ✨ LIVE in Concert!September 24th / Portland, OR - Dante's (21+)September 25th / Seattle, WA - El Corazon (All Ages)December 12th / Houst...
I hit GO on the keyboard-automation program, and let go of the mouse to wait and observe.
unfortunately since I'm still slightly bedridden, I'm in a recliner, and my mousepad is curving over one round arm. So the mouse slipped down, then hit my ass, which made it register a left click, switching away from my PS2 emulator and into File Explorer
remaining stuff to do: 1. extract the scripts from the mission briefings / other text files? 2. decode all the voicelines into WAVs 2b. optionally autotranscribe them 3. decode the font? I'm looking at the files and it's mostly obvious, but it may be WAY easier to use my Automatic Visual Font Extraction scheme on it 4. find all the character portraits and extract those 5. find a .JP ISO and re-run all this to see if there's more left in that version
arg. I finally got my injection code to properly pull out the backgrounds... but they are coming as multiple separate textures, thanks to how they're loaded. and I don't have the ability to put them back together. I'm gonna have to do something weirder
Mika 6 years ago, Big Guts Yamano Dai looks like he's about to cry Shadow of a fallen mother_Large The cameraman was delighted The cameraman panics The cameraman is very surprised
ugh. not all fullwidth characters can be encoded into shift-jis, of course.
the whole point of fullwidth in unicode is to enable roundtripping with encodings like shift-jis, but there's 4 codepoints in the U+FF01 to U+FF5E range that aren't encodable in shift-his!
weird dialogue scripting engine: it seems to stop paying attention to tags if it hits a missing character.
I'm rendering "|A|<WAITKEY>" and it pauses, because of the WAITKEY. But if instead of A it's a character that isn't in the font, it renders a blank and then treats <WAITKEY> as plain text, so it doesn't pause, and my screenshotter goes off at the wrong time
okay I have grabbed three unicode blocks: * general punctuation * latin-1 * full-width
I haven't found a way to find out what characters are in the font, so that should be good coverage for non-japanese text. I've just extracted the characters, I'm going to need to spend a while massaging the image->font import script into doing what I need with this image pile
I've been tearing apart Kerbal Space Program's UI the last few days and having similar reactions (several of the button sprites are 64x64 scaled up to 69x69)
Oof, I'm expecting compression algorithms to be mostly "I am very smart" piles of abject insanity. Please promise me you'll take regular sanity breaks.
I don't know which one it is but it bothers me so much how this RE tool litters the output with pointer casts rather than inferring correct types for its synthesized locals from the effective type rules.
please let the world know if the Nanao offing themselves route thing the one gamefaq about this game talks about is true or just a hoax. We could never get it and it sounds the most L is real thing ever.
🗦new🗧 FireFly
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •hmm. a switch with 7 subfunctions, two of which have already been identified as LoadLargeChara and LoadSmallChara.
So... generic image loader, or dialogue script evaluator?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the load image looks like:
cVar1 = (**(code **)(*(int *)(param_1 + 0xda8) + 0xc))
(param_1 + 0xda4,param_1 + 0x624,*(undefined1 *)(param_1 + 0xe1c),0);
so we've got C++ with vtables, yay
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •vtables are contentious in reverse engineering. they can often reveal a lot of structure which is very useful to a reverse engineer.
but they also make everything way more complicated which makes my head hurt
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay thankfully they're using one of those vtable implementations where the first slot points to a string that describes the vtable
so I've located C_Scenario and it seems to have a virtual member function that evaluates individual opcodes
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Tomoe_Large_Normal.FACE
well, it's actually 友絵_大_通常
but here's the fun part: it's shift-jis! nooooooo
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🏳️⚧️ • • •BaB::C_Buffer<BaB::C_String *>
YEP. it's a C_Buffer that's templated on C_Strings
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •extracted some script from RAM:
v1-3-1\x00Hello.<RET>We\u3000bring\u3000you\u3000breaking\u3000news.\x00
v1-3-2\x00It’s...\x00
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so each line of script has a name at the beginning, then a nul, then the text, then another nul
so like, the first line of text in the game is v1-3-1, then v1-3-2 through v-1-3-10
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 I have matched up some code from the CONTROL.DY file with the extracted RAM
the snippet:
"tialize\00\xFD\xF8\x97\x09main"
matches up with:
"tialize\0\f8\0\0\0\0\0\x01\0\0\0\0\0\0main"
so... some kind of RLE?
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay so it turns out I already found the function that decodes the text:
00159350 TextDecode
So I know where to focus my efforts sometime when it's not 5am
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •wake up next day, go to doctor, get back, relax into bed and check project status:
reverse a decompression algorithm
well you know I'm still recovering from surgery, I should take it easy, maybe I'll just play Civilization V for a couple hours
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay so this compression algorithm first starts by erasing memory in 64-byte chunks, using 8 64bit writes each iteration
erasing a total of... 4k? I think? it counts weird
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🏳️⚧️ • • •okay I have manually extracted a 285 byte compressed chunk that decompresses to 421 bytes
so I can test the decompression routine I'm gonna have to write
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •got it. I can list all the files in all the subdirs. It only supports a top dir + a subdir, you can't nest deeper than that.
There's a total of 1971 files in CONTROL.DY
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •there's two VFS files (CONTROl.DY and REMOTE.DAN) and they use DIFFERENT DIRECTORY FORMATS
why? because FUCK ME that's why
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I think DAN is mostly (or completely?) audio files, and it doesn't look like they compressed any of them.
at least not using their homegrown compression, they're probably some other audio compression format
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so what I think is the dialogue files are these genericly named files like:
V58\10c-1
no extension. They start with "BA", a file length, and 2k of zeroes
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 a 4k scratchpad circular buffer, which it seems to keep updated on each iteration.
it maintains two key variables, which I've named (somewhat arbitrarily) sliding_mask and control.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •each iteration through the loop, control is set to sliding mask, and at the end of the loop sliding mask is shifted right by 1.
in the loop, there's a first check:
if sliding mask & 256 == 0, we set control to the 4 bytes off the input pointer (which I call "main pointer" for reasons).
then the sliding mask is set to control OR'd with 0xFF00, and we advance the main pointer one byte
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •then there's the big check:
does control & 1 == 0?
if so, we go into the RLE logic, which is Complicated
if not, we copy 1 byte from input to output, advance the pointer, and loop
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •then we set write_len to the second byte of main_ptr ANDed with 0xF, and advance the main pointer by 2.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •like I've said before, compression isn't my strong point, but this seems like a simpler form of an LZ compression?
just instead of a dictionary, they're using a circular buffer, and they've skipped any huffman coding steps
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •yeah and if they didn't compress anything, they'd have wasted about 98 megabytes.
Load speed, maybe? I'm playing on an emulator off an SSD but this might have been a nightmare on a real PS2, especially since they load a lot of files in no particular order and at CD speeds
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🏳️⚧️ • • •int main(int argc,char *argv){
I'm not sure what I hate more:
that this compiles or that I typed it without realizing the obvious mistake
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •1. extract the scripts from the mission briefings / other text files?
2. decode all the voicelines into WAVs
2b. optionally autotranscribe them
3. decode the font? I'm looking at the files and it's mostly obvious, but it may be WAY easier to use my Automatic Visual Font Extraction scheme on it
4. find all the character portraits and extract those
5. find a .JP ISO and re-run all this to see if there's more left in that version
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •huh. it uses a scripting system called "BAT" (not a real batch file, surely?) which seems to be a list of commands.Example file, SIREN.BAT:
openmap map\map01
CameraPos 0 700 0 700 3.14
object object\Siren.vob
objectpad 4
objectteam 1
CameraPos 0 625 0 800 0
probject object\player1.vob object\Siren.vob 0 0
objectteam 0
CameraPos 0 700 0 700 0
console 0
FadeIn 2
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the MAP folder inside CONTROL.DY has MAP01 through MAP09, MAPBLK, and EFFECTTEST
I'm guessing EFFECTTEST is unused
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •the first file under OBJECT in CONTROL.DY is "AISAMPLE.VOB"
figures. even in 2002, you can't escape AI slop!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ah-ha! so Robot Alchemic Drive was made by Sandlot in 2002.
In 2003 they released the first of the Earth Defense Force series, Simple 2000 Series Vol. 31: The Chikyū Bōeigun/Monster Attack.
and I just checked: that game uses the same VFS format for its datafiles!
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🏳️⚧️ • • •oh interesting! there's a prototype, which uses a different naming scheme for the two VFS files:
it calls them RAD.EE and RAD.IOP
That's Emotion Engine (CPU/GPU) and I/O Processor.
And that split makes sense for the CONTROL.DY/REMOTE.DAN too: CONTROL is files the CPU/GPU needs, like levels and textures and subtitles, while REMOTE is sound files
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •interesting: one of the modules it loads is called ISFSOUND and contains the string "ISF_SOUND_DRIVER_BY_BaB_2001/2002"
"BA" is the magic number for the voice files
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Cy reshared this.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Ben Lubar (any pronouns)
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Ben Lubar (any pronouns) • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •bunch of functions in a raw that are all mysteriously no-ops
somebody used a define to turn off a logging function, I bet
Wulfy—Speaker to the machines
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Wulfy—Speaker to the machines • • •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 three versions of the 3 filenames I'm looking at, in shift-jis hex, translated name, original name.
(I need to make a program to compile this shit for me, manually assembling this is a pain!)
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •NO ONE SHOULD HAVE THIS PROBLEM IN 2025
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •either I need to encode an intermediate file in shift-jis, or refactor program A to output json
the latter is unfun work compared to the ease of the former...
but the former should be considered a crime in many countries. for the good of the internet, do not create more shift-jis files
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay look I don't want everyone to think I took an hour and a half to add CSV export to my scripts and import it into google sheets and make it translate them all
there was some Life Events that took me away from video game hacking for an hour. I don't want you to think I'm losing my touch here
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 bare minimum test when doing this kind of reverse engineering: CAN YOU BREAK IT?
in this case, yes, yes I can. The portrait hasn't loaded properly, because I scrambled the filenames. That proves I'm poking in the right place!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ah-ha! the first portrait shown in the second tutorial is Kaoruko News_Small_Tension.
now I can inject over it!
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 think I can. or close enough to it.
I think it's time... for a keyboard
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I skipped the keyboard and just edited the savestate as a test.
FUN FACT: this is what happens if you fuck up the filename list! it loads the filename you told it to, then hangs.
This is faster than letting the level finish loading, so now I'm going to crash it on purpose
Furbland's Very Jolly Mastodon reshared this.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •dang it. it doesn't always crash properly. it might crash improperly.
I'm gonna need to carefully crash it.
just Claire again and again
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to just Claire again and again • • •@sif I have stomping solutions:
qwantz.com/index.php?comic=1
Dinosaur Comics!
qwantz.comFoone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Charlie Stross
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Charlie Stross • • •@cstross "supervillain" is one of the more fun moods to be in while programming.
am I hacking this game the "right" way? absolutely not. I'm hacking it the way that's FUN TO CODE, and damn the "rules"
Charlie Stross
in reply to Foone🏳️⚧️ • • •We Must Dissent
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to We Must Dissent • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I think between when I wrote this code and now, some library I depend on changed in some way that's non-obvious.
either that or I'm going mad.
⚧Kunikleto Celeste⚧
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to ⚧Kunikleto Celeste⚧ • • •@celestestormysea youtube.com/watch?v=8ZcqaolcjU…
Let's get mischievous and polyamorous
The Cult of Dionysus ✨ The Orion Experience
YouTubeFoone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •and it makes no difference
WHAT THE ON IS FUCKING GOING
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I should look up the 2bit hack that wrote this keyboard library
unfortunately it's GPL'd to some clown named "Pagliacci"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •MOTHERFUCKER CHANGED IN SEPTEMBER:
github.com/earlephilhower/Keyb…
my code is failing because it doesn't call HID_Keyboard::begin() , but the last time I used this code, HID_Keyboard::begin() didn't exist
Update for dynamic USB configuration · earlephilhower/Keyboard@3635ab6
GitHubFoone🏳️⚧️
in reply to Foone🏳️⚧️ • • •SHE LIVES
man this library is a nightmare to get working every time I change computers. I need to shiny it up and release it
I've been thinking that above paragraph since 2019
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I hit GO on the keyboard-automation program, and let go of the mouse to wait and observe.
unfortunately since I'm still slightly bedridden, I'm in a recliner, and my mousepad is curving over one round arm. So the mouse slipped down, then hit my ass, which made it register a left click, switching away from my PS2 emulator and into File Explorer
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •yep it worked on 6 of em. Next step, do all 203 of them, at something like 20 seconds an image
See you in an hour and a bit?
(hopefully. otherwise I'll post DAMN IT IT BROKE)
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so that's #4 done.
digipres.club/@foone/115760308…
Foone🏳️⚧️
2025-12-22 00:08:48
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •StarkRG
in reply to Foone🏳️⚧️ • • •[aware event]
in reply to Foone🏳️⚧️ • • •MOIN 🇺🇦
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to MOIN 🇺🇦 • • •@moin it had to have compiled, I'm looking at the decompiled binary!
it's Robot Alchemic Drive, a PS2 giant robot game
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay this game 100% has a console in it, I'm seeing tons of references to it.
I wonder if the code to render and interact with it is still here
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •I found a class called clKksCallback and another called clKksItouCallback. I typed "Itou" into google translate, only to learn it means "Ito"
useful
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ɗ𐐩ʃƕρʋ
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •also I just realized this game lists two programmers: Toshio Noguchi and Yoshihiro Itou
I think Itou just named their callbacks
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •and I don't have the ability to put them back together. I'm gonna have to do something weirder
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay I've extracted them all, with caveats:
the first two (these BNN ones) are too connected to separate them out, apparently. so I have one screenshot for two filenames
Also, that screen is animated. and I can't really handle that: but it's the only one, so I'm just gonna let it be
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •nah, quality is virtually identical: 640x460 vs 640x448
so other than removing the animated part there'd be no point
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay so I have all the small portraits and the backgrounds.
next up, the large portraits!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •some fun filenames:
Mika 6 years ago, Big Guts
Yamano Dai looks like he's about to cry
Shadow of a fallen mother_Large
The cameraman was delighted
The cameraman panics
The cameraman is very surprised
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •The animated background:
90 frames of balls
turns out it loops perfectly!
EDIT: Apparently WebP doesn't work here. GIF it is then
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •so the CONTROL.DY file contains two font files:
FONT.P2F
FONTE.P2F
Which one is the dialogue font? NEITHER APPARENTLY
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ThatKomputerKat reshared this.
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay I have text injection. repeatable and automatable.
Also it turns out those special tags, like WAITKEY? only work if you spell them in full-width.
So "<WAITKEY>", not "<WAITKEY>"
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •ugh. not all fullwidth characters can be encoded into shift-jis, of course.
the whole point of fullwidth in unicode is to enable roundtripping with encodings like shift-jis, but there's 4 codepoints in the U+FF01 to U+FF5E range that aren't encodable in shift-his!
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •"/'/-/~
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •weird dialogue scripting engine: it seems to stop paying attention to tags if it hits a missing character.
I'm rendering "|A|<WAITKEY>" and it pauses, because of the WAITKEY. But if instead of A it's a character that isn't in the font, it renders a blank and then treats <WAITKEY> as plain text, so it doesn't pause, and my screenshotter goes off at the wrong time
Foone🏳️⚧️
in reply to Foone🏳️⚧️ • • •okay I have grabbed three unicode blocks:
* general punctuation
* latin-1
* full-width
I haven't found a way to find out what characters are in the font, so that should be good coverage for non-japanese text.
I've just extracted the characters, I'm going to need to spend a while massaging the image->font import script into doing what I need with this image pile
Andrew
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Andrew • • •Nuclear Oatmeal
in reply to Foone🏳️⚧️ • • •Chip
in reply to Foone🏳️⚧️ • • •real tournament when unreal tournament walks in 💽 --> 39c3
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to real tournament when unreal tournament walks in 💽 --> 39c3 • • •just Claire again and again
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to just Claire again and again • • •Cy
in reply to Foone🏳️⚧️ • • •Jason Parker (he/they)
in reply to Foone🏳️⚧️ • • •Mad Engineering
in reply to Foone🏳️⚧️ • • •Please promise me you'll take regular sanity breaks.
maaneeack
in reply to Foone🏳️⚧️ • • •disorderlyf
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to disorderlyf • • •jonathankoren™
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to jonathankoren™ • • •Cassandrich
in reply to Foone🏳️⚧️ • • •zero-escape
in reply to Foone🏳️⚧️ • • •“Advanced paging architecture“
But that’s just a level above the actual partition.
So just fat32?
Foone🏳️⚧️
in reply to zero-escape • • •Ash
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Ash • • •Ash
in reply to Foone🏳️⚧️ • • •Foone🏳️⚧️
in reply to Ash • • •