nathanielbabiak 2021-09-30 05:48 (Edited)
I'm super excited to share this one - it's the first level from 1992's Wolfenstein 3D! There's so much more to do!
(Btw, this doesn't use my Pxl Library.)
Right now, there's no "finish" to the maze. The "objective" is just to find the switch. (You can't press it yet.) The tile map contains all the secrets from the original game (but you can't press the hidden panels either yet).
Textures have been added because this version's so much faster than my old version. Here's some of the speed improvements that make it possible:
It uses an entirely different display system of fixed 2x1 pixel blocks (they can't be drawn 1x1, or at any larger size either, it's the only block size possible with this system, where as the old version could customize the resolution arbitrarily).
I've learned a bunch about FP32 and can guarantee there won't be any div-by-zero errors in the code, so a bunch of error checking code is omitted for speed. For example, in some locations I've used 31.999 rather than 32, or I'll divide by a variable that ranges from -1 to 1 continuously, but won't ever hit 0 exactly due to fixed-precision arithmetic.
I've been meticulous about abusing the LowRes NX clock cycles. Both
/ (division) and
RESTORE are just a single clock cycle each (including the restored label)
All in, it's actually a bit faster than my old version even with the textures included. This runs around 18 FPS, where-as the old version ran around 13. (The FPS counter on the old one was deceptive, as the main loop would run 26 FPS but only one half of the screen was being updated each frame, so it was only 13 FPS effectively. This version updates the whole screen, so it's truly the framerate shown.)
qwaffe 2021-09-30 05:54
i did not know this was possible
nathanielbabiak 2021-09-30 06:22
Me too! But once the thought for how to do the display system popped into my head, it just kind'a clicked together.
Timo 2021-09-30 07:53
No idea neither :O
I’ll have to check the code to find the magic…
nathanielbabiak 2021-09-30 12:27 (Edited)
There's a section in
SUB D_INIT with a bunch of nested for-loops that go from 0 to 3. After those loops, insert
SAVE 2, "MAIN CHARACTERS", $8000, $1000 and you'll get a visual of the scheme I've described here in my first long reply.
The raster interrupt is similar to the popular "microtext" interrupt, except I've spaced it out to 4x2 pixels per cell, rather than 4x6 as microtext does, and I've mirrored it top-bottom.
rilden 2021-09-30 14:47 (Edited)
This scheme fits so nicely in LowRes NX's specifications:
With this scheme you only need to modify the bg scroll offsets in the raster interrupt to get a full screen image.
CubicleHead 2021-09-30 14:50
I am never in my life going to understand how on earth you did this
rilden 2021-09-30 15:14 (Edited)
@CubicleHead you should check out micro text. It explains how to display 4x6 pixel cells. The difference in this demo is that the cells are 4x2 pixels.
Making a 3d maze is of course more complicated, but you can also break it down into simple steps that you can understand separately.
rilden 2021-09-30 17:01 (Edited)
@nathanielbabiak did you write the CC subroutine to check the cycle cost of your code? I also wrote a cycle counter, you can check it out here: (https://lowresnx.inutilis.com/topic.php?id=1374). To measure the cycle cost replace a=5 with your code in the test subroutine.
SP4CEBAR 2021-09-30 17:09
This is awesome!
SP4CEBAR 2021-09-30 17:12
Also, I may have clipped trough a wall or something, it says that the line with
"CELL D_CX, CY, CH + D_TXY012CH( TEX0, TX0, TY0) + D_TXY112CH( TEX1, TX1, TY1 )" went out of bounds
Diamondwolf3393 2021-09-30 20:24
Wow, this is amazing! I love the textured walls.
nathanielbabiak 2021-09-30 22:37 (Edited)
@rilden - You appreciate the same thing I do - this scheme fits in perfectly with the LowRes NX specifications!
Also, you may not have tested your cycle counter in this way, but it sometimes produces different results for instructions occurring inside raster interrupts vs those same instructions occurring outside raster interrupts. (There could be some aspect of the way the fantasy console works that clock cycle counting doesn't always match in both spaces, I think it's "fuzzy".) I really just wrote the CC routine to provide a comparison between multiple code options, since I'm not sure what makes the clock cycle count "fuzzy" in the first place, I figured looping many-many times might be a better approach.
@SP4CEBAR - yeah that issue is commented on line 3 of the code. It happens, but it won't in the final version, once all other features are finalized. For now, just don't hang out in doorways too much.
rilden 2021-10-01 08:35
Can you provide an example of code that produces different cycle counts inside a raster interrupt? I noticed that an empty sub consumes 1 cycle in the raster interrupt, so if you have code that consumes x cycles, it will consume (x+1)*128 cycles when put inside a raster interrupt.
Nicky 2021-10-01 13:56
G-9 2021-10-01 14:12
nathanielbabiak 2021-10-02 19:39 (Edited)
@ridlen, nope, you're correct. I can't reproduce the "bug" that I thought I found in the fantasy console last year. Disregard the
strikethroughs above, my mistake.
(From memory I don't recall the specific instruction, unfortunately, but it wasn't off-by-one, it was off by 3 to 5 clock cycles, and the count was different depending if the instruction executed in main code, in VBL, or in RASTER. I do recall investigating and concluding your code wasn't the culprit, but until I've got an example, there's not really much more I can do that'd be productive.)
Timo 2021-10-03 07:34
Cpu cycles CAN be fuzzy I think. Each command line can be calculated exactly, but the interpreter cannot separate the execution of a line between VBLs. So some VBLs may use too many cycles, but then the next VBL has a lower limit to compensate.
nathanielbabiak 2021-10-07 00:05
Timo, the more I think about your response the more it makes sense - thank you!
nathanielbabiak 2021-10-16 01:02
I'm featured! I'm mulling the idea of omitting the horizon mirroring and just using 2x2 "bloxels" rather than the 2x1 currently (among other improvements)... What do y'all think?
Timo 2021-10-16 07:18
I think mirroring is a cool trick. Depends on the textures if it's worth to go down to 2x2.
nathanielbabiak 2021-10-17 00:31 (Edited)
Mirroring is such a cool trick! But, I've got enough clock cycles remaining that I can import the SS soldiers from the original game... they're going to look pretty funny with two heads/shoulders mirrored over the horizon.
And thank you all for the Likes!
G-9 2021-10-17 07:16
You deserve them :3
TrashCan Games 2022-04-25 13:12
This is so cool.
nathanielbabiak 2022-04-25 18:32 (Edited)
Thanks! I'm actually working on an update. This version uses all 256 characters in a pretty convoluted way - I reduced the resolution in my latest version to use only 64, enough that I can include billboard sprites and 3D polys. I've got the doors and the secret panels working too, based on the code from my other ray casting demo. In that demo you can press B to toggle all the doors/panels in the level.