The thing that will kill me about working this way isn’t the memory limitations or x86 quirks, it’s that NeoPaint does not support cut/paste while zoomed in and I have to manipulate exact 16x16 pixel squares with an oversensitive trackball
Today I implemented tile walkability and looping sprite animations. Note that the guy can go places the car can’t.
It is spooky to me how quickly this has started coming together after two months of tech fiddling. It... paid off? I’m not used to this.
Implemented entities, and running scripts when the player bumps into them. I think I’ve officially written a game engine?? Like there’s a couple of nice things I still wanna add to it but I could stop and just focus on making a thing with this if I wanted. Holy shit.
Implementing a nicer / richer syntax for writing dialog and uhhh
Project has suddenly started immediately terminating on startup, like, before my code even runs??
It looks like maybe the 512-byte cache I just added somehow exceeded my 64kb RAM budget and Turbo C++ just doesn't tell you when you're over??
so remember when I was like “oh the source of all my startup performance problems is definitely byte-at-a-time unbuffered file reads”? https://mastodon.social/@SpindleyQ/101648207901180365
So I implemented a file cache and startup speed stayed pretty much the same. Turns out the problem is actually that tight Jorth loops over thousands of items are Not Fast :/
Hmm, interestingly the interpreter I defined in C is no faster at compiling all my Jorth code than my bootstrapped interpreter written in Jorth, which I guess makes sense given how little code it is
So it’s really the general VM overhead that’s killing me, and to solve that I’ve really only got two options:
* start rewriting the VM in assembly
* precompile code into an image that can be directly loaded into memory
Implemented image saving / loading! Startup time has gone from 27 seconds to, like, 3. When attempting to load game.jor it checks to see if game.jim exists and is newer than game.jor, and if so, loads it straight into RAM. If not, it compiles game.jor and then saves out the image to game.jim. Image loading has a basic sanity check to ensure it’s loading into RAM at the expected address.
Image loading works for the 90% case but occasionally there are side effects that I don't capture, so I rewrote load/save in jorth and added a post-load hook. Mostly works great, but loading a file in the post-load hook in order to make sure ITS hook is called seems to crash everything...
Argh, nope, image save/load works fine, I just wasn't putting quite enough code into the post-load hook, so side-effects necessary for the game to run without crashing weren't happening when loading from an image :P
For the record, Jorth source files have the extension .JOR, while precompiled image files have the extension .JIM (jean image)
Implemented traveling between areas! Each area unloads its code before loading the next, which should allow me to ensure that I don't run out of RAM to hold text. (I think I've got about 6kb left which _should_ be plenty, I hope...)
Definitely need to design a little helper DSL for defining reactions to the player bumping into areas without sprites, that code is already getting ugly...
Built my DSL - all my player collision code is much cleaner now.
Basically I have N things I need to check before I move the player - is it bumping into an object? Is the terrain walkable? Am I leaving the bounds of the map? - and if one of those questions is true, it needs to optionally perform an action and bail early on the rest. "else if" is not really a workable concept in Forth, so I needed to find another way to simplify this.
Turns out lightweight coroutines are a pretty elegant solution to this! I implemented basically the exact inverse of my each/more construct (which yields in a loop until the coroutine returns 0) - begin/search yields in a loop until the coroutine returns non-zero, then aborts it.
Yesterday was my birthday and my son made me little clay figures of my EGA sprites!
Oh no I have completely run out of fun tech to build and now I have to make maps and write and draw stuff. Haaaaaaalp
I’ve made some progress with this but I don’t wanna post a constant stream of screenshots of everything I map out because then y’all won’t have any surprises when you eventually play the game.
Hoping I get some useful / inspiring feedback when I take it to Dirty Rectangles next week because I am far from certain I have an interesting game in me right now
Found a fun tech project this evening: create a git repository with a reasonably complete commit history and back it up somewhere. So you can download and play my WIP game now (I kept the EXEs in the repo on purpose), peek at the source code, repurpose my unoptimized Forth implementation for your own ends, whatever. Why not.
https://bitbucket.org/SpindleyQ/pete286/src/master/
SpindleyQ / pete286
/ source /
— Bitbucket
Slowly realized that the speed of Jorth’s interpreter is likely bottlenecked by symbol lookup. Implemented an easy standard optimization I hadn’t bothered with (don’t do a string comparison if the lengths don’t match!) and suddenly cold startup goes from almost 30 seconds to 20 seconds.
Still glad I built precompiled image support but that’s a significant win
So my game loop was calling "tick" and "draw" by looking up the words in the dictionary every frame. Decided to cache the lookup; not as a serious optimization, just as a little cleanup.
Did I mention symbol lookup is by far the slowest thing in my Jorth interpreter? HOLY SHIT the game runs SO much smoother now. I couldn't believe it, I just started wandering around in-game, marvelling at how the animation wasn't stuttering, with a huge grin on my face.
PLUS, there was initially a bug where my C->Jorth code couldn't handle calling "tick" and "draw", and in trying to fix that, I realized I could get rid of a bunch of ugly special cases and substantially clean up my VM loop. All my core VM functions are now, like, 3 lines of code, I removed a bunch of overhead, and my code can correctly do MORE things than it could before. I finally feel like I have a real Forth implementation on my hands.
Added a shitty party system so Chuck the horse can follow Pete around. Not sure if it I want to improve it so they can move simultaneously, or just make Pete ride the horse.
Also this happens when Chuck follows Pete into his house, hmmmm
Added the ability to choose between conversational options / implement dialog trees. Hard to believe I’ve gone this long without it!
aaah I came up with a cool idea that fixes a bunch of story problems I was having. I wrote a _bunch_ of new stuff for the game today (in comparison to... literally any other time I've worked on the story)
might actually finish this thing someday after all
Remember when I started this project in December? Today is when I finally have access to a working serial mouse.
Out of all the retro hardware I have had to scavenge I did NOT expect a serial mouse to be this much work!
Previously:
* completely nonworking Dexxa mouse, in box
* brandless 3 button mouse, unrecognized by CuteMouse
* unusably flaky 3 button Genius mouse (button would click randomly while moving)
* Microsoft EasyBall trackball, which, while ridiculous, worked, except no right mouse button
* 3-button QuickShot trackball, sticky when moving left iirc
* 2-button Logitech trackball. My sole usable pointing device until today.
Been slowly poking at writing an EGA sprite / tile editor. Started writing it in Jorth using my existing graphics engine but that got complicated way too fast (partly just because EGA is complicated!) so I’m writing specialized graphics code in C again and it’s Good. Jorth still drives the high level logic because why not, that way I get a REPL.
"Hey Jeremy why are you writing your own sprite editor" I mean, besides the obvious "building everything myself the hard way" reason, see this toot from February? https://mastodon.social/@SpindleyQ/101661425411468111
I realized that I was trying fruitlessly to design the finished game without drawing any more tiles or sprites because my NeoPaint workflow was so miserable. And that's ridiculous because I enjoy drawing _way_ more than writing and there were a bunch of elements I wanted to put in that I haven't drawn yet!
like honestly the thing that will get me to actually finish this game is just reminding myself that drawing is fun and that I really want to put a curling club into a videogame because I have never seen it done
Sprite editor is shaping up nicely. Control logic fits in a screenful of Jorth code but already I can test animations by swapping back and forth between sprites quickly. Now I know I have a walk cycle I gotta fix but it doesn't save sprites yet. Soon!
Saving and loading wooooorks
My sprites are now stored only in my custom format (which is just a straight memory dump) instead of TIF, and I don't have any code to SAVE TIF files, so, goodbye forever NeoPaint I guess, I hope I don't need flood fill and that I never irreversibly corrupt my sprite file
Embedded the sprite editor into the game and suddenly I want to make shit look better because I can just hit tab and edit things! Like there's a dark gray bit on the car that's supposed to be a license plate or a grill but it's the same colour as the road. I can just... fix that!
It doesn't exactly leave graphics memory in a pristine state but whatever, I can fix that if it bugs me
Tried to add a sprite preview, and that bit works pretty well, but uh there may be some hardware state I'm not properly resetting
Adding background tile editing to my in-game sprite editor and man EGA graphics engine glitches are FUN
(Video: a mouse cursor acts as a flashlight illuminating a square of correctly rendered tiles while most of the rest of the screen is either black or random tiled garbage, in the vague shape of the starting map)
Cause: was passing far pointer to a function that took a near pointer. Even though this could literally never work, in Turbo C this triggers a warning, not an error
I made a boat
It’s a good boat
I also added a bunch of features to my in-game sprite editor to make making the boat go more smoothly
Like, copy/paste of tiles & sprites, horizontal flip, nudge up/down
It’s SO much nicer than NeoPaint now
I really like turning off noclip and driving my boat through the forest, I may put that into the game somehow
Felt like drawing EGA pixel skeletons pushing curling brooms today so I guess that’s going into my game somehow