Got it! I looked at the generated ASM and figured out that DS was being ASSUMEd to a symbol called “DGROUP”; so I just explicitly set DS to that at the start of the callback and no more crashy!
I am definitely doing something to confuse CuteMouse’s cursor-drawing routine though... probably it assumes I have writing to all four planes enabled https://mastodon.social/media/uax66anGIreYRARWjGs
I’ve been pondering scrolling for a few days, and whether I could figure out how to write a huge smooth-scrolling playfield or whether I’d just flip from one screen to the next. This evening it occurred to me that surely at some point the Commander Keen source code must’ve been released and I could just see how they handled scrolling. And indeed Keen Dreams is GPLed! https://github.com/keendreams/keen
Hmmmm this is... a little overwhelming. Lots of extra stuff that makes me wonder if I’m missing something important. Gotta keep in mind that it’s an entire game, after many rounds of optimization, instead of a week’s worth of occasional hacking, and my slower, dumber code can still lead to an outcome I’m happy with.
Ok, here’s what I definitely do understand:
Keen has two “pages” of video memory that it flips between. Each page represents an image slightly larger than the screen that it can smoothly pan around in. We’re talking, like, 16 pixels wider.
Keen keeps track of which 16x16 tiles are dirty via a dirt-simple byte array where they mark each tile position 1 or 0 - because only 21x15 tiles are onscreen, this only costs a few hundred bytes and is a huge optimization. I’ll probably steal this idea. (Extremely common retroprogramming pattern that has basically disappeared from modern computing: knowing there are, at most, N of something, where N is small.)
The tiles are redrawn by copying from what the code refers to as the “master screen”, which is an area of video memory after the two pages.
I don’t know how this memory is structured, but I don’t really need to - because of the page sizes, I know that a full redraw into a page MUST happen regularly without slowing everything down. So as long as the tiles live in video memory and I have a reasonably efficient copy loop I should be fine.
This morning an old Michael Abrash article taught me exactly how to trivially speed up my current tile drawing routine 4x by caching tiles in video memory so this makes sense to me.
I really wanted to play with the split screen register, so now there's a static footer and I can scroll around the map with the arrow keys. Scrolling is a bit slower 'cause I have an actual map in RAM now. Name is absolutely not final.
Trying to figure out how to efficiently draw semitransparent sprites in EGA. It is... not as simple as I thought. Reading the Graphics Programming Black Book chapters about fast animation and some of the methods he's describing are absurd - chapter 43 is like "if you don't mind having every sprite be 1 colour and only using 5 colours total, here's a neat trick" and no actually I do mind those constraints, that's not helpful advice
I'll probably have a quick look at the Keen Dreams source again and then just build something slow and naive
Came up with my own strategy for sprite drawing; so far it seems to be going pretty swell
Very important to document these glitches before I fix them IMO. I've almost got the sprites drawing in the right place, though they're not even close to the right data. I replaced the background tiles with the car sprites I drew just to make sure my TIF loader was reading them OK.
Hey, I can see a mangled version of my car sprite! And it moves around smoothly!
I have unmangled my car sprite! Now to figure out why only the grass tile is being used as a background, and also wtf is going on with my pixel mask, jeez
Coding in C for the 286 is kind of like coding in a dynamic scripting language except the only data types are "array of bytes" and "little-endian words"
Like these bytes have structure but it's probably more trouble than it's worth to try to explain to the type system what it looks like
It's fun when figuring out a problem with something then uncovers exciting new problems with that thing
Aaaand it finally works as designed!
Implemented smooth horizontal scrolling, which in EGA makes the footer jitter. There’s a VGA-only fix but I think I’ll switch course a little and scroll the footer onscreen at times where the player can’t move. Of course getting rid of the footer ended up exposing a new delightful glitch
Starting to factor out the game loop; added the ability to pop-up the footer by tapping the space bar, which pauses normal game logic.
Nothing visually new today, just a bunch of overdue code cleanup. Everything used to be in one giant C file but now there's proper modules and header files. Fun Turbo C++ tip: to create a new multifile project, select "Open Project" and type in the name of a file that doesn't exist
I almost set up a Twitch stream but was having trouble with my headset making me sound like a weird glitchy robot for some reason
I’ve been frustrated at how difficult it is to log stuff for debugging when your only video card is currently in use, so I grabbed a null modem cable, connected my *other* 286, a Toshiba T3100e with a very dead hard drive but a working boot floppy, and wrote a dumb serial port byte-banging routine
BTW if anyone has experience tricking old BIOSes that only know two possible hard disk geometries into booting from a big compact flash card, hit me up
Time to join my two retrodev threads: Jorth ( jean forth) now runs in-game over my serial port!
Michael Abrash: Here’s how you reprogram the PC’s timer, but be warned! It will fuck with your system clock until it reboots! Here’s exactly what happens for this particular application and why
André LaMothe: yolo just chain your ISRs and shit will probably work out? Don’t worry about it, paste the code in, I don’t have time to explain and you don’t care. Also let’s just run all of your game logic in the timer interrupt handler, this is how multitasking works, what could go wrong
I mean, LaMothe was _absolutely right_ when I was a kid reading Teach Yourself Game Programming in 21 Days, I didn’t care and I would not have understood. And he explained the concepts well enough that they were accessible to me when the time came to learn them for real.
Finally hit a bug where my computer doesn’t hang but it DOES corrupt the system state enough that when it crashes, subsequent runs stop working quite right and only a reboot clears it up
So, that’s fun
*hacker voice* I’m in
Oof! Got it. Two bugs conspired to cause a stack overflow:
* if a task was set to have its output ignored, it was leaving each character on the parameter stack. So the silent loading of the base definitions would leave a bunch of junk on the stack if there was any output. Usually there isn’t, so I didn’t notice.
* I added a definition that contained a comment before I defined the word that interprets comments, so the interpreter dumped a bunch of errors on the stack trying to figure THAT out
The tricky stuff I was messing with last night when I started noticing crashes - multitasking and compiler improvements - that was all totally fine. I just forgot a DROP in some I/O code last week.
went to implement simple text drawing yesterday but ended up writing Jorth code to do animation lerps
managed to successfully write a word that takes five parameters on the stack, so I assume I'll be receiving some sort of Forth Programmer Certificate of Achievement in the mail soon
(Jorth still has no words that can touch anything on the stack beyond the top three values)
Tried to implement text drawing but something is fucked and it only draws garbage
It _should_ be a very simple BIOS call to fetch a pointer to the built-in 8x8 EGA font and just use it, I’m clearly missing something fundamental
had the idea to peek at the DOSBox source to verify the BIOS call works like I expect and, yup, it's very not complicated :/
@rick_777 dst, src: yes. s and o were debugging helpers to try to verify that the registers were changing after the int statement, and that the C variables being updated by the assembly. Answer: s and o got overwritten with the pre-call values as expected, but the other two C variables never got touched.
I posted a reply with the eventual solution, if you’re curious.
Cybrespace is an instance of Mastodon, a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.