Keen Game Engine (for lack of a better name): VGA Keen DEMO

Here is where to post about the latest Commander Keen fangame or modification you've finished, a new website you've made, or another Keen-related creation.
gerstrong
Vorticon Elite
Posts: 1244
Joined: Wed Dec 31, 2008 14:44
Location: Frankfurt - Germany
Contact:

Post by gerstrong »

kvee wrote:
Levellass wrote:Well darn. There's something I could have used a few years ago. That's some nice coding right there.
Hey, thanks! :]
Well the C version is infinitely better, the way I deal with timing here is kinda funny. And there should be a delay between OPL2 writes, as the datasheet says.

(also btw, when deleting the visuals, I've managed to remove

Code: Select all

GOSUB BACKUPTIMER
you should call it right after

Code: Select all

SPEED = 1193182 / 560
...sorry about that)
C++ Code:

http://github.com/gerstrong/Commander-G ... /IMFPlayer

With a bit of OPL 2 and 3 emulation used in CG.
Having fun developing stuff...
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

kvee wrote: (also btw, when deleting the visuals, I've managed to remove

Code: Select all

GOSUB BACKUPTIMER
you should call it right after

Code: Select all

SPEED = 1193182 / 560
...sorry about that)
No problem! I was wondering what that sub was. Didn't affect performance though, as far as I can tell.

I'm having the worst time trying to get this thing timed properly. At the normal 560Hz timer setting, when I run the main loop code every time the game loop rolls around, the music is very slow and jittery (kind of what I expected). But when I move that code to the main module and try to use event-trapping statements to run it as fast as possible, it sounds the same.

Running that main loop code as fast as possible is apparently what happens inside your FOR-NEXT loop in the original program - is that correct?

I'm guessing my problem is just not understanding exactly what happens inside that main loop. You say it has to read from the IMF file every 1/560th of a second? Then what about the delays, during which it's not reading? I'm kind of confused... :confused

I can post a link to the latest code if you need it to tell me what's wrong. In the meantime I'll keep working on it, maybe I'll have an epiphany today 8)
I flermmed the plootash just like you asked.
User avatar
kvee
Vortininja
Posts: 67
Joined: Sat Sep 26, 2015 11:17
Contact:

Post by kvee »

keenmaster486 wrote:No problem! I was wondering what that sub was. Didn't affect performance though, as far as I can tell.
Well the program changes the frequency of one of PC's timers, which happens to be the one that is also used for date/time, so I backup / restore the proper time after I'm done playing
keenmaster486 wrote:I'm having the worst time trying to get this thing timed properly. At the normal 560Hz timer setting, when I run the main loop code every time the game loop rolls around, the music is very slow and jittery (kind of what I expected). But when I move that code to the main module and try to use event-trapping statements to run it as fast as possible, it sounds the same.

Running that main loop code as fast as possible is apparently what happens inside your FOR-NEXT loop in the original program - is that correct?
TBH I don't remember how this worked exactly either, but I'm sure I monitor the timer value and wait for it to change just as much as is necessary (and whenever I encounter a delay in IMF, I just increase the time that must pass before reading the next command).

The main loop IS a busy loop, but it still just checks the timer value and waits for it to change.
User avatar
kvee
Vortininja
Posts: 67
Joined: Sat Sep 26, 2015 11:17
Contact:

Post by kvee »

