Documentation/Plugin Developer's Kit

Subject: Plugin Author: Lonny Pursell HTML conversion created with STG2HTML v0.75 Written by Lonny Pursell and ENCOM Note: Images are not supported. Index


Plugin Developer's Kit
Introduction Handling file extensions Loading overview Saving overview Image info structure Using the image plugins Overview of plugin functions Palette handling General program overview Error handling GFA-Basic source code Plugin Stack size Dithering Loading animations Improvements over other codecs Changes from previous API Misc notes Revision history Please contact me if you find an error or something seems unclear. Written by Lonny Pursell WWW: (contact)


The requested document was not found.


Page not found.

Lonny Pursell



GFA-Basic is the best BASIC for the Atari!


Yet another plugin format? Quite frankly I wasn't all pleased with the LDG solution. If you don't use 'C' you're forced to install LDG.PRG (TSR) and it's plagued with a memory leak. SLB with callbacks are worse as the complexity of the GFA-Basic code required to use them seems to outweigh their usefulness just to save a few bytes. My dream is to have these work on all operating systems without being forced to install anything. I'm hoping others will adopt them and find them useful. These plugins don't require the installation of anything. They should work with SingleTOS, MiNT, MagiC, etc. Where appropiate the pluigns return standard Atari bitmaps. Bitmaps are always word aligned and ready for blitting. In cases where a standard bitmap can't be returned, the caller must deal with the transformation themselves. That's not entirely true if one is willing to use NVDI v5.03, however that's beyond the scope of this document. Plugins will always deliver images right side up. The plugin will handle all this for you. Targa and BMP are good examples. Multiple plugins can be loaded simultaneously, but you will have to manage multiple img_info structures. That's also beyond the scope of this document. I do not recommend loading all plugins at once. At the most two could be loaded to allow image conversion. Plugins return detailed information when rejecting an image file. A return value of zero of (0) indicates no errors. Anything else indicates an error. See table of error codes below. The caller should try to inform the end user as to why the image didn't load. Plugins are loosely based on zView codecs. The functionality is similar, however all the annoying shortcomings have been addressed. Plugins are not compatible with zView. They are not reentrant, nor can they be shared by two processes at the same time. They have been splits into Load (*.IL) and Save (*.IS) plugins. Recap: Pros: Load 90+ file formats, including formats like JPEG, PNG, and TIFF Future proof, new image plugins can be made without recoding the app Caller doesn't need to know the technical details of the image files Can be loaded and unloaded on the fly, reduced memory footprint Delivers ST formats as native Atari bitmaps/palettes Bitmaps always arrive word aligned, right side up, and ready to blit Split into Load and Save plugins to reduce memory footprint Better file extension handling, can bbe 1 to 4 characters Cons: Plugins do not convert bitmaps to the current video mode Some bitmaps arrive in non-atari formats, such as JPEG, TIFF, etc.

Handling file extensions

To properly handle file names like or foo.jpeg the extension field is 4 characters per entry. Example: "TIF TIFF" They are padded with spaces and the length of the string will be a multiple of four. There's no entry in the function table specifying the number of extensions in the list. This is obtained easily with: count=LEN(ext_list$)/4 When doing comparisons the extra spaces need to be trimmed. FUNCTION is_ext(ext$,ext_list$) $F% ' ext$ target ' returns true or false LOCAL f! LOCAL tmp$ LOCAL i& ' ext$=UPPER$(ext$) ' FOR i&=1 TO LEN(ext_list$) STEP 4 tmp$=TRIM$(MID$(ext_list$,i&,4)) IF ext$=tmp$ !found match? f!=TRUE EXIT IF TRUE !exit loop ENDIF NEXT i& ' RETURN f! ENDFUNC

Loading overview

Plugins return image data in several formats. The plugin decides which format will best preserve the image quality. Image data will be returned as a native Atari bitmap word aligned and ready to blit if possible. The palette will also be returned in a native Atari format if possible. Some image formats are exceptions to this rule. The image data formats are: PX_ATARI1 ST 2 colors PX_ATARI2 ST 4 colors PX_ATARI4 ST 16 colors PX_ATARI8 ST 256 colors PX_ATARI16 Falcon030 5/6/5 (high-color) PX_PREF8 8bit chunky/color mapped (2 to 256 color) PX_PREF15 15bit rgb 5/5/5 (high color) PX_VGA15 15bit rgb 5/5/5 (high color, byte swapped) PX_PREF24 24bit rgb 8/8/8 (true color) PX_VGA24 24bit bgr 8/8/8 (true color, reserved) PX_PREF32 32bit argb a/8/8/8 (true color) PX_VGA32 32bit rgba 8/8/8/a (true color, reversed) The image data format is reported as an NVDI pixel format. This makes it easy to use NVDI for those that want to go that route. See NVDI.H for more info. Images are processed in one call and always arrive right side up and ready to blit. The image data is placed in a buffer supplied by the caller. The size of the buffer should be: BMPSIZE(width,height,AND(px_format,PX_BITS)); The palette types are: 0 None high/true color (no palette) 1 ST 3/3/3 ----x210x210x210 Setcolor() 2 STE 4/4/4 ----032103210321 Setcolor() 3 TT030 4/4/4 ----321032103210 EsetColor() 4 Falcon 8/8/x/8 RG0B VgetRGB()/VsetRGB() 5 VDI 0-1000 3 RGB words vq_color() in VDI order 6 VDIX 0-1000 3 RGB words vq_color() in Xbios order 7 RGB 0-255 3 RGB bytes true color not padded 8 RGBX 0-255 4 RGBX bytes true color padded Once the bitmap/palette arrive the caller has a few options: 1) If the video mode matches the bitmap, it's ready to blit 2) Caller can manage the bitmap/palette with custom code 3) Caller can use NVDI to transform the bitmap (also dither/scale) In most cases, if it's an Atari image file format, expect a native Atari bimap and palette. Exceptions to this rule are JPEG, TIFF, WebP, or other image formats not native to the Atari ST. In most cases the exceptions will be 8-bit chunky color mapped or true color. Formats the use tricky stuff like rasters to get more colors than normal will not arrive in native Atari formats.

