As an exercise, I want you to consider how you'd design a bitmap graphics editor (like MS Paint, GIMP, etc).Deprecated wrote:For the 8086 targets I had initially considered limiting the kernel and associated modules to having a total of 64k of memory for data. With the Watcom compiler that is no longer necessary and each module can have it's own data segment while still having access to global kernel memory. By specifying __loadds in addition to __far for all functions used as entry points there should be few if any issues with inter-module calls. Although Watcom does support the __huge specifier for data that crosses segment boundaries it's still too early to consider it's usage.
You'd have something to load a file's header and decode it, then you'd do something "pixel_data = malloc(vertical_size * horizontal_size * sizeof(PIXEL) );" to allocate a buffer, then you'd decode the rest of the file into the buffer. After that you'd have a bunch of routines to work on the pixel data (in the buffer) - things like setting pixels, drawing lines, filling areas, etc; and maybe some more stuff that works on the image as a whole (resize, blur/sharpen, lighter/darker, etc). You'd also have code to save the file (generate appropriate headers, etc for a specific file format, and write the pixel data from the buffer to the file); plus some user interface code, etc. It all seems relatively simple really.
Of course the code to load the file would convert the pixels into a generic format, so that all of the rest of the code only needs to handle that generic format (so you don't need 10 different routines to draw a line in 10 different pixel formats, for example). The generic pixel format would need alpha/transparency plus 4 more fields for colour data (whether it's "RGB" or something else). You could get away with 8 bits per component here (or 4 bytes per pixel for "ARGB"), but for things like gamma correction, etc you'd probably want something larger (maybe a "float" for each component) to minimise error and get the best results. I don't know, but it all still seems relatively simple.
To make it portable (so you can compile it as a 16-bit version, a 32-bit version and a 64-bit version) all you need to do is tell the compiler to use a "large" or "huge" memory model, and put things like "__loadds" and " __far" at appropriate places.
It all just seems simple. I mean, that's all you'd have to do right?
Assuming we're only using 4 bytes per pixel, with 640 KiB of RAM (the absolute maximum possible for 8086, leaving no RAM for any code or anything else) it'd be limited to 163840 pixels. That's enough for a 400 * 400 image, which is fine for, um, icons? Oops. Even for a 8086 you'd want to try to support images that are 640 * 350 or more (even before VGA, most "EGA compatible" cards supported 640 * 480).
The main problem is the memory allocation "pixel_data = malloc(vertical_size * horizontal_size * sizeof(PIXEL) );". It just can't work - even with multiple data segments you run out of RAM; and because we're talking about real mode it's impossible for the OS to implement anything like swap space. To get around that I'd probably consider creating a temporary file for the pixel data, and using whatever RAM I could get my hands on for a "most recently used" pixel data cache. Every piece of code that touches the pixel data would have to be changed to make the "pixel cache" work, which is everything except the user interface code. Basically you'd have to radically redesign the entire application to make it work. Doh.
Ok, so we redesign the thing to use a pixel data cache or something. Now it's slower than it could/should be for 80386 and later. How do we get around that? I've got an idea: let's just make 2 different versions - one version for 8086 and one version that people would actually use.
Cheers,
Brendan