To clarify, the PEEK(&H46D) and PEEK(&H46C) commands are crucial to how this all works, as they read the timer value that changes automatically (out of QBasic's scope).

(The actual reason is because these are incremented by the PC's timer hardware / BIOS interrupt, just to be exact.)
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

OK, here's an update:
Yesterday afternoon, after my last post, I went back and tried again, and managed to get the music *sort of* working by doing the following:

1. Increasing the speed of the timer by a factor of x (from the default 560Hz)
2. In READTIMER, dividing by x to compensate for the increased timer speed
3. Using ON TIMER(1) to run the main imfplay loop code, thereby approximating a busy loop. (this works because we've increased the timer speed to something like 20000 Hz)
4. Having a "loop-around" variable for PEEK(&H46D) since every time that loops over from 255 to 0 the player hangs, so we have a "false" variable that continues past 255 at the same speed. Kind of dorky but it works.

I also added a sub called "IMFLOOP" which reloads the file, resets some variables, and effectively loops the music.

It works pretty well, there is noticeable jitter, but when x is made at least 20 it sounds not too bad.

It does slow down the program noticeably however (not a problem yet since it can still do 25 fps) but it sure seems like there ought to be a better way to do this. Any thoughts?
I flermmed the plootash just like you asked.
User avatar
kvee
Vortininja
Posts: 67
Joined: Sat Sep 26, 2015 11:17
Contact:

Post by kvee »

You could always try doing it the async way: don't have a tightly timed loop, instead whenever you call some subroutine that would handle IMF playback, just look at how much time has passed and process all IMF events up to that time. I have no idea how well that would work, but it might be way better for an engine that cannot afford to waste all the CPU time on music (which was never a concern for imfplay really).

Another idea (a variation of the first one) is to leverage the 70Hz VGA vblank (you might be using it already?) which works out nicely, since it's a nice 1/8 of 560 Hz. Process all the IMF delays as they are, then make one iteration count for 8 ticks.

I don't know how they implemented the playback routine in original Keens, but I'd guess it was using a low-level timer interrupt that just advanced some pointer, looked at the current remaining delay and wrote to OPL2 if needed. If you wanted something like this with all the performance benefits, you could always go with a TSR, but that's all sorts of complicated + you've got an extra binary to take care of.

Well that's just some ideas that came to mind.
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

Alright, it's time for another update, this time a big one!

I've added and/or changed the following things:

1. Implemented kvee's IMFPLAY code (thanks, kvee!) to the best of my ability, although the timing's still a little weird! Annoying but that's the way it is for now. I have managed to reconcile the music timing with the main game loop timing though. They *should* be independent of each other, up to a point.
2. Cleaned up the code big time, making everything more efficient and faster in the process. It now runs at the required 24fps at 30000 DOSBox cycles, or about a 486DX2/66. Before it ran at about 10fps at 20000 cycles, so that's an improvement.
3. Made the loading process MUCH faster; now it takes about a half a second to load as opposed to taking 20-30 seconds before. Much better.
4. Reworked the physics somewhat. Now it looks and feels much more like actual Keen.
5. Now it loads ALL the sprites from Keen 4, and not just the player ones. This is for future use, as I haven't implemented enemies yet.
6. Added more debug info in debug mode and added an actual error handling routine.

A great way to tell if you're running it at full capacity is if you press F10+D, this opens the debug information and tells you your current maximum frames per second in the middle of the screen. That number should be about 30 or above when Keen's not moving, since it dips significantly when the screen scrolls.

Note that the engine throttles the fps at 24, so things might look a little choppy compared to actual Keen. If I make the engine fast enough in the future, I might make the movement smoother and increase the framerate, but it works for now. It's much better than it was though.

It also has rudimentary slopes, but they really don't work at all and I'm banging my head against the wall trying to figure out how Keen originally did it. Anyone have some help for me there?

Here's the download link: https://drive.google.com/open?id=0Bwrva ... DlDQ0poWGs

Edit: Here's a demo video: https://youtu.be/_eqRrTDYkfA
I flermmed the plootash just like you asked.
User avatar
kvee
Vortininja
Posts: 67
Joined: Sat Sep 26, 2015 11:17
Contact:

Post by kvee »

Wow, impressive! It's confuse-able with the original at this point, I'd say.
Keening_Product
Kuliwho?
Posts: 2167
Joined: Fri Jan 20, 2012 7:02
Location: Tied up in the Oracle Chamber's basement
Contact:

Post by Keening_Product »

Agreed. I've only had a chance to watch the video but the physics -look- about right.
Keening_Product was defeated before the game.

"Wise words. One day I may even understand what they mean." - Levellass
User avatar
Roobar
Vorticon Elite
Posts: 3267
Joined: Tue Jan 08, 2008 16:12
Contact:

Post by Roobar »

It's an improvement alright, but it's not confuse-able with the original. I can spot it right away.
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

I'd say the video of this is confuseable with a video of the original :p

But can anyone elucidate for me on how the Galaxy engine does sloped tiles?
I flermmed the plootash just like you asked.
Keening_Product
Kuliwho?
Posts: 2167
Joined: Fri Jan 20, 2012 7:02
Location: Tied up in the Oracle Chamber's basement
Contact:

Post by Keening_Product »

It's pretty easy to understand keenmaster, you just have to think about it from a different angle.
Keening_Product was defeated before the game.

"Wise words. One day I may even understand what they mean." - Levellass
User avatar
Levellass
S-Triazine
Posts: 5265
Joined: Tue Sep 23, 2008 6:40

Post by Levellass »

Ugh, it's terrible. You notice Keen walks *down* them faster and *up* them slower? And that steeper slopes slow him more? There's the whole 'stick to ground' parameter too. Bleargh.
What you really need, not what you think you ought to want.
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

OK, I whipped up a version of IMFPLAY that supports DRO (version 1 only) files. Since it only supports version 1.0 (or 0.1) files, you would have to use an old version of DOSBox (e.g. 0.72) for recording, or you can use the latest version and convert the files to v1 with DROTrimmer. I only supported version 1 since it was much easier to implement (I didn't want to have to deal with codetables :dead )

It completely ignores the header since we're 100% sure we're feeding it only DRO v1 files, goes straight to the data and starts playing.

It should work with pretty much any DRO v1 file, including those with stereo OPL3 stuff!

Here it is, along with a bunch of demo DRO files for testing and ADPLAY and IMFPLAY 2.1 for comparison (those only support OPL2, so they drop notes on some songs): https://drive.google.com/open?id=0Bwrva ... UxHQ2hYZGM

It's called IMFPLAY2.BAS/EXE in that folder.

Edit: Please, please tell me if you find any bugs; some files are played incorrectly (sometimes unless the OPL3 chip is initialized first by ADPLAY or IMFPLAY 2.1) and I can't figure out why!
I flermmed the plootash just like you asked.
User avatar
keenmaster486
Vorticon Elite
Posts: 542
Joined: Sun Mar 20, 2016 18:29
Location: Tranquility Base
Contact:

Post by keenmaster486 »

Another update: Version Alpha 0.17, which may be the last version for a while as I am headed to college and won't have much time for this sort of thing.

Right now it's easier to list the features that aren't implemented than to list those that are:

Features left to implement:
-World map
-Enemies (sprites are all there, just have to do behaviors)
-Elevators
-Gates
-misc stuff like conveyor belts, checkpoints, etc.

Everything else is there, buggy as it may be. You can turn the scorebox on or off in the configure menu, as it may slow things down a bit.

Once again, be sure to crank DOSBox to at least 40000 cycles to make it work right.

Download link: https://drive.google.com/open?id=0Bwrva ... WpkZGpBbXM

Another demo video (with terrible compression artifacts, argh): http://youtu.be/bVpLcyYYAPI

Well, it may be a while before I post another update, but I definitely want to finish this and make it as good as I can.

Happy Keening, everyone!
I flermmed the plootash just like you asked.
Post Reply