Saving overview

When saving images the plugin expects the image data in full 24-bit. The pixel format should match NVDI's PX_PREF24. For the sake of clarity lets say we have a sample image: Sample in this case is 320x200 image data size = (320 * 200) * 3 every 3 bytes represents 1 pixel (RGB order) byte values will range from 0 to 255 R0 G0 B0, R1 G1 B1, R2 G2 B2, ... , R319, G319, B319 Note: The plugin expects the image data to be word aligned, meaning correctly aligned for blitting. The pixel width should be evenly divisible by 16. This makes using NVDI 5 inside the plugins much easier. There's no palette since the image data itself is direct color.

Image info structure

Plugins communicate with the caller via an IMGINFO structure. It's passed to all plugin subroutines. The plugin will then alter the fields of the structure. The structure should be zeroed before use. Which IMGINFO structure fields should be used to determine the data format? (marked with an '*') Field Description ---------------- ------------------------------------------------------------ width width in pixels height height in pixels planes 1 to 32, informational use only! colors calculated colors, informational use only! pages image/frame count, used by multipage documents or animations delay frame delay in 200th of a second, for animations palette valid if pal_type > 0 space for 256 colors regardless if it uses less background_color color used for transparency (24-bit xRGB, white = $00FFFFFF) page_wanted frame to load, always 0 for images (passed in) also used for loading animations info string describing image format max 39 chars, null terminated more additonal image information max 39 chars, null terminated compression string describing compression method max 29 chars, null terminated vdi_handle vdi handle of the caller (must be sent to the plugin) px_format* NVDI pixel format that describes image data layout pal_type palette type bpl bytes per line, always word aligned The proper way to determine the image data format: Use px_format, bit planes can be gotten with planes=AND(px_format,PX_BITS) Never rely on fields 'planes' or 'colors'. These fields are provided for informational use only. They describe the content of the original file, not the layout of the image data the plugin is sending. Relying on these will cause failure. For further reading see PLUGIN.H included with this archive.

Using the image plugins

Fixed location of plugins: c:\gemsys\plugin\ The full path would be something like: c:\gemsys\plugin\ Loading a plugin: bp%=pexec(path,3,null,null) !3 = load, but don't go ~MFREE(long{bp%+44}) !free the env ram, not needed ~MSHRINK(bp%,256+LONG{bp%+12}+LONG{bp%+20}+LONG{bp%+28}) !shrink to basepage values ~SSYSTEM(22,bp%,-1) !flush caches just incase bp% is the basepage of the plugin, it's used to reference a specific plugin once loaded. If bp%<=0 something when wrong. Fetch the pointer to the function table: getfnctab%=LONG{bp%+&H8} !calc entry point of main() fnctab%=C:getfnctab%() !get pointer to function table Get the entry points of all functions: plugin_init%=LONG{ptr%+28} !required pluing_exit%=LONG{ptr%+32} !optional These loading/saving: plugin_open%=LONG{ptr%+36} !open file plugin_rw%=LONG{ptr%+40} !read or write file plugin_close%=LONG{ptr%+44} !close file To unload an plugin: ~MFREE(bp%) If you want to keep multiple plugins resident don't close them until you are done with all of them. You will have to keep track of multiple plugins. It's easy to write wrappers for loading and unloading the plugins: plugin_load() and plugin_unload() For further information see plugin.h.

Overview of plugin functions

Initialize: plugin_init() Loading and saving: plugin_open(load) plugin_open(save) plugin_rw(load) plugin_rw(save) plugin_close(load) plugin_close(save)


Description Allows the plugin to initialize itself. Must be called first before any other calls. Should be called after loading the plugin. Call C: void plugin_init(void); GFA: ~C:plugin_init%() Parameters None Return None See also plugin_close()


Description Opens the file and gathers information. Should be called after plugin_init(). Call C: int32 plugin_open(IMGINFO info, const char *name); GFA: status&=C:plugin_open(L:info%,L:V:name$) Parameters name: full path to the input image file info: IMGINFO structure (see plugin.h) info->options Setting depends on plugin (see plugin options) info->vdi_handle Callers VDI workstation handle info->aes_global Pointer to callers AES Global array info->background_color Background color for transparent pixels Return Status of the call, 0=Ok else error code (see ec_error.h) The call will populate the info structure: (see plugin.h) info->width Width in pixels info->height Height in pixels info->planes Bits per pixel (informational use only) info->colors Total colors (informational use only) info->pal_type Descibes the palette type info->pages Total images/frames in the file info->palette If not true color, the palette info->info File format details info->more Additional information about the file (optional) info->compression Compression method info->px_format Describes the pixel format of the bitmap (see nvdi.h) Notes It would be wise to clear the info structure prior to making this call. See also plugin_rw(load), plugin_close(load)


