468 karma · joined April 8, 2015
A higher spec version of Tiler is available as TileMotion, which has a JavaScript demo decoding 1080p video in software here: https://gligli.github.io/tilemotion/demo/
If you want to see what it's supposed to look like, copy the screenshot into GIMP, go into "Color, Levels" and in the "Input Levels" section, there should be a textbox+spinner with a "1.00". Set that to 0.45.
https://en.wikipedia.org/wiki/Galaksija_(computer)
https://media.ccc.de/v/29c3-5178-en-the_ultimate_galaksija_t...
Years later, I was surprised to see the exact same cat on a "port" to the Sega Dreamcast VMU (a memory card that can function as a stand-alone device, with a 48x32 pixel screen,) where pressing a button would play one of the animations. It makes a little more sense now, finding out that the cat images were released into the public domain.
It looks like I misremembered/misinterpreted some stuff. It looks like the top of the head behaves like the sides of the head, extending upward, forming a + shape.
Judging by how the arm/leg damage works, it the collision hit zones rotate with the enemy. Offset appears to be were the collision point is releative to the character's rotation, since it's also used to determine front/back and left/right collision. So for a hit to count as a headshot, it has to hit a cardinal octant of the collision cylinder.
Edit:
Updated diagram: https://imgur.com/a/Mec7HGm
The collision shape used for a character in DX is a single cylinder. The game looks at where on the cylinder the collision point of the shot is, and tries to figure out if it's a head, body, or leg shot. It does this by checking how high the collision point is, with the lower X% being legs, top Y% being the head, and the middle being the body.
If a shot hits the head section, it runs some additional checks, and can sometimes still count as a body hit. There was some weird code that, after you stared at it long enough, looks like it ended up splitting the head area into compass aligned 1/8ths (so north, north-east, east, etc) and hits to the N-E-S-W octants would count as a head shot, and a hit to the NE-NW-SE-SW octants would count as body shots. (I couldn't tell if the angles rotate with the character, or are absolute relative to the world.) I think there was also a check for hits on the top cap of the cylinder, so that the hit would have to be close to the center of the cylinder to count as head hit, and near the outer rim would count as a body hit.
Hm, I should just make a diagram. Here: https://imgur.com/a/KG6MF1k
I guess what they were trying to do was make the actual head hitbox a smaller section of the head level, so that a shot that should go over the shoulder and miss would just count as a body shot and not a true headshot. And if you made a test map, with the player and a static test enemy placed in a line, this could work reliably from a fixed position. But when you actually play DX, and approach enemies from various angles, headshots inexplicably fail.
I used publicly available documentation (like https://www.ludd.ltu.se/~jlo/dc/ and the now defunct dcdev Yahoo Group), looked at the existing open source KOS driver, and looked at the source for Dreamcast emulators to figure out how things worked.
The GPU in the Dreamcast is a bit more complicated than PSX/PS2/GC since it doesn't accept polygons and draw them directly to the framebuffer. It's a tile-based deferred renderer, like many mobile GPUs, so it instead writes the polygons to a buffer in video RAM, then later walks through the polygons and renders the scene in tiles to an on-chip 32x32 pixel buffer, which finally gets written to RAM once.
This allows the Dreamcast to have a depth-only fillrate close to the 360 and PS3 (DC is 3.2 GPix/s vs 360/PS3 4.0 GPix/s), and it basically preforms a depth-only prepass to avoid doing texture reads for obscured texels. It can also preform per-pixel transparency sorting (order-independent transparency) with effectively no limit to the number of overlapping pixels (but the sorter is O(n^2), so a lot of overlap can become very expensive).
To get a working driver for the Dreamcast, you have to set up some structures in video RAM so that the hardware knows what polygons are in what tile. Another thing the driver needs to do is coordinate the part of the hardware that takes polygon commands and writes them to video RAM, and the part that actually does rendering. You typically double buffer the polygons, so that while the hardware is rendering one frame, user code can submit polygons in parallel for the next frame to another buffer.
My driver started as just code in "int main()" to get stuff on the screen, then I gradually separated stuff out from that into a real driver.
I don't think I found the sun/moon code (or more likely I did, but didn't realize what exactly it was doing, Ghidra SH4 has serious problems with floating point instructions making following anything that uses them almost impossible) but I did find most of the other time related code for updating the clock/calendar.
One weird thing I found while doing that is about the in-game watch. You always have a watch in your inventory, so you'd think it would be hard coded in, but it's treated like any other item. The game also has code to check if the watch is missing and add it back in anyways. But the code that draws the on-screen clock also checks if you don't have the watch, and won't draw the clock if you don't have it (or at least part of the UI clock logic is disabled, I haven't actually tried seeing what happens if you don't have a watch to verify if my interpretation is correct).
On the PAL version, the code that checks for a missing watch is at 0x0c180dc6 (that's where the code is loaded into memory, subtract 0xc010000 to get the address in 1ST_READ.BIN), and I think the code for drawing the clock (or at maybe it was just updating the hands of the clock?) is at 0x0c18290a.
Dreamcast Shenmue has code to support other video modes, like alternate resolutions (320x240p!), antialiasing, and 24/32 bit color. They're a bit bugged, like when using antialiasing, the 2D elements being squashed into the left half of the screen, and some strange issue with the screen position for the RAMDAC being setting incorrectly, causing the screen to vibrate left/right by a pixel or two, but the 3D models were drawn correctly.
24-bit color worked surprisingly well (even if the flag intended to enable it didn't seem to work, and I had to force it elsewhere.) I would have thought that having less video RAM free would have caused serious problems, but the game just loaded fewer NPCs. It was strange playing without dithering.
When updating the cursor position, check if line being output overlaps with the cursor. If it isn't, it's safe to update the hardware cursor immediately, without tearing. Otherwise, defer updating the cursor until later (vblank would work) to avoid tearing.
Of course, this assumes it's possible to read what row of the frame buffer is being displayed. I think most hardware would support it, but I could see driver support being poorly tested, or possibly even missing entirely from Linux's video APIs.
https://www.dreamcast-talk.com/forum/viewtopic.php?f=5&t=165...
TASes are pretty much always measured from power on to last button input required to trigger the credits. With normal speedrun, timing various from game to game, but a common method is timing from selecting new game to the last hit on the final boss. So games with long openings or with interactive post-final boss sequences that have to be played before the credits start would have inflated times on the TAS.
The TAS counts about an extra 15 seconds before the game starts. The TAS reaches the point the speed run stops counting at 18:52, and continues to play out the ending. So the TAS would be measured as about 18:37 using speed run timing, so the speed run is still genuinely faster than the TAS, but less than the official numbers indicate.
It seems like the speed run uses a glitch that the TAS deliberately avoided. From the TAS description:
> At the same time, a major new glitch allowing Ecco to go through nearly any wall was not used because the frequency of its use would make the run very repetitive.