Conversation
Yes, I also noticed it but I don’t understand how it happens. It draws three pixel which is what DrawDisk does for radius=1, but it should not do it due to if(r<=1) drawpixel… |
|
Oh, I see, it is |
Ok, I'll fix it in this PR. |
|
Wow, this scanline drawing is amazing. I need to get this to elks-viewer! One question - how should I use this code - will it make its way to the libc, or I should just copy over the files? |
|
btw, should I pursue a bmp to jpg converter (or vice-versa, which is basically done), in order we can have a more complete image editing ecosystem in ELKS? Also - we need to improve "file" command to identify at least bmp, jpg, ppm and pgm format, as now they are fully supported on ELKS viewer, and can be easily supported by a "elks-imagemagic" I could derive from elks-viewer. Should I add this "file" improvement to a TODO somewhere? |
Are you talking about the API, which allows an array of 4-bit colors to be drawn, or the speed with which Paint now draws its icons/buttons? The big speedup with with Paint bmp's came as a result of caching the palette color conversion, not drawscanline. In fact, I've been unable to see any actual speed difference between drawscanline and calling drawpixel for each pixel, when using the ASM drawpixel routines we now have. I haven't tested on real hardware though. (The difference could be tested on real hardware using USE_DRAWSCANLINE=1 or not in drawbmp.c). I'm not sold on drawscanline yet (as it is kind of big with no visible speed increase), which came from SVGALib, but I've included it in Paint because it's helped to get the macros built for a general C routine to manipulate VGA registers for all three compilers, which is now done.
I hope to get this stuff added to libc, but we're not quite there yet. We now have toolchain/examples, Paint, and your code, all with slight variations. I'm thinking we'll probably use this Paint code as a start, then add your 256-color pal_ routines and palette management stuff after this settles down a bit. If you could test Paint on real hardware with and without USE_DRAWSCANLINE that would help determine which direction to go. What will help the process of moving to libc would be ensuring that elks-viewer encoders/decoders, etc routines are already in separate files/headers and and callable like library routines, if they're not already. Each module should be as independent as possible, and depend on graphics.h and their own (possibly shared) header, if possible.
Our work in Paint is showing that the BMP format is well suited for ELKS since the files can be 4- or 8-bit RLE encoded for small size and rapidly decoded, we have a definite need for "any image format" to BMP format image conversion. In particular, handling some of the problems there seem to be no host tools for would be great. These features would include taking an image (including a BMP image), and converting it to BMP using:
This can probably be easiest done by finding the Linux |
|
Hi @ghaerr , Something strange is going on with BMP drawing. I converted icons to what is called "Standard palette for 16 color systems" in Gray became LightGray. UPDATE: here are new icon examples |
Try adding the following diff to drawbmp.c: That will display the actual VGA pixel color (once) for each bmp. I'm wondering if perhaps find_nearest_color isn't working correctly or maybe returning light gray rather than gray. |
|
Just tried the above over here with your new paint.bmp: So, yes, that's what's happening, the original shows cache 8 as the first color, so find_nearest_color seems not to be working. Can you check that the actual palette values produced in the BMP file in fact match the VGA standard palette in drawbmp.c? (BTW, you're using the "CGA" palette with #if 1, right? If not, then recompile with #if 0 in drawbmp for the time being.) |
Ok - that's the problem confirmed. Selecting the "CGA" palette in drawbmp.c and the images are correct. Long story short, there is some debate as to what is the actual palette used on VGA. In Nano-X, we are using the "older" version: but in drawbmp.c (and thus this project), we are using the "CGA" palette, which, according to some a bunch of online documentation, is "more correct": Let me try to find that link. So that begs the question, which is "correct" and which should we be using? |
|
Here's the article. Let me know what you think. |
|
One way we could get around this mess would be to assume a "standard" palette when a BMP is seen that has exactly 16 palette entries. If there are 16 entries, we could just skip the palette match lookup entirely, and assume that the palette index is in fact the VGA or CGA color, and just use that index unmodified. We would also assume that the palette is in "standard" order when its 16 entries. That will then work regardless of our palette. If the BMP has 256 entries (as produced normally by other tools, etc), then we'd use the process we're using now. What do you think? If your BMPs now have only 16 entries, I can write some code that will make this all work, for both your new and old bmp files. |
|
A second idea of how to deal with this would be to keep the palette which we are using now (CGA), as it has seemed to work well with your existing tools and seems to display those BMPs correctly using our find_nearest_color() against it. Instead, just modify your conversion tool to output a CGA palette rather than VGA palette. Thoughts? |
|
Another note, it seems circle.bmp is not matching the 3rd and 4th indices encountered properly, resulting in incorrect output. I hadn't noticed this visually, but see it with the new debug output: |
From the above discussion, I suggest staying with the palette we're already using, the CGA palette (#if 1), since that palette apparently (from the article) more closely matches the actual IBM screen and emulator output. Then when your conversion tool changes RGB values to palette values, it will convert to the palette that is used in most emulators and apparently real hardware screens in use today. |
This is because they were created by optimizing the palette. In fact they contain only 3 or 4 colors because icons don’t use more. Only the new icons I’ve send above contain “standard” VGA palette with all 16 colors. So I think you can read number of colors in bmp and assume the palette is standard if there are exactly 16 of them. |
Ok. I switch to the CGA palette in icons and #if 1. |
|
We can also introduce our own |
I see. So we don't really need a full palette.
Yes, lets do that.
Actually, as a result of this testing I am now realizing that I was incorrect in thinking that there is a "standard" palette that will work for everything. Instead, we're going to have to continue to use the CGA palette which maps closest to current reality, it seems. That's ok though. However, I am now thinking that it would be better to just include the actual palette entries, but only for the indices actually used. In this way, the .bmp files stay very small, but also remain completely .bmp compatible. IMO, it would be better to stay with a standard .bmp format (and keep them as small as possible), than to introduce our own .ico format which is different. So what we're probably talking about is doing almost what you've done - having a post processor on the .bmp files that make them small, and then write just the number of entries required, which for our purposes will always match the CGA palette. So we're not using the CGA palette to speed up display, as I had first imagined, but instead using it to match colors better with emulators and real screens. |
That may help, but the bigger issue is how a bmp aligns with a disk sector or block: on MINIX, all file access is read two sectors at a time (=1K blocks) so what really matters is when an icon is very close to a 1K boundary; e.g. a 1025-byte bmp file will actually cause 2k disk to be read. I would think the amount of time spent reading ~64 bytes of palette internally using Here are the current (non-converted) bmp file sizes: The only problem image is paint, which is just over 2K, so 3K will be read from disk. Is that image compressed using RLE? |
Yes, it is RLE compressed. My encoding is not the most optimal but it is better than what |
In Next, one needs to switch to COM1 (
To get EGA running (VGA is semi broken) one needs to put ibm ega bios to |
|
You can also try VGA by setting |
|
Then how do I turn on/off the mouse, since it doesn't work automatically like QEMU with a mouse down in the window?
You mean with 'config_overlays = ["ibm_vga"]' ? Do I need an additional config_overlays = section for VGA? I don't want to mess with VGA if it doesn't work, I'm having enough trouble getting EGA to work.
Ok. Is there a way to get ELKS kernel serial output on COM1 for debug statements? On QEMU I normally set serial console to COM1 to get debug statements and then have the mouse set to COM2, for just that reason. |
|
And then how do you get it to remember the floppy image that you selected? It doesn't remember the last setting, I have to manually select the floppy from elks/image/fd.img each time? |
|
Ok I have EGA working and Paint paints (interestingly enough for its cycle-accuracy, it seems the display aspect is not the same, the circles are now slight ovals), and the mouse cursor shows, but haven't figured out how to attach/disattach the mouse nor how to remember the floppy image. Thank you! Tried below but didn't work: |
You can double click on the emulated screen to attach mouse and middle click to release it. The latter doesn't work on my MacBook because there is no middle click on a trackpad. That is why there is |
I don't know. There is a lot of debug information in the drop-down menu. Also MartyPC has a discord channel where you can ask @dbalsom directly. |
I never figured that out. I click every time on a required floppy manually :))) |
Got that working, thanks. But after double-clicking on screen and capturing mouse, The MartyPC error message scroll horizontally at the bottom of the screen too fast to read.
Yeah, for all the work that went into MartyPC, it's not very user friendly. |
Well, 640x350 image is stretched to 4:3 aspect ratio... |
It is still a very early version. There are many things to do. It got mouse only recently as far as I understand, fancy floppy drive support which can deal with copy protection, no real VGA still... |
Agree |
which file did you edit? |
martypc.toml, the same one I've been editing |
|
What's the double [[ for in [[overlays]] ? Why not just single [overlays] ? I find that confusing. |
Not this. Go to |
I find many Rust-related things confusing. As well as C-related things. The only non confusing things are Fortran, Python, and Mathematica :) |
If I interpreted this correctly, you want the last used disk image that was mounted to be remembered and re-mounted the next time the emulator is started? |
That would be very useful! |
double brackets in TOML represent arrays. The file defines an array of overlays. |
Are you talking about the notification widget in the bottom right that pops up, or the console log scroll? |
The bottom right stuff that shows for a few seconds then disappears. This happens when selecting a drive manually, and by the time you get to try to read the messages, they are gone. IMO they would be better either not displayed, or be able to be scrolled back, if there's something important to read. When the emulator starts up, there's so much debug info, but the important thing for the user is which image is mounted, which isn't displayed anywhere, or at least I don't see it. Can that be passed as an argument? I suppose all this is related to what an emulator would be used for. For ELKS, I use it to test new images, and it is nice to be able to change images (i.e. floppy sizes, etc) without editing a configuration file, and certainly without having to run a GUI. Also what would be nice is not having to wait through the boot process every startup, but I suppose that's not easily possible given the emulator is bare CPU and interprets the BIOS startup code as well. Again, I suppose differing requirements for different uses. |
I am sorry you are frustrated. I am doing the best I can, and continually trying to make things easier to use. It is a lot of work for one person, and sometimes I feel overwhelmed. |
Yes, that blue pesky message in the bottom right sometimes is too quick to read |
Okay, I can make them stay on the screen longer. |
|
Another very useful something (which MartyPC may already have) is the ability to support displaying serial output from the guest somewhere. With QEMU, this can be set to just scroll onto the terminal which started the emulator. This allows displaying debug output to say, COM1 or COM2, while the mouse is operating on another port.
I'm not really, it is always hard for me to learn something new. You've done a fantastic job, I saw @Vutshi's screenshot of the emulator running an instruction trace, very cool! Can't wait to figure how to turn that on. I would suggest that most all options (e.g. EGA, VGA etc) be preset somewhere, even if turned off, so that one can quickly learn by scanning the config file. It is very hard to learn when there is a directory hierarchy and multiple configuration files, initially one has no idea where to look. And I'm using a macOS artifact build, so I'm not sure everything is included as in a normal installation, since I can't build directly on my laptop. These are only my very first thoughts, please don't take them personally, the actual look and feel of the emulator on-screen looks very very nice and the multi-window output seems pretty neat also. I understand what a huge effort it is to get something like this even built, let alone working. I am excited to learn more about MartyPC. |
Oh great, that will work well :)
Since the boot image itself is likely different for every use or MartyPC, I would say that having a command line option would be extremely useful!
Good to know. My suggest was that, since there's so much being displayed on the console by MartyPC anyways, why not also show the boot image, since that confirms to the user what is actually being booted. I would assume that a command line option would override the config file filename=, for instance, so a confirmation would be good.
Well, I'm an old UNIX programmer and use the command line all day long. Changing image locations by scrolling through a file open dialog is... well, very slow. Especially since I'm starting martypc from the command line anyways.
I would definitely like to specify the most oft-changed option(s) on the command line, since I'm running from a command line. This would be the boot image, as described above. The window can remain as it is with menu drop downs, that's no big deal.
That would be a GREAT command line or config option! :) There is a community need for a cycle-accurate emulator: in fact this is the reason I'm setting up MartyPC, because @Vutshi and I are trying to speed up Paint (BTW, its 10x faster than before when you tried it!). I'm making small adjustments in 8088 ASM code and am trying to be able to discern some draw-speed differences without using real hardware. QEMU just doesn't work well for that, and many of the other emulators are way too hard to setup. Yes, MartyPC has been relatively easy to setup, it just needs a little fine-tuning and presets in config files and you're there :) Back to the community use case: having a cycle-accurate emulator that can be run on the command line out of the box with a few options would be fantastic, as there just isn't anything out there that does that. The kinds of things I'm suggesting would be typical very basic options like the following command line suggests, with no config edits required: or something like that. Thank you for your comments! |
This is sort of a result of the TOML parser library i'm using not having the ability to write back to the TOML file without destroying all the comments and ordering in it. I have been experimenting with a different TOML parser that can, but using it is a bit more laborious as it constructs a large dictionary. Plus it's surprisingly difficult to ascertain what options should change. For example, maybe you always want to play Frog Fractions, so you specify Frog Fractions Disk 1 in the configuration. MartyPC loads up and starts the game - great, but at some point while playing you have to put in Frog Fractions Disk 2. Now if I save that to the config, the next time will load Disk 2 and won't boot. Is that a problem itself? I could add yet another option to the config, like "save_last_loaded_image" if that's what you want. I have also been dabbling with the idea of defining "workspace" configurations, which save any customizations you've made from the main configuration, like window positions, breakpoints, images loaded, etc. I have also thought about adding a "recent images" menu for quick access to the last N images you loaded, and that could be saved in the config. Making a good user interface is not easy!
I'm unlikely to copy linux device names exactly. The IBM PC can actually support up to 8 floppy drives which is crazy but I want to be able to support esoteric things like that. I think using numbers 0-7 is more clear to people with no linux experience
We could also make a generic mount directive, and specify the device as sort of a uri
We have lots of things we could want to "mount", PCjr cartridges, floppy disks, VHD images, even cassettes, (someday) CD-ROMS, etc? You can currently select the video mode on the command line, via my config overlay system, so Overlays can add a lot of hardware with associated options quite easily, assuming they are defined. I have overlays now for a mouse on com1 or com2, so, I think the overlay system is very powerful but I need to document it better and expand on it. It is not clear what your options even are for adding overlays unless you go poking around in the overlay definitions. Anyway, this making this issue thread wildly off-topic. I have a discord here https://discord.gg/8Gv7mVz4CC where I'd be happy to have you, you could give me direct feedback there and watch development progress. |




Adds libc fmemcpy for OWC only.
Adds fdstmemcpy for GCC and C86 to paint.
Ports vga_scanline to C86.
@Vutshi: I just noticed, are you aware that the single pixel brush "button" is now showing two horizontal pixels (instead of a single pixel) after your last commit or so? Drawing is still down with a single pixel. This PR doesn't change any render.c code.