Description Get the bitmap. The entire bitmap will be returned. Before calling this function the caller should calculate the required buffer size making sure it's enough for a word aligned bitmap. The plugin sends a ready to blit bitmap. The caller also needs to calculate the bytes per lines. bms = bmpsize(info->width, info->height, info->planes) bpl = bms \ info->height Alternately one can use NVDI 5's newer off screen bitmaps and let NVDI figure out the bitmap size. The bpl can be found in the gcbitmap structure. Call C: int32 plugin_rw(IMGINFO info, uint8 *buffer); GFA: status&=C:plugin_rw%(L:info%, L:buffer%) Parameters info: IMGINFO structure (see plugin.h) buffer: Address where to place the bitmap info->page_wanted Requested image/frame info->bpl Bytes per line of callers buffer Return Status of the call, 0=Ok else error code (see ec_error.h) Notes After the call the entire bitmap will be in the callers buffer. See also plugin_open(load), plugin_close(load)


Description Close image file and free all memory. This is very important. Must be called even if plugin_open(load) or plugin_rw(load) fail. Failure to do so will result in memory leaks and/or running out of file handles! Call C: int32 plugin_close(IMGINFO info); GFA: status&=C:plugin_close%(L:info%) Parameters info: IMGINFO structure (see plugin.h) Return Status of the call, 0=Ok else error code (see ec_error.h) Notes Doesn't unload the plugin. See also plugin_open(load), plugin_rw(load)


Description Creates the image file and begins the saving process. Must be called after plugin_init(). Call C: int32 plugin_open(IMGINFO info, const char *name); GFA: status&=C:plugin_open%(L:info%,L:V:name$) Parameters name: full path to the output image file info: IMGINFO structure (see plugin.h) info->options Setting depends on plugin (see plugin options) info->width Width in pixels info->height Height in pixels info->bpl Byte per line for the image buffer caller sends info->vdi_handle Callers workstation handle info->aes_global Pointer to callers AES Global array Return Status of the call, 0=Ok else error code (see ec_error.h) The call populates the info structure: (see plugin.h) info->planes Bits per pixel info->colors Total colors info->pages Number of images/frames, typically 1 info->info File format details info->more Informational (optional) info->compression Compression method (optional) Notes It would be wise to clear the info structure prior to making this call. The values returned in the structure are for informaitonal use only. They dont' really serve any useful purpose. See also plugin_rw(save), plugin_close(save)


Description Send the image data. The entire bitmap will be passed. Image data must be word aligned (blit'able), pixel width evenly divisble by 16. Call C: int32 plugin_rw(IMGINFO info, uint8 *buffer); GFA: status&=plugin_rw(L:info%,L:buffer%) Parameters info: IMGINFO structure (see plugin.h) buffer: Address of the bitmap Return Status of the call, 0=Ok else error code (see ec_error.h) See also plugin_open(save), plugin_close(save)


Description Close image file and free all memory. This is very important. Must be called even if plugin_open(save) or plugin_rw(save) fail. Failure to do so will result in memory leaks and/or running out of file handles! Call C: int32 plugin_close(IMGINFO info); GFA: status&=C:plugin_close%(L:info%) Parameters info: IMGINFO structure (see plugin.h) Return Status of the call, 0=Ok else error code (see ec_error.h) Notes Doesn't unload the plugin. plugin_open(save), plugin_rw(save) See also

plugin options

Set plugin options. Only certain plugins support options. Different plugins have a different number of options. Any unused options should be ignored. There's 8 reserved structure entries for options. info->options = 0 Use sane defaults 1 Use custom settings Note: An out of range option can cause an error. Options marked with an * are defaults.
Load options: Currently no plugin support options. info->options should be set to 0.
Save options: JPEG TIFF WEBP info->option1 Quality + + + info->option2 Compression + info->option3 Color space + info->option4 Progrssive + info->option5 info->option6 info->option7 info->option8 JPEG: (3 options) 1) quality: 1 to 100 (90*) 2) color space: 1 = Grayscale 2 = RGB* 3) progressive: 0 = No* 1 = Yes TIFF: (2 options) 1) quality: 1 to 100 (75*) 2) compression: 1 = None 5 = LZW* 7 = JPG-DCT 32773 = Mac-RLE 32946 = Deflate WEBP: (1 option) 1) quality: 0 to 100 (75*) Example: Set JPEG save options: info->option1 = 95; /* quality */ info->option3 = 1; /* color space */ info->option4 = 0; /* progressive */ See also plugin_open(load), plugin_open(save)

Palette handling

It's up to the caller to manage the palette. The plugin will send a palette type. They are: None (0) No palette. Only valid for direct color, 15-bit to 32-bit ST (1) Palette is 3 bits per RGB arranged as words Bits: ____xRRRxGGGxBBB -> ____x210x210x210 I0, I1, I2, ... See Xbios function Setcolor() STE (2) Palette is 4 bits per RGB arranged as words Bits: ____RRRRGGGGBBBB -> ____032103210321 I0, I1, I2, ... See Xbios function Setcolor() TT030 (3) Palette is 4 bits per RGB arranged as words Bits: ____RRRRGGGGBBBB> ____321032103210 -> I0, I1, I2, ... See Xbios function EsetColor() Falcon (4) Palette is 8 bits per RGB arranged as longs Bits: RRRRRRRRGGGGGGGG________BBBBBBBB -> 7654321076543210________76543210 I0, I1, I2, ... See Xbios function VsetRGB() VDI (5) Palette is arranged as words, 3 words per RGB Each word is 0 to 1000 R0, G0, B0, R1, G1, B1, ... See VDI function vs_color() The index order is VDI order VDIX (6) Palette is arranged as words, 3 words per RGB Each word is 0 to 1000 R0, G0, B0, R1, G1, B1, ... See VDI function vs_color() The index order is Xbios order RGB (7) Palette is arranged as bytes, 3 bytes per RGB Each byte is 0 to 255 R0, G0, B0, R1, G1, B1, ... There's no system call for this one RGBX (8) Palette is arranged as bytes, 4 bytes per RGBX, padded to make it even Each byte is 0 to 255, excpet the 4th byte which is filler (X) R0, G0, B0, X0, R1, G1, B1, X1, ... There's no system call for this one

