Mode 14 - a new graphics mode coming

I got an idea while on my way to bed last night.

It appears full screen update of a 220x176 buffer @ 50 FPS is possible afterall.

Keep in mind this is not doing anything else but the graphics. But nevertheless, it really is refreshing from a 220x176 screenbuffer at 50 frames per second. Oscilloscope timebase is 5ms/div and there are 4 divs (every frame flips low / high)

5 Likes

This mode is special, because it creates 8 colors by masking. There is no palette. You have 8 fixed colors at 220x176 resolution.

The colors you can use are:

… which is actually the EGA palette minus the luminescence signal.

3 Likes

But could you do anything worthwhile with this mode and those horrible colors?

Hmmm…

and

… perhaps you could!

1 Like

Here’s a “Hello world!” binary you can try in this new mode

hello.bin (33.1 KB)

@Hanski : FPS counter is not showing the right value this is verified with oscilloscope to run 31,5 fps. The counter says 14 fps. Something is wrong.

1 Like

I like how the bits line up with the RGB components so it’s technically 1-bit per channel.

(Also magenta and cyan are underrated.)


If the colours are a bit limited, maybe you could have a multiplier to tweak what they map to (ussing an indexed global palette is off the table)?

(Then again, shifting and multiplying might be slower than fetching from memory.)

1 Like

That’s exactly what it is. Thats how the old EGA monitor cable worked, and where I got the idea from.

Maybe. I will need to test.

EDIT: the trick to optimizing on a device like this, is to keep the loop so simple, that everything fits in the registers. That is why accessing screenbuffer, palette buffer etc with indexes is not actually maybe the fastest way: registers need to be stored, and then recalled when you fetch data from different locations.

If you look at the assembly code generated per mask, its not half bad actually! Its about 15 cycles per pixel.

Mind you, I was able to crunch out about 10% speed increase from all modes while I was it :wink:

(1757)              *scptr++ = R_MASK * (t&0x1); t >>= 1;
00003C90	ands	r5, r0
00003C92	lsls	r5, r5, #11
00003C94	negs	r5, r5
00003C96	strh	r5, [r2, #2]
00003C98	asrs	r5, r1, #2
1 Like

I’ve come across enhanced graphics adaptor before, I’d just forgotten that it lined up so well with RGB. I guess I remember the second half better because all the colours followed a pattern except for the darker yellow which they somehow modified to brown.

I checked and they actually mapped the 1 bits to 0xAA for the darker colours, which is probably why the multiplication idea came to mind.

(Your adding this wouldn’t be related to Operation Wolf, would it? I remember a similar-looking game being mentioned here a while back.)


That is pretty small.

I was confused by the lsls negs combo, but I’m guessing that’s an optimised version of the multiplication.
(It’s equivalent to multiplying by -2, so I’m guessing R_MASK is equivalent to -2.)
I’m guessing t is signed by the fact asrs was generated instead of lsrs (I assume that’s what it would be called).
(Either that or it’s just a compiler anomaly.)

I think I’ll add brushing up on ARM ASM to my todo list.


Looking up EGA games, there’s quite a few decent ones.

Yes, looks like using bitshift (and unsigned variables?) instead of multiplication could save one instruction per mask.

I did not spot “t >>= 1” in the assembler as that is done for each mask too.

The result is saved to scptr (scanline buffer?) here already. I could be faster to save results of the rgb components to a register and only store the final rgb value to the scanline buffer.

1 Like

That is weird. I think I once verified the FPS counter by moving a bitmap one pixel at a time horizontally and measured with a clock the time it takes to go over the screen.

I am pretty sure of this. I used the EXT0 pin high/low every second frame. Then measured length of pulse on several timebases. Same result in the Mode 14 trial and Pixonia using the default 110x88x16 color mode

ok, I have to re-check the counter.

I think we could look at it together to figure out a best way to test it

Would the visual test do the job: Move a 10x10 bitmap one pixel right each frame, do that 100 times, measure the time, check if it matches to the FPS counter.

Of course, it might be difficult to see if some frames are skipped for some reason.

Or even harder to see if some frames are drawn twice to LCD without an application knowing it :wink:

But that is how we could start anyway. There could as well be just some stupid calculation error by me. One thing I could improve is to round the fps value correctly to the integer, but that is a minor thing.

I think we might do something more elegant and hook it up to the ticker interrupt / use the RTC to get it really accurate

@Hanski: please download the binary and see it for yourself. Its kind of nice!

you sure this is working correctly? the screen seems to display it in an almoust consistant 4to5 chunks
can i try out the code?

I will upload this on github tomorrow. Atm I am sleeping :wink:

2 Likes

That is so he mode is use if I could actually program a game. Or even an application.

Supercool!EGA is my fav pallete!
This is not mine but you can do lot of more!

3 Likes

i tried this out on hardware, it looks like dithering is a viable option if you want a specific tone

4 Likes