221 lines
6.5 KiB
C
221 lines
6.5 KiB
C
/* ------------------------------------------------------------------------
|
|
System : Manx Aztec C65 Version 3.2b
|
|
MS-DOS cross-development environment
|
|
Platform : Apple IIe 128K PRODOS 8
|
|
Program : d2save.c
|
|
Description : G2 Library Routine
|
|
DHGR Save for ProDOS SYS Programs
|
|
Saves 3 formats from DHGR Page 2:
|
|
|
|
0 - BIN/AUX BSaved Pairs
|
|
1 - A2FC BSaved Chunks
|
|
2 - DHR Raw Raster Images
|
|
|
|
Overwrites existing file if it exists.
|
|
Danger Will Robinson! If a write error
|
|
occurs the damaged file(s) will be
|
|
removed and all will be lost.
|
|
|
|
Does Not Save Run-Length Encoded DHX
|
|
XPacked Images nor XCrunched XCC and
|
|
XRC color indices which take altogether
|
|
too long to uncrunch to make them
|
|
practical for most things at time of
|
|
this writing.
|
|
|
|
Written by : Bill Buckels
|
|
Revision Date: February 2013
|
|
|
|
Licence : You may use this code for whatever you wish as long
|
|
as you agree that Bill Buckels has no warranty or
|
|
liability obligations whatsoever from said use.
|
|
------------------------------------------------------------------------ */
|
|
|
|
/* save a file from double hires screen 2
|
|
in 2 formats - A2FC or DHR */
|
|
#include <fcntl.h>
|
|
#include <prodir.h>
|
|
|
|
extern unsigned HB[];
|
|
|
|
#define BLOCK_SIZE 3840
|
|
|
|
int d2save(basename,ftype)
|
|
char *basename;
|
|
int ftype;
|
|
{
|
|
unsigned int src,src2,target;
|
|
int fh,i=0,j=0,status=-2,y,x,x1,x2;
|
|
char hdr[5], binfile[20], auxfile[20], *workbuf = (char *)4192, *ptr;
|
|
struct fileinfo *fi = (struct fileinfo *)4192;
|
|
|
|
/* allow filetype to be specified by ascii numeric value to
|
|
simplify calls using keyboard input logic */
|
|
if (ftype > 47 && ftype < 58) ftype -= 48;
|
|
|
|
|
|
/* create output names for save from basename */
|
|
for (;;) {
|
|
auxfile[i] = binfile[i] = basename[i];
|
|
if (binfile[i] == 0 || binfile[i] == '.') {
|
|
auxfile[i] = '.'; binfile[i++] = '.';
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
/* remove any existing extension and add our standard
|
|
3 character extension for the filetype specified */
|
|
if (ftype == 0) {
|
|
auxfile[i] = 'A'; binfile[i++] = 'B';
|
|
auxfile[i] = 'U'; binfile[i++] = 'I';
|
|
auxfile[i] = 'X'; binfile[i++] = 'N';
|
|
}
|
|
else if (ftype == 1) {
|
|
auxfile[i++] = '2';
|
|
auxfile[i++] = 'F';
|
|
auxfile[i++] = 'C';
|
|
}
|
|
else {
|
|
/* also create DHR header */
|
|
hdr[j++] = auxfile[i++] = 'D';
|
|
hdr[j++] = auxfile[i++] = 'H';
|
|
hdr[j++] = auxfile[i++] = 'R';
|
|
hdr[j++] = 80;
|
|
hdr[j] = 192;
|
|
}
|
|
auxfile[i] = binfile[i] = 0;
|
|
|
|
/* when Aztec C creates a file in ProDOS the filetype is set to 4 (text file).
|
|
in the past I modified the code for open to create binary files (filetype 6)
|
|
and called my function bopen which is part of the G3 library.
|
|
however the bopen code duplicates the aztec c code for open with this one
|
|
small change and therefore creates a larger program when open is also used
|
|
in the same program.
|
|
|
|
an alternative method to work around this is to create the file, close it,
|
|
modify the filetype from text to binary using setfinfo and then re-open the
|
|
file and write to it. See below. Since I wanted to set the load address
|
|
anyway I kill two birds with one stone by using setfinfo.
|
|
|
|
I have no idea why the Aztec C developers did not use a bitmask like
|
|
microsoft did to specify a binary or text file.
|
|
*/
|
|
|
|
if((fh=open(auxfile, O_WRONLY|O_TRUNC|O_CREAT,0xc3)) == -1) return -1;
|
|
close(fh);
|
|
|
|
/* call ProDOS to set the file type to binary and
|
|
the subtype to the load address */
|
|
/* set load address to screen 1 for AUX file
|
|
BASIC programs may expect this */
|
|
|
|
if (getfinfo (auxfile, fi) != -1) {
|
|
fi->file_type = 6;
|
|
if (ftype == 0) fi->aux_type = 0x2000; /* screen 1 */
|
|
else fi->aux_type = 0x4000; /* screen 2 */
|
|
setfinfo(auxfile,fi);
|
|
}
|
|
if((fh=open(auxfile, O_WRONLY,0xc3)) == -1) {
|
|
unlink(auxfile);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* save screen based on filetype specified */
|
|
|
|
/* write AUX or A2FC file */
|
|
if (ftype == 0 || ftype == 1) {
|
|
/* move 8192 bytes from auxiliary screen memory and write to file */
|
|
src = 0x4000;
|
|
auxtomain(src,src+3999,4192);
|
|
for (;;) {
|
|
if (write(fh,workbuf,4000) != 4000) break;
|
|
src+=4000;
|
|
auxtomain(src,src+3999,4192);
|
|
if (write(fh,workbuf,4000) != 4000) break;
|
|
src+=4000;
|
|
auxtomain(src,src+191,4192);
|
|
if (write(fh,workbuf,192) != 192) break;
|
|
/* add 8192 bytes to A2FC from main screen memory */
|
|
if (ftype == 1) {
|
|
if (write(fh,(char *)0x4000,0x2000) != 0x2000) break;
|
|
}
|
|
status =0;
|
|
break;
|
|
}
|
|
}
|
|
else if (write(fh,hdr,5) == 5) {
|
|
/* write DHR file - if no error from writing the header
|
|
write the image data */
|
|
status = 0;
|
|
y = 0;
|
|
/* write 4 blocks of 48 scanlines */
|
|
for (x = 0; x < 4; x++) {
|
|
|
|
/* move 48 scanlines into write buffer area at 4192
|
|
interleaving auxmem with mainmem rasters */
|
|
for (x1 = 0, x2=40; x1 < BLOCK_SIZE; x1+=80,x2+=80) {
|
|
|
|
/* move a scanline from auxiliary screen memory
|
|
every even 40 bytes in the buffer */
|
|
src = HB[y];
|
|
src2 = src+39;
|
|
target = (unsigned int)&workbuf[x1];
|
|
auxtomain(src,src2,target);
|
|
|
|
/* interleaf a scanline from main screen memory
|
|
for the following 40 bytes */
|
|
ptr = (char *)src;
|
|
target = (unsigned int)&workbuf[x2];
|
|
movmem(ptr,target,40);
|
|
y++;
|
|
}
|
|
|
|
/* write the block and check for errors */
|
|
if (write(fh,workbuf,BLOCK_SIZE) < BLOCK_SIZE) {
|
|
status = -2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
close(fh);
|
|
|
|
/* if a write error has occurred remove
|
|
the partial file and outa' here */
|
|
if (status != 0) {
|
|
unlink(auxfile);
|
|
return status;
|
|
}
|
|
|
|
if (ftype != 0) return 0;
|
|
|
|
/* if writing BIN/AUX file pairs save main screen memory
|
|
directly to the BIN file - for the other filetypes
|
|
there is no second file */
|
|
status = -3;
|
|
for(;;) {
|
|
if((fh=open(binfile, O_WRONLY|O_TRUNC|O_CREAT,0xc3)) == -1) break;
|
|
close(fh);
|
|
if (getfinfo (binfile, fi) != -1) {
|
|
fi->file_type = 6;
|
|
fi->aux_type = 0x2000;
|
|
setfinfo(binfile,fi);
|
|
}
|
|
if((fh=open(binfile, O_WRONLY,0xc3)) == -1) break;
|
|
status = 0;
|
|
if (write(fh,(char *)0x4000,0x2000) != 0x2000) status = -4;
|
|
close(fh);
|
|
break;
|
|
}
|
|
|
|
if (status != 0) {
|
|
unlink(auxfile);
|
|
unlink(binfile);
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|