General program overview

For loading: Load the desired plugin -> status&=@plugin_load(...) Call the plugin_init() routine of the pluign (required) Create the IMGINFO structure (plugin_open(load) will update the structure) Set info->options to zero Set info->vdi_handle Call plugin_open(load) to gather information about the desired image Calculate bpl (bytes per line) Set info->bpl Set info->page_wanted to 0 (images have only 1 frame) Call plugin_rw(load) to get the bitmap/palette Call plugin_close(load) to free the plugin resources Unload the plugin -> status&=@plugin_unload() You will have to decide how to process the bitmap/palette
For saving: Load the desired plugin -> status&=@plugin_load() Call the plugin_init() routine of the plugin (required) Create the IMGINFO structure (plugin_open(save) will update the structure) Set info->options accordingly (see save options for more information) Set info->width Set info->height Set info->vdi_handle Set info->bpl Call plugin_open(save) to create desired image file Call plugin_rw(save) with buffer address (24-bit bitmap) Call pluginr_close(save) to free the plugin resources Unload the plugin -> status&=@plugin_unload() In both cases the stucture should be zeroed before use. Functions that return values return signed 32-bit longs.

Error handling

The plugin returns usable error codes. Zero (0) is considered ok. Values other than zero should be treated as error codes. Example: status&=C:plugin_open%(L:V:path$,L:info%) IF status& !file was rejected? errtext$=@err_to_txt$(status&) !convert to human readable text ENDIF These functions return error codes: plugin_open, plugin_rw, plugin_close Packaged along with the plugins is a 'C' header file (EC_ERROR.H) with a list of defines covering all possible error codes. It's up to the caller to translate the error code into human readable form and display it. It's done this way to keep the size of the plugins to a minimum. See contents of file EC_ERROR.H:

GFA-Basic source code

For further assistance see il_load.gfa and is_save.gfa source listings. I used ABSOLUTE to make things a bit easier since I'm only ever working with a single plugin. Pointer operations like {img_info%+offset&} could also be used, whatever floats your boat. ;o) > PROCEDURE plugin.h ' plugin structure ' ii_struct_size&=1192+512 !structure size in bytes ' ' method 1: increases binary size ' INLINE imginfo_%,1192 ' ' method 2: under mint, ram is rouned up to 8k blocks ' imginfo_%=MALLOC(ii_struct_size&) ' IF imginfo_%=NULL ' ' throw an alert! ' EDIT ' ENDIF ' ' method 3: use gfa's internal ram DIM imginfo_|(ii_struct_size&) imginfo_%=V:imginfo_|(0) ' ' see plugin.h (if this structure ever changes, these offsets need updated!) ' setup direct read/write access to structure elements ' ABSOLUTE ii_width&,imginfo_%+0 !image width in pixels ABSOLUTE ii_height&,imginfo_%+2 !image height in pixels ABSOLUTE ii_reserved1&,imginfo_%+4 !unused ABSOLUTE ii_planes&,imginfo_%+6 !info only, can't rely on it ABSOLUTE ii_colors%,imginfo_%+8 !info only, can't rely on it ABSOLUTE ii_pal_type&,imginfo_%+12 !palette type ABSOLUTE ii_pages&,imginfo_%+14 !number of pages/frames in the file ABSOLUTE ii_delay&,imginfo_%+16 !for animations, frame delay (200th of a second) ABSOLUTE ii_reserved3&,imginfo_%+18 !unused ABSOLUTE ii_reserved4&,imginfo_%+20 !unused ABSOLUTE ii_reserved2&,imginfo_%+22 !unused ABSOLUTE ii_vdi_handle&,imginfo_%+24 !callers vdi handle ii_palette%=imginfo_%+26 !padded to 4 bytes, 'rgb0', thus 256*4 bytes total ABSOLUTE ii_background_color%,imginfo_%+1050+512 !as a long '0rgb' (transparent color) ABSOLUTE ii_bpl&,imginfo_%+1054+512 !bytes per line ABSOLUTE ii_page_wanted&,imginfo_%+1056+512 !request this page, 0 to frames-1 ii_info%=imginfo_%+1058+512 !null terminated string (40 bytes) ii_more%=imginfo_%+1098+512 !null terminated string (40 bytes) ii_compression%=imginfo_%+1138+512 !null terminated string (30 bytes) ABSOLUTE ii_px_format%,imginfo_%+1168+512 !nvdi 5 pixel format ' ' beyond this point is private stuff used by the plugin ' ' absolute ii_priv_ptr_%,imginfo_%+1172 ' absolute ii_priv_ptr_more_%,imginfo_%+1176 ' absolute ii_priv_ptr_more__%,imginfo_%+1180 ' absolute ii_priv_var_%,imginfo_%+1184 ' absolute ii_priv_var_more_%,imginfo_%+1188 ' RETURN

Plugin Stack size

Plugins that require a large stack (> 8 kb) need to have the super bit set in the program header. GBE has special support via PLUGIN_LOAD().


