| 1 | /*
|
|---|
| 2 |
|
|---|
| 3 | gbmkps.c - IBM KIPS support
|
|---|
| 4 |
|
|---|
| 5 | Reads array as 8 bit palettised colour.
|
|---|
| 6 | Writes 8 bit palettised colour.
|
|---|
| 7 | Input options: pal,kpl (default: pal)
|
|---|
| 8 | Output options: pal,kpl (default: pal)
|
|---|
| 9 |
|
|---|
| 10 | */
|
|---|
| 11 |
|
|---|
| 12 | /*...sincludes:0:*/
|
|---|
| 13 | #include <stdio.h>
|
|---|
| 14 | #include <ctype.h>
|
|---|
| 15 | #include <stddef.h>
|
|---|
| 16 | #include <stdlib.h>
|
|---|
| 17 | #include <string.h>
|
|---|
| 18 | #include "gbm.h"
|
|---|
| 19 | #include "gbmhelp.h"
|
|---|
| 20 |
|
|---|
| 21 | /*...vgbm\46\h:0:*/
|
|---|
| 22 | /*...vgbmhelp\46\h:0:*/
|
|---|
| 23 |
|
|---|
| 24 | /* Handle case for UNIX machines where O_BINARY has no meaning */
|
|---|
| 25 |
|
|---|
| 26 | #ifndef O_BINARY
|
|---|
| 27 | #define O_BINARY 0
|
|---|
| 28 | #endif
|
|---|
| 29 | /*...e*/
|
|---|
| 30 |
|
|---|
| 31 | /*...suseful:0:*/
|
|---|
| 32 | #define low_byte(w) ((byte) ( (w)&0x00ffU) )
|
|---|
| 33 | #define high_byte(w) ((byte) (((unsigned)(w)&0xff00U)>>8))
|
|---|
| 34 | #define make_word(a,b) (((word)a) + (((word)b) << 8))
|
|---|
| 35 | /*...e*/
|
|---|
| 36 | /*...sextension:0:*/
|
|---|
| 37 | static char *extension(char *fn)
|
|---|
| 38 | {
|
|---|
| 39 | char *dot, *slash;
|
|---|
| 40 |
|
|---|
| 41 | if ( (dot = strrchr(fn, '.')) == NULL )
|
|---|
| 42 | return NULL;
|
|---|
| 43 |
|
|---|
| 44 | if ( (slash = strpbrk(fn, "/\\")) == NULL )
|
|---|
| 45 | return dot + 1;
|
|---|
| 46 |
|
|---|
| 47 | return ( slash < dot ) ? dot + 1 : NULL;
|
|---|
| 48 | }
|
|---|
| 49 | /*...e*/
|
|---|
| 50 |
|
|---|
| 51 | static GBMFT kps_gbmft =
|
|---|
| 52 | {
|
|---|
| 53 | "KIPS",
|
|---|
| 54 | "IBM KIPS",
|
|---|
| 55 | "KPS",
|
|---|
| 56 | GBM_FT_R8|
|
|---|
| 57 | GBM_FT_W8,
|
|---|
| 58 | };
|
|---|
| 59 |
|
|---|
| 60 | #define GBM_ERR_KPS_OPEN ((GBM_ERR) 500)
|
|---|
| 61 | #define GBM_ERR_KPS_CREATE ((GBM_ERR) 501)
|
|---|
| 62 |
|
|---|
| 63 | /*...skps file header definition:0:*/
|
|---|
| 64 | /*
|
|---|
| 65 | This defines the 32 byte header found on .KPS and .KPL files.
|
|---|
| 66 | */
|
|---|
| 67 |
|
|---|
| 68 | #define KPS_SIGNITURE "DFIMAG00"
|
|---|
| 69 |
|
|---|
| 70 | typedef struct
|
|---|
| 71 | {
|
|---|
| 72 | byte signiture[8]; /* Usually "DFIMAG00" */
|
|---|
| 73 | byte height_low;
|
|---|
| 74 | byte height_high; /* Image height in pixels */
|
|---|
| 75 | byte width_low;
|
|---|
| 76 | byte width_high; /* Image width in pixels */
|
|---|
| 77 | byte unknown[20]; /* 20 unknown bytes */
|
|---|
| 78 | } KPS_HEADER;
|
|---|
| 79 | /*...e*/
|
|---|
| 80 |
|
|---|
| 81 | typedef struct
|
|---|
| 82 | {
|
|---|
| 83 | char fn[600+1];
|
|---|
| 84 | BOOLEAN kpl;
|
|---|
| 85 | } KPS_PRIV;
|
|---|
| 86 |
|
|---|
| 87 | /*...skps_qft:0:*/
|
|---|
| 88 | GBM_ERR kps_qft(GBMFT *gbmft)
|
|---|
| 89 | {
|
|---|
| 90 | *gbmft = kps_gbmft;
|
|---|
| 91 | return GBM_ERR_OK;
|
|---|
| 92 | }
|
|---|
| 93 | /*...e*/
|
|---|
| 94 | /*...skps_rhdr:0:*/
|
|---|
| 95 | GBM_ERR kps_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
|
|---|
| 96 | {
|
|---|
| 97 | BOOLEAN pal = ( gbm_find_word(opt, "pal") != NULL );
|
|---|
| 98 | BOOLEAN kpl = ( gbm_find_word(opt, "kpl") != NULL );
|
|---|
| 99 | KPS_HEADER kps_header;
|
|---|
| 100 | KPS_PRIV *priv = (KPS_PRIV *) gbm->priv;
|
|---|
| 101 | int w, h;
|
|---|
| 102 |
|
|---|
| 103 | if ( kpl && pal )
|
|---|
| 104 | return GBM_ERR_BAD_OPTION;
|
|---|
| 105 |
|
|---|
| 106 | gbm_file_read(fd, (char *) &kps_header, sizeof(KPS_HEADER));
|
|---|
| 107 |
|
|---|
| 108 | if ( memcmp(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE)) )
|
|---|
| 109 | return GBM_ERR_BAD_MAGIC;
|
|---|
| 110 |
|
|---|
| 111 | w = make_word(kps_header.width_low , kps_header.width_high );
|
|---|
| 112 | h = make_word(kps_header.height_low, kps_header.height_high);
|
|---|
| 113 |
|
|---|
| 114 | if ( w <= 0 || h <= 0 )
|
|---|
| 115 | return GBM_ERR_BAD_SIZE;
|
|---|
| 116 |
|
|---|
| 117 | gbm->w = w;
|
|---|
| 118 | gbm->h = h;
|
|---|
| 119 | gbm->bpp = 8;
|
|---|
| 120 |
|
|---|
| 121 | /* Keep these for a later kps_rpal() call */
|
|---|
| 122 |
|
|---|
| 123 | strcpy(priv->fn, fn);
|
|---|
| 124 | priv->kpl = kpl;
|
|---|
| 125 |
|
|---|
| 126 | return GBM_ERR_OK;
|
|---|
| 127 | }
|
|---|
| 128 | /*...e*/
|
|---|
| 129 | /*...skps_rpal:0:*/
|
|---|
| 130 | GBM_ERR kps_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
|
|---|
| 131 | {
|
|---|
| 132 | KPS_PRIV *priv = (KPS_PRIV *) gbm->priv;
|
|---|
| 133 | char fn2[600+1], *ext;
|
|---|
| 134 |
|
|---|
| 135 | fd=fd; /* Suppress 'unref arg' compiler warning */
|
|---|
| 136 |
|
|---|
| 137 | strcpy(fn2, priv->fn);
|
|---|
| 138 | ext = extension(fn2);
|
|---|
| 139 | if ( priv->kpl )
|
|---|
| 140 | /*...sread a \46\kpl palette file:16:*/
|
|---|
| 141 | {
|
|---|
| 142 | int fd2, i, w, h;
|
|---|
| 143 | byte p[3][0x100];
|
|---|
| 144 | KPS_HEADER kps_header;
|
|---|
| 145 |
|
|---|
| 146 | if ( ext != NULL )
|
|---|
| 147 | strcpy(ext, "kpl");
|
|---|
| 148 | else
|
|---|
| 149 | strcat(fn2, ".kpl");
|
|---|
| 150 |
|
|---|
| 151 | if ( (fd2 = gbm_file_open(fn2, O_RDONLY|O_BINARY)) == -1 )
|
|---|
| 152 | return GBM_ERR_KPS_OPEN;
|
|---|
| 153 |
|
|---|
| 154 | gbm_file_read(fd2, (char *) &kps_header, sizeof(KPS_HEADER));
|
|---|
| 155 | if ( memcmp(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE)) )
|
|---|
| 156 | return GBM_ERR_BAD_MAGIC;
|
|---|
| 157 |
|
|---|
| 158 | w = make_word(kps_header.width_low , kps_header.width_high );
|
|---|
| 159 | h = make_word(kps_header.height_low, kps_header.height_high);
|
|---|
| 160 |
|
|---|
| 161 | if ( w != 0x100 || h != 3 )
|
|---|
| 162 | return GBM_ERR_BAD_SIZE;
|
|---|
| 163 |
|
|---|
| 164 | gbm_file_read(fd2, &(p[0][0]), 0x300);
|
|---|
| 165 | gbm_file_close(fd2);
|
|---|
| 166 |
|
|---|
| 167 | for ( i = 0; i < 0x100; i++ )
|
|---|
| 168 | {
|
|---|
| 169 | gbmrgb[i].r = p[0][i];
|
|---|
| 170 | gbmrgb[i].b = p[1][i];
|
|---|
| 171 | gbmrgb[i].g = p[2][i];
|
|---|
| 172 | }
|
|---|
| 173 | }
|
|---|
| 174 | /*...e*/
|
|---|
| 175 | else
|
|---|
| 176 | /*...sread a \46\pal palette file:16:*/
|
|---|
| 177 | {
|
|---|
| 178 | int fd2, i;
|
|---|
| 179 | byte b[4];
|
|---|
| 180 |
|
|---|
| 181 | if ( ext != NULL )
|
|---|
| 182 | strcpy(ext, "pal");
|
|---|
| 183 | else
|
|---|
| 184 | strcat(fn2, ".pal");
|
|---|
| 185 |
|
|---|
| 186 | if ( (fd2 = gbm_file_open(fn2, O_RDONLY|O_BINARY)) == -1 )
|
|---|
| 187 | return GBM_ERR_KPS_OPEN;
|
|---|
| 188 |
|
|---|
| 189 | for ( i = 0; i < 0x100; i++ )
|
|---|
| 190 | {
|
|---|
| 191 | gbm_file_read(fd2, (char *) b, 4);
|
|---|
| 192 | gbmrgb[i].r = b[0];
|
|---|
| 193 | gbmrgb[i].b = b[1];
|
|---|
| 194 | gbmrgb[i].g = b[2];
|
|---|
| 195 | }
|
|---|
| 196 | gbm_file_close(fd2);
|
|---|
| 197 | }
|
|---|
| 198 | /*...e*/
|
|---|
| 199 |
|
|---|
| 200 | return GBM_ERR_OK;
|
|---|
| 201 | }
|
|---|
| 202 | /*...e*/
|
|---|
| 203 | /*...skps_rdata:0:*/
|
|---|
| 204 | GBM_ERR kps_rdata(int fd, GBM *gbm, byte *data)
|
|---|
| 205 | {
|
|---|
| 206 | int i, stride;
|
|---|
| 207 | byte *p;
|
|---|
| 208 |
|
|---|
| 209 | stride = ((gbm->w + 3) & ~3);
|
|---|
| 210 | p = data + ((gbm->h - 1) * stride);
|
|---|
| 211 | for ( i = gbm->h - 1; i >= 0; i-- )
|
|---|
| 212 | {
|
|---|
| 213 | gbm_file_read(fd, p, gbm->w);
|
|---|
| 214 | p -= stride;
|
|---|
| 215 | }
|
|---|
| 216 |
|
|---|
| 217 | return GBM_ERR_OK;
|
|---|
| 218 | }
|
|---|
| 219 | /*...e*/
|
|---|
| 220 | /*...skps_w:0:*/
|
|---|
| 221 | GBM_ERR kps_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
|
|---|
| 222 | {
|
|---|
| 223 | KPS_HEADER kps_header;
|
|---|
| 224 | int i, stride;
|
|---|
| 225 | const byte *p;
|
|---|
| 226 | char fn2[600+1], *ext;
|
|---|
| 227 | BOOLEAN pal = ( gbm_find_word(opt, "pal") != NULL );
|
|---|
| 228 | BOOLEAN kpl = ( gbm_find_word(opt, "kpl") != NULL );
|
|---|
| 229 |
|
|---|
| 230 | if ( gbm->bpp != 8 )
|
|---|
| 231 | return GBM_ERR_NOT_SUPP;
|
|---|
| 232 |
|
|---|
| 233 | if ( pal && kpl )
|
|---|
| 234 | return GBM_ERR_BAD_OPTION;
|
|---|
| 235 |
|
|---|
| 236 | memcpy(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE));
|
|---|
| 237 | kps_header.width_low = low_byte(gbm->w);
|
|---|
| 238 | kps_header.width_high = high_byte(gbm->w);
|
|---|
| 239 | kps_header.height_low = low_byte(gbm->h);
|
|---|
| 240 | kps_header.height_high = high_byte(gbm->h);
|
|---|
| 241 | kps_header.unknown[0] = 1;
|
|---|
| 242 | memset(&kps_header.unknown[1], 0, 19);
|
|---|
| 243 | gbm_file_write(fd, (char *) &kps_header, sizeof(KPS_HEADER));
|
|---|
| 244 |
|
|---|
| 245 | stride = ((gbm->w + 3) & ~3);
|
|---|
| 246 | p = data + ((gbm->h - 1) * stride);
|
|---|
| 247 | for ( i = gbm->h - 1; i >= 0; i-- )
|
|---|
| 248 | {
|
|---|
| 249 | gbm_file_write(fd, p, gbm->w);
|
|---|
| 250 | p -= stride;
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | strcpy(fn2, fn);
|
|---|
| 254 | ext = extension(fn2);
|
|---|
| 255 | if ( kpl )
|
|---|
| 256 | /*...swrite a \46\kpl palette file:16:*/
|
|---|
| 257 | {
|
|---|
| 258 | int fd2, j;
|
|---|
| 259 | byte palette[3][0x100];
|
|---|
| 260 |
|
|---|
| 261 | if ( ext != NULL )
|
|---|
| 262 | strcpy(ext, "kpl");
|
|---|
| 263 | else
|
|---|
| 264 | strcat(fn2, ".kpl");
|
|---|
| 265 |
|
|---|
| 266 | if ( (fd2 = gbm_file_create(fn2, O_WRONLY|O_BINARY)) == -1 )
|
|---|
| 267 | return GBM_ERR_KPS_CREATE;
|
|---|
| 268 |
|
|---|
| 269 | kps_header.width_low = low_byte(0x100);
|
|---|
| 270 | kps_header.width_high = high_byte(0x100);
|
|---|
| 271 | kps_header.height_low = low_byte(3);
|
|---|
| 272 | kps_header.height_high = high_byte(3);
|
|---|
| 273 | gbm_file_write(fd2, (char *) &kps_header, sizeof(KPS_HEADER));
|
|---|
| 274 |
|
|---|
| 275 | for ( j = 0; j < 0x100; j++ )
|
|---|
| 276 | {
|
|---|
| 277 | palette[0][j] = gbmrgb[j].r;
|
|---|
| 278 | palette[1][j] = gbmrgb[j].b;
|
|---|
| 279 | palette[2][j] = gbmrgb[j].g;
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | gbm_file_write(fd2, &(palette[0][0]), 0x300);
|
|---|
| 283 | gbm_file_close(fd2);
|
|---|
| 284 | }
|
|---|
| 285 | /*...e*/
|
|---|
| 286 | else
|
|---|
| 287 | /*...swrite a \46\pal palette file:16:*/
|
|---|
| 288 | {
|
|---|
| 289 | int fd2;
|
|---|
| 290 | byte b[4];
|
|---|
| 291 |
|
|---|
| 292 | if ( ext != NULL )
|
|---|
| 293 | strcpy(ext, "pal");
|
|---|
| 294 | else
|
|---|
| 295 | strcat(fn2, ".pal");
|
|---|
| 296 |
|
|---|
| 297 | if ( (fd2 = gbm_file_create(fn2, O_WRONLY|O_BINARY)) == -1 )
|
|---|
| 298 | return GBM_ERR_KPS_CREATE;
|
|---|
| 299 |
|
|---|
| 300 | b[3] = 0;
|
|---|
| 301 | for ( i = 0; i < 0x100; i++ )
|
|---|
| 302 | {
|
|---|
| 303 | b[0] = gbmrgb[i].r;
|
|---|
| 304 | b[1] = gbmrgb[i].b;
|
|---|
| 305 | b[2] = gbmrgb[i].g;
|
|---|
| 306 | gbm_file_write(fd2, (char *) b, 4);
|
|---|
| 307 | }
|
|---|
| 308 | gbm_file_close(fd2);
|
|---|
| 309 | }
|
|---|
| 310 | /*...e*/
|
|---|
| 311 |
|
|---|
| 312 | return GBM_ERR_OK;
|
|---|
| 313 | }
|
|---|
| 314 | /*...e*/
|
|---|
| 315 | /*...skps_err:0:*/
|
|---|
| 316 | const char *kps_err(GBM_ERR rc)
|
|---|
| 317 | {
|
|---|
| 318 | switch ( (int) rc )
|
|---|
| 319 | {
|
|---|
| 320 | case GBM_ERR_KPS_OPEN:
|
|---|
| 321 | return "can't open complementary palette file";
|
|---|
| 322 | case GBM_ERR_KPS_CREATE:
|
|---|
| 323 | return "can't create complementary palette file";
|
|---|
| 324 | }
|
|---|
| 325 | return NULL;
|
|---|
| 326 | }
|
|---|
| 327 | /*...e*/
|
|---|