Hello, old friend, today you're going to teach me how to hook the keyboard interrupt again https://mastodon.social/media/q_jH0jjh9xYy3GlHgKs
I have successfully loaded tiles from a TIF file that I drew in NeoPaint, converted them internally into EGA planar format, and drawn them to the screen. https://mastodon.social/media/Yg3wSvnVGXp8Foz1Te4
Just implemented page flipping, as a prelude to maybe implementing smooth scrolling.
It’s pretty amazing how little code this is? Like once you have a grasp on how EGA memory is laid out and you’ve got Michael Abrash telling you which registers you can poke to do neat stuff, it’s not complicated? This shit DESTROYED me as a teenager though, I never got ANY of it working outside the basic mode 13h linear framebuffer
It’s really astonishing to me how different the experience of programming a 286 is compared to what I do at my job, how starkly the priorities are different
At my job, I make sure the code I write is flexible and correct. I build safeguards to ensure bad things will not happen when someone makes a change or grows the system
For this project, I put together a pile of purpose-built subroutines and macros, kept simple enough that I could delete and rewrite any of them a dozen different ways
Mouse support is trickier than I expected! It would be easy if I just polled the state every frame but I decided to try to install a callback. I think I need to set the DS register at the start of the callback in order to access my data - I’m scribbling over something important and the computer hangs. But how do I know the value I should set it to? Is it even possible to do this in the small memory model? Argh
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
Well, definitely that, but it also plays _very_ badly with my page flipping implementation - you can see it writing into video memory when I’m flipped to the second page! sooo I guess I’ll be drawing my own damn mouse cursor https://mastodon.social/media/QGLwPAjaEOSkSqTnnq4
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.
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.
Also thanks to @darius reminding me of its existence I now have Dangerous Dave in Copyright Infringement running on my 286, along with John Romero’s tilemap editor, and I’m kinda thinking it’d be fucking rad to use it to build my maps instead of slogging through writing my own
Implemented my tile-blitting speedup
Pro: it is indeed much faster
Con: don't quite have all the bugs worked out yet https://mastodon.social/media/LEqZ5yj7ynPKv3PK5YU
There we go! https://mastodon.social/media/qBbVrs6TDxIE04AhoUY
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’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
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
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
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)
(This is the Jorth ( jean forth) VM printing out the address of each C function being called while it’s executing its busy loop, btw. The idea was I’d make it crash and then do forensics on the last few numbers to figure out where it died. The last displayed number turned out to be 0, meaning I could easily check for null and set a real breakpoint in Turbo C++, and that’s how I caught the stack overflow.)
@SpindleyQ this looks incredible and I'm so glad I don't have to do this to debug anything
@hellojed my understanding is that a common setup was to have a second video card, using a different video standard so video memory didn’t overlap, to run your IDE / debugger on a second monitor
@SpindleyQ Holy shit! Is that an orange gas/plasma monochrome screen? on a laptop with mechanical keys?
Also I spent way too much time in Telix back in the day; would dial 4 or 5 BBSes a day. ... man I should get into telnet/ssh bbses ..
@SpindleyQ this is L337 as all get-out, good work
@jplebreton I could’ve just plugged it into my Raspberry Pi but it would’ve felt wrong
@SpindleyQ There is an compact flash to IDE adapter I'm sure is around here somewhere I used to use. I had a 4 MB card in it.
@AskChip yeah, I’m using one in my desktop 286, but that bios lets me enter custom geometry. The T3100 bios assumes you have one of the two hard disk configurations it shipped with, so finding a CF card that's an exact match would be... challenging. Plus I'd love to have more space if I can!
@SpindleyQ So 40 or 80 meg. This looks like it would work, as long as you formatted the drive in another machine: http://www.aetherwide.com/vignettes/20070530-1.html
@SpindleyQ You want XTIDE: https://code.google.com/archive/p/xtideuniversalbios/
You can burn that image and stick it in the socket of an ISA network card. Or you can buy this PCB and build your own ISA card to put it on: https://www.lo-tech.co.uk/product/8-bit-ide-adapter-pcb/
@SpindleyQ You also need an IDE->CF adapter and the appropriate CF card. You have to use a CF card that supports Fixed Disk mode. Anything on eBay sold as "industrial compact flash" should. Used to be that SanDisk cards could have the mode set with a DOS utility, but modern cards have removed support entirely and you have to pay SanDisk 2x for the industrial version now.
@ieure hmmmm... This is definitely what I want, but I'm working with an unusual form factor (Toshiba T3100e)... I know it's got an add-on modem in it, wonder if it's a standard ISA connector
@SpindleyQ Ooh, yeah. That's going to be challenging. Worst case, maybe you can use the CF card as the larger of the two built-in geometries.
@ieure Certainly no harm in trying, anyway. Thanks for the pointers!
@SpindleyQ Sure thing! Good luck, hope you work something out.
@ieure of a *network* card...? o.O
@ieure huh, i looked it up and kinda see how it works. that's... so bizarre!
@maple Yep. They're just the easiest way to do the thing.
@SpindleyQ Holy shit is that a Toshiba T3200?
@Sifuri_Ibex T3100e! Picked it up for $12 at a thrift store.
Is it mov destination, source?
If so, you assign s and o with uninitialized data;
Otherwise, the pop statement at the bottom overwrites the variables you just set.
@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.
@SpindleyQ Hrm, the GIF speed dropped quite a bit once uploaded and processed. Maybe it's better this way..
@rabbitboots oh my god, every detail of this is so dead on!
Rad as hell
@SpindleyQ a serial port is always the best solution - nice work!
Follow friends and discover new ones. Publish anything you want: links, pictures, text, video. This server is run by the main developers of the Mastodon project. Everyone is welcome as long as you follow our code of conduct!