Dithering can be achieved three ways: 1) NVDI v5.03 -> vr_transfer_bits(), tested and works. 2) Try using screen.ldg from the LDG website, untested. 3) Roll your own dithering, good luck. Note: Only NVDI v5.03 dithers correctly, lesser versions are all bugged.

Loading animations

Loading animations is similar to loading an image. The difference is you take field entry pages (number of frames) and load exactly that many images. For each frame requested page_wanted is increased. You have to convert and store all the frames. Each frame has it's own delay and these will need to be stored as well. After all frames are loaded play them back in a loop using the delays.

Improvements over other codecs

Compared to zView/LDG: Plugins do not require LDG All main calls return detailed error codes Most plugins have a smaller binary footprint (except a few built with gcc) API has been simplified Supports file extensions from 1 to 4 characters Images always arrive right side up, less work for the caller Expanded compression field for more detailed information An addtional line of information available for extra format details Dedicated structure for plugin details: format name, author name, version, build date, and a line of additional info Split into Load and Save plugins to reduce memory footprint Not scan line based, faster image transfers Compared to zView/SLB: Plugins do not require the SLB interface. Pretty much the same results since this mutated zView does not bother to address 99% of the above issues other than attempting to make them smaller. However, my plugins still win in some cases on binary size. This depends on how many C library calls are made. To make matters worse, SLB's (with callbacks) are very non-C friendly. It does offer the addtional line of information, but that's it. Breakdown of the flaws in the LDG design Complete lack of error codes. Even though a codec knows exactly what went wrong it has no way to pass that back to the caller. No joke! File extensions are fixed at 3 chars, thus '' can't be loaded. Likewise it has issues with long file names Example: It sees 'image.tiff' as 'image.iff' Compression field limited to 5 characters LDG memory leaks, as LDG.PRG is known to be buggy Forces the caller to manage upside down images. No provisions for codec info like author name, version, build date, etc Doesn't handle export only codecs correctly, assumes they can import as well Scan line based, slower Single codec contains load and save code, larger memory footprint

Changes from previous API

Parameters reversed on plugin_open() and encoder_open(). Function decoder_get_txt() and encoder_options() removed. Function table made smaller. Encoder/Decoder options are now passed in the IMGINFO structure. IMGINFO structure size increased to add new entries. Internal plugin_deinit() removed.

Misc notes

Just some stuff I put here so I don't forget it. You can't trust 'planes'. The proof is in zView's own source code archive. See godldg.c where it sets planes to 16, but transforms the image data to 24-bit before sending it to zView. In tgaldg.c planes is set to match the tga header and then 15/16-bit images are again converted to 24-bit before being sent to zView. Quite a few plugins were written by me. They are created with Pure C. Unfortunately GFA-Basic can't be used to create them. GEM-View plugins are a mixture of 'C' and assembler and harder to create. The plugin documentation is all in German. Partly why I decided to create zView style plugins. Since they rely on file extensions, they need to be unique to all plugins. This means if you have two or more file formats that use the same file extension, then one plugins must deal with them all. Not entirely elegant but doable. At least for GFA, if you think wrapping the C:() functions in pretty wrappers is a good idea, you'd be wrong. It will actually slow down the scan line fetching since GFA pass parameters on the stack.


Joakim Högberg (aka GokMasE) testing Janez Valant (aka SWE) testing Anders Lindström testing and bug reports Zorro for creating a flawed design. Thorsten Otto for creating a varaint that's clunky at best with GFA.


