Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Viewport/Camera #69

Open
mupfdev opened this issue Feb 7, 2025 · 3 comments
Open

[Feature] Viewport/Camera #69

mupfdev opened this issue Feb 7, 2025 · 3 comments

Comments

@mupfdev
Copy link

mupfdev commented Feb 7, 2025

Hey,
I'm would love to port omnispeak to a rather obscure platform. However, because of the quite unusual aspect ratio and resolution (11:13, 176x208), I would love to have a viewport/camera around the Keen character. I haven't gone deep into the source code yet, so does the engine support this? If not, how much work is required for such a feature?

@sulix
Copy link
Owner

sulix commented Feb 8, 2025

Hi,

(I'm guessing the platform is the N-Gage, judging from all the notifications with a similar name I've been getting for the SDL repository. :-) )

Unfortunately, Keen and therefore Omnispeak have hardcoded the 320×200 resolution pretty much everywhere, so supporting a different resolution wouldn't be an easy task. In addition, if the camera behaviour changes, all of the pre-recorded demos will go out-of-sync.

I do hope to eventually get around to supporting other resolutions myself (largely to support other aspect ratios as in #36), but it will require quite a lot of work.

My rough strategy would be:

  • The display backends (in id_vl_*.c) currently accept a VGA screen mode (and only support 0x0D: 320×200). This needs updating to just take width and height.
  • All of the fullscreen / menu graphics are 320×200 (or have hardcoded coordinates based on this resolution): maybe supporting a change of resolution between the menus and the game (which has fewer hardcoded things) would be a good first step.
  • The game actually renders to a backbuffer bigger than the screen, and scrolls a window within that. You might get away with having the same window.
  • The actual tilemap / sprite rendering code lives in id_rf.c: that's where the buffer sizes are defined.
  • The camera lives in ck_play.c — there are two cameras, one for the world map (and the Keen 4 underwater 'Well of Wishes' level), and one for all other in-level gameplay.
  • A number of the variables which affect game behaviour live in the EPISODE.CKx data file: off the top of my head, none of these are particularly camera related, save for the 'active object limits', which are probably more of a problem if you want to make the resolution larger, rather than smaller.

In short, doing this "properly" will probably require a fair bit of reworking of some of the graphics code. But you might get away by just hacking a different display resolution in and adjusting the camera code (or, better still, adding a second 'offset camera' in to avoid the sync difficulties).

That being said, there's already an (admittedly a bit less accurate) clone of Commander Keen for the GBA, which has a smaller screen resolution. Alas, it doesn't have an SDL backend, but it might be another interesting project to try:
https://github.com/john314thegeekygenius/CKGBA

Let me know if you make any progress or have any more questions. And I do intend to make some changes to the display code which might make supporting other display resolutions easier in the future, so I'll let you know when that happens.

Cheers,
— David

@mupfdev
Copy link
Author

mupfdev commented Feb 8, 2025

Thank you for taking the time to answer my question so thoroughly. That helps me a lot.

The game actually renders to a backbuffer bigger than the screen, and scrolls a window within that. You might get away with having the same window.

This is the most promising lead. I'll start by looking into this. :)

@sulix
Copy link
Owner

sulix commented Feb 10, 2025

I dug a little further into this, and it's probably not quite as bad as I thought.

The final display resolution lives in id_vl_private.h, as VL_EGAVGA_GFX_WIDTH and VL_EGAVGA_GFX_HEIGHT: not that this doesn't include the blue 'overscan border', which you may wish to disable in options.

The camera code live in ck_play.c, and you'll need to modify CK_CentreCamera(), CK_MapCamera() and CK_NormalCamera(), though note that:

  • This will break synchronisation with the original game demos, as enemies behave differently offscreen.
  • This won't affect the limits of scrolling, which are handled in id_rf below. So expect Keen to still be offscreen at the edge of the levels, for instance.

The actual rendering code lives in id_rf.h and id_rf.c. This takes its own view of the size of the rendered screen, which is measured in tiles (each being 16px×16px), and declared as RF_SCREEN_WIDTH_TILES and RF_SCREEN_HEIGHT_TILES.

  • However, Keen renders to a larger backbuffer than is visible, so you'll also need to update RF_BUFFER_WIDTH_TILES and RF_BUFFER_HEIGHT_TILES to each be one more than the screen width/height. Otherwise, the game can try to render invalid tiles offscreen, and crash.
  • This is partly because the ID_RF values are used to handle scroll limits.
  • Note that other things may rely on the buffer size: for instance, much of the UI code, which has lots of hardcoded coordinates, will try to render to this buffer. I've not seen any issues myself yet (other than the UI being cut off), but I wouldn't be surprised if this could crash somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants