Square kernel, 200x200 pixel goodness!

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Square kernel, 200x200 pixel goodness!

Post by Jubatian »

So here it comes!

EDIT: Repository link: https://github.com/Jubatian/Uzebox-Square-Kernel

I am still on a phone, dunno when I will be able to get proper Internet access. So no GitHub yet, source for experimenting is just packed up and attached. Along with two demos. And well, a third too, the image viewer from earlier of course runs on this, too.

But what is this?

An entirely new kernel with a reasonably simple and straightforward C interface, no fuss, no kludges, it just does the job. It has a neat 200x200 square display, square pixels of course, so it is easy to pixel for. Wild SPI RAM driving all included, tucked away under the hood.

The sprites and tiles demo shows the basics of its tiled mode. It is 16 colours, you can have up to 85 RAM tiles for your sprites, which sprites are output from the SPI RAM. The background can have a full 256 tile set in ROM, the map (VRAM) is in SPI RAM. You can shrink and expand the view with the controller (up / down).

The bitmap operations demo shows how it can manipulate the SPI RAM bitmaps. It shows this on a 232x200 bitmap, but the routines also work on 200 pixels wide bitmaps. The oddities of the layout necessary for display is hidden.

Currently of course it is all experimental with little documentation (most of the callable functions are currently described in the kernel's assembly sources where they are defined).

It also has a 3 channel audio engine (neither inline, nor vsync mixer), the core is there, but currently it lacks a patch processor, so you can not get anything out of it yet. Later!

I just thought it would be nice to drop something in this still water here :)
Attachments
bitmap_ops_test.zip
Bitmap operations demo binary
(25.78 KiB) Downloaded 595 times
tiles_sprites_test.zip
Tiles and sprites demo binary
(28.63 KiB) Downloaded 573 times
square_kernel.tar.bz2
Square kernel source and examples
(485.35 KiB) Downloaded 576 times
Last edited by Jubatian on Thu Dec 13, 2018 11:38 pm, edited 1 time in total.
User avatar
L4rry
Posts: 242
Joined: Sun Dec 28, 2014 7:19 am
Location: Cape Town, South Africa

Re: Square kernel, 200x200 pixel goodness!

Post by L4rry »

Really cool :)

I like the RPG (tile and sprites) demo. So is this a 4 bpp encoding for the 16 colors with a fixed palette? I'm looking forward to working with a high sprite count, smooth 2 axis scrolling video mode. 8-bit Serious Sam anybody? :D

Right now for me it's a pile on at work with the holidays approaching with no space to breath. After that I can hopefully finish my networking mod for Tank Fu over the holidays. Then I would love to get my hands dirty with one of the newer video modes / kernels.

Definitely keeping an eye on this one.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by nicksen782 »

The demos are impressive!

I read through sq_kernel.s and sq_kernel.h. Seems like everything is covered!

I found this in the sq_kernel.h:
#define SQ_COLOR8(r, g, b) (((r >> 5) & 0x07U) | ((g >> 2) & 0x38U) | ((b) & 0xC0U))

I have a similar function in an app of mine:
var index = (B & 0xc0) + ((G >> 2) & 0x38) + (R >> 5);

You are adding the values and I'm ORing them. I also have a mask on the red to block out any non-red bits, which may be a little redundant.

I can also go backwards:
// * Get 24-bit rgb version of 1-byte rgb332.
rgb_decode332 : function(RGB332) {
// Accepts RGB332 byte and converts back to 24-bit RGB.
var nR = ((((RGB332 >> 0) & 7) * (255 / 7))); // red
var nG = ((((RGB332 >> 3) & 7) * (255 / 7))); // green
var nB = ((((RGB332 >> 5) & 6) * (255 / 7))); // blue

// Output all values as an object.
return { red: nR, green: nG, blue: nB };
}

I get a bit of a color change when using it though. It is very minor but it is there. What could improve my reverse function?

... Okay, back to the sq_kernel. Wow. Seeing that second demo with the overhead view doing the 8-way scrolling was awesome. How is this different from the existing SPIRAM VRAM mode? (My ASM is weak, sorry.)

I see the c-callable functions in sq_kernel.h. I am not sure how to use the public functions though. I did read through the demo code, I just don't think I understand the concepts. I'm seeing some arrays defined that are of size 4096. That is not possible with Uzebox since that is exactly the number of bytes of RAM available. So, does that data get written to SD or XRAM as binary? I usually refer to this as "C2BIN". I think d3thadd3r refers to it as something similar. (Just read the bytes direct to binary.)

Oh, how do you convert an image for display?

Is there support for changing colors/palette?

Very awesome!

I added the demos to the demos category.
IMGVIEW: https://www.nicksen782.net/UAM5/emu.php?gameid=266
TEST_SWIDE: https://www.nicksen782.net/UAM5/emu.php?gameid=267
TEST_TILES: https://www.nicksen782.net/UAM5/emu.php?gameid=268
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by Jubatian »

Huh, thank you both, sorry for not providing links, images or any formatting, using this phone is a pain even for the basics.

I really hope I can resolve some by the holidays, but it might happen that I will be without proper Internet (Right now some broken system wouldn't let me in my new bank account, and I am having rent and bills to pay and a bunch of money transferred onto it for that. Just great. I will have to ask for a couple of hours off of work again).

Larry: I hope I will get this a bit more mature by the holidays! Palettes are not fixed, you can do color tricks or fades by manipulating them (there are 2 palettes, one for the tile & sprites region, and one for the bitmap). You can also set up Color 0 replace on every scanline (FoaD sky), and by manipulating the rows, parallax scrolling can also be achieved.

Nicksen: the RGB conversion has a problem for blue. You have to shift it all the way down, and multiply by 255/3. Now you have blues 0, 2, 4 and 6, so multiplying this by 255/7 obviously won't get you the proper intensity ramp.

I mask red since the compiler will optimize it out anyway if the input was uint8_t. But that's a macro, it could receive different types, where it may break without it.

Which SPI RAM VRAM mode you refer to? It differs from all the existing ones. I believe what you may have (by Lee as far as I can recall) is one which just moved a regular Mode 3 VRAM into SPI RAM. 256 tiles split between RAM and ROM tiles, VRAM has to be restored before giving it back to the user.

This one is more similar to Mode 748. The SPI VRAM is independent, it is only read for sprite blitting, up to 256 ROM tiles. What's new is that this uses a list for RAM tiles which list is parsed on the fly by the video mode. I talked about the concept, but this is the first actual implementation. It costs only 3 RAM bytes per allocated RAM tile, same as the restore list of Mode3. Mode 748 needed an entire overlay VRAM (about 700 bytes).

The advantage is that this is fast and robust, you can not break the map. It is suitable for frame reset which this kernel uses (you have to set up a frame routine, which later gets called after every frame).

Anyway frame reset.

It isn't that hairy like Mode 74. Normally the reset is not permitted to happen, and the kernel will skip a frame (blank screen) if you fail to return from the frame routine on time (before next frame). This means if you want to load stuff from the SD card, or mess around with setting up a lot of data in SPI RAM, it will just work. But you can also tell the kernel to just go ahead, and cut off whatever you are doing when the next frame is due. The sprites & tiles demo shows this, SQ_VideoEnable() asks for this. And of course all the render functions are designed to support this without breaking anything.

There is also a neat feature for bitmaps: the scheduled operations. These are on the bottom of sq_kernel.h. Calling one of these schedules an appropriate bitmap operation to be completed in spare frame time. It is an easy way to build game menus and such, or to use the bitmap for low-priority status display.

The MAP functions I hope are understandable: they simply provide a high level map abstraction, allowing you to place sprites by map coordinates, all the clipping handled proper.

The memory management may feel a bit odd.

This kernel introduces generic pointers, the MEM functions exploit this. This means the kernel autodetects whether the pointer is RAM or ROM by its value, and automatically does the appropriate thing. It is possible by the linker script accompanying the kernel, which places code in the lower region, so all the data you might access is above 0x1100. A bit like if you had an ATtiny.

Hope this sheds some light on what is going on in there!

I also give you a small package of further images to check out, now these are not mine. Larry Elmore and a few others. In particular look up the game DragonStrike, and you may do some comparisons, what a fine-tunes quantizer can do.
Attachments
uimgview_dragons.zip
Here be dragons
(158.33 KiB) Downloaded 562 times
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by Jubatian »

Finally I have some internet, so I could start to sort some stuff out.

I added a repository link to the top:
https://github.com/Jubatian/Uzebox-Square-Kernel

If you want to convert some images for the bitmap mode, use this repo:
https://github.com/Jubatian/InsaniQuant/tree/uzebox

Use the provided shell script to build images like this:

Code: Select all

./iquant.sh image.png 16 image.dat 0 d
The input image must be exactly 232x200. The format actually doesn't matter as it will be processed by ImageMagick to feed into the quantizer. Of course if you want to do some coding, you could use other dimensions according to your needs (the image viewer demo will detect images by size).
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by nicksen782 »

New toys! I'm going go try to put together a slide show too!

Hey can streams have transparency? I'm thinking of some rolling clouds.
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by Jubatian »

nicksen782 wrote: Fri Dec 14, 2018 1:01 am New toys! I'm going go try to put together a slide show too!

Hey can streams have transparency? I'm thinking of some rolling clouds.
No transparency, sorry, it is already quite slow due to the SPI transactions, for transparent copies, an extra read-back stage would be required. I thought about it, but there just isn't a reasonable useful solution in this regard. The problem you will face after a transparent blit that for the next animation stage, you would have to restore the bg. and blit over it again. Since the operation is slow, you can't do it in one VBlank (at least not for anything moderately sized), so things will flicker.

The general solution for animations would be a keyframe + differential frames approach, that each new frame has the rectangular portions containing changes compared to the previous one.

For a drifting could over a horizontally uniform background, you could just copy a cloud image over and over again (it will both erase the previous and draw the new one, just have sufficient sky around the cloud on the copied image to cover up the previous), however you will still need some frames as copying is 8px boundary constrained. You may however also use Color0 replacement on the background to get a "rasterbar" sky (works even in 232x200 mode if you can spare the RAM for the 200 Color0 values for each scanline).

If you need transparency for an idea, and a 3 color source image is OK, there are also the 2bpp blit functions (direct or scheduled) which I mostly intended for text, but they are not 8px boundary constrained.
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by Jubatian »

Sorry for my absence, seems like it is just becoming the norm that as soon as I leave work for the end of year holiday, my body attempts to self-destruct. Ridiculous as it is, I am ordinarily healthy, often getting through the year at worst catching a cold sometime, however at Christmas it is bedtime for me. Like struggling to crawl even to the bathroom for a week. Exactly something I so much needed while still busy sorting out my relocation...

Anyway, little by little, I could get the audio engine of this thing mostly up and running by now.

Attached there is an example of it working, using all three channels, and also demonstrating something new on the Uzebox: True frequency sweep. That is a true logarithmic sweep as a sweep should be working. The frequency sweep can be used either within patches or started through functions (the two can not be used simultaneously on a channel since they would override each other).

This doesn't demonstrate Channel 2's Amplitude Modulation capability, but that works too. Tremolo is actually sort of an amplitude modulation already using a sine wave, however it is calculated only once in a frame (60Hz), and has a limited capability of selecting rates. Channel 2's AM is 3 KHz, capable to use any waveform, and may optionally use a rate relative to the playing note, so some complex effects can be constructed using it.

The patch format is identical to the normal Uzebox kernel, most of the commands are also there with the same function.

The kernel by default has a simple patch set, so just calling SQ_NoteOn() and SQ_NoteOff() on channels would already produce audio.

What this kernel doesn't have, and won't have is a music engine. Like with Mode 3 like sprite abstractions, I believe this part rather belongs to the user's domain, to create a music engine fitting the particular game and whatever source of music data the creator may devise or decide to use. For dealing with getting music and effects coexisting, a channel importance function (SQ_GetChannelImportance()) is also provided, which can return an importance value (in note volume) of whatever is currently playing on the channel. So again here it is left to the user to devise dynamic channel allocation schemes if he wished so.

In some regard this is a significant milestone: it is now proven that the kernel can actually do all that complex stuff which a kernel is meant to be doing.
Attachments
SQSprtst.uze
With some audio effects added
(32.5 KiB) Downloaded 556 times
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by nicksen782 »

This... is... GREAT! So exciting. It's like a whole new Uzebox in a way. Your other modes were awesome but it is clear that you are working on making an easy-to-use kernel and with all these great features.

I hear the audio sweep. That's neat. But it was multiple notes. What would be the difference between playing multiple notes and a music engine?
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Square kernel, 200x200 pixel goodness!

Post by Jubatian »

Thanks!
nicksen782 wrote: Sat Dec 29, 2018 7:41 pmWhat would be the difference between playing multiple notes and a music engine?
A Midi decoder for example :) In the current Uzebox kernel a Midi and a Mod player is integrated, so if you have Midi or Mod data, you are one step closer to have the music playing than with this kernel. Here you would have to add the Midi decoder on your own, pulling off the Midi stream from wherever you want (such as the SPI RAM). In this regard this new kernel can make even slightly more advanced things simpler: There are no mechanisms getting in the way of rolling your own music player, neither in figuring out methods for allocating the channels between music and effects.

By the way do any of you have ideas like how nice it would be to use this on an "unexpanded" (no SPI RAM) Uzebox?

Getting there actually wouldn't be too difficult, although it would demand some significant amount of work. Maybe it would also be possible to get 208 pixels width for the tiled mode, not much, but could make a difference (with SPI RAM this is not possible for a couple of reasons).
Post Reply