#define NVDI_COOKIE 0x4E564449L /* 'NVDI' */ #define NVDI_VERSION 0x0503 #define VQ_EXTENDED 1 #define CSPACE_RGB 1 #define CBITMAP_MAGIC 'cbtm' /*----------------------------------------------------------------------------------------*/ /* Structures */ /*----------------------------------------------------------------------------------------*/ typedef struct _gcbitmap { /* Public bitmap description (with version header) */ int32 magic; /* Structure identifier 'cbtm' */ int32 length; /* Structure length */ int32 format; /* Structure format (0) */ int32 reserved; /* Reserved (0) */ uint8 *addr; /* Bitmap address */ int32 width; /* Width of a line in bytes */ int32 bits; /* Bit depth */ uint32 px_format; /* Pixel format */ int32 xmin; /* minimum discrete x-coordinate of the bitmap */ int32 ymin; /* minimum discrete y-coordinate of the bitmap */ int32 xmax; /* maximum discrete x-coordinate of the bitmap + 1 */ int32 ymax; /* maximum discrete y-coordinate of the bitmap + 1 */ uint8 *ctab; /* Reference to the color table or 0L */ uint8 *itab; /* Reference to the inverse color table or 0L */ int32 reserved0; /* Reserved (0) */ int32 reserved1; /* Reserved (0) */ } GCBITMAP; /*----------------------------------------------------------------------------------------*/ /* Constants for pixel formats */ /*----------------------------------------------------------------------------------------*/ #define PX_1COMP 0x01000000L /* Pixel consists of one used component: color index */ #define PX_3COMP 0x03000000L /* Pixel consists of three components used, e.g. RGB */ #define PX_4COMP 0x04000000L /* Pixel consists of four components used, e.g. CMYK */ #define PX_REVERSED 0x00800000L /* Pixel is output in reverse byte order */ #define PX_xFIRST 0x00400000L /* Unused bits precede the used bits (viewed in Motorola format) */ #define PX_kFIRST 0x00200000L /* K is in front of CMY (viewed in Motorola format) */ #define PX_aFIRST 0x00100000L /* Alpha channels are in front of the color bits (viewed in Motorola format) */ #define PX_PACKED 0x00020000L /* Bits are stored consecutively */ #define PX_PLANES 0x00010000L /* Bits are distributed over several levels (order: 0, 1, ..., n) */ #define PX_IPLANES 0x00000000L /* Bits are distributed over several words (order: 0, 1, ..., n) */ #define PX_USES1 0x00000100L /* 1 bit of the pixel is used */ #define PX_USES2 0x00000200L /* 2 bits of the pixel are used */ #define PX_USES3 0x00000300L /* 3 bits of the pixel are used */ #define PX_USES4 0x00000400L /* 4 bits of the pixel are used */ #define PX_USES8 0x00000800L /* 8 bits of the pixel are used */ #define PX_USES15 0x00000f00L /* 15 bits of the pixel are used */ #define PX_USES16 0x00001000L /* 16 bits of the pixel are used */ #define PX_USES24 0x00001800L /* 24 bits of the pixel are used */ #define PX_USES32 0x00002000L /* 32 bits of the pixel are used */ #define PX_USES48 0x00003000L /* 48 bits of the pixel are used */ #define PX_1BIT 0x00000001L /* Pixel consists of 1 bit */ #define PX_2BIT 0x00000002L /* Pixel consists of 2 bits */ #define PX_3BIT 0x00000003L /* Pixel consists of 2 bits */ #define PX_4BIT 0x00000004L /* Pixel consists of 2 bits */ #define PX_8BIT 0x00000008L /* Pixel consists of 2 bits */ #define PX_16BIT 0x00000010L /* Pixel consists of 2 bits */ #define PX_24BIT 0x00000018L /* Pixel consists of 2 bits */ #define PX_32BIT 0x00000020L /* Pixel consists of 2 bits */ #define PX_48BIT 0x00000030L /* Pixel consists of 2 bits */ #define PX_CMPNTS 0x0f000000L /* Mask for number of pixel components */ #define PX_FLAGS 0x00f00000L /* Mask for various flags */ #define PX_PACKING 0x00030000L /* Mask for pixel format */ #define PX_USED 0x00003f00L /* Mask for the number of bits used */ #define PX_BITS 0x0000003fL /* Mask for the number of bits per pixel */ /*----------------------------------------------------------------------------------------*/ /* Pixel formats for ATARI graphics */ /*----------------------------------------------------------------------------------------*/ #define PX_ATARI1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_ATARI2 ( PX_IPLANES + PX_1COMP + PX_USES2 + PX_2BIT ) #define PX_ATARI4 ( PX_IPLANES + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_ATARI8 ( PX_IPLANES + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_FALCON15 ( PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) /*----------------------------------------------------------------------------------------*/ /* Pixel formats for Macintosh */ /*----------------------------------------------------------------------------------------*/ #define PX_MAC1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_MAC4 ( PX_PACKED + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_MAC8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_MAC15 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_MAC32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /*----------------------------------------------------------------------------------------*/ /* Pixel formats for graphics cards */ /*----------------------------------------------------------------------------------------*/ #define PX_VGA1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_VGA4 ( PX_PLANES + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_VGA8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_VGA15 ( PX_REVERSED + PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_VGA16 ( PX_REVERSED + PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) #define PX_VGA24 ( PX_REVERSED + PX_PACKED + PX_3COMP + PX_USES24 + PX_24BIT ) #define PX_VGA32 ( PX_REVERSED + PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) #define PX_MATRIX16 ( PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) #define PX_NOVA32 ( PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /*----------------------------------------------------------------------------------------*/ /* Pixel formats for printers */ /*----------------------------------------------------------------------------------------*/ #define PX_PRN1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_PRN8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_PRN32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /*----------------------------------------------------------------------------------------*/ /* Preferred (fast) pixel formats for bitmaps */ /*----------------------------------------------------------------------------------------*/ #define PX_PREF1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_PREF2 ( PX_PACKED + PX_1COMP + PX_USES2 + PX_2BIT ) #define PX_PREF4 ( PX_PACKED + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_PREF8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_PREF15 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_PREF32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) #define PX_PREF24 ( PX_PACKED + PX_3COMP + PX_USES24 + PX_24BIT ) /* lp */ #define PX_ATARI16 ( PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) /* lp */ /*----------------------------------------------------------------------------------------*/ /* Transfer modes for bitmaps */ /*----------------------------------------------------------------------------------------*/ /* Mode constants */ #define T_NOT 4 /* Constant for inversion in logical transfer modes */ #define T_COLORIZE 16 /* Constant for coloring */ #define T_LOGIC_MODE 0 #define T_DRAW_MODE 32 #define T_ARITH_MODE 64 /* Constants for arithmetic transfer modes */ #define T_DITHER_MODE 128 /* Constant for dithering */ /* Logical transfer modes */ #define T_LOGIC_COPY T_LOGIC_MODE+0 #define T_LOGIC_OR T_LOGIC_MODE+1 #define T_LOGIC_XOR T_LOGIC_MODE+2 #define T_LOGIC_AND T_LOGIC_MODE+3 #define T_LOGIC_NOT_COPY T_LOGIC_MODE+4 #define T_LOGIC_NOT_OR T_LOGIC_MODE+5 #define T_LOGIC_NOT_XOR T_LOGIC_MODE+6 #define T_LOGIC_NOT_AND T_LOGIC_MODE+7 /* Drawing modes */ #define T_REPLACE T_DRAW_MODE+0 #define T_TRANSPARENT T_DRAW_MODE+1 #define T_HILITE T_DRAW_MODE+2 #define T_REVERS_TRANSPARENT T_DRAW_MODE+3 /* Arithmetische Transfermodi */ #define T_BLEND T_ARITH_MODE+0 #define T_ADD T_ARITH_MODE+1 #define T_ADD_OVER T_ARITH_MODE+2 #define T_SUB T_ARITH_MODE+3 #define T_MAX T_ARITH_MODE+5 #define T_SUB_OVER T_ARITH_MODE+6 #define T_MIN T_ARITH_MODE+7 /* eof */


/* error codes for all plugins */ /* note: 1 to 9 are not used, we start at 10 */ /* if negative it's a standard gemdos error code */ /* if positive it's related to the content of the file */ /* standard gemdos error codes, these are just here for my reference */ /* codecs return gemdos error codes where it makes sense */ #define EC_Fwrite -10 /* fwrite failed, size in/out didn't match, or negative error code */ #define EC_Fread -11 /* fread failed, size in/out didn't match, or negative error code */ #define EC_Fopen -33 /* fopen failed, image file not found */ #define EC_Fcreate -36 /* fcreate failed */ #define EC_Fclose -37 /* fclose failed */ #define EC_Malloc -39 /* malloc failed */ #define EC_Mfree -40 /* mfree failed */ #define EC_Fseek -64 /* fseek failed, truncated file or eof */ #define EC_Ok 0 /* no error */ /* error codes related to file content */ /* these will be used in multiple plugins and new ones in the future */ #define EC_CompType 10 /* header -> unsupported compression type */ #define EC_DecompError 11 /* error during decompression phase */ #define EC_ResolutionType 12 /* header -> unsupported mode code neo/degas */ #define EC_ImageType 13 /* header -> unsupported image type */ #define EC_PixelDepth 14 /* header -> unsupported pixel depth */ #define EC_ColorMapDepth 15 /* header -> unsupported color map depth */ #define EC_ColorMapType 16 /* header -> unsupported color map type */ #define EC_FileLength 17 /* incorrect file length */ #define EC_FileId 18 /* header -> unknown file identifier */ #define EC_HeaderLength 19 /* header -> unsupported header length */ #define EC_WidthNegative 20 /* header -> image width < 0 */ #define EC_HeightNegative 21 /* header -> image height < 0 */ #define EC_InternalError 22 /* non-specific, subfunction failure: png/gif */ #define EC_ColorSpace 23 /* header -> unsupported color space */ #define EC_ColorMapLength 24 /* header -> unsupported color map length */ #define EC_MaskType 25 /* header -> unsupported mask type */ #define EC_ChunkId 26 /* unsupported chunk identifier: iff */ #define EC_FileType 27 /* received wrong file type */ #define EC_FrameCount 28 /* frame count exceeds limit */ #define EC_ColorCount 29 /* header -> unsupported color count */ #define EC_BitmapLength 30 /* header -> calc'd length doesn't match */ #define EC_HeaderVersion 31 /* header -> unsupported version */ #define EC_HeightSmall 32 /* header -> unsupported height, to small: fnt */ #define EC_CompLength 33 /* header -> incorrect compressed size: spx */ #define EC_FrameType 34 /* header -> unsupported frame type: seq */ #define EC_RequiresNVDI 35 /* NVDI not installed */ #define EC_FuncNotDefined 36 /* function not implemented */ /* new as of 12/18/2021 */ #define EC_StructLength 37 /* incorrect structure length */ #define EC_RequiresJPD 38 /* JPEGD DSP decoder not installed */ #define EC_OpenDriverJPD 39 /* JPEGD OpenDriver() failed */ #define EC_GetImageInfoJPD 40 /* JPEGD GetImageInfo() failed */ #define EC_GetImageSizeJPD 41 /* JPEGD GetImageSize() failed */ #define EC_DecodeImageJPD 42 /* JPEGD DecodeImage() failed */ #define EC_OrientationBad 43 /* orientation unsupported */ #define EC_BadHandleVDI 44 /* Invalid VDI handle */ #define EC_v_open_bmERR 45 /* Failed at v_open_bm() */ #define EC_WordWidth 46 /* Pixel width not divisible by 16 */ #define EC_BufferOverrun 47 /* data could exceed buffer, aborted */ #define EC_DecoderOptions 48 /* decoder option out of range */ #define EC_EncoderOptions 49 /* encoder option out of range */ #define EC_WidthOver4K 50 /* width exceeds 4096 pixels */ #define EC_DirectColorERR 51 /* plugin doesn't support direct color */ #define EC_Requires256 52 /* plugin requires 256 color mode */ #define EC_BadGlobalAES 53 /* Invalid pointer to AES global array */ #define EC_InvalidHeader 54 /* Header failed sandity check(s) */ /* new error codes will be added to the end of this list as needed */ /* eof */


