Closed tyama501 closed 1 year ago
Hello @ghaerr ,
I have done the first entry in my to-do list on https://github.com/jbruchon/elks/issues/1312#issuecomment-1152870664 and now I have been working the second one.
I modified bioshd as follows, finally I quit using CONFIG_BLK_DEV_BFD_HARD.
https://github.com/tyama501/elks/compare/53171a5...f246f55
Detecting 2 FD drives.
Mounting 1440/1232 at same time still have some trouble. I added swich_drive98() and successfully probe floppy and switch device address and sector_size but FAT says 616k and cannot see files. How should I fix this?
Using FD1440 image and mount 1440/1232.
Thank you.
Hello @tyama501,
I modified bioshd as follows, finally I quit using CONFIG_BLK_DEV_BFD_HARD.
Nice. I will take a look at this later today when I have some time.
I added swich_drive98() and successfully probe floppy and switch device address and sector_size but FAT says 616k and cannot see files.
Hmmm... even though you are saying that you have changed the sector_size in the bioshd.c table, it seems that it is still using 512 byte sector size, as 616K is shown, rather than 1232K. Of course, that will be the reason you can't see files, as the block size somehow is still wrong.
I would put in some printk's in various areas to ensure sector_size is in fact 1024, rather than what seems to be 512.
Also, perhaps mount 1232K drive first to see if that changes the results.
Finally, grep for CONFIG_IMG_FD1232 throughout the source and make sure that you can dynamically handle the ifdefs, which will likely have to all be removed (except for boot code), to handle dynamic switching between FD types.
Thank you!
It seems CONFIG_VAR_SECTOR_SIZE is only defined for CONFIG_IMG_FD1232.
elks/include/linuxmt/config.h
I will try moving this under ifdef CONFIG_ARCH_PC98 and always define it.
I will try moving this under ifdef CONFIG_ARCH_PC98 and always define it.
Good catch! I'll bet that's the problem, as without it the FAT code assumes 512 bytes/sector for optimization reasons...
Thank you @ghaerr ,
It worked!
I will do some more testing.
Hello @ghaerr
I added int1B codes similar to boot_sect to Setup.S for bootopts. https://github.com/tyama501/elks/commit/162588635bc8b76803eb77bd4b38932734b6ecd2
I haven't debugged much yet, but it seems it still says ignored.
$DEF_OPTSEG for PC-98 is defined 0x60 not 0x50 but it is ok right?
Oops it seems I destroyed $ax. I will try again tomorrow.
$DEF_OPTSEG for PC-98 is defined 0x60 not 0x50 but it is ok right?
Yes, config.h looks good for you. You said some time ago that PC-98 uses segment 0x50, correct?
Hello @ghaerr ,
You said some time ago that PC-98 uses segment 0x50, correct?
Correct.
I modified and this code worked at least for FD1232. https://github.com/tyama501/elks/compare/9d65759...a2c7c64
Booting with option init=/bin/sh
I will test a little more. What does it happen if I use #root=hda1? Is this mean booting from fd but using harddisk for userland?
I modified and this code worked at least for FD1232.
That's great!! PC-98 now supports /bootopts options! Thank you :)
What is the reason for the deletion of the inc %dl
on line 993? Does that mean the comment on 991 and 995 need to change? I couldn't see any other change offsetting the inc %dl change.
Also, it seems even though PC-98 now supports FD1232 and FD1440 disks, we still have to specify which at compile-time in order to boot, is that correct?
What does it happen if I use #root=hda1? Is this mean booting from fd but using harddisk for userland?
If you specify root=/dev/hda1 (or any other block device), then the kernel will boot as normal, except it will mount the specified device as the root filesystem, with no other changes.
Hello @ghaerr
What is the reason for the deletion of the inc %dl on line 993?
I deleted the inc %dl under #ifdef CONFIG_ARCH_PC98 on line 993 and moved it to line 871 and line 874. This is because int1B sector number starts from "1" for the floppy disk but it starts from "0" for the hard disk.
Also, it seems even though PC-98 now supports FD1232 and FD1440 disks, we still have to specify which at compile-time in order to boot, is that correct?
For boot_sect.S, the boot sector was too tight to detect whether it is 1232 or 1440 and change the sector size. This time I just copied the code for setup.S. (I maybe change this if the solution for boot_sect.S is found)
Thank you.
root=hda1 seems working.
I have a question about TZ. When I set TZ=JST-9 in bootopts it appears as TZ=-9 while booting but when I printenv does not show TZ values.
I looked the source and found the bootopts only set tz_init() in init/main.c.
In clock.c tzset() is used and the source of libc/time/tzset.c is using getenv("TZ"). Is it ok there is no TZ env in the printenv?
Hello @tyama501,
When I set TZ=JST-9 in bootopts it appears as TZ=-9 while booting but when I printenv does not show TZ values.
It seems I broke this in my PR #1330, while adding CONFIG_SYS_NO_BININIT. Nice catch! The TZ env variable, and any other environment variables set in /bootopts (i.e. any capitalized strings of the form "VAR=value") should be shown in the shell's environment. I will submit a PR to correct this problem, thank you!
Thank you @ghaerr
With your patch it worked.
Hello @tyama501,
With your patch it worked.
Thanks for testing! I just pushed a small cleanup to merge some strings and I'll commit it. I also noticed that the ROOTDEV= env variable is only set when CONFIG_BOOTOPS is defined, but I'm leaving that alone for now. (The purpose for that is to enable /etc/mount.cfg to know the name of the root device for fsck testing, if wanted).
I'm glad you have CONFIG_BOOTOPS running on PC-98, go ahead with a PR for that when you're ready. Unfortunately, we're not quite able to reduce the size of the FAT boot sector (yet), so we'll still have to live with a compiled-in CONFIG_FDxxxx option for boot for now, even though /bootopts can later specify a separate root volume, which is nice.
Hopefully having /bootopts will speed your ability to test and enhance the PC-98 platform. Let me know if you think of other ideas that would be a good fit for a /bootopts option.
Thank you!
Hello @ghaerr ,
Something is drawn with Nano-X nxterm but it seems there is a long way to go.
Here is my test code vgaplan4_pc98.c. https://github.com/tyama501/elks/commit/a2eb461f0fffa9c1b2dc7023d4c74b0f45993c98
There are some variations of graphic accelerator hardware in PC-98 like graphic charger to draw 4planes at once but I haven't using any for now. (It might be faster (and easier) using bios call.)
Also I have noticed that if I press any key, sblk error occur while redrawing and exit to console.
And I haven't considered about MODE_XOR/OR/AND.
Hello @tyama501,
I would say that, that at this point, it might be well worth considering to build a stand-alone program in the nano-X directory, which could be essentially your vgaplan4_pc98.c with main
added, and built standalone with a quick hack to nano-X/Makefile (call it nxterm and it should be automatically copied).
Comment out all the assert
calls and typedef int PSD; typedef int PIXELVAL;
to get rid of the need for other header files.
The main
function will initialize the graphical screen and call ega_init(0). Then, direct calls to ega_drawhorzline(0, x1, x2, 15), or ega_drawpixel(0, x, y, 15) can be tested without all the extra stuff. The program can hang on a read(1, ...), then exit graphics mode and exit afterwards. You should be able to fairly quickly debug exactly was draw pixel and draw line are doing, with the much simplified program. (When lines are pointed the wrong direction, as above, I have found this is usually x and y being reversed, for instance).
I noticed you still have EGA adapter code in Lines 81-84, should they be removed?
If you think it might be easier using the BIOS calls, you could copy them in under the ega_xxx functions, much like was done in BASIC. However, you're not really doing your own drawing in that case, so not as much fun.
Once you have the horizontal, vertical, and single pixel draw code working, along with the entry and exit functions to graphics mode, we can then uncomment the asserts, delete the other commented-out code and move the driver back into nano-X. Don't worry about the XOR/OR/AND modes for the time being.
Thank you!
Thanks, nice idea for debugging.
Hello @ghaerr ,
By debugging with the stand-alone environment, it's getting better. https://github.com/tyama501/elks/commit/2e3384e72b0938f3d9b76bc8613631c98581b6c4
The mouse cursor is drawn properly with nxterm.
Although the color is not correct, nxworld is drawn.
I have a couple of questions.
In the orginal driver vgaplan4.c, ega_drawholzline has --x2 at the top of the function. Why is this needed? (I thought drawing is done while(x1 < x2) so the final point is not included even without this.)
ega_drawhorzline(PSD psd, unsigned int x1, unsigned int x2, unsigned int y, PIXELVAL c) { FARADDR dst, last;
--x2;
One more thing. PC-98 is 640x400 and not VGA 640x480. Where should I limit to 400 lines?
Thank you.
Hello @tyama501,
Wow, your implementation has come a long way forward, nice!!
Although the color is not correct, nxworld is drawn.
Is this in your test program, or using nxtern in nano-X? Nano-X has a somewhat complicated method of mapping colors to actual bits sent to the driver. This is done in the driver open routine, using psd->ncolors and possible palette modes. We can get into that later.
n the orginal driver vgaplan4.c, ega_drawholzline has --x2 at the top of the function. Why is this needed? (I thought drawing is done while(x1 < x2) so the final point is not included even without this.)
The version of nano-X on ELKS is very old (it is the last version that still compiled on 16-its, over 20 years old). Thus, I can't say why that was needed (or not). I would suggest removing it and testing to see whether the number of pixels is drawn properly without it.
PC-98 is 640x400 and not VGA 640x480. Where should I limit to 400 lines?
This is set in the driver open routine (see scr_bios.c):
/* init driver variables depending on ega/vga mode*/
psd->xres = 640;
psd->yres = VGAMODE? 480: 350;
psd->planes = 4;
psd->bpp = 4;
psd->ncolors = 16;
psd->pixtype = PF_PALETTE;
You might want to think about just creating a scr_pc98.c which contains the entire driver source for PC-98, rather than trying to integrate into the IBM PC BIOS and EGA/VGA code. That will allow you to do whatever you want, and I think will be cleaner overall.
Thank you!
Thank you @ghaerr ,
Is this in your test program, or using nxtern in nano-X?
These are using the driver in nano-X with nxterm and nxworld.
I forgot that the order of the color in EGA is RGB but the PC-98 Vram order is GRB. So, I need to write to the different plane. I will try it next time.
You might want to think about just creating a scr_pc98.c which contains the entire driver source for PC-98,
OK, I will do it.
I forgot that the order of the color in EGA is RGB but the PC-98 Vram order is GRB. So, I need to write to the different plane. I will try it next time.
For now, you can do that. But the longer term solution is to adjust the nano-X palette, such that the RGB colors are the program selects, end up matching palette indices that match perfectly with the GRB plane layout, rather than adjust the PIXELVAL in the driver. This ultimately improves speed quite a bit. However, it is possible this could be done in the driver at full speed, depending on whether a lookup table is used or not.
Your work is impressive, the mouse cursor looks great and nxworld also looks good. How fast/slow is the display?
I meant I missed the order of the screenbase_table I added. So the Green and Red are opposite.
Well I am now setting the emulator for 486, 25MHz which is same for my pc-9801bx, not bad but I cannot judge since it exits immediately if I press key. Probably reading the pixel still has problem.
Hello @ghaerr
Thus, I can't say why that was needed (or not).
I checked with basic "peek" and found at least for my code --x is not needed. So I removed it. I also used mask[] table instead of shift for speed up.
After limiting to 640x400 and modified screenbase_table, now I think line and color are correct.
I also took video for nxworld and nxlandmine drawing. (Maybe it is not fast...)
nxterm
nxworld
nxlandmine
I still cannot figure out why nxterm exit immediately. nxworld and nxlandmine keep running when I press key.
Also fonts are not available? "#" is corrupted in nxterm. How does they handle fonts?
Thank you.
Hello @tyama501,
Thanks for the pictures and screencasts, things look great! I don't think the nxworld painting is too slow, it seems about the same on my systems. It is kind of cool that the PC-98 allows for "text" characters on the same screen as the graphical output. I suppose that's because the text characters are actually graphically drawn, instead of produced by a hardware ROM character generator?
Also fonts are not available? How does they handle fonts?
Fonts can be either compiled in or loaded from disk in nano-X. I have some BDF conversion tools that would allow for conversion of Japanese fonts into nano-X in the future. For now, the standard nano-X font is compiled in, but requires the BLIT routines in order to draw. The older mechanism used to draw the font glyphs bit-by-bit using the driver drawpixel routine, but that was very slow, So the current mechanism draws them much faster using the driver blit entry point, which is a little complicated. It basically tries to replicate an in-ram glyph definition to the VGA screen as fast as possible. For frame buffer systems, this is basically a fast memory move, with some possible conversions. But for VGA, it is a lot more complicated since a direct memory move won't work, and variations are made depending on the location of the source and destination ram.
Thus, you'll need to implement the ega_blit
routine in order to see text output. I think most of this code is in the drivers/mempl4.c. As you will see, there are four versions of this blit, depending on whether the source and/or destination are main memory or VGA memory. Take a look at it, and I'll help.
"#" is corrupted in nxterm.
This is likely because the ega_blit routines are not yet ported to PC-98, as described above. The only character output by nxterm would be the superuser shell prompt.
I still cannot figure out why nxterm exit immediately.
This could be an issue with the nxterm pty code not working - I will test nxterm on my system and report back.
I also just noticed from your screenshot that nxterm is running out of heap memory (as seen from the sys_brk() fail messages). Please add an -maout-heap=0xffff
to the linker line to allocate max heap. It is possible this has always been the case, but the failure messages can't be seen on IBM PC, since the console stops displaying printf text character output once in graphics mode.
Also, seeing the complexities of the PC-98 port, I like your current idea better of using scr_pc98.c, but then keeping the other routines in seperate files, (e.g. vgaplan4_pc98.c), and also likely to come memplan4_pc98.c.
Overall, I'd say you're making great progress!!
Thank you.
Hello @tyama501,
I still cannot figure out why nxterm exit immediately. This could be an issue with the nxterm pty code not working - I will test nxterm on my system I also just noticed from your screenshot that nxterm is running out of heap memory (as seen from the sys_brk() fail messages).
I tested nxterm on QEMU and it is not reporting sys_brk fail messages to the console. I'm not sure why that would be happening on your system, although I remember that the PC-98 BIOS did use quite a bit more stack than PC BIOS. However, there should be no BIOS calls taking place while running ELKS applications, except for on the kernel stack.
Lets see if this exit problem persists after adding max heap to nxterm.
Thank you!
Hello @ghaerr ,
It seems no difference with -maout-heap=0xffff. sys_brk() fail occur.
I tried if I can run nxterm on "screen" and see it from background screen, but it seems cannot create pty /dev/ptyp2.
There are still IBM bioscalls like int10 remaining, so I need to remove those.
Sorry, I put -maout-heap=0xffff at wrong place.
After adding it to linker, sys_brk() is not occur. But exiting with "can't create pty" even not using "screen".
It seems every time hit the key GsInit will occur and the second time the above message appears and exit.
There are still IBM bioscalls like int10 remaining, so I need to remove tho
Where are these calls, I do not understand. Are they in your PC-98 nano-X graphics driver? It is certainly possibly those calls are using excess stack, as PC-98 BIOS uses much more stack than PC BIOS, from previous experiments.
After adding it to linker, sys_brk() is not occur.
OK, so it seems we are getting different results on PC-98 system/emulation, since this is not needed on PC.
Perhaps we are getting stack overflow (although this is tested for by the kernel). You might add -maout-stack=8192
to double the stack allocation.
It seems every time hit the key GsInit will occur
GsInit should never be called twice - so it seems we are getting the stack trashed. Lets try the extra stack allocation above and see what that does. I still don't know why the sys_brk are occurring, unless perhaps your driver is causing nano-X to allocate some memory for screen (this should not be happening).
But exiting with "can't create pty" even not using "screen".
I think the reason for this is the term_init
function in nterm.c loops up to three times trying to open a pseudo-tty. It already opened two of them (for the two incorrect invocations of GsInit), and there is to third /dev/ptyp2 on FAT disks. We could add that in fs/msdos/inode.c but that would then likely just crash after fourth attempt).
In summary - it seems the stack is getting trashed for some reason. Also extra memory is being allocated for reasons not yet understood, could be result of psd-> settings in screen driver.
Hello @ghaerr
Where are these calls, I do not understand. Are they in your PC-98 nano-X graphics driver?
I just copied scr_bios.c to scr_pc98.c so it was remaining. This will crash real PC but the NekoProject emulator avoid crashing for unimplemented bios call. Any way I removed it. It didn't change.
I added -maout-stack=8192 but this has no change too.
I noticed that nxworld is also repeating GrOpen, GsInit etc. when I hit enter key. It won't exit since it doesn't use pty.
I also got bit confused about HAVEBLIT. I was accidently defining HAVEBLIT = 1. I didn't know it was in vgaplan4.h.
I tried HAVEBLIT = 0 but it doesn't change. I thought the functions in mempl4 are used when HAVEBLIT=1 but it seems the function vgaplan4_pc98.c are used. How this happen?
Hello @tyama501,
Sounds good that you removed unneeded INT 10 calls, and added larger stack.
It seems we are getting stack trashing for sure, since GsOpen and GsInit should never be called twice in same application. If I were to guess, it seems that main() itself is being re-entered. Perhaps put additional printf() in main to determine if that is the case. If so, then we need to determine when it is being reentered. Is the reentry occurring only after first event (e.g. keypress)? Or does reentry occur prior to going to nano-X main even loop?
We need to track down the routine that trashes the stack. I will guess that is is one of the routines in PC-98 used to initialize the graphics, and/or output graphics.
I also got bit confused about HAVEBLIT. I was accidently defining HAVEBLIT = 1. I didn't know it was in vgaplan4.h.
The HAVEBLIT define is somewhat dated, but should remain defined =1. Basically, when the entire Nano-X project moved to blit routines for output glyphs (and images), there were no more single-pixel drawing. This opened the door to memory blitting (as opposed to blitting to VGA), and that is the reason for all the routines: memplan4 does the memory blits, and vgaplan4 does the VGA blits. There are a total of four functions required, for the following cases: MEM->VGA, VGA->MEM, MEM->MEM, VGA->VGA.
Thank you!
Hello @ghaerr ,
OK, nxterm worked.
The result for "ls -al ../" :)
It seems the reason it didn't work is that I haven't used mou_null.c. I just commented out opening the mouse but that caused problem. After using mou_null.c it worked.
I still using basic to set graphic mode so I need to incorporate it to the driver. And also need to modify memplane4. (Now it is working with HAVEBLIT=1 without modifying it. I still don't know why.)
Thank you.
Hello @tyama501,
The result for "ls -al ../" :)
Yes, highly readable LOL... NOT! (I've seen screens like that many times before in graphics development :)
It seems the reason it didn't work is that I haven't used mou_null.c. I just commented out opening the mouse but that caused problem. After using mou_null.c it worked.
Hmmm, that's pretty strange. The default mouse driver, drivers/mou_ser.c, opens /dev/ttyS0. It appears that opening that file on PC-98 (with no working serial driver) was causing the problems. We should put that on our list to look into. The open should fail, with no valid serial driver. It apparently did not, and was trashing the stack!!
And also need to modify memplan4.
After you get more of the memplan4 <-> vgaplan4 blits working, the text should display. The text will be output using the mem->vga bit routine, so you might try that one first. The other three are much less used.
(Now it is working with HAVEBLIT=1 without modifying it. I still don't know why.)
You will want to keep HAVEBLIT=1. I think it is only appearing to work, since the characters are obviously drawing from garbage in the existing blit routine.
I'm glad you were able to figure out the stack trashing - I wouldn't have guessed the serial port to be the issue!!
Thank you!
Hello @ghaerr ,
Now, the nxterm is using driver/romfont.c with int10h, is that correct?
I haven't modified the memplane yet, but I need to also modify romfont.c using I/O port access.
PC-98 has single byte charactor and double byte kanji charactor rom but it seems 6x7 pixel or 7x13 pixel.
The romfont.c is now fixed to 14 pixel height?
Hello @tyama501,
Now, the nxterm is using driver/romfont.c with int10h, is that correct? The romfont.c is now fixed to 14 pixel height?
Yes. And now I see your issue more clearly. I keep thinking of the modern Microwindows repo, where there is much more font support. I was incorrect stating that font glyphs are drawn using blit - they are still drawn using the driver drawpixel routine (see engine/devdraw.c::GdText() and GdBitmap() for exactly how). Thus, you will not need to complete the blit routines in order to get nxterm working. The reason that it is displaying incorrectly now is that the IBM PC ROM glyph data is not present on PC-98.
The routines in drivers/romfont.c use a far pointer to access the ROM glyph data directly, after getting the pointer using INT 10. The routine pcrom_gettextbits
and pcrom_gettextsize
should be rewritten to supply the character glyph data and character width/height respectively. The support for compiled-in fonts is in drivers/genfont.c, but it seems this is not compiled in for ELKS at this time.
If you can access the PC-98 character ROM using a far pointer, this will work. Otherwise, we will have to compile-in the data. For now, nano-X will only use an 8-bit glyph index.
Thank you!
Thank you @ghaerr ,
I see. I will focus on getting single byte ROM character for now. PC-98 character ROM is not mapped in main memory so we need to get the data by IO read. I will try it.
Hello @ghaerr ,
I got rom characters printing on nxterm although somehow it is a little diluting. (The mouse pointer also diluted so it may be different issue. )
I added romfont_pc98.c. I also added initial codes to scr_pc98.c similar to basic.
https://github.com/tyama501/elks/compare/7e6a428...62c3fab
May I do initial commit after some cleaning the codes?
There are still some things I don't know
Thank you.
Hello @tyama501,
This is fantastic, super work!
I got rom characters printing on nxterm although somehow it is a little diluting. (The mouse pointer also diluted so it may be different issue. )
Since this is in both cursor and character draw code, this could be in the drawpixel driver code, possibly an off-by-one depending on exactly the x/y position drawn. I don't quite have time now, but will review your code and comment later today.
May I do initial commit after some cleaning the codes?
Yes, plan on that. I will find time to review your current work and comment later today.
LDFLAGS += -maout-heap=0xffff is needed. Less heap hangs up the nxterm even I only use 5Kbytes in scr_pc98.c
Sounds like we are very tight on application data segment memory.
The nxlandmine exit immediately if I press arrow key.
This is likely because arrow keys now send ESC ..., and ESC terminates nxlandmine. We can fix that.
Thank you!
Hello @tyama501,
I have reviewed your new Nano-X PC-98 screen driver and it looks great. Please send it over when you are ready, and we will commit it.
I haven't yet any other suggestions on why some screen dots are not being displayed (i.e. your dilution issue), but I will look further at the full driver once your enhancements are committed.
Thank you!
Hello @ghaerr ,
Thank you for the review, I will commit after some clean-up.
I found the mouse pointer is not diluted in the previous picture before I implemented rom character reading.
There might be some hardware timing that we cannot write to the vram. (Now I am not waiting any VSYNC)
(Now I am not waiting any VSYNC)
I tried waiting VSYNC before reading a font. No difference except for getting slow display.
It seems the problem does not occur if I don't place the hardware ROM file from PC-9801.
NP21/w without the ROM file, using the host emulation.
DosBox-X emulation
Hello @ghaerr ,
I tested with real PC-9801BX and found the font character is totally broken. So, it seems the code is not best solution for the real PC.
I have a question about VGA/EGA graphics plane in IBM PC. Can it be written any time while displaying? There is no need to wait VSYNC and now the pixels are drawn any time?
I am not sure the PC-98 graphic specification precisely yet. It seems to have double vram that can separate the writing plane and the display plane. Now the writing plane and the display plane are set to be same.
One more thing I would like to try is to read all single byte ROM fonts to allocated memory at the initialization and using it for faster reading. I will do that next week.
Totally broken and vram data is corrupted at right bottom.
Hello @tyama501,
Wow, sorry to hear that font drawing on real hardware doesn't work at all!!
have a question about VGA/EGA graphics plane in IBM PC. Can it be written any time while displaying?
Yes, there are no requirements for wait states on VGA/EGA. However, CGA will display snow if drawn without waiting for VTRACE.
Totally broken and vram data is corrupted at right bottom.
Thank you for the screenshot. My thoughts are that it seems hline draw and line draw seem to be working very well. I am not sure about draw pixel, but am guessing probably works, since cursor is displayed properly. Thus, the likely problem is accessing the font character set and/or drawing them. For simplicity, perhaps create an RAM font, set to all 1's using memset(), and seeing whether text display works (of course, it would display all block characters). Or perhaps your idea of reading single-byte ROM fonts into memory would accomplish the same thing. Since the "ROM" glyphs did display (almost) properly on the DosBox-X and Neko emulators, we probably have the font display code working properly, but instead are just not gaining proper access to the font data on real hardware.
Thank you!
Reading the font to allocated memory did not make much difference at least on emulator. I will check farther...
I am thinking to try switching the double VRAM (display plane/draw plane) in vgaplane4_pc98.
It needs to draw twice but it should make able to draw anytime.
Maybe buffering to the draw plane, waiting VSYNC, switch it to the display plane, then transfer all data to the new draw plane from the new display plane would be better.
Continued conversation from https://github.com/jbruchon/elks/issues/1238