/* FragRag (C) Copyright 1990-2008 Bill Buckels */
/* previously revised Oct 14, 1991 */
/* last revised May 2008 */
/* converts from an IBM Bsaved PUT to an apple image fragment */
/* extension is RAG */
/* also outputs a run length encoded version of the RAG */
/* extension is RAX */
/* also outputs a text version of the RAG and RAX */
/* suitable for embedding in Aztec C programs */
/* extension is RAT */
/* this is an extended version of FragRag which
creates runlength encoded files in addition to the
standard output of raw files created by the
previous version.
The size improvement varies and can be minimal and
may not be worth the effort of decoding these,
This version has other additional features that
are not present in the orginal, but is a
programmer's utility so not written in a
bulletproof manner.
*/
/* The FRAGGLE.EXE utility will produce PUT format
images from CGA 4-Color BSaved Files which are
freely available on the IBM-PC. Clipshop can be
used to create 4 Color BSaved Files from the
Windows Clipboard and other sources as can several
old utilites. A version of FRAGGLE is included with
this program.
To learn more about all this visit my wikipedia
page at
http://en.wikipedia.org/wiki/BSAVE_%28graphics_image_format%29
Use FRAGGLE.EXE to create the PUT image fragments
that you will be using in your Apple II programs.
Download Clipshop at
www.clipshop.ca
*/
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <dos.h>
#include <bios.h>
#include <malloc.h>
#include <string.h>
#include <graph.h>
#define bitsperbyte 8
/* default palette is orange, blue */
/* allow base palette to be changed to green, violet from the
command line */
/* allow palette change for specific rasters using mapping file
of the same base name as the image fragment */
unsigned char paltype = 0x80;
unsigned char palettemap[192];
/* map the 4 color CGA to the Apple palette
color 0 - black
color 1 - cyan to blue
color 2 - magenta to orange
color 3 - white
allow an optional color reversal of blue and orange
*/
unsigned char blue = 1, orange = 2;
int reverse = 0;
int clip = 0;
int batch = 0;
unsigned char encbuf[8194];
/* pcx encoder helper */
/* the writer for the encline function */
int encput(unsigned char byt,unsigned char cnt, FILE *pcxfile)
{
if(cnt){
if((cnt==1)&& (0xc0 != (0xc0 &byt))){
if(EOF == fputc((int)byt,pcxfile))
return(0);
return(1);
}
else{
if(EOF==fputc((int)0xc0|cnt,pcxfile))
return(0);
if(EOF==fputc((int)byt,pcxfile))
return(0);
return(2);
}
}
return(0);
}
/* encode a line in pcxformat encoding */
/* encodes a raw line and writes it out to disk */
int encline(unsigned char *inbuff,int inlen, FILE *pcxfile)
{
unsigned char this,last;
int srcindex,i;
int total;
unsigned char runcount;
total=0;
last = *(inbuff); runcount=1;
for(srcindex=1;srcindex!=inlen;srcindex++){
this= *(++inbuff);
if(this==last){
runcount++;
if(runcount==63){
if(!(i=encput(last,runcount,pcxfile)))
return(0);
total+=i;
runcount=0;
}
}
else{
if(runcount){
if(!(i=encput(last,runcount,pcxfile)))
return(0);
total+=i;
}
last=this;
runcount=1;
}
}
if(runcount){
if(!(i=encput(last,runcount,pcxfile)))
return(0);
return(total+i);
}
return (total);
}
unsigned int tempwidth, tempheight;
int fragin(char *fragment)
{
FILE *fp;
int fh;
unsigned char far *buffer;
unsigned char far *crt= (char *)0xb8000000l;
unsigned int width, height;
unsigned int buffersize,headerlength=7;
unsigned char floodcolor, ch;
fp=fopen(fragment,"rb");
if (NULL == fp)return -1;
buffersize=filelength(fileno(fp))-headerlength;
fclose(fp);
buffer=_fmalloc(buffersize);
if (NULL == buffer)return -2;
fh = open(fragment,O_RDONLY|O_BINARY);
if (fh == -1) {
_ffree(buffer);
return -3;
}
read(fh,buffer,7);
if (buffer[0] != 0xfd) {
close(fh);
_ffree(buffer);
return -4;
}
read(fh,buffer,buffersize);
close(fh);
width=(buffer[0]|buffer[1]<<8) ;
tempwidth=width/2;
if((width%bitsperbyte)!=0)
width=(width/bitsperbyte)+1;
else width=(width/bitsperbyte) ;
height=(buffer[2]|buffer[3]<<8);
tempheight = height;
if (clip == 1) {
floodcolor=buffer[4];
memset(crt,floodcolor,0x4000);
}
_putimage(0,0,buffer,_GPSET);
if (reverse)
for (height = 0; height < 0x4000; height++)
crt[height] ^= 0xff;
_ffree(buffer);
if (batch == 0) {
/* a little menu here to reverse back again etc.
add commands as required */
while (batch == 0) {
ch = toupper(getch());
switch(ch) {
case 0: getch(); batch = 1; break;/* clear arrow keys */
case 'R':
for (height = 0; height < 0x4000; height++)
crt[height] ^= 0xff;
break;
case 27:
return -5;
default:
batch = 1;
break;
}
}
}
return 0;
}
/* return the color value of the pixel at x, y */
unsigned char getpixel(int x, int y)
{
union REGS inregs, outregs;
inregs.h.ah = '\x0d';
inregs.x.cx = x;
inregs.x.dx = y;
int86(0x10, &inregs,&outregs);
return outregs.h.al;
}
int OrangeBlackWhite(char *buf0, char *name, char *name2, char *name3, char *mapname)
{
FILE *fp, *fp2, *fp3, *fmap;
int pcxctr = 0;
char bytebuf[41];
unsigned char inbuf[282],outbuf[282];
unsigned char bit[7];
unsigned char bytewidth,rasters;
int pixels;
int topx=0,botx=0,topy=0,boty=0;
int x,xx,xxx,y,bytes;
char ch;
int value, height,idx;
unsigned int xsize;
if(tempwidth%14 !=0)
botx = topx+((tempwidth/14)*14)+14; /* multiple of 14 */
else
botx = topx+tempwidth;
boty = topy + tempheight;
pixels = (botx-topx)+1;
rasters = tempheight;
bytewidth = (unsigned char)(pixels/7);
fp = fopen(name,"wb");
if (NULL == fp)return -1;
fp2 = fopen(name2,"wb");
if (NULL == fp2) {
fclose(fp);
return -1;
}
fp3 = fopen(name3,"w");
if (NULL != fp3) {
/* the c array contains width in bytes, height in rasters
followed by data */
fprintf(fp3,"/* %s.rat Embedded Graphics Image Created by\n"
" FragRag(C) Copyright Bill Buckels 1990-2008 */\n\n",buf0);
fprintf(fp3,"/* suitable for embedding in Aztec C Apple II Programs */\n");
fprintf(fp3,"/* width in bytes, height in rasters, data... */\n\n");
}
/* create a header for the RAG and RAX files */
/* meaning is raster width in bytes x number of rasters */
fputc(bytewidth,fp);
fputc(rasters,fp);
fputc(bytewidth,fp2);
fputc(rasters,fp2);
/*
use an external mapping file to allow for override
of orange or green palette for selected rasters
otherwise the same base palette will be used
for the entire fragment
each line in the mapping file should either be
y=,v=
or
y=,v=,h=
this mapping will override any base palette
*/
for (y=0; y < 192; y++)
palettemap[y] = paltype; /* set default */
fmap=fopen(mapname,"r");
/* the following mapping does not check for overlaps
FIFO logic is used. The next mapping will overwrite
the previous mapping if any overlaps. */
if (NULL != fmap) {
while (NULL != fgets(inbuf, 128, fmap)){
y = -1;
value = paltype;
height = 1; /* height if omitted assumed 1 row */
for (idx = 0; inbuf[idx] != 0;idx++) {
switch(toupper(inbuf[idx]))
{
case 'H': if (inbuf[idx+1] != '=')break;
height= atoi(&inbuf[idx+2]);
/* heights can be higher
than screen width
but never lower than 1 */
if (height < 1)height = 0;
if (height > 191)height = 191;
break;
/* if y is out of range no remap */
case 'Y': if (inbuf[idx+1] != '=')break;
y= atoi(&inbuf[idx+2]);
if (y < 0 || y > 191)y = -1;
break;
case 'V': if (inbuf[idx+1] != '=')break;
ch = toupper(inbuf[idx+2]);
if (ch == 'O') {
value = 0x80; break;
}
if (ch == 'G') {
value = 0; break;
}
/* only zero will map to green */
value= atoi(&inbuf[idx+2]);
if (value != 0)value = 0x80;
break;
}
}
if (y > -1 && y < 192 && height > 0) {
height = height + y;
for (x = y; x < height; x++) {
if (x > 191)break;
palettemap[y] = (unsigned char)value;
}
}
}
fclose(fmap);
}
for(y=topy;y<boty;y++)
{
/* start by assuming everything is black*/
for(x=0;x<282;x++)outbuf[x]=0;
for(x=0;x<41;x++)bytebuf[x]=0;
/* next accumulate the white values */
for(x=0;x<pixels;x++)
{
inbuf[x]=getpixel(x+topx,y);
if(inbuf[x] == 3)outbuf[x] = 1;
}
/* next check for secondary color */
inbuf[280]=inbuf[279];
xx=1;
xxx=2;
for(x=0;x<pixels;x++)
{
/* if we have blue write it out */
/* on the ibm, paired blue pixels will result in
a blue pixel on the apple. the same logic holds
true for orange. results will vary of course. */
if(inbuf[x] == blue && inbuf[xx] == blue)
{
if(x%2==0)
{
outbuf[x] = 1;
outbuf[xx] = 0;
}
else
{
outbuf[xx] = 1;
outbuf[xxx] = 0;
}
}
/* and if we have orange write it out */
if(inbuf[x] == orange && inbuf[xx] == orange )
{
if(x%2==0)
{
outbuf[x] = 0;
outbuf[xx] = 1;
}
else
{
outbuf[xx] = 0;
outbuf[xxx] = 1;
}
}
xx++;
xxx++;
}
/* now pack the raster and write out the file */
paltype = palettemap[y];
x = 0;
for(bytes=0;bytes<bytewidth;bytes++)
{
for(xx=0;xx<7;xx++)
{
bit[xx]=outbuf[x];
x++;
}
bytebuf[bytes]=(paltype |bit[6]<<6|bit[5]<<5|bit[4]<<4|
bit[3]<<3|bit[2]<<2|bit[1]<<1|bit[0]);
fputc(bytebuf[bytes],fp);
encbuf[pcxctr] = bytebuf[bytes];
pcxctr++;
}
/* make another pass and loop until finished */
}
fclose(fp);
if(NULL != fp3) {
fprintf(fp3,"#define RAW 1\n\n#ifdef RAW\n");
fprintf(fp3,"/* raw array of Apple II RAG image */\n");
fprintf(fp3,"unsigned char %s[%d] = {\n%3d,%3d,",buf0,pcxctr+2,bytewidth,rasters);
fflush(fp3);
y=0;
idx = 2;
for (y = 0; y < pcxctr; y++) {
x=encbuf[y];
fprintf(fp3,"%3d",x);
if(y == (pcxctr-1))fprintf(fp3,"};");
else fputc(',',fp3);
idx++;
if (idx==11) {
fputc('\n',fp3);
fflush(fp3);
idx=0;
}
}
}
if (NULL != fp2){
/* write the encoded file */
encline((unsigned char *)&encbuf[0],pcxctr,fp2);
fclose(fp2);
}
/* write the encoded C array */
if (NULL != fp3){
fp2 = fopen(name2,"rb");
if (NULL != fp2) {
xsize =filelength(fileno(fp2));
rewind(fp2);
fprintf(fp3,"\n#else\n");
fprintf(fp3,"/* encoded array of Apple II RAG image */\n");
fprintf(fp3,"unsigned char %s[%u] = {\n",buf0,xsize);
idx = 0;
x= fgetc(fp2);
fprintf(fp3,"%3d",x);
do {
x = fgetc(fp2);
if (x == EOF) {
fprintf(fp3,"};\n");
break;
}
fputc(',',fp3);
idx++;
if (idx == 11) {
fputc('\n',fp3);
fflush(fp3);
idx = 0;
}
fprintf(fp3,"%3d",x);
}while (x!=EOF);
fclose(fp2);
}
fprintf(fp3,"#endif\n");
fclose(fp3);
}
return 0;
}
main(int argc,char *argv[])
{
int idx;
char buf0[66],buf1[66],buf2[66],buf3[66],buf4[66];
char *wordptr;
char c;
paltype = 0x80;
clip = 0;
if (argc < 2) {
puts("FragRag (C) Copyright Bill Buckels 1990-2008");
puts("All Rights Reserved.");
puts("Usage is \"FRAGRAG MY.PUT\"");
puts("Option \"FRAGRAG MY.PUT G\" - Violet Green Palette");
puts("Option \"FRAGRAG MY.PUT O\" - Blue Orange Palette (default)");
puts("Option \"FRAGRAG MY.PUT F\" - Flip Blue to Orange, Orange to Blue");
puts("Option \"FRAGRAG MY.PUT B\" - Batch Mode (do not pause for keypress)");
puts("Option \"FRAGRAG MY.PUT R\" - Reverse Image");
puts("Option \"FRAGRAG MY.PUT OFBR\" - Options can be combined.");
puts("Outputs \"MY.RAG MY.RAX MY.RAT\" Raw, Encoded and Embedded Apple II Graphic");
puts("Read the source code for additional options (mapping file etc.).");
}
else {
strcpy(buf0,argv[1]);
strcpy(buf1,buf0);
if (argc > 2) {
strcpy(buf2,argv[2]);
for (idx = 0; buf2[idx] != 0; idx++) {
c = toupper(buf2[idx]);
switch(c) {
case 'G': paltype = 0; break;
case 'O': paltype = 0x80; break;
case 'C': clip = 1; break;
case 'F': blue = 2;
orange = 1;
break;
case 'B': batch = 1; break;
case 'R': reverse = 1; break;
}
}
}
_setvideomode(5);
if(fragin(buf1) == 0) {
wordptr=strtok(buf0,".");
sprintf(buf1,"%s.RAG",buf0);
sprintf(buf2,"%s.RAX",buf0);
sprintf(buf3,"%s.RAT",buf0);
sprintf(buf4,"%s.MAP",buf0);
OrangeBlackWhite(buf0,buf1,buf2,buf3,buf4);
}
_setvideomode(3);
}
exit(0);
}
|