/* * Plugin header file, API v2.00 */ #include <plugin\types2b.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <tos.h> #include <setjmp.h> #include <vdi.h> #include <plugin\nvdi.h> #include <plugin\ec_error.h> #ifdef __PUREC__ #define CDECL cdecl #else #include <compiler.h> #define CDECL __CDECL #endif #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef MIN #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #endif /* FNCTAB structure */ typedef struct { /* offset */ uint32 id; /* 0 id -> 'GB32' */ uint16 version; /* 4 version: $0112 -> v1.12 */ uint16 flags; /* 6 bits: 0=load 1=save 2-15=not used */ char *ext_list; /* 8 extention list, 4 chars each, null terminated */ char *format; /* 12 format name, null terminated */ char *author; /* 16 plugin author, null terminated */ char *misc; /* 20 additional information, null terminated */ char *timestamp; /* 24 build date/time, null terminated */ void *plg_init; /* 28 plugin init, required */ void *plg_userdef; /* 32 caller can put whatever here */ void *plg_open; /* 36 open image for read, nulls if save plugin */ void *plg_rw; /* 40 read/write image data */ void *plg_close; /* 44 close file, free all resources */ } FNCTAB; /* 48 bytes total */ /* Palette types type size in bytes */ #define CPAL_NONE 0 /* 0 */ #define CPAL_ST 1 /* 32 16*2 */ #define CPAL_STE 2 /* 32 16*2 */ #define CPAL_TT030 3 /* 512 256*2 */ #define CPAL_FALCON 4 /* 1024 256*4 */ #define CPAL_VDI 5 /* 1536 256*(3*2) */ #define CPAL_VDIX 6 /* 1536 256*(3*2) */ #define CPAL_RGB 7 /* 768 256*3 */ #define CPAL_RGBX 8 /* 1024 256*(3+1) padded */ typedef struct { uint8 red; uint8 green; uint8 blue; } COLOR_MAP; /* IMGINFO structure */ typedef struct { /* size offset */ int16 width; /* pixel width 2 +0000 */ int16 height; /* pixel height 2 +0002 */ int16 options; /* options flag: true=set/false=defaults 2 +0004 */ uint16 planes; /* bits per pixel 2 +0006 */ uint32 colors; /* total colors 4 +0008 */ int16 pal_type; /* palette type 0 to 8 2 +0012 */ uint16 pages; /* number of frames/images in the file 2 +0014 */ uint16 delay; /* animation delay, 200th sec. between each frame 2 +0016 */ int16 reserved1; /* unused 2 +0018 */ void *aes_global; /* ptr to aes global array 4 +0020 */ int16 vdi_handle; /* callers vdi handle 2 +0024 */ COLOR_MAP palette[256]; /* palette, layout depends on the image 1536 +0026 */ uint8 pal[512]; /* filler to get palette to 1536 bytes */ uint32 background_color; /* use for transparent color (xxRRGGBB) 4 +1562 */ uint16 bpl; /* bytes per line, caller image buffer 2 +1566 */ uint16 page_wanted; /* frame/image to fetch, 0 to pages - 1 2 +1568 */ char info[40]; /* image info, ex: "Gif 87a" 40 +1570 */ char more[40]; /* Extra picture info, ex: "Interlaced" 40 +1610 */ char compression[30]; /* compression type, ex: "LZW" 30 +1650 */ uint32 px_format; /* nvdi 5 pixel format, describes bitmap layout 4 +1680 */ /* options: encoder decoder */ int32 option1; /* quality - 4 +1684 */ int32 option2; /* compression - 4 +1688 */ int32 option3; /* color space - 4 +1692 */ int32 option4; /* progressive - 4 +1696 */ int32 option5; /* - - 4 +1700 */ int32 option6; /* - - 4 +1704 */ int32 option7; /* - - 4 +1708 */ int32 option8; /* - - 4 +1712 */ /* private data for plugins */ void *_priv_ptr; /* 4 +1716 */ void *_priv_ptr_more; /* 4 +1720 */ void *__priv_ptr_more; /* 4 +1724 */ int32 _priv_var; /* 4 +1728 */ int32 _priv_var_more; /* 4 +1732 */ } IMGINFO; /* total 1736 */ /* prototypes */ void CDECL plugin_init(void); void CDECL plugin_deinit(void); /* these must be int32 or c:asm%() fails with 'number not a word' in gfa */ int32 CDECL plugin_open(IMGINFO *info, const char *name); int32 CDECL plugin_rw(IMGINFO *info, uint8 *buffer); int32 CDECL plugin_close(IMGINFO *info); #define INFO_TIMESTAMP (__DATE__" "__TIME__) /* build date/time */ #define INFO_ID 0x47423332L /* 'GB32' */ FNCTAB fnctab = { INFO_ID, INFO_VERSION, INFO_FLAGS, INFO_EXTENSIONS, INFO_FORMAT, INFO_AUTHOR, INFO_MISC, INFO_TIMESTAMP, plugin_init, 0L, plugin_open, plugin_rw, plugin_close, }; /* eof */

Revision history

v1.00 12/21/2021 1st public release (API v1.00) v2.00 03/26/2023 New plugin API v2.00 IL_LOAD.GFA replaces IM_LOAD.GFA IS_SAVE.GFA replaces IM_SAVE.GFA Split developers kit into it's own HYPertext v2.01 11/14/2023 background setting added v2.02 11/29/2023 support for plugins with large stacks Added pointer to AES global array to API


C Changes from previous API Credits D Default Dithering E EC_ERROR.H ec_error.h ENCOM error code error codes Error handling F Falcon FNCTAB function table G General program overview GFA-Basic GFA-Basic source code H Handling file extensions Help I Image info structure IMGINFO Improvements over other codecs index Introduction L Loading animations Loading overview Lonny Pursell M Main Misc notes N None NVDI nvdi.h NVDI.H O Overview of plugin functions P Palette handling palette type palette types pal_type plugin options Plugin Stack size plugin.h PLUGIN.H plugin_close(load) plugin_close(save) plugin_init() plugin_open(load) plugin_open(save) plugin_rw(load) plugin_rw(save) px_format R Revision history RGB RGBX S save options Saving overview ST STE T TT030 U Using the image plugins V VDI VDIX