KOALA Paint and Other Bitmapped Graphics in Aztec C64

Started by BillBuckels, April 14, 2008, 02:18 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

BillBuckels



CBINLODE - bitmapped graphics file loader

This is a bitmapped graphics viewer program for C64 HIRES and MultiColor BSaved screens. These screens can be created on the C64 if you are so inclined to write a program to do so, or from both IBM-PC and C64 Image Sources by using my ClipShop program for Windows XP.

The programming tools that I distribute with Aztec64 will also create these (and other C64 graphics) from IBM-PC graphics. This program also handles HIRES Doodle Draw and HIRES Art Studio and MultiColor Koala Painter Screen Images that can also be created in ClipShop as well as by a variety of other sources.


/* cbinlode.c (C) Copyright Bill Buckels 2008 */


/* a picture viewer for the Commodore 64   */
/* written in Manx Aztec C65 Version 1.05h */
/* runs under Commodore BASIC 2            */
/* displays BSaved HIRES and Multi-Color Images */
/* requires a text script called piclist   */



/*

Image Support

The images supported by this program are either split images of the type
created by my ClipShop program and require the file extensions that ClipShop
provides, or are Art Studio, Doodle Draw or Koala Paint uncompressed images,
with the file extensions of .ART, .DD, or .KOA that are supported by
ClipShop and other C64 image conversion utilities currently in use.

Images are read directly from disk into to their respective memory areas.

The images created by ClipShop store the palette(s) in a separate file from
the bitmap. Bitmaps are all 8002 bytes long and palette files are all 1002
bytes long. The first two bytes are a BSaved Header followed by data.

In the case of ClipShop's multicolor images, a third file (a second palette
file) contains the third color and background color. The background is in
the high nibble and is identical in all of the 1000 positions used by C64
palettes.

The first byte of the second palette is used to set the border (low nibble)
and background (high nibble) colors and then transferred to the first
multicolor position in memory, followed by reading the other 999 bytes
containing the rest of the third colors in the second palette directly to
the remaining 999 multicolor positions in memory.

In all cases, each ClipShop file is read in 2 passes, with the first pass
removing the header information and the second pass being read directly to
memory. Since I am doing a raw read, there probably isn't a more efficient
way to do this.

In the case of the ART, DD, and KOA images I do almost the same thing but
all bitmap and palette information comes from a single file.

Image Load Strategy

The image file extension drives the loader, but if a file name without an
extension is entered is typed-in I use the following strategy:

First I try to open a HIRES BSaved file with a single palette. I depend
entirely on naming convention so I expect an extension of ".BHI" for the
bitmap file paired with a palette file of ".VHI".

Second, if that fails, I try to open a Multi-Color BSaved File with an
extension of ".BMC" and 2 palette files with extensions of ".VMC" and ".CMC"
respectively again depending entirely on naming convention.

If both of those strategies fail, then I try for a .KOA, .ART, and .DD file
respectively.

If that fails, I just give-up and assume that whatever they are loading is a
HIRES BSaved image without a palette, so I set a black and white palette
manually and let them use whatever naming they like.

This part can be expanded to test for other image types that the C64
supports. The header and file information could have been used in the loader
to make it more robust in auto-detecting the many C64 graphics that exist,
as well as file length and load addresses stored in the image. It is only in
the interests of keeping this simple that I am using file extensions as "the
easy way out" in my loader routine and limiting my strategy to keep this
program smaller and more readable.

*/



/* memory map for creating C64 graphics programs in Aztec C

0x800 - (2048) - basic load address
0x810 - binary base address
0x4000 - data load address (advance as necessary if problems)
0x4400 - code load address (advance as necessary for more data)

for embedding a HIRES image
insert vram before bitmap

1000 bytes for vram storage
8000 bytes for bitmap

insert bitmap at default screen address when program loads
insert vram 1K before bitmap
0x2000
0x1c00

the bitmap is immediately displayed on the screen and vram
storage is then moved immediately to the actual vram address

for embedding a 1024 byte 8 x 8 fontset (characters 0-127)
insert fontset 2K before bitmap
0x1800

I have found in practice that no insertion of data can be done
below these areas.


*/
#define CMAIN 1

#include <poke.h>
#include <colors.h>
#include <stdio.h>

#define NONE 0
#define BHI 1
#define BMC 2
#define ART 3
#define DD  4
#define KOA 5

int itype = NONE;

char tmpbuf[3];

char image[40];
char *palette[40];
char *cmap[40];

/* since less than 25 C64 images can be placed on a CBINLODE disk
   the following pointer array is sufficient for memory
   storage of image names from the PICLIST.
   This allows the PICLIST to be opened once at the start of the
   program then to be read into memory referenced by this array */
char *inames[25];


nocr(ptr, cr)
char *ptr;
char cr;
{
int idx;

if (cr == '.')itype = NONE;

for (idx=0;ptr[idx] != 0; idx++) {
    if (ptr[idx] == cr) {
   ptr[idx] = 0;

   if (cr == '.') {
  if (ptr[idx+1] == 'B' && ptr[idx+2] == 'H' && ptr[idx+3] == 'I') {
  itype = BHI;
  break;
  }
  if (ptr[idx+1] == 'B' && ptr[idx+2] == 'M' && ptr[idx+3] == 'C') {
  itype = BMC;
  break;
  }
  if (ptr[idx+1] == 'A' && ptr[idx+2] == 'R' && ptr[idx+3] == 'T') {
  itype = ART;
  break;
  }
  if (ptr[idx+1] == 'D' && ptr[idx+2] == 'D') {
  itype = DD;
  break;
  }
  if (ptr[idx+1] == 'K' && ptr[idx+2] == 'O' && ptr[idx+3] == 'A') {
  itype = KOA;
  break;
  }
   }

   break;
}

}

}


FILE *fp = NULL;
char buffer[128];

int xkey = 90; /* exit = Z */

main()
{
int c,fh,idx,jdx;

    scr_clear();

    /* background color, bordercolor */
    scr_back(C64_LBLUE,C64_BLUE);

/* set to hires mode 320 x 200 and display the logo */
    setcrtmode(1);
    setlogo();

    pfont("Please Wait...",9,13,0,1,-1);

    /* open the piclist and read the images into the buffer */
    /* I am using a fixed field length of 40 characters in the buffer */
    for (idx = 0;idx < 25; idx++)inames[idx] = NULL;
    fp = fopen("PICLIST","r");
if (fp!=NULL) {
  idx = 0;
  jdx = 0;
  while (fgets(buffer,128,fp) != NULL) {
  if (idx > 24)break;
          nocr(buffer,'\n');
          buffer[39]=0;
          inames[idx] = (char *)&vstore[jdx];
          strcpy(inames[idx],buffer);
          idx++;
          jdx +=40; /* 40 character field length */

  }
  fclose(fp);

    }


    /* clear all keypressess */
    while (kbhit()); /* wait for key release */
    kbflush();

    pfont("Press Any Key.",9,13,0,1,-1); /* erase please wait */

    while (!kbhit()); /* wait for key press */
    /* clear last palette */
    gclr(-1,0,0);
    setcrtmode(0);
    scr_clear();

    /* clear bmp */
    gclr(0,-1,-1);
    while (kbhit()); /* wait for key release */
    /* clear the buffer */
    kbflush();

BEGERR:


    /* home cursor, clear screen */
    scr_clear();

    /* background color, bordercolor */
    scr_back(C64_LBLUE,C64_BLUE);

    scr_txtcolor(C64_BWHITE); /* bright white text */

    printf("CBINLOAD.PRG BY BILL BUCKELS 2007\n\nPICTURES:\n\n");

jdx = 65; /* ascii 'A' */
for (idx = 0; idx < 25; idx++) {
   if (inames[idx] == NULL)break;
   printf("  %c - %s\n",jdx, inames[idx]);
   jdx++;
}
printf("  %c - QUIT TO BASIC\n",xkey);


RENTER:

    printf("\nENTER PICTURE:");
    gets(buffer);
    if (buffer[0] == 0 || (buffer[1] == 0 && buffer[0] == xkey)) goto ENDERR;

    jdx=0;
    if (buffer[1] == 0) {
   jdx = 999;
   if (buffer[0] > 64 && buffer[0] < 90) {
        idx = buffer[0] - 65;
        if (inames[idx] != NULL){
strcpy(buffer,inames[idx]);
jdx = 0;
}
   }

}
if (jdx == 999) {
printf("INVALID MENU OPTION.");
goto RENTER;
}


    strcpy(image,buffer);
    nocr(image,'.');
    strcpy(palette,image);
    strcpy(cmap,image);


    switch(itype) {
   case KOA:
   case ART:
   case DD:
   case BMC:
   case BHI:
        fh = open(buffer,0); break;
   default:
        /* try to open as hires with palette */
        strcat(image,".BHI");
        fh = open(image,0);
        if (fh!= -1) {
itype = BHI; break;
}
        /* if that fails try to open as multicolor with palette and cmap */
        strcpy(image, palette);
strcat(image,".BMC");
        fh = open(image,0);
        if (fh!= -1) {
itype = BMC; break;
}
/* if that fails try to open as Koala Painter */
strcpy(image, palette);
strcat(image,".KOA");
        fh = open(image,0);
        if (fh!= -1) {
itype = KOA; break;
}
/* if that fails try to open as Art */
strcpy(image, palette);
strcat(image,".ART");
        fh = open(image,0);
        if (fh!= -1) {
itype = ART; break;
}
/* if that fails try to open as Doodle Draw */
strcpy(image, palette);
strcat(image,".DD");
        fh = open(image,0);
        if (fh!= -1) {
itype = DD; break;
}
/* if all fail assume hires without palette */
fh = open(buffer,0); break;

}

    if (fh == -1) {
printf("CAN'T OPEN %s",buffer);
goto RENTER;
}


scr_clear();

setcrtmode(1);

    switch(itype) {
case KOA:
/* Koala Painter */
/* second step required for multicolor graphics mode */
setcrtmode(2);

    palette[0] = 0;
    cmap[0] = 0;

    break;

    case ART:
    palette[0] = 0;
    cmap[0] = 0;
    break;

    case DD:
        /* doodle draw stores the palette before the bitmap */
        palette[0] = 0;
        cmap[0] = 0;
        read(fh,tmpbuf,2);
        read(fh,vram,1000);
        read(fh,buffer,22); /* padding - the last 2 bytes will be thrown away below */
        break;

case BMC:
    /* second step required for multicolor graphics mode */
            setcrtmode(2);

            strcat(palette,".VMC");
            strcat(cmap,".CMC");

            break;

case BHI:
default:
    strcat(palette,".VHI");
}

    read(fh,tmpbuf,2);
    read(fh,bmp,8000);
    if (itype == KOA || itype== ART)read(fh,vram,1000);
    if (itype == KOA) {
read(fh,cram,1000);
read(fh,buffer,1);
/* background color, bordercolor */
        scr_back((buffer[0] & 0xf),(cram[0] & 0xf));
}

    close(fh);

    if (palette[0] != 0) {
    fh = open(palette,0);
    if (fh != -1) {
read(fh,tmpbuf,2);
read(fh,vram,1000);
close(fh);
}
else {
for (idx = 0; idx < 1000; idx++)vram[idx] = C64_BWHITE;

}
}

    /* multicolor mode */
    if (itype == BMC) {
            fh = open(cmap,0);
if (fh != -1) {
read(fh,tmpbuf,3);
/* background color, bordercolor */
                scr_back((tmpbuf[2] >> 4),(tmpbuf[2] & 0xf));
                cram[0] = tmpbuf[2];
read(fh,&cram[1],999);
close(fh);
        }
}


    /* clear all keypressess */
    while (kbhit());
    kbflush();
    c = getch();

    /* clear last palette and bitmap */
    gclr(0,0,0);

    setcrtmode(0);

    if (c!=xkey) goto BEGERR;

ENDERR:

scr_reset();
exit(0);
}


MAKEFILE

# ---------------------------------------------
# Aztec C64 makefile by bill buckels 2007
# ---------------------------------------------

PRG=cbinlode

$(PRG).B64: $(PRG).asm
   as65 $(PRG).asm
   del $(PRG).asm
   copy $(CLIB65)B64NAT.LIB .
   copy $(CLIB65)C64NAT.LIB .
   ln65 $(PRG).rel B64NAT.LIB C64NAT.LIB -b 810 -d 4080 -c 4480
   del $(PRG).rel
   del C64NAT.LIB
   del B64NAT.LIB
   copy BAGGAGE\$(PRG).bhi .
   copy BAGGAGE\$(PRG).vhi .
   ADDLOGO $(PRG)
   MKBASIC $(PRG).sys $(PRG).prg
   del $(PRG)
   del $(PRG).sys
   del $(PRG).bhi
   del $(PRG).vhi
   
$(PRG).asm: $(PRG).c MAKEFILE
    copy $(INCL65)stdio.h .
    copy $(INCL65)poke.h .
    copy $(INCL65)colors.h .
    c65 $(PRG).c
    del stdio.h
    del poke.h
    del colors.h



BillBuckels

FRAG64X

This utility is one of many that I have provided (for FREE of course) with the Aztec C64 C Compiler, but guess what?, this can be used with whatever C compiler or whatever Computer Language you wish for both the C64 and the C128 to produce converted graphics from IBM-PC stuff to CBM stuff.

Amiga guys and Mac and Linux guys can adapt this if they wish. It was written for you too, so go ahead. You will however need to cut-in some screen stuff and would just probably be best running this in a DOS emulator and it's only a 16 bit MS-DOS program after all.


/* Frag64x (C) Copyright 2008 Bill Buckels */

#include <stdio.h>
#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

unsigned int tempwidth, tempheight;

char buf1[66],buf2[66], buf3[66], buf4[66], ext[5],ext2[5];
char vhi[66], cmc[66], vmc[66];


int Color1, Color2, Color3, background;

/* poke values for colors */
/* not used - left here for reference */
#define C64_BLACK 0
#define C64_BWHITE 1
#define C64_RED 2
#define C64_CYAN 3
#define C64_PURPLE 4
#define C64_GREEN 5
#define C64_BLUE 6
#define C64_YELLOW 7
#define C64_ORANGE 8
#define C64_BROWN 9
#define C64_LRED 10
#define C64_DGRAY 11
#define C64_MGRAY 12
#define C64_LGREEN 13
#define C64_LBLUE 14
#define C64_LGRAY 15

/* 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;
}

void putpixel(int x, int y,int pixelvalue)
{
    union REGS inregs, outregs;

    inregs.h.ah = '\x0c';
    inregs.h.al = pixelvalue;
    inregs.x.cx = x;
    inregs.x.dx = y;

    int86(0x10, &inregs,&outregs);
}

/* pcx encoder helper */
int encput(unsigned char byt,unsigned char cnt, FILE *pcxfile)       // the writer for the encline function
{
          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 */
int encline(unsigned char *inbuff,int inlen, FILE *pcxfile)  // encodes a raw line and writes it out to disk
{
    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);

}


int fragin(char *fragment)
{

     FILE *fp;

     int fh,action,x,y,x1,y1,result;
     unsigned char far *buffer;
     unsigned char far *crt= (char *)0xb8000000l;
     unsigned int width, height;
     unsigned int buffersize,headerlength=7;
     unsigned char floodcolor;
     char c,d;

    fp=fopen(fragment,"rb");

    if (NULL == fp)return 1;


    buffersize=filelength(fileno(fp))-headerlength;
    fclose(fp);

    buffer=_fmalloc(buffersize);

    if (NULL == buffer)return 1;

    fh = open(fragment,O_RDONLY|O_BINARY);
    read(fh,buffer,7);

    /* minimal header check */
    if (buffer[0] != 0xfd) {
close(fh);
_ffree(buffer);
return 1;
}


    /* check for a fullscreen BSAVED image */
    /* the minimimum size for a BSAVED screen is larger than the maximum for a fullscreen PUT */
    if (buffersize > 16191) {
    read(fh,crt,16192);
    close(fh);
    _getimage(0,0,319,199,buffer);

}
    else {
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;

   /*
   floodcolor=buffer[4];
   memset(crt,floodcolor,0x4000);

   */

    _putimage(0,0,buffer,_GPSET);

    result = 0;
    while ((c = toupper(getch()))!=13) {

   if (c == 27) {
   result = 1;
   break;
   }

       if (c == 'B')floodcolor = 0;
       if (c == 'C')floodcolor = 1;
       if (c == 'M')floodcolor = 2;
       if (c == 'W')floodcolor = 3;

       if (c == 'A') action = _GAND;
       if (c == '0') action = _GOR;
       if (c == 'R') action = _GPRESET;
       if (c == 'N' || c == 'H' || c == 'H') action = _GPSET;
       if (c == 'X') action = _GXOR;

switch(c)
{
case 0:     getch(); break; /* fkeys are not valid here */
case 'H':
             _putimage(0,0,buffer,action);
            width = tempwidth / 2;
            for (y = 0; y < tempheight; y++) {
   x1 = tempwidth - 1;
                       for (x = 0; x < width; x++) {
        c =  getpixel(x,y);
        d =  getpixel(x1,y);
        putpixel(x,y,d);     /* swap horizontal pixels */
        putpixel(x1,y,c);
        x1--;
   }
}
x = tempwidth - 1;
y = tempheight - 1;
_getimage(0,0,x,y,buffer);
break;
case 'V':
             _putimage(0,0,buffer,action);
            height = tempheight / 2;
            y1 = tempheight - 1;
            for (y = 0; y < height; y++) {
                       for (x = 0; x < tempwidth; x++) {
        c =  getpixel(x,y);       /* swap vertical pixels */
        d =  getpixel(x,y1);
        putpixel(x,y,d);
        putpixel(x,y1,c);
   }
   y1--;
}
x = tempwidth - 1;
y = tempheight - 1;
_getimage(0,0,x,y,buffer);
break;




case 'X':
case 'R':
case 'N':
case 'O':
case 'A':
   _putimage(0,0,buffer,action);
   c=getch();
   if (c == 0)getch();
   if (c == 27) _putimage(0,0,buffer,_GPSET);
   break;
case 'S':  _putimage(1,0,buffer,_GPSET);
   c=getch();
   if (c == 0)getch();
   if (c == 27) _putimage(0,0,buffer,_GPSET);
   break;

            case 'B':
            case 'C':
case 'M':
case 'W':  for(y = 0; y < 200; y++)
for (x = 1; x < 320; x+=2)
   if (getpixel(x,y) == floodcolor)
  putpixel(x-1,y,floodcolor);

   c=getch();
   if (c == 0)getch();

   if (c == 27) _putimage(0,0,buffer,_GPSET);
   break;


}

    }

    _ffree(buffer);
    return result;

}


unsigned char bigbuf[8000];

/* saves a hires C64 image */
int savefrag64(char *name, int mode)
{

FILE *fp, *fp2=NULL,*fp3=NULL;
int x, y, x1, y1, rows, columns, row, col;
unsigned c, ch, ctr = 0, header = 0, idx;

if(tempwidth%8 !=0)
  tempwidth  = ((tempwidth/8)*8)+8; /* multiple of 8 */

if(tempheight%8 !=0)
  tempheight  = ((tempheight/8)*8)+8; /* multiple of 8 */

columns = tempwidth/8;
rows = tempheight/8;

fp = fopen(name,"wb");

if (NULL == fp) {
/* perror(name); */
return 1;
}

fp2 = fopen(buf3,"wb");
fp3 = fopen(buf4,"w");



   /* create a header */
   /* meaning is rows x columns if a fragment */

   /* image is block oriented */
   if (tempwidth == 320 && tempheight == 200) {
   fputc(0,fp);
   fputc(0x20,fp); /* if a full screen, image is bsaved with colors */
   }
   else {
   /* if a fragment, the image is saved without colors */
   /* fragments use the colors of the background image */
   /* the row and column info necessary to display is included */
   /* as the header instead of the load address. */
   fputc(rows,fp); /* this is oriented to how the loader works */
   fputc(columns,fp); /* and to how the C64 screen is arranged */
   if (NULL != fp2) {
    /* compressed fragments do not have color values */
    /* but they contain the row and column info necessary to unpack */
    header = 2;
    fputc(rows,fp2);
    fputc(columns,fp2);
   }
   }


   if (NULL != fp3) {
    /* the c array does not contain any positioning or color info, just data */
    fprintf(fp3,"/* %s.h Graphics Image Header Created by\n"
                "   Frag64x(C) Copyright Bill Buckels 2008 */\n\n",buf1);

    fprintf(fp3,"/* these arrays are suitable for embedding in Aztec C64 Programs */\n");
    fprintf(fp3,"/* remove or change the names of the following as required */\n");

    fprintf(fp3,"int %smode = %d;\n",buf1,mode);
    fprintf(fp3,"int %srows = %d;\n",buf1,rows);
    fprintf(fp3,"int %scols = %d;\n",buf1,columns);
   }



   for (row = 0; row < rows; row++) {
   for (col = 0; col < columns; col++) {

   y = row * 8;
   x = col * 8;

       for (y1 = y; y1 < (y+8); y1++) {
  c = 0;
      for (x1 = x; x1 < (x+8); x1+=mode) {
       c = c << mode;
       if (mode == 1) {
   if (getpixel(x1,y1) != 0)c = c|1; /* map colors to white */
   }
       else {
   ch = getpixel(x1,y1);
   c = c | ch;
   }
  }
  if (mode == 1)c = c^0xff;
  fputc(c,fp);
  if (NULL != fp2)bigbuf[ctr] = c;
  ctr++;
  }

   }
   }




   fclose(fp);

   if (NULL != fp3) {
   switch(mode) {
   case 2:

/* light blue and light red defaults */
c = (Color1 << 4 | Color2);
fprintf(fp3,"int %svram = %d;\n",buf1,c);

c = (background << 4 | Color3);
fprintf(fp3,"int %scram = %d;\n",buf1,c);
fprintf(fp3,"int %sbk = %d;\n",buf1,background);
fprintf(fp3,"int %sc1 = %d;\n",buf1,Color1);
fprintf(fp3,"int %sc2 = %d;\n",buf1,Color2);
fprintf(fp3,"int %sc3 = %d;\n",buf1,Color3);
break;


   default:

c = (Color2 << 4 | Color1);
fprintf(fp3,"int %svram = %d;\n",buf1,c);
fprintf(fp3,"int %sc1 = %d;\n",buf1,Color1);
fprintf(fp3,"int %sc2 = %d;\n",buf1,Color2);
break;


   }
   }

   /* if a full screen, save the colors */
   if (tempwidth == 320 && tempheight == 200) {
   switch(mode) {
       case 2:
                 fp = fopen(vmc,"wb");
                 if (NULL == fp) break;
                 fputc(0,fp);
fputc(0x1C,fp);
/* light blue and light red defaults */
                 c = (Color1 << 4 | Color2);
for (x = 0; x <1000; x++)fputc(c,fp);
                 fclose(fp);

                 /* fullscreen multicolor compressed is vram value
                    followed by cram value followed by encoded data */
                 if (NULL != fp2)fputc(c,fp2);

                     fp = fopen(cmc,"wb");
                 if (NULL == fp) break;
                 fputc(0,fp);
fputc(0xD8,fp);
             c = (background << 4 | Color3);
                 for (x = 0; x <1000; x++)fputc(c,fp); /* default white colormap */
                 fclose(fp);

             /* fullscreen multicolor compressed is vram value
                    followed by cram value followed by encoded data */
                 if (NULL != fp2){
fputc(c,fp2);
                  encline((unsigned char *)&bigbuf[0],8000,fp2);
                  fclose(fp2);
                  header = 2;
}
                     break;


       default:  fp = fopen(vhi,"wb");
                 if (NULL == fp) break;
                 fputc(0,fp);
fputc(0x1C,fp);
c = (Color2 << 4 | Color1);
for (x = 0; x <1000; x++)fputc(c,fp);
fclose(fp);

                     /* fullscreen hires compressed is vram value followed by encoded data */
                 if (NULL != fp2){
header = 1;
fputc(c,fp2);
                  encline((unsigned char *)&bigbuf[0],8000,fp2);
                  fclose(fp2);
}
break;


   }


   }
   else {
if (NULL != fp2){
encline((unsigned char *)&bigbuf[0],ctr,fp2);
fclose(fp2);
}

   }

   if (NULL != fp3){

       fp2 = fopen(buf3,"rb");

       fprintf(fp3,"#define RAW 1\n#ifdef RAW\n");
       fprintf(fp3,"/* raw array of C64 image */\n");
       fprintf(fp3,"char %s[%d] = {\n",buf1,ctr);

       c=0;
       for (idx = 0; idx < ctr; idx++) {
  x=bigbuf[idx];
      fprintf(fp3,"%3d",x);
      if(idx == (ctr-1))fprintf(fp3,"};");
      else fprintf(fp3,",");
          c++;
      if (c==11) {
  fprintf(fp3,"\n");
  c=0;
  }

   }
       fprintf(fp3,"\n#else\n");


       c=filelength(fileno(fp2))-header;
       fprintf(fp3,"/* pcx encoded array of C64 image */\n");
       fprintf(fp3,"char %sx[%d] = {\n",buf1,c);
       for (idx = 0; idx < header; idx++)fgetc(fp2);
       idx = 0;
       x= fgetc(fp2);
       fprintf(fp3,"%3d",x);
       do {
   x= fgetc(fp2);
   if (x== EOF) {
   fprintf(fp3,"};\n#endif\n");
   break;
   }
   fprintf(fp3,","); idx++;
   if (idx == 11) {
      fprintf(fp3,"\n");
      idx = 0;
   }
   fprintf(fp3,"%3d",x);

   }
       while (x!=EOF);
       fclose(fp2);
       fclose(fp3);
   }

   return 0;

}

main(int argc,char *argv[])
{
   int result,mode,idx;
   char *wordptr,c;

   if (argc < 2) {
      puts("Frag64X (C) Copyright 2008 Bill Buckels");
      puts("All Rights Reserved.");
      puts("Usage is \"FRAG64X MY.PUT\"");
      puts("Option   \"FRAG64X MY.PUT 2\"");
      puts("Option   \"FRAG64X MY.PUT 4\"");
      puts("Options   Number of Colors (2 or 4)");
      puts("Default   2 Colors");
      puts("Input     IBM-PC 4 Color CGA BSaved Image Fragment");
      puts("Output    Commodore 64 HIRES or Multi-Color Image Fragent");
      puts("Extension MY.fr2 (2 Color) or MY.fr4 (4 Color) for fragments");
      puts("Extension MY.BHI (2 Color) or MY.BMC (4 Color) for Full Screen");
      puts("Encoded   MY.f2x (2 Color) or MY.f4x (4 Color) for fragments");
      puts("Encoded   MY.BHX (2 Color) or MY.BMX (4 Color) for Full Screen");
      puts("Header    MY.h encoded static array option for Aztec C64 Programs");
      puts("Option 2  Color Mapping (Default is B&W (hires) or BRW on Black)");
      puts("          Color Map Values are in the range of 0-15");
      puts("Option 2  \"FRAG64X MY.PUT 2 Color1 background\"");
      puts("Option 2  \"FRAG64X MY.PUT 4 Color1 Color2 Color3 background\"");
      puts("          Color Mapping is for Fullscreen Only (320 x 200)");
      puts("Hotkeys   Enter=Save * Esc=Abort * H=Horizontal Flip * V=Vertical Flip");
      puts("          Widen Pixels - B=Black, C=Cyan, M=Magenta, W=White");
      puts("          Effects - A=AND, O=OR, X=XOR, R=REVERSE, N=NORMAL (reset)");
      exit(result);

   }

   /* if we are saving a hires fragment
      we encode every pixel.

      if we are saving a multicolor fragment
      we encode every second pixel.

      in either case the background is assumed
      to be black for the entire image.

      this makes CGA mode fragments ideal for
      encoding both screens and fragments.

      any palette that we wish to set in our
      programs can be mapped to each of the
      available colors in real time.

      a consistent palette needs to used anyway
      if we are combining screens and fragments.

      */

     strcpy(ext,".fr2");
     strcpy(ext2,".f2x");

     mode = 1;

     Color1 = 1;
     Color2 = 0;
     Color3 = 1;
     background = 0;


     if (argc > 2) {
if (argv[2][0] == '4') {
strcpy(ext,".fr4");
strcpy(ext2,".f4x");
mode = 2;
             Color1 = 14; /* lblue */
             Color2 = 10; /* lred  */
}
if (argc > 3) Color1 = atoi(argv[3])&0xf;
if (argc > 4) Color2 = atoi(argv[4])&0xf;
if (argc > 5) Color3 = atoi(argv[5])&0xf;
if (argc > 6) background = atoi(argv[6])&0xf;
}

_setvideomode(5); /* CGA 4 Color */
result = fragin(argv[1]);

if (result == 0) {

/* full screen */
if (tempwidth == 320 && tempheight == 200) {
if (mode == 1)  {
strcpy(ext,".bhi");
strcpy(ext2,".bhx");
}
else {
strcpy(ext,".bmc");
strcpy(ext2,".bmx");
}
}

strcpy(buf1,argv[1]);
wordptr=strtok(buf1,".");
sprintf(buf2,"%s%s",buf1,ext);
sprintf(buf3,"%s%s",buf1,ext2);
sprintf(vhi,"%s.vhi",buf1);
sprintf(cmc,"%s.cmc",buf1);
sprintf(vmc,"%s.vmc",buf1);
sprintf(buf4,"%s.h",buf1);

for (idx = 0; buf1[idx]!= 0; idx++)buf1[idx] = tolower(buf1[idx]);

result = savefrag64(buf2,mode);

    }
_setvideomode(3); /* CGA 80 Col Color Text */

    if (result == 0){
puts("Success!");
sprintf(buf2,"dir /O:D /b %s.???",buf1);
system(buf2);
}
    else {
puts("Unable to save C64 image!");
}

    exit(result);
}


Continued Next Message...

BillBuckels

FRAG64X

Continued from previous message...

The following are the header comments from the frag64x source code... they explain alot.


/* this is an extended version of Frag64 which creates
   runlength encoded files and arrays in addition to
   the standard output of Frag64.

   The size improvement varies and can be minimal and
   may not be worth the effort of cluttering-up your disk,
   so I have left the simple version in place as well as
   this one for the more size conscious of you.

   For overlays that use graphics, embedding compressed
   graphics in the form of run-length encoded arrays
   can be very useful in terms of performance as well as
   space saving since the C64 disk drive access is slow
   when loading external files in addition to overlays,

   This version has other additional features that are
   not present in Frag64 and if clutter is not an issue
   use this one.

   */

/* converts from an IBM Bsaved PUT to a C64 image fragment */
/* fullscreen PIC's convert to BSAVED C64 Images with Colors */
/* extensions are fr2 or fr4 for fragments */
/* extensions are BHI or BMC for BSAVED C64 Images */
/* Color File Extensions are VHI or VMC and CMC */
/* The full screen files are in the Clipshop format */

/* 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.

   To learn more about all this visit my wikipedia page at

   http://en.wikipedia.org/wiki/BSAVE_(graphics_image_format)

   Generally speaking you are better-off to use FRAGGLE.EXE
   menu option 5 to create the PUT image fragments that you will
   be using in your C64 programs because these are saved in 8 x 8
   graphics blocks which is perfect for C64 conversion.

   Note that when converting from a 4 color image to a HIRES
   image on the C64, any color other than black is taken as white.

   Also note that when converting from a 4 color image to a
   Multicolor image on the C64, every second pixel is skipped
   since the horizontal resolution is only 160 pixels in Multicolor
   mode. This means that you should use lines of 2 pixels in
   width for your line elements and stay away from altrenating pixel
   pattern files. Solid color works best in colored areas.

   If you want to preserve detail in a Multicolor mode image
   you may need to draw it as a 160 x 100 picture on the
   IBM then scale it x 2 and BSAVE it before using FRAGGLE.EXE.

   Alernately just make sure your horizontal pixels are two wide
   and you will probably be ok in most cases.

   If you want your text and graphics to be near perfect in the
   horizontal axis in a Multicolor image that is what you must do,
   and for any menu screens that is what I would suggest. Your
   line elements in your artwork will be somewhat jagged but your
   results will be quite manageable for combining fragments
   with background screens and a common palette.

   I consider the sprites on a C64 a little small for my preferences
   on this type of programming, and I much prefer a clean image
   fragment instead even if I need to reduce to 4 colors.

   Lastly, this utility provides a command line override for
   mapping to your choice of each of the C64 colors 0-15 for
   your full screens.

   This gives you a choice of any 2-colors in your HIRES images
   and any 4-colors in your Multicolor images, which I feel provides
   a reasonable amount of flexibility in choosing a color scheme
   to combine fragments and screens.

   You have this source code if you want to customize this utility
   further. The 8 x 8 color block on a C64 makes converting a 4 color
   image a little tricky and as a programmer's tool I have gone about
   as far as I think is generally reasonable, but many more schemes
   are possible even with this lot. For example, widening your black
   lines or white lines on line-art in a multicolor image will
   guarantee that detail is not lost in some cases. In others it will
   destroy your graphics by creating blotches

   For these types of things hotkeys are used in this program.
   You can read the source to see what they are and try them
   for yourself. I stopped short of scaling and so forth and again
   you can add these functions yourself if you like.

   On a further note...

   Clipshop has more options for general purpose conversion of full
   screens but combining those with fragments will likely prove
   problematic, and even Clipshop conversions will prove problematic
   on their own, since color precedence is used to map the most used
   colors and colors are not what and where you might expect them
   from block to block and will be lost altogether if a complex
   image and no spot is available.

   Much better to deal with less colors and guaranteed results with
   this utility is my conclusion over the years of mucking with all
   this is what I think. Do your fancy stuff in a paint program
   first and use this utility to process the finished artwork is
   what I suggest.

   'Nuff Said.

   Download Clipshop at

   www.clipshop.ca

   */

MAKEFILE

# ---------------------------------------------------------
# Microsoft C 8 makefile by Bill Buckels 2008
# ---------------------------------------------------------
PRG=frag64X
PRG2=curlib
all: ..\$(PRG).exe ..\$(PRG2).exe

$(PRG).obj: $(PRG).c
      cl -c -AL -Zp1 $(PRG).c

$(PRG2).obj: $(PRG2).c
      cl -c -AL -Zp1 $(PRG2).c

..\$(PRG).exe: $(PRG).obj $(PRG).c MAKEFILE
     link $(PRG).obj,..\$(PRG).exe, NUL, /ST:8192 /NOE /NOD oldnames llibce graphics, NUL
     del $(PRG).obj
     
..\$(PRG2).exe: $(PRG2).obj $(PRG2).c MAKEFILE
     link $(PRG2).obj,..\$(PRG2).exe, NUL, /ST:8192 /NOE /NOD oldnames llibce graphics, NUL
     del $(PRG2).obj
   



BillBuckels

#3
CURLIB

You may have noticed that the MAKEFILE for FRAG64X also builds a program called CURLIB. If you didn't it doesn't much matter because all that is done for you anyway and you only need to use curlib if you get fancy. But CURLIB does provide a utility for putting some little graphics fragments into a bloadable file. The problem you will have if you don't use Aztec C is that these need to be manipulated and you will in fact need to get fancy.


/* curlib.c (C) Copyright Bill Buckels 2008 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char curbuf[1000];

FILE *fp=NULL, *fp2=NULL, *fp3=NULL, *fp4=NULL;

main(int argc, char *argv[])
{
int ctr = 0,c;

/* this is a special purpose utility for
   creating cursor libraries that are embeded into
   aztec C programs instead of vram using up to 3 fragments
   or files named on the command line.

   the caveat is that you keep the maximum size
   of all 3 files to 1000 bytes total.

   You will generally want to create a cursor library using
   a left and right hand cursor and a musical note to indicate
   whether sound is in use or not.

   */

   if (argc < 2) {
      puts("Usage is \"Curlib [frag1] [frag2] [frag3]\"");
      exit(1);
   }


   fp = fopen("cursor.vhi","wb");
   fputc(0,fp);
   fputc(0x1C,fp);

   fp2 = fopen(argv[1],"rb");
   if (argc > 2) fp3 = fopen(argv[2],"rb");
   if (argc > 3) fp4 = fopen(argv[3],"rb");


   if (NULL != fp2) {
       while ((c = fgetc(fp2))!=EOF) {
   if (ctr < 1000)fputc(c,fp);
   ctr++;
   }

   }
   if (NULL != fp3) {
       while ((c = fgetc(fp3))!=EOF) {
   if (ctr < 1000)fputc(c,fp);
   ctr++;
   }

   }
   if (NULL != fp4) {
       while ((c = fgetc(fp4))!=EOF) {
   if (ctr < 1000)fputc(c,fp);
   ctr++;
   }

   }

   while (ctr < 1000) {
  fputc(0,fp);
  ctr++;
   }


   if (NULL!=fp)fclose(fp);
   if (NULL!=fp2)fclose(fp2);
   if (NULL!=fp3)fclose(fp3);
   if (NULL!=fp4)fclose(fp4);

   exit(0);

}


Note: The technical term "Fancy" means the same thing as the English term. Usually compilers don't come with much fancy stuff and also BASIC 2 certainly didn't... you needed to poke around alot. BASIC 7 on the C128 was quite an improvement but for doing graphics you really can't beat C for all around usability.

Now exactly where one gets these IBM-PC image fragments to make into CBM image fragments might surprise you especially if you haven't read the Wikipedia Article.

Continued Next Message...

BillBuckels

#4

FRAGGLE
Continued from Curlib...

Well Jim henson was a Bearded Male and so am I but that and the fact that we both created something called "FRAGGLE" could well be the only resemblance.

Now in case someone gets the idea that I am a C snob or something, that's only one of my personnas and the reality is that "When In Rome"... so here's a little bit of BASIC from the IBM-PC side that also comes with the the Aztec C64 cross-compiler. This definetly is useful if you also use ClipShop to snag images in Windows XP and convert them to IBM-PC BASIC BSaved Images because then you can use FRAGGLE to chop them-up into little pieces and stick them in Aztec C64 programs (or whatever).


'FRAGGLE.BAS by Bill Buckels 1990
'Written in QuickBASIC Version 4.5
'produces and displays image fragments
'created from BASIC BSAVED MED RES CGA IMAGES
'Revised 2007 as a pure QuickBasic Program
'Removed PCX support because not written in QuickBasic
'Added resave back to BSaved Image
'Revised program structure for readability
'Increased error handling and added error messages
'Removed automatic naming from basename.
'Now using the .PUT extension when saving.
'Added 8 x 8 Block Based Fragments for C64 Style Saves

DEFINT A-Z
'allocate memory for picture buffer
DIM PIC(8002)                              'picture buffer
'constants for keypress values
NUL$ = CHR$(0)
UP$ = NUL$ + CHR$(72)
DN$ = NUL$ + CHR$(80)
LT$ = NUL$ + CHR$(75)
RT$ = NUL$ + CHR$(77)
ESC$ = CHR$(27)
ENTER$ = CHR$(13)
'constants for keypress status
FLAG = 0
ZERO = 0
ONE =  1
TWO =  2
DONE = 3
ABORT = 0

ERRORLEVEL = 0
ON ERROR GOTO ERRORHANDLE

SCREEN 1

DO

'bounds of the screen
X1 = 0: X2 = 319: Y1 = 0: Y2 = 199

GOSUB DRAWMENU 'Menu Routine
GOSUB GETCHOICE

IF ERRORLEVEL = 0 THEN
SELECT CASE PICTYPE%
CASE 1,5
'if we have been asked to fraggle
GOSUB VARFRAG
CASE 2
'if we're not fragging we're viewing so we stop and wait in that case
KEYPRESS$ = INPUT$(1)

CASE 3
'make a menu chip
GOSUB FIXEDFRAG 

CASE 4 'bsave fragment
GOSUB RESAVE

END SELECT
END IF

ABORT = ZERO
ERRORLEVEL = 0
LOOP UNTIL PICNAME$ = "FINISHED"
END


DRAWMENU:

CLS

LINE (2,2)-(317,102),2,b
LINE (0,0)-(319,102),1,b
LOCATE 2,2
PRINT " FRAGGLE(C)
LOCATE 3,2
PRINT " Copyright Bill Buckels 1990-2007"
LOCATE 5,2
PRINT "    1)   Fraggle a BSaved Image"
LOCATE 6,2
PRINT "    2)   Load an Image Fragment"
LOCATE 7,2
PRINT "    3)   Fraggle 88 x 52 from BSaved"
LOCATE 8, 2
PRINT "    4)   BSave a Fraggled Image"
LOCATE 9, 2
PRINT "    5)   Fraggle C64 Style from BSaved"
LOCATE 10,2
PRINT "    ESC  EXIT"

' menu explanations

LINE (2,104)-(317,197),1,b
LINE (0,104)-(319,199),2,b
LOCATE 15, 2
PRINT " Summary of Fraggle Hot Keys:"
LOCATE 17, 2
PRINT " R      - Reverse Video"
LOCATE 18, 2
PRINT " L      - Adjust Length By 1 pixel"
LOCATE 19, 2
PRINT " W      - Adjust Width By 1 pixel"
LOCATE 20, 2
PRINT " ESC    - Abandon Operation"
LOCATE 21, 2
PRINT " ENTER  - 1st and 2nd corners"
LOCATE 22, 2
PRINT "          Save Fragment"
LOCATE 23, 2
PRINT " ARROWS - Change Clip Position";

'get input
LOCATE 12,2
PRINT " Select from the above Menu options.";


RETURN


GETCHOICE:
  'menu input subroutine
  PICTYPE$ = INPUT$(1)
  PICTYPE% = VAL(PICTYPE$)
  SELECT CASE PICTYPE%
  CASE 1, 3, 5
        CLS
  PRINT "Raw Load"
FILES "*.BAS"
  CASE 2, 4
        CLS
PRINT "Image Fragment Load"
    FILES "*.PUT"
  CASE ELSE
      END
  END SELECT
 
  LINE(0,180)- (319,195),0,BF
  LINE(0,180)- (319,195),2,B
  LINE(2,182)- (317,193),1,B
  LOCATE 24,2
  SELECT CASE PICTYPE%
  CASE 1, 3, 5
  INPUT " PICTURE"; PICNAME$
  CASE 2, 4
  INPUT " FRAGMENT"; PICNAME$
  END SELECT
 
  IF PICNAME$ = "" THEN
  PICTYPE%=0
  ELSE
    CLS
    GOSUB LOADPIC
  END IF     

RETURN     


LOADPIC:
  ' picture loader subroutine
  SELECT CASE PICTYPE%

  CASE 1, 3, 5   'Raw Data
      SEGMENT = &HB800              'Use Screen Segment
      OFFSET = &H0
      DEF SEG = SEGMENT
      BLOAD PICNAME$, OFFSET        'Bload the Picture

  CASE 2, 4
      'load image fragments
      SEGMENT = VARSEG(PIC(0))
      OFFSET = VARPTR(PIC(0))

      DEF SEG = SEGMENT
      BLOAD PICNAME$, OFFSET
      XTAB = INT((640 - PIC(0)) / 4)   'center horizontally
      PUT (XTAB, 0), PIC, PSET         'put picture

  END SELECT
  DEF SEG  'Go back to original segment
 
  IF ERRORLEVEL > 0 THEN
      CLS
      LINE (0,0)-(319,24),0,BF
      LINE (0,0)-(319,24),1,B
      LOCATE 2,2
      PRINT PICNAME$ + " NOT loaded. Press a key..."
      A$ = INPUT$(1)     
  END IF
 
RETURN


VARFRAG:
  ' subroutine for saving variable size image fragments
  ' backup the picture
  GET (X1, Y1)-(X2, Y2), PIC
  'and do an elastic box with a DOTTED line in two colors
  LINE (X1, Y1)-(X2, Y2), 2, B, &HAAAA
  LINE (X1, Y1)-(X2, Y2), 3, B, &H5555

  IF PICTYPE% = 5 THEN
       INCR% = 8
  ELSE
       INCR% = 4
  END IF


  ENTER% = 1 'FRAG PART ONE- SET THE TOP LEFT CORNER
  FLAG = 0
  WHILE FLAG = 0
    KEYPRESS$ = INKEY$
    SELECT CASE KEYPRESS$
    CASE "R", "r" 'reverse video
PUT (0,0),PIC,PRESET
GET (0,0)-(319,199), PIC
PUT (0,0),PIC,PSET
FLAG=ONE
    CASE "L", "l" 'fine tuning
        IF INCR% = 4 THEN
  IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT Y1 = 0 THEN
Y1 = Y1 - 1
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
  ELSE  ' BOTTOM RIGHT CORNER
      IF Y2 > (Y1 + 4) THEN
Y2 = Y2 - 1
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
  END IF
END IF
    CASE "W", "w"
        IF INCR% = 4 THEN
  IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT X1 = 0 THEN
X1 = X1 - 1
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
  ELSE  ' BOTTOM RIGHT CORNER
      IF X2 > (X1 + 4) THEN
X2 = X2 - 1
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
  END IF
END IF
    CASE UP$ 'up arrow
IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT Y1 = 0 THEN
Y1 = Y1 - INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
ELSE  ' BOTTOM RIGHT CORNER
      IF Y2 > (Y1 + INCR%) THEN
Y2 = Y2 - INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
END IF
    CASE DN$ 'down arrow
IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT Y1 > Y2 - INCR% THEN
Y1 = Y1 + INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
ELSE  ' BOTTOM RIGHT CORNER
      IF NOT Y2 = 199 THEN
Y2 = Y2 + INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
END IF
    CASE LT$ 'left arrow
IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT X1 = 0 THEN
X1 = X1 - INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
ELSE  ' BOTTOM RIGHT CORNER
      IF X2 > (X1 + INCR%) THEN
X2 = X2 - INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
END IF
    CASE RT$ 'right arrow
IF ENTER% = 1 THEN ' TOP LEFT CORNER
      IF NOT X1 > X2 - INCR% THEN
X1 = X1 + INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
ELSE  ' BOTTOM RIGHT CORNER
      IF NOT X2 = 319 THEN
X2 = X2 + INCR%
PUT (0, 0), PIC, PSET
FLAG = ONE
      END IF
END IF
    CASE ESC$
ABORT = TWO
FLAG = DONE
    CASE ENTER$
ENTER% = ENTER% + 1 'FRAG PART TWO - SET THE BOTTOM RIGHT CORNER
IF ENTER% > 2 THEN FLAG = DONE
    END SELECT
    IF FLAG = ONE THEN
'change the position of the elastic box
'based on the last arrow or positional keypress
LINE (X1, Y1)-(X2, Y2), 2, B, &HAAAA
LINE (X1, Y1)-(X2, Y2), 3, B, &H5555
FLAG = 0
    END IF
  WEND

  IF ABORT = ZERO THEN
      GOSUB SAVEFRAG 'SAVE IF ESCAPE WAS NOT PRESSED
  END IF

RETURN



FIXEDFRAG:
  ' subroutine for saving 88 x 52 fixed size image fragments
  ' or 24 x 21 Double C4 Sprite
  ' backup the picture
  GET (X1, Y1)-(X2, Y2), PIC
  ' use a printshop compatible image size
  ' 88 x 52
  X1=0 : X2=87 : Y1 = 0 : Y2=51
 
 
  'and do an elastic box with a DOTTED line
  'in two colors to show-up regardless
  LINE (X1, Y1)-(X2, Y2), 2, B, &HAAAA
  LINE (X1, Y1)-(X2, Y2), 3, B, &H5555

  FLAG = 0

  WHILE FLAG = 0
    KEYPRESS$ = INKEY$
   
    SELECT CASE KEYPRESS$
    CASE "R", "r"  'reverse video
PUT (0,0),PIC,PRESET
GET (0,0)-(319,199), PIC
PUT (0,0),PIC,PSET
FLAG=ONE
    CASE UP$
              IF NOT Y1 = 0 THEN
Y1 = Y1 - 4
Y2 = Y2 - 4
PUT (0, 0), PIC, PSET
FLAG = ONE
              END IF
    CASE DN$  'down arrow
              IF NOT (Y2+4)>199 THEN
Y2 = Y2 + 4
Y1 = Y1 + 4
PUT (0, 0), PIC, PSET
FLAG = ONE
              END IF
    CASE LT$  'left arrow
              IF NOT X1 = 0 THEN
X1 = X1 - 4
X2 = X2 - 4
PUT (0, 0), PIC, PSET
FLAG = ONE
              END IF
    CASE RT$  'right arrow
              IF NOT (X2+4)>319 THEN
X1 = X1 + 4
X2 = X2 + 4
PUT (0, 0), PIC, PSET
FLAG = ONE
              END IF
    CASE ESC$
ABORT = TWO
FLAG = DONE
    CASE ENTER$
FLAG = DONE
    END SELECT
   
    IF FLAG = ONE THEN
'change the position of the elastic box
'based on the last arrow or positional keypress
LINE (X1, Y1)-(X2, Y2), 2, B, &HAAAA
LINE (X1, Y1)-(X2, Y2), 3, B, &H5555
FLAG = 0
    END IF
  WEND
 
  IF ABORT = ZERO THEN
  GOSUB SAVEFRAG 'SAVE IF ESCAPE WAS NOT PRESSED
  END IF

RETURN



SAVEFRAG:
  'subroutine for saving an image fragment
  'blot the screen one last time
  'give the file name from the a .PUT extension
  PUT (0, 0), PIC, PSET
  GET (X1, Y1)-(X2, Y2), PIC
  LINE (0,0)-(319,24),0,BF
  LINE (0,0)-(319,24),1,B
  LOCATE 2,2
  INPUT "FRAGMENT NAME"; NEWPIC$
  IF NEWPIC$ = "" THEN RETURN
 
  FRAG$ = NEWPIC$
  NEWPIC$ = ""
 
  A$ = ""
  A% = 1
  'parse until the period
  WHILE NOT A$ = "."
    IF A% < LEN(FRAG$)+1 THEN
      A$ = MID$(FRAG$, A%, 1)
    ELSE
      A$ = "."
    END IF
    NEWPIC$ = NEWPIC$ + A$
    A% = A% + 1
  WEND
  NEWPIC$ = NEWPIC$ + "PUT"
  'put the window into an array
  'then point to the array
  'and save it to disk
 
  SEGMENT = VARSEG(PIC(0))
  OFFSET = VARPTR(PIC(0))
  DEF SEG = SEGMENT
  'find the width and the height
  'and calculate the length of the array
  'raster lines break on byte boundaries
  'the array header is two words in length
  WIDE = INT((((X2 - X1) * 2) + 7) / 8)
  HIGH = (Y2 - Y1)+1
  PICSIZE = 4 + (WIDE * HIGH) +1
  BSAVE NEWPIC$, OFFSET, PICSIZE
  DEF SEG
 
  CLS
  LINE (0,0)-(319,24),0,BF
  LINE (0,0)-(319,24),1,B
  LOCATE 2,2
  IF ERRORLEVEL = 0 THEN
    PRINT NEWPIC$ + " saved. Press a key..."
  ELSE
    PRINT NEWPIC$ + " NOT saved. Press a key..."
  END IF
  A$ = INPUT$(1) 
     
RETURN             
 
RESAVE:
  'subroutine for saving a Bsaved Image
  'from an image fragment
  GET (X1, Y1)-(X2, Y2), PIC
  LINE (0,0)-(319,24),0,BF
  LINE (0,0)-(319,24),1,B
  LOCATE 2,2
  INPUT "NEW NAME"; NEWPIC$
  IF NEWPIC$ = "" THEN RETURN

  FRAG$ = NEWPIC$
  NEWPIC$ = ""

  A$ = ""
  A% = 1
  'parse until the period
  WHILE NOT A$ = "."
    IF A% < LEN(FRAG$)+1 THEN
      A$ = MID$(FRAG$, A%, 1)
    ELSE
      A$ = "."
    END IF
    NEWPIC$ = NEWPIC$ + A$
    A% = A% + 1
  WEND
  NEWPIC$ = NEWPIC$ + "BAS"

  'restore the screen
  'and save it to disk
  PUT (0, 0), PIC, PSET
  SEGMENT = &HB800              'Use Screen Segment
  OFFSET = &H0
  DEF SEG = SEGMENT
  PICSIZE = 16384
  BSAVE NEWPIC$, OFFSET, PICSIZE
  DEF SEG

  CLS
  LINE (0,0)-(319,24),0,BF
  LINE (0,0)-(319,24),1,B
  LOCATE 2,2
  IF ERRORLEVEL = 0 THEN
    PRINT NEWPIC$ + " saved. Press a key..."
  ELSE
    PRINT NEWPIC$ + " NOT saved. Press a key..."
  END IF
  A$ = INPUT$(1)
 
RETURN               

ERRORHANDLE:
     BEEP
     ERRORLEVEL = 1
     RESUME NEXT

MAKE.BAT

@echo off

IF NOT EXIST FRAGGLE.BAS GOTO ENDER

        BC FRAGGLE,,NUL /e/v/x
IF NOT EXIST FRAGGLE.OBJ GOTO ENDER

        LINK /NOD /NOE FRAGGLE,,NUL,BCOM45.LIB
        ERASE FRAGGLE.OBJ
IF NOT EXIST FRAGGLE.EXE GOTO ENDER
        echo FRAGGLE.exe Created !
        copy FRAGGLE.EXE ..\.
GOTO FINISH

:ENDER
        echo Sorry... Problem Encountered.
:FINISH


Continued Next Message...

BillBuckels

The Crux of the Biscuit

Well kids, now here's where we see how to use all those pieces of graphics that we snagged over on the IBM-PC in our Aztec-C programs for the C64. The tools that we have been looking at work pretty well but we could also have written a bunch of C128 basic 7 programs to get these for us. I personally wouldn't bother as you can see...


"What Time Is It?" Title Screen

When the program loads the Title Screen will display during loading, then the Main Menu will appear when the program starts after it is loaded.


/* time.c (C) Copyright Bill Buckels 2008 */

/* this program is an expert level AztecC64 program */
/* it uses overlays and is just generally advanced */
/* if you haven't worked your way through the samples
   and other projects you may need to refer to those
   to really understand what is going-on here.

   then again, you may not. */



#define CMAIN 1

#include <poke.h>
#include <colors.h>
#include <math.h>
#include <time.h>
#include <sid.h>

main()
{
int c=0;

    scr_clear();

    /* background color, bordercolor */
    scr_back(tbk,C64_BLUE);

/* set multicolor mode 160 x 200 and display the logo */
/* this program uses a matched palette */

ovloader("CINIT",2,0);
    gclr(-1,tvram,tcram); /* keep this palette for the duration of the program */

    /* clear all keypresses */
    while (kbhit()); /* wait for key release */
    kbflush();

    /* start program by calling the menu */
    for (;;)
    {
       multi = 3;
       c = ovloader("MAINMENU",c);

       if (c == 3)break;


       switch(c) {
   case 0: ovloader("T640",0); break;
   case 1: ovloader("T641",0); break;
   case 2: ovloader("T642",0); break;

   }
       gclr(-1,tvram,tcram); /* reset default palette */

    }

    /* clean-up and exit */

    /* clear last palette and bitmap */
    gclr(0,0,0);
    ovloader("CINIT",0,2);
scr_clear();

    /* clear all keypressess */
    while (kbhit());
    kbflush();
    /* stuff something in the keyboard to make Aztec C happy */
    kbuf[0] = 'X';
    kbuflen[0]=1;
getchar();
scr_clear(); /* clear screen to erase the X */

exit(0);
}



libmain()
{
    /* dummy calls */
/* library functions that must be saved in main overlay */
/* add as required and careful about library functions
   that use other library functions.

   you will need to learn to balance your overlays for
   larger applications. put the common calls in
   the main application, and put the once-used or
   special calls in their own overlays.

   this speaks to the architecture of any overlay
   framework in any environment whether it is on the
   apple ][, C64, or old MS-DOS when memory was scarce.

   an exhaustive topic. 'nuff said.

*/

/* see note above. this code is never executed */
getpixel(0,0,2);
putimage(snote,3,2,22,38,2);
toupper(getch());
box(0, 0, 159, 199, 3, 2);
palset(vram,0,0,0,0,0,0);
decode_scr(bmp,bmp,0);
}

/* about 1/3 of a second */
happy()
{
if (sndflag  == 1) playnote(72,333,V_XYL,V_XYL,V_XYL);

}

/* about 1/3 of a second */
sappy()
{

if (sndflag  == 1) playnote(12,333,0,0,0);

}

/* randomize 5 sets of hours and 5 sets of minutes  */
/* return the selected answer from the group        */
/* we must make certain that there is no repetition */
/* in groups of 5 hours.                            */

/* jiffy clock */
int *jiffy = (int *)160;

randval()
{
    int i,temp,temp2, j;

   /* there are either 25 or 50 hours choices               */
   /* if we pick them sequentially there will be no repeats */
   /* they have been shuffled fairly well.                  */


   j = jiffy[0];
   if (j < 0)j = (j * -1);

   randseed = (j % 25);

   if(hrslimit==12) {
   temp=24;
   }
   else {
   randseed = randseed + 25;
       temp=49;
    }

   temp2=temp-24;

    for(i=0;i<5;i++)
    {
      randseed = (randseed + 1);
      if(randseed>temp)randseed=temp2;
      randhrs[i]=(int)hrseed[randseed];
      }


    /* get one of the 25 minute choices */
    randseed = (randseed + randhrs[0]);
    temp=24;

    for(i=0;i<5;i++)
    {
      randseed = (randseed + 1);
      if(randseed>temp)randseed=0;
      randmins[i]=(int)minseed[randseed];
      }

    /* return an answer within the range of questions */
    return randhrs[0]%multi;
}


circlepoints(x,y,baselength,fdegrees)
int *x, *y;
int baselength;
float fdegrees;
{
    float xtemp;
    float ytemp;
    int degrees = (int )fdegrees;
    float aspect_h, aspect_v;

    aspect_h = (float)1.16;
    aspect_v = (float)1;

/*  starting at 12 O'clock    */
/* use a switch for the break */
switch(degrees)
{


    default:

/* within range */
if(degrees<0 || degrees >359)degrees=0;

/*  0-45  sin */
if(degrees < 45)
{
xtemp = (float) sine_cosine[degrees][0];
ytemp = (float) sine_cosine[degrees][1];
ytemp = ytemp * -1;
break;
}

/* 45-90  cos */
if(degrees < 90)
{
xtemp = (float) sine_cosine[90-degrees][1];
ytemp = (float) sine_cosine[90-degrees][0];
ytemp = ytemp * -1;
break;
}

   /* 90 - 135 */
   if(degrees < 135)
   {
xtemp = (float) sine_cosine[degrees-90][1];
ytemp = (float) sine_cosine[degrees-90][0];
break;
}

/* 135 - 180 */
   if(degrees< 180)
   {
xtemp = (float) sine_cosine[180-degrees][0];
ytemp = (float) sine_cosine[180-degrees][1];
break;
}

   /* 180 - 225 */
   if(degrees< 225)
   {
xtemp = (float) sine_cosine[degrees-180][0];
xtemp = xtemp * -1;
ytemp = (float) sine_cosine[degrees-180][1];
break;
}

   /* 225 - 270 */
   if(degrees< 270)
   {
xtemp = (float) sine_cosine[270-degrees][1];
xtemp = xtemp * -1;
ytemp = (float) sine_cosine[270-degrees][0];
break;
}

   /*  270 - 315 */
   if(degrees< 315)
   {
xtemp = (float) sine_cosine[degrees-270][1];
xtemp = xtemp * -1;
ytemp = (float) sine_cosine[degrees-270][0];
ytemp = ytemp * -1;
break;
}

/* 315 - 360 */
xtemp = (float) sine_cosine[360-degrees][0];
xtemp = xtemp * -1;
ytemp = (float) sine_cosine[360-degrees][1];
ytemp = ytemp * -1;
    }

    ytemp = ytemp/32767;
    xtemp = xtemp/32767;

    xtemp *= (aspect_h*baselength);
    ytemp *= (aspect_v*baselength);

    *x += (int )xtemp;
    *y += (int )ytemp;

}


/* (C) Copyright 2008 Bill Buckels */
/* What Time is It - C64 Version by Bill Buckels */
/* screen mode initialization module */

ovmain(name, mode, prev)
int mode, prev;
{
       /* since this is called only twice during the program */
       /* it gets its own overlay */
       /* this allows more room for code in the main program */
       crtmode(prev);
       prev = setcrtmode(mode);
       return prev;
}



Continued Next Message...

BillBuckels


"What Time Is It?" Main Menu Screen

"What Time Is It?" has 3 Learning Activities (Games) which can be selected from the Main Menu by moving the Snail Cursor with the Arrow Keys to the desired activity then started by pressing the [RETURN] Key. Each Learning activity is a Game based on a different type of analog clock formatted as a series of 20 screens presenting the time on the analog clock as a question and 3 or 5 multiple choice answers in digital clock format.

For the first 10 screens 3 digital clocks are displayed. This is "level 1". For the following 10 screens 5 digital clocks are displayed. This is "level 2". The student selects the answer for each screen, and when 10 screens are complete, the Student is presented with a musical reward. After the reward for completing 20 screens, the student is returned to the Main Menu.

Activities followed by musical rewards is the basic format of all the programs in the "Collection Les Petites espadrilles". The fourth Main Menu choice exits the Main Menu and ends the program and returns to BASIC. It is the equivalent of pressing the X Key. Sound can be toggled on or off at the Main Menu or during any of the activities by pressing S.


If you look below you can clearly see a large chunk of graphics array staring at you. When you read the source further lots of cursor manipulation and so forth is happening and you should be able to see what we use CURLIB for.


/* mainmenu.c (C) Copyright Bill Buckels 2008 */

#include <poke.h>
#include <time.h>

int crows[2] = { 6,14};
int ccols[2] = { 11,20};

/* pcx encoded array of C64 menu image */
char tmenu[2745] = {
85,199, 64, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199,  0, 85,199,  0,
85,199,  0, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199, 64, 85,199,  0,
85,199,  0, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199,  0, 85,199,  0,
85,199,  0, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  1,200,
64,244,  0,  1,  4, 20, 17,  0,  1, 20, 80,
64,  0, 12, 63, 21, 80,194,  0,194,  3,194,
192, 85,194, 64,  0,194,252,194,236,  0, 84,
  5,196,  0,  3,195,  0, 64, 20,  4, 17,193,
192,199,  0, 64,240,  0,200, 64,244,  0,  1,
  4, 20, 17,  0,  1, 20, 80, 64,  0, 12, 63,
21, 80,194,  0,194,  3,194,192, 85,194, 64,
  0,194,252,193,204,193,236,  0, 84,  5,196,
  0,  3,195,  0, 64, 20,  4, 17,193,192,199,
  0, 64,232,  0,200,  1,200, 64,233,  0,194,
  1,194,  4, 16,194, 20, 64,197,  0,193,255,
193,252,196, 12,195,  0,197,192,196,  0,194,
160,172,197,160,  3,199,  0,198,192,  0,  3,
80, 16,194,  4,195,  1,193,196,199,  0, 64,
232,  0,200, 64,233,  0,194,  1,194,  4, 16,
194, 20, 64,197,  0,193,255,193,252,196, 12,
194,  0,  3,197,192,  0,193,255,194,204,194,
224,193,236,160,172,175,163,175,  3,196,  0,
193,252,193,243, 60,198,192,  0,  3, 80, 16,
194,  4,195,  1,193,196,199,  0, 64,224,  0,
200,  1,200, 64,228,  0,196,  1,196, 64,196,
  0,195, 60, 63,196,  0,195,192,205,  0,200,
160,200,  0,  3,194,  0,195,  3,194,  0,195,
192,194,  0,193,192,194,  0,194, 64,198, 16,
232,  0,200, 64,228,  0,196,  1,196, 64,196,
  0,195, 60, 63,196,  0,193,192,193,195,193,
192, 51,193,255,194, 51,193,255,193,207,193,
252,198,  0,163,199,160, 51, 60,  0,194, 15,
196,  3,194,  0,193,195,194,243,193,240, 48,
195,192,194,  0,193,192,194,  0,194, 64,198,
16,224,  0,200,  1,200, 64,224,  0,200,  1,
15,194, 12, 15, 64,194,  3,194,  0,196,192,
205,  0,197,  1,  0,194,160, 80,195, 86, 80,
196,  0,195,170,197,  0,128,168,128,195,  0,
60,194,  3, 12,194,  3, 60, 16,195,  4, 20,
195,  4,232,  0,200, 64,224,  0,200,  1, 15,
194, 12, 15, 64,194,  3,194,  0,193,204,193,
255,194,204, 60,195,  0,197,192,196,  0,197,
  1,  0,194,160, 80,195, 84, 80,160,202,  0,
194, 63, 15, 12, 15,194,  0, 60,194,  3, 12,
193,195,  3, 60, 16,195,  4, 20,195,  4,224,
  0,200,  1,200, 64,224,  0,197,  1,200,  0,
195, 64,194,  0,193,240,194,204,193,240,194,
204,227,  0,197,  3,197,  0,194,192,193,240,
199, 16, 64,232,  0,200, 64,224,  0,197,  1,
200,  0,195, 64,  3, 15,193,243,194,207,193,
240,194,204, 48,195,204, 48, 12, 63, 12,197,
  0,193,192, 48,193,243,197,160,194,163,160,
  0,  3, 15,194,  3,193,255,194,204,  0, 48,
193,192,193,243,193,207, 51,194,  3,197,  0,
194,192,193,240,199, 16, 64,224,  0,200,  1,
200, 64,232,  0, 64,194, 20, 16,194,  4,194,
  1,193,240,202,  0,193,252,195, 12, 48,199,
  0,  3,197,  0,194,192,196,  0,195,  3,197,
  0,193,192,  0,196,192,193,196,195,  1,194,
  4, 16,194, 64,238,  0,200, 64,232,  0, 64,
194, 20, 16,194,  4,194,  1,193,240,199,  0,
194, 12,  0,193,252,195, 12, 48, 63,193,195,
194,  3,195,  0,  3,172,160,193,204, 48,  0,
194,192,  0,194,240,  0,195,  3,197,  0,193,
192,  0,196,192,193,196,195,  1,194,  4, 16,
194, 64,230,  0,200,  1,200, 64,240,  0, 65,
194, 20,  4,  1,195,  0,194, 48,194,  0, 64,
80, 20,  1,195,  3,196,  0, 80,193,240,194,
48,193,240,194,  0,194, 64,  0,  3,196,  0,
  5, 84,194,196,  1,  4, 20, 64,194,  0, 80,
64,246,  0,200, 64,240,  0, 65,194, 20,  4,
  1,195,  0,194, 48,194,  0, 64, 80, 20,  1,
195,  3,196,  0, 80,193,240,194, 48,193,240,
194,  0,194, 64,  0,  3,196,  0,  5, 84,194,
196,  1,  4, 20, 64,194,  0, 80, 64,238,  0,
200,  1,200, 64,255,  0,  0, 21,199,  0, 85,
255,  0,208,  0,200, 64,255,  0,  0, 21,199,
  0, 85,255,  0,200,  0,200,  1,200, 64,255,
  0,255,  0,218,  0,200, 64,255,  0,255,  0,
210,  0,200,  1,195, 64,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,194,240,
193,204,195,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,198,  0,194, 85,198,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,198,  0,194, 65,195,195,195,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,195,  0,195, 64,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,198,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,198,  0,194, 85,198,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,198,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,195,  0,195,  1,194, 85,204,  0,
199,  3,  0,193,255,197,  0,193,255,193,204,
193,195,  3,195,  0,  3,193,195,195,  0,193,
207,194,192, 15,194,  0, 15, 12,193,204, 15,
12,193,204, 12,  0,199,204,  0, 60,193,204,
194,192,194,204, 60,  0,195,204,193,252,195,
204,  0,193,252,198, 48,203,  0, 63,194, 12,
194,  3,196,195,199,  0,193,252,194, 48,194,
192,195,  0,193,252,194,  0,193,252,194,  0,
193,240,197,204,193,240,  0, 48,197,204, 48,
  0,197,195,193,255, 60,  0,195, 51,194, 63,
194, 51,225,  0,196,  3,  0,194,  3,  0,193,
195, 51,  3,193,195,194, 51,193,195,  0,193,
195,194, 51,193,195,195,  3,  0,193,195,194,
51,193,243,195, 51,  0,193,195, 51,195,  3,
51,193,195,  0,193,240,  0,  3,193,192,  0,
  3,193,240,  0,194,  3,193,243,  3,  0,193,
243,  3,  0,193,195, 51,  3,193,195,194, 51,
193,195,  0,193,243,194,  3,193,195,194,  3,
193,243,  0,198,  3,193,243,  0,193,243,194,
  3,193,195,194,  3,193,243,  0,193,195, 48,
195,  0, 48,193,192,  0,193,243,198,195,  0,
12,197, 51, 12,  0,194, 51,194, 63,195, 51,
222,  0,194,  3,  0, 12,194, 60,194,204, 12,
15,194,204,194,240,194,192,  0,193,255,199,
  0, 15,197,  0,194, 12,193,204,197,  0, 15,
194, 12,197,  0,193,207,194, 12,197,  0,193,
207,194,  3,197,  0,193,192,209,  0,  3,194,
195,195, 60,194,195,200,  0,193,192,199,  0,
193,252,197,  0,195,204,197,  0,193,240,194,
204,255,  0,205,  0,194, 60,194, 15,196,  0,
60,194,240,193,192,199,  0,  3,199,  0,193,
240,197,  0,194, 12, 15,197,  0, 51,194,243,
197,  0,193,243,194,  3,197,  0,195, 51,197,
  0,195, 48,240,  0,194, 12, 48,194, 12,194,
  3,198,  0, 15, 12,193,204,197,  3,193,255,
196,  0, 15,197,  0,194, 12,193,204, 15,196,
  0, 15,194, 12,193,207,196,  0, 15,194, 12,
193,204,196,  0,196,  3,212,  0,  3,194, 12,
63,199,  0,197,195,193,192,194, 48,193,252,
198,  0,193,252,197,  0,195,204,193,240,196,
  0,193,240,195,192,255,  0,205,  0,194,  3,
194, 15,194, 60,194,  0,195,192,194,240, 60,
196,  0,  3,199,  0,193,240,197,  0, 15,195,
12,196,  0,196, 51,196,  0,193,195,194,  3,
193,243,196,  0,194,243,194, 51,196,  0,195,
48,193,192,238,  0,194, 85,196, 64,194,  0,
194, 85,196,  0,193,204, 60,194, 85,198,  0,
194, 85,198,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,198,  0,194, 85,198,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,196,  0,194,195,194, 65,198,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,198,  0,194, 85,196, 64,194,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,198,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,198,  0,194, 85,198,  0,194, 85,
198,  0,194, 85,198,  0,194, 85,198,  0,194,
85,198,  0,194, 85,198,  0,194, 85,198,  0,
194, 85,198,  0,194, 85,198,  0,194, 85,198,
  0,194, 85,198,  0,194, 85,196,  1,200, 64,
237,  0,193,255,193,195,193,243,197,  0,193,
192,  0,193,192,200,  0,  3,194, 12, 15,194,
12, 15,  0, 60,195, 51,194,243, 60,206,  0,
195,  3,197,  0,193,240,  0,193,192,240,  0,
200, 64,255,  0,255,  0,210,  0,200,  1,200,
64,232,  0,195, 12,193,243,196,  0,196,192,
  0,  1,  4, 20,194,  0,  1, 20, 80, 64,  0,
12,  0, 21, 80,194,  0,194,  3,193,192,  0,
85,194, 64,  0,194,252,193,204,194,  0, 84,
  5,199,  0,  3, 64, 20,  4, 17,195, 48,193,
192,244,  0,200, 64,247,  0,  2,196,  0, 42,
194,128,197,  0,170,199,  0,170,199,  0,170,
200,  0,194,128, 32,240,  0,200,  1,200, 64,
217,  0, 15, 12, 15,195,  3, 15,  0, 60,197,
204, 60,194,  0,194,  1,194,  4, 16, 20, 17,
64,197,  0,193,255, 63,196, 12,195,  0,197,
192,195,  0,193,204,194,240,193,252,196,  0,
194,  3,198,  0,199,192,  0, 64, 80, 16,194,
  4,195,  1,  0, 12, 63,196, 15, 12,  0,193,
240,197, 48,193,240,224,  0,200, 64,239,  0,
194,  2,194,  8,194, 32,194,128,225,  0, 32,
194,  8,194,  2,200,  0,194,128, 32,232,  0,
200,  1,200, 64,229,  0,195,  1, 20,196, 64,
195,  0,193,252,195, 60, 63,195,  0,196,192,
211,  0,  2,195,  0, 10,194, 42,170,168,194,
  3,194,  0,195,  3,  0,193,196,195,192,194,
  0,193,192,  0,195, 64,197, 16,232,  0,200,
64,232,  0,  2,194,  8,197, 32,210,  0,  3,
12, 60,195,204,  0, 48,193,204,193,207,196,
204,196,  0,196,192,200,  0, 32,194,  8,197,
  2,232,  0,200,  1,200, 64,211,  0,195,  3,
195,  0,194,195, 51, 48,193,240, 48, 51,  1,
193,193,  1,197,193,  0, 15,194, 12, 15, 64,
194,  3,194,  0,196,192,205,  0,197,  1,  2,
10, 42, 90, 86,194, 84, 90,194,160,128,207,
  0, 60,194,  3, 12,194,  3,194, 16,  4,  7,
  4, 20,194,  4,194,  0,193,255,193,240,193,
252,195,195,224,  0,200, 64,232,  0,200, 32,
208,  0,196,204,196,192,195,204, 12,196,  0,
194,192,193,207,194,243,193,207, 12, 48,200,
  0,200,  2,232,  0,200,  1,200, 64,224,  0,
198,  1,200,  0,194, 64,195,  0,193,240,194,
204,193,240,193,204,208,  0,194, 42,195, 10,
195,  2,194,  0,194,128,195,160,168,196,  0,
196,  3, 60,197,  0,194,192,  4,199, 16,193,
252,231,  0,200, 64,232,  0,200, 32,208,  0,
198,192,194, 48,  0,194,192,195, 48,194,  0,
198, 48,194,192,200,  0,200,  2,232,  0,200,
  1,200, 64,220,  0,194,  3,194, 12,196,  0,
15, 51,194,243,194, 64,194, 20, 16,194,  4,
  1,193,204,193,240,202,  0,193,252,195, 12,
206,  0,194,192,194,168,195, 42, 10,  2,  0,
  3,195,  0,193,192,  0,194,192,193,240,193,
192,193,196,195,  1,194,  4,195, 64,  0,194,
15,194,  3,196,  0, 60,195,204,224,  0,200,
64,232,  0,195, 32,194,  8,194,  2,200,  0,
128,200,  0,197, 12,195,  0,196,  3,212,  0,
195,  2,194,  8,194, 32,128,232,  0,200,  1,
200, 64,216,  0, 15,199,  0,194,243,193,207,
197,  0,  1,200,  0, 65,194, 20,  4,  1,194,
  0,195, 48,194,  0, 64, 80, 20,196,  3,197,
  0,193,240,194, 48,193,240,194,  0, 64,194,
  0,  3,196,  0,  5,193,192,194,196,  1,  4,
20, 64,  0, 16, 80, 64,197,  0,194, 12, 15,
197,  0,194,204, 60,229,  0,200, 64,240,  0,
128,194, 32,194,  8,194,  2,200,  0,128,217,
  0,194,  2,194,  8,194, 32,194,128,239,  0,
200,  1,200, 64,232,  0, 15,194,  3, 15,194,
  3, 15,  0,193,252,193,192,193,240,195, 12,
193,240,  0,  1,199,  0, 80, 21,  0, 15,194,
  0,  3,  0, 64, 85,  0, 60,194,243, 51,193,
243, 84,199,  0,194, 15,194,  3,194, 12, 15,
  0,193,252,193,192,193,240,195, 12,193,240,
241,  0,200, 64,248,  0,128, 42,199,  0,170,
199,  0,170,199,  0,170,198,  0,128,247,  0,
200,  1,199, 64, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199,  0, 85,199,  0,
85,199,  0, 85,199,  0, 85,  0, 15,197,  0,
85,193,243, 60,197,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199,  0, 85,199,  0,
85,199, 64, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  0, 85,199,  0, 85,199,  0,
85,199,  0, 85,199,  0, 85,199,  0, 85,199,
  0, 85,199,  0, 85,199,  0, 85,199,  0, 85,
199,  0, 85,199,  1, 85};

char *sback = (char *)&tmenu[0]; /* reuse the screen buffer */

#define PUT 0
#define GET 1
#define P_AND 2

ovmain(name, choice)
int choice;
{

int c, crow, ccol;
char *ptr;

decode_scr(&tmenu[0],bmp,8000);

    putimage(snback,3,2,22,38,GET); /* save note area */
    /* display note if sound is on */
    if (sndflag == 1)putimage(snote,3,2,22,38,P_AND);

    while (kbhit()); /* wait for key release */
    kbflush();


    happy();
for (;;) {

switch(choice)
{
case 0:  crow = crows[0]; ccol = ccols[0]; ptr = sleft;  break;
case 1:  crow = crows[0]; ccol = ccols[1]; ptr = sright; break;
case 2:  crow = crows[1]; ccol = ccols[0]; ptr = sleft;  break;
case 3:
default: crow = crows[1]; ccol = ccols[1]; ptr = sright; break;


}
putimage(sback,srows,scols,crow,ccol,GET); /* save the screen */
putimage(ptr,srows,scols,crow,ccol,P_AND); /* put the cursor into position */

BEGIN:;

    c = toupper(getch());

    if (c == 13 || c == 32)  {
    if (choice == 3) sappy();
    else happy();
break;
}
    if (c == 'X') {
   choice = 3;
   sappy();
   break;
}
if (c == 'S') {
if (sndflag == 0) {
               putimage(snote,3,2,22,38,P_AND);
   sndflag = 1;
}
else {
sndflag = 0;
putimage(snback,3,2,22,38,PUT);
}
happy();
}
if (c == '3') {
multi = 3;
happy();
}
if (c == '5') {
multi = 5;
happy();
}


/*

#define UP_ARROW      145
#define DOWN_ARROW   17
#define LEFT_ARROW   157
#define RIGHT_ARROW   29

*/
        if (c != 145 && c != 17 && c != 157 && c != 29) goto BEGIN;

putimage(sback,srows,scols,crow,ccol,PUT); /* put the screen back */

    switch(c) {

   case 17:
   case 145: choice = choice + 2;
             if (choice > 3)choice = choice - 4;
             break;

   case 157: choice = choice - 1;
             if (choice < 0)choice = 3;
             break;

   case 29:  choice = choice + 1;
             if (choice > 3)choice = 0;
             break;
}

}

    /* don't waste any code cleaning-up */
    putimage(sback,srows,scols,crow,ccol,PUT); /* put the screen back */
return(choice);
}


Unpacking The Graphics

Just in case you thought this part would be hard... IT ISN'T! Here's the Aztec C64 library function that I wrote for the occasion.


/* (C) Copyright Bill Buckels 2008 */

/* decode screen arrays saved with pcx run-length ecoding */
/* decode full screen images onto screen */
/* decode fragments into buffers */

decode_scr(ptr, bptr, target)
char *ptr, *bptr;
int target;
{
int ctr=0, x, xcnt,ch;
    int offset=0;

do{

/* start with a seed count */
xcnt=1;
    ch=ptr[ctr];
    ctr++;

    /* check to see if its raw */
    /* if its not, run encoded */
    if(0xC0 == (ch & 0xc0)){
       xcnt = 0x3f & ch;
       ch = ptr[ctr];
       ctr++;
    }
    for(x=0;x<xcnt;x++){
if (offset < target) bptr[offset] = ch;
else break;

offset++;
}

     } while(offset<target);

}


Continued Next Message...

BillBuckels


Activity 1: 12 Hour Analog Clock - Hours Only

The 12-hour clock is a convention of time keeping in which the day runs from midnight to noon, then from noon to midnight, and is divided into 2 periods of 12 hours, numbered from 0 to 12. The 12-hour clock is only dominant in a handful of countries, particularly the United States and Canada (except Quebec). The 24-hour clock is the most commonly used time notation in the world today.

This activity teaches hours in the 12-hour clock time format. For each screen, a random time is displayed on the 12-hour analog clock. To the right of the analog clock is a multiple choice menu of different times in digital clock format, with only one that matches the time that is displayed on the analog clock.

For each screen, when the Snail Cursor is to moved to the digital clock that matches the analog clock, and the [RETURN] Key is pressed, a section of the Drain Pipe on the left of the screen will fill with water. For every 10 screens the water will empty from the drain pipe, and give the Snail a "bath".


Data for this module is below.


/* t640.c (C) Copyright Bill Buckels 2008 */
/* gameplay module 0 */

#include <poke.h>
#include <time.h>
#include <sid.h>

char *timebuf="  :00"; /* digital clock text */
char *clrbuf ="     ";
int bkrows = 8;
int bkcols = 6;

/* locations for the digital clock on the right */
/* box cords are given in byte, raster */
/* box is offset 4 rasters from top and bottom of 8 raster font */
/* boxes are 16 rasters high and spaced 16 rasters apart vertically */
/* text cords are given in col, row */
/* multiply col x 4 to use pixel plotting functions for multicolor mode */
/* multiply col x 8 to use pixel plotting functions for hires mode */
/* multiply row x 8 for pixel plotting in both modes */
int boxcords[6][6]={
                      /* box cords */        /* textcords */
                      32,4,     39, 19,     33, 1,
                      32,36,    39, 51,     33, 5,
                      32,68,    39, 83,     33, 9,
                      32,100,   39, 115,    33, 13,
                      32,132,   39, 147,    33, 17,
                      32,164,   0,  0,      0,  0};


/* screen image for this module */
/* followed by the clock at 2092 */
/* 2 pcx encoded arrays of C64 images */

/* the reason I combined these was to provide
   a contiguous buffer area to unpack
   the clock and to save the screen behind the
   snail cursor...

   in a low memory environment sometimes
   a little knitting is required

   This program's memory is pushed right
   to the top of what is available on the C64.

*/
char t640x[] = {
193,255,199,192,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  3,200,192,255,  0,255,
  0,255,  0,255,  0,244,  0,200,  3,200,192,
255,  0,255,  0,255,  0,255,  0,244,  0,200,
  3,193,240,193,252,193,215,197,213,195,  0,
194,192,195,112,255,  0,255,  0,255,  0,255,
  0,236,  0,200,  3,193,213,193,245,193,253,
197,205,196, 92,196, 87,255,  0,255,  0,255,
  0,255,  0,236,  0,200,  3,195,195,193,253,
195,245,193,253,196, 87,195, 85, 87,195,  0,
193,192,195,112,193,192,255,  0,216,  0,  1,
199,  0, 85,199,  0, 84,255,  0,255,  0,250,
  0,200,  3,200,195,200, 87,255,  0,205,  0,
  1,  4, 16, 64,  0,  5, 20, 64,  0,194, 64,
76, 84, 64,197,  0,193,192,195,  4,  0, 51,
193,252, 48, 51,  5,196,  0,194,192,  0, 64,
20,  1,196,  0, 12,194,  0, 64, 80, 20, 21,
17, 64,198,  0, 64, 80,255,  0,255,  0,226,
  0,200,  3,195,195,193,253,195,245,193,253,
196, 87,195, 85, 87,195,  0,193,192,195,112,
193,192,248,  0,194,  1,  4, 20, 16,195, 64,
200,  0, 63,197, 12,194,  0,198,192,194,  0,
51, 60, 63,199,  0,193,192,197,  0, 60,197,
12,202,  0, 16,194,  4,  1,200,  0,194, 64,
194, 16,255,  0,255,  0,218,  0,200,  3,200,
195,200, 87,248,  0,194,  1,195,  4,195, 16,
194,  0, 79, 15,196,  3,194,  0,193,240,197,
204,242,  0, 48,193,204, 12,194, 48,193,192,
16, 20, 84,  4,195,  1,200,  0, 64,255,  0,
255,  0,210,  0,200,  3,195,195,193,253,195,
245,193,253,196, 87,195, 85, 87,195,  0,193,
192,195,112,193,192,240,  0,194, 16,198, 64,
  3,199,  0,193,240,247,  0,193,252,207,  0,
199, 64, 16,255,  0,255,  0,210,  0,200,  3,
200,195,200, 87,248,  0, 64,194, 67, 80,196,
64,193,240,194, 48,193,240,194, 48,193,192,
218,  0,  4,195, 21,  4,226,  0,193,240,194,
48,193,241,194, 48,193,240,  0,195, 16, 80,
196, 16,255,  0,255,  0,210,  0,200,  3,195,
195,193,253,195,245,193,253,196, 87,195, 85,
87,195,  0,193,192,195,112,193,192,240,  0,
197, 64,195, 16,199,  0,  3,199,  0,193,192,
255,  0,  0,200, 64,255,  0,255,  0,210,  0,
200,  3,200,195,200, 87,248,  0,194, 16,195,
  4,194,  1,  0,196,  3, 67,  3,  0, 64,194,
48,193,192,194, 48,193,192,242,  0, 48,193,
192,194,204,193,252,194, 12,  0,195,  1,  4,
84, 20,194, 16,255,  0,255,  0,218,  0,200,
  3,195,195,193,253,195,245,193,253,196, 87,
195, 85, 87,195,  0,193,192,195,112,193,192,
248,  0,194, 64, 16, 20,  4,194,  1,200,  0,
64, 63, 51,195,  3,194, 12, 64,204,  0,194,
12, 48, 63,201,  0, 60, 48, 60,195, 12, 60,
199,  0, 64,195,  0,  1,194,  4, 16, 80, 16,
194, 64,255,  0,255,  0,223,  0,200,  3,200,
195,200, 87,255,  0,201,  0, 16,  4,  1,197,
  0,194, 64,  0, 64, 20,  5,199,  0, 64, 84,
  1,194, 51, 15,  0,195,  4, 85,198,  0,  5,
84,196,  0,  1, 20, 64,  0, 17, 21, 20, 80,
64,195,  0, 64,255,  0,255,  0,233,  0,198,
  3, 23, 87,195,195,193,253,195,245,193,253,
196, 87,195, 85, 87,195,  0,193,192,195,112,
193,192,255,  0,255,  0,255,  0,255,  0,203,
  0,  1,197,  0,  5, 21, 85,194,  0,  1, 21,
194, 85, 80, 64,  5, 21, 85, 84, 80,195,  0,
87, 83, 67,196,  3, 23,200,195,200, 87,255,
  0,255,  0,255,  0,250,  0,  1,196,  0,  1,
  5,194, 85,194,  0,  5, 21, 85, 84, 80,  0,
  5,194, 85, 84, 64,195,  0, 84, 80,196,  0,
  5, 21,195,  0,  1, 21,194, 85, 80,  0,  5,
21, 85, 84, 80,194,  0,194, 87, 83, 67,196,
  3,195,195,193,253,195,245,193,253,196, 87,
195, 85, 87,195,  0,193,192,195,112,193,192,
255,  0,255,  0,255,  0,218,  0,  5,196,  0,
  1, 21,194, 85,  0,  1,  5,194, 85, 84, 64,
  0, 21,194, 85, 80,196,  0, 84, 64,195,  0,
  1,  5, 85,195,  0,  5, 21,194, 85, 84,  1,
  5,195, 85, 80,194,  0,194, 85, 80, 64,196,
  0, 64,207,  0,198,  3, 23, 87,200,195,200,
87,255,  0,255,  0,255,  0,201,  0,  1, 21,
196,  0,  5, 21, 85, 84,  0,  1, 21,194, 85,
80, 64,  0,194, 85, 84, 64,196,  0, 80, 64,
195,  0,  1, 21, 85,194,  0,  1,  5,195, 85,
80,  1, 21,194, 85, 84, 80,194,  0,194, 85,
80, 64,196,  0, 64,206,  0,  5,196,  0,  1,
21,194, 85,194,  0,  5, 21,196, 85,  5,198,
85, 84,198, 87, 67,  3,195,195,193,253,195,
245,193,253,196, 87,195, 85, 87,195,  0,193,
192,195,112,193,192,255,  0,255,  0,232,  0,
  5, 21,195,  0,  1,  5,194, 85, 84,  0,  5,
21, 85, 84, 80,194,  0,194, 85, 80, 64,195,
  0,  1, 80,196,  0,  5, 21, 85,194,  0,  1,
21,194, 85, 84, 80,  5,195, 85, 84, 64,194,
  0, 85, 84, 80,197,  0, 64,204,  0,  1,  5,
85,195,  0,  1, 21,195, 85,  0,  1, 21,196,
85, 84,197, 85, 84, 64,  0,195, 85, 84, 64,
195,  0, 85, 80, 64,197,  0, 64,199,  0,198,
  3,  7, 87,200,195,199, 87, 85,198,  0,194,
192,255,  0,255,  0,207,  0,  1,  5, 85,195,
  0,  1, 21,194, 85, 80,  1,  5,194, 85, 84,
64,194,  0, 85, 84, 80,196,  0,  5, 64,195,
  0,  1,  5,194, 85,194,  0,  5, 21,194, 85,
84, 64, 21,195, 85, 80,195,  0, 85, 84, 64,
203,  0,  1,  5,196,  0,  1, 21,194, 85,194,
  0,  1, 21,196, 85,  5,196, 85, 84, 64,  0,
195, 85, 84, 64,195,  0, 85, 84, 64,197,  0,
64,197,  0,  5, 85,196,  0,  1, 21,194, 85,
195,  0,  5,196, 85,  0,  1,198, 85, 21,199,
85,200, 87,195,195,197,192,194, 85,194,213,
193,245, 53, 61, 13,193,240,112,124, 92, 95,
194, 87, 85,198,  0,194,192,255,  0,238,  0,
  1, 21, 85,195,  0,  5,194, 85, 84, 64,  1,
21,194, 85, 80, 64,194,  0, 85, 84, 64,195,
  0,  1,  5,196,  0,  1, 21,194, 85,  0,  1,
  5,195, 85, 80, 64, 21,194, 85, 84, 64,195,
  0, 85, 80, 64,203,  0,  5, 85,195,  0,  1,
  5,195, 85,  0,  5, 21,195, 85, 80,  0,195,
85, 84, 80,195,  0, 85, 84, 64,196,  0,  1,
80,196,  0,  1, 21, 85,196,  0, 21,195, 85,
194,  0,  5,197, 85,  5,214, 85, 84,198, 85,
84,  0,197, 85, 84,194,  0,196, 85, 84,195,
  0,195, 87, 83,196,  3,200,192, 15,194,  3,
197,  0,194, 85,194,213,193,245, 53, 61, 13,
193,240,127,198, 85,194,  0,193,255,197, 85,
194,  0,193,192,127,196, 85,195,  0,193,255,
196, 85,195,  0,193,255,196, 85,195,  0,193,
255,196, 85,195,  0,193,255,196, 85,195,  0,
193,255,196, 85,195,  0,193,255,196, 85,195,
  0,193,255,196, 85, 63,194, 51,193,255,196,
115,196,  0,194, 85,196,  0,  5, 21, 85, 84,
194,  0,  5, 21, 85, 84, 80,195,  0, 85, 80,
64,195,  0,  1, 21,196,  0,  1,  5,194, 85,
  0,  1, 21,194, 85, 84, 80,  0,195, 85, 80,
64,195,  0, 84, 80,197,  0,  1,197,  0,  5,
85, 80,194,  0,  1, 21, 85, 80, 64,  0,  5,
21, 85, 84, 64,195,  0,194, 85, 64,196,  0,
  5, 80,196,  0,  5,194, 85,195,  0,  5,195,
85, 80,  0,  1, 21,195, 85, 84,  0, 21,196,
85, 84,194,  0,196, 85, 84,195,  0,195, 85,
84,196,  0,194, 85, 84,196,  0,  1, 85, 84,
197,  0, 85, 84,197,  0,  5, 85,198,  0,194,
85,197,  0,  1,194, 85,197,  0,195, 85,196,
  0,  1,195, 85,196,  3,196, 87,200,192,200,
  0, 15,  3,198,  0, 85,193,213, 63,197,  0,
195, 85,193,255,196,  0,196, 85,193,255,195,
  0,196, 85,193,255,195,  0,196, 85,193,255,
195,  0,196, 85,193,255,195,  0,196, 85,193,
255,195,  0,196, 85,193,255,195,  0,196, 85,
193,255,195,  0,196, 85,193,255,195,  0,127,
115,127,115,193,243,194, 51, 63,195,  0,196,
85,196,  0,196, 85,194,  0,  5,197, 85,  0,
199, 85,  0, 80,195, 64, 80,194, 85,197,  0,
21,194, 85,194,  0,  1,  5,196, 85,  0, 21,
198, 85,  0,195, 64, 80,195, 85,195,  0,  1,
21,195, 85,194,  0,  5,197, 85,  0,199, 85,
  0,199, 85,  0,195, 64, 80,195, 85,197,  0,
195, 85,195,  0,  1,  0,195, 85,194,  0,  1,
85,  0,195, 85,  0,  1, 85, 84,  0,195, 85,
  0,194, 85,194,  0,195, 85,  0,194, 85,194,
  0,195, 85,  0,194, 85,194,  0,195, 85,  0,
85,195,  0,195, 85,  0, 85,195,  0,195, 85,
  0, 85,195,  0,195, 85,  0, 64,195,  0,195,
85,  0,196,  3,195, 87,  3,199,192,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  0,
193,255,199,  0,193,255,199,  0,193,255,199,
  0,193,255,199,  0,193,255,199,  0,193,255,
199,  0,193,255,199,  0,193,255,199,  0,193,
255,199,  0,193,255,199,  0,193,255,199,  3,
193,255,
212,  0,  1,  4, 16, 64,  0,  5, 20, 64,  0,
194, 64, 76, 84, 64,197,  0,193,192,195,  4,
  0, 51,193,252, 48, 51,  5,196,  0,194,192,
  0, 64, 20,  1,196,  0, 12,194,  0, 64, 80,
20, 21, 17, 64,198,  0, 64, 80,216,  0,194,
  1,  4, 20, 16,195, 64,200,  0, 63,197, 12,
194,  0,198,192,194,  0, 51, 60, 63,199,  0,
193,192,197,  0, 60,197, 12,202,  0, 16,194,
  4,  1,200,  0,194, 64,194, 16,200,  0,194,
  1,195,  4,195, 16,194,  0, 79, 15,196,  3,
194,  0,193,240,197,204,242,  0, 48,193,204,
12,194, 48,193,192, 16, 20, 84,  4,195,  1,
200,  0, 64,194, 16,198, 64,  3,199,  0,193,
240,247,  0,193,252,207,  0,199, 64, 16, 64,
194, 67, 80,196, 64,193,240,194, 48,193,240,
194, 48,193,192,218,  0,  4,195, 21,  4,226,
  0,193,240,194, 48,193,241,194, 48,193,240,
  0,195, 16, 80,196, 16,197, 64,195, 16,199,
  0,  3,199,  0,193,192,255,  0,  0,200, 64,
194, 16,195,  4,194,  1,  0,196,  3, 67,  3,
  0, 64,194, 48,193,192,194, 48,193,192,242,
  0, 48,193,192,194,204,193,252,194, 12,  0,
195,  1,  4, 84, 20,194, 16,208,  0,194, 64,
16, 20,  4,194,  1,200,  0, 64, 63, 51,195,
  3,194, 12, 64,204,  0,194, 12, 48, 63,201,
  0, 60, 48, 60,195, 12, 60,199,  0, 64,195,
  0,  1,194,  4, 16, 80, 16,194, 64,221,  0,
16,  4,  1,197,  0,194, 64,  0, 64, 20,  5,
199,  0, 64, 84,  1,194, 51, 15,  0,195,  4,
85,198,  0,  5, 84,196,  0,  1, 20, 64,  0,
17, 21, 20, 80, 64,195,  0, 64,215,  0};


/* clock face to erase hands */
int clkrows = 9;
int clkcols = 12;
int clkrow = 6;
int clkcol = 9;
int clksize = 864;


char c640x = (char *)&t640x[2092];
char *clk = (char *)&t640x[0];
char *sback = (char *)&t640x[864]; /* reuse the packed buffer */
char *timebak = (char *)&t640x[1224];
/*
char timebak[48];
*/
/* spout stuff */
char sprow[9] = {3,6,8,10,12,14,16,18,20};

/*
int sp1rows = 17;
*/
int sp1cols = 3;
int sp2rows = 4;
int sp2cols = 14;

/* wave stuff */
int splrows = 10;
int splcols = 26;

/* musical array created from IBM snd file lubeyloo.snd */
/* array structure is midi note number, duration (18.2 ticks sec) */
/* these are song-parts created by sndfrag. I edited the output
   for readability. doing a song this way requires no particular
   musical knowledge, just counting skills. most programmers
   are pretty fair in this area. Note that the character
   255 in these arrays means a pause between notes, and the
   0, 0 pair indicates the end of a song.
   you can see the B64NAT.LIB sid.c source for more detail */

/* here we go lubey-loo */
char lub0[]={
62,   2,
255,  1,
62,   2,
255,  1,
62,   2,
255,  1,
66,   5,
255,  1,
62,   2,
255,  1,
69,   11,
0,    0};

/* here we go lubey-lie */
char lub1[]={
62,   2,
255,  1,
62,   2,
255,  1,
62,   2,
255,  1,
66,   5,
255,  1,
62,   2,
255,  1,
64,   11,
0,    0};

/* here we go lubey-loo
   same as lub0 so use lub0 twice.
char lub2[]={
62,   2,
255,  1,
62,   2,
255,  1,
62,  2,
255,  1,
66,  5,
255,  1,
62,  2,
255,  1,
69,  11,
0,   0};
*/

/* all on a saturday...
   all on a saturday...
   (repeated twice)  */
char lub3[]={
69,   2,
255,  1,
71,   2,
255,  1,
69,   2,
255,  1,
  67,  2,
255,  1,
66,   2,
255,  1,
64,   2,
0,    0};

/* all on a saturday night. */
char lub4[]={
69,   2,
255,  1,
71,   2,
255,  1,
69,   2,
255,  1,
  67,  2,
255,  1,
66,   2,
255,  1,
64,   2,
255,  1,
62,   11,
0,    0};


#define PUT 0
#define GET 1
#define P_AND 2



The Next Message contains the Code for this module.

Continued Next Message...


BillBuckels

Code for Previous Module

There is probably little point in posting all 3 gameplay modules in this lot because they are all pretty similar. Now there is lots of other relative information that is not included in this online summary that I have done. You really need to download this whole affair and look at it in the detail that it deserves.

This is intended only as an overview of how we handle bitmapped graphics in an Aztec C program.


/* t640.c (C) Copyright Bill Buckels 2008 */
/* gameplay module 0 */

ovmain(name, answers)
int answers;
{

int c, crow, ccol, pos = 5, oldpos = 5, choice;
char *ptr;
int lastbox, x1, y1, x2, y2;

    gclr(0,-1,-1); /* clear screen */

    dowave(0); /* turn the blue off in the wave area */
    /* remove the blue in the pipe */
    for (c=1; c < 10; c++)dospout(c,0);

    /* unpack the screen onto the display */
decode_scr(&t640x[0],bmp,8000);
decode_scr(&t640x[2092],&t640x[0],clksize); /* unpack the clock from the end of
                                  the main screen to the beginning */

    putimage(snback,3,2,22,38,GET); /* save note area */
    /* display note if sound is on */
    if (sndflag == 1)putimage(snote,3,2,22,38,P_AND);

    while (kbhit()); /* wait for key release */
    kbflush();


  hrslimit=12; /* this module uses a 12 hour digital clock */
  lastbox = 0; /* draw each box only once */

  for (;;) {


    if (lastbox!=5) {
for (c = lastbox; c < multi; c++) {
   x1 = boxcords[c][0] * 4;
   y1 = boxcords[c][1];
   x2 = boxcords[c][2] * 4;
   y2 = boxcords[c][3];
   box(x1, y1, x2, y2, 3, 2);
   lastbox = multi;
}
    }

/* save background over font on last box position */
/* this prevents the colors in the wave from being
   wiped-out by the text in the font area on-screen. */
if (multi == 5) {
x1 = boxcords[4][4];
y1 = boxcords[4][5];
if (sndflag ==  1)putimage(snback,3,2,22,38,PUT);
putimage(timebak,bkrows,bkcols,y1,x1,GET);
if (sndflag ==  1)putimage(snote,3,2,22,38,P_AND);

}

/* do the first clock in the series */
choice=randval();
/* this module uses hours only so set minutes to 0 */
for(c=0;c<multi;c++)randmins[c]=0;
dohands(randhrs[choice],randmins[choice]);
    c = 0;
happy();

for (;;) {


if (pos == 5)ptr=sright;
else ptr = sleft;

ccol = boxcords[pos][0]-10;
crow = boxcords[pos][1];
crow = crow/8;

putimage(sback,srows,scols,crow,ccol,GET); /* save the screen */
putimage(ptr,srows,scols,crow,ccol,P_AND); /* put the cursor into position */

BEGIN:;

    c = toupper(getch());


        /* answer selection - spacebar or enter */
    if (c == 13 || c==32)  {

if (choice == pos) {

/* erase the wrong times */
for(c=0;c<multi;c++)
{
x1 = boxcords[c][4];
y1 = boxcords[c][5];
if(c!=choice) pfont(clrbuf,y1,x1,tc2,tc1,tc3);

}

putimage(sback,srows,scols,crow,ccol,PUT); /* put the screen back */

/* move the snail down */
pos = 5;
ptr=sright;
ccol = boxcords[pos][0]-10;
crow = boxcords[pos][1];
crow = crow/8;

putimage(sback,srows,scols,crow,ccol,GET); /* save the screen */
putimage(ptr,srows,scols,crow,ccol,P_AND); /* put the cursor into position */

answers++;

/* get a reward every 10 times */
if(answers==10||answers==20) {
  /* erase the correct time */
  x1 = boxcords[choice][4];
  y1 = boxcords[choice][5];
  pfont(clrbuf,y1,x1,tc2,tc1,tc3);
  if (multi == 5) {
  x1 = boxcords[4][4];
  y1 = boxcords[4][5];
  putimage(timebak,bkrows,bkcols,y1,x1,PUT);
  if (sndflag == 1)putimage(snote,3,2,22,38,P_AND);
  }
  break;
}

/* count off the answers */
/* fill the pipe */
dospout(answers,1);
if (sndflag == 1) {
/* play up to 9 notes starting at c-5 */
/* play each note for 200 milliseconds */
x1 = answers;
if (answers > 10)x1 = (x1-10);
/* go up the scale with a xylophone */
for(c=0;c<x1;c++) playnote(c+72,200,V_XYL,V_XYL,V_XYL);
}
/* erase the correct time */
x1 = boxcords[choice][4];
y1 = boxcords[choice][5];
pfont(clrbuf,y1,x1,tc2,tc1,tc3);

/* do the next clock in the series */
choice=randval();
/* this module uses hours only so set minutes to 0 */
for(c=0;c<multi;c++)randmins[c]=0;
dohands(randhrs[choice],randmins[choice]);
c = 0;
    }
    else {
   sappy();
}


}
    if (c == 'X') {
   sappy();
   for(c=0;c<multi;c++)
{
x1 = boxcords[c][4];
y1 = boxcords[c][5];
    pfont(clrbuf,y1,x1,tc2,tc1,tc3);

}
   if (multi == 5) {
    x1 = boxcords[4][4];
    y1 = boxcords[4][5];
    putimage(timebak,bkrows,bkcols,y1,x1,PUT);
    if (sndflag ==  1)putimage(snote,3,2,22,38,P_AND);
   }
   answers = 0;
   break;
}
if (c == 'S') {
if (sndflag == 0) {
               putimage(snote,3,2,22,38,P_AND);
   sndflag = 1;
}
else {
sndflag = 0;
putimage(snback,3,2,22,38,PUT);
}
happy();
}

/*

#define UP_ARROW      145
#define DOWN_ARROW   17
#define LEFT_ARROW   157
#define RIGHT_ARROW   29

*/
        if (c != 145 && c != 17) goto BEGIN;
        oldpos = pos;

    switch(c) {
           case 145:  /* uparrow */
                      if (pos == 0) break;
                      if (pos == 5) {
     pos = (multi-1); break;
  }
                      pos--;
                      break;


   case 17:  /* down arrow */
             if (pos == 5) break;
             if (pos == (multi - 1))break;
             pos++;
             break;


}
/* if no change in position cycle */
if (pos == oldpos) {
sappy();
goto BEGIN;
}

putimage(sback,srows,scols,crow,ccol,PUT); /* put the screen back */

}
if (answers != 0)reward();
/* either exiting or reward */
putimage(sback,srows,scols,crow,ccol,PUT); /* put the screen back */
if (answers == 20 || answers == 0)break;
    multi = 5;
   }
   /* don't waste any code cleaning-up */
   return(answers);
}

dohands(hour,minute)
int hour, minute;
{
   /* centre of the circle */
   int x1=116, y1=84, x2,y2;
   /* length of the hands */
   int hrbase=20, minbase=26;

   /* variables for time update */
   int temp;
   int part1;
   int part2;
   int x;

   double hrdegs;
   double mindegs;

   /* erase the old hands */
    putimage(clk,clkrows,clkcols,clkrow,clkcol,PUT);

   /* update the time */

   /* convert hours to ascii and plot in the appropriate box */
   temp=0;
   while(temp<multi)
   {
    part1=randhrs[temp]/10;
    part2=randhrs[temp]%10;

    if(part1==0)part1=32;
    else part1+=48;
    if(part2==0 && part1==32)part2=32;
    else part2+=48;

    timebuf[0]=(char)part1;
    timebuf[1]=(char)part2;

    part1=(randmins[temp]/10)+48;
    part2=(randmins[temp]%10)+48;
    timebuf[3]=(char)part1;
    timebuf[4]=(char)part2;

    /* zeros are hard to see in multicolor mode
       so use uppercase 'O' */
    for (x = 0; timebuf[x] != 0;x++)
        if (timebuf[x] == 48) timebuf[x] = 'O';

    pfont(timebuf,boxcords[temp][5],boxcords[temp][4],tbk,tc3,tc3);
    temp++;
    }

   mindegs=(double)6*minute;

   while(hour>11)hour-=12;
   hrdegs= (double)30*hour;
   /* adjust for between hours */
   hrdegs+= (double).5*minute;


   /* draw the new hands */
   x2=x1;
   y2=y1;
   circlepoints(&x2,&y2,minbase,mindegs);
   /* draw the minute hand */
   drawline(x1/2,y1,x2/2,y2,1,2);

   x2=x1;
   y2=y1;
   circlepoints(&x2,&y2,hrbase,hrdegs);
   /* draw the hour hand */
   drawline(x1/2,y1,x2/2,y2,3,2);

}


/* fill the spout with water from the top down during the game */
/* empty the spout during the reward */
/* valid values are 1-9 */
dospout(idx, onoff)
int idx, onoff;
{
int row, rows, cols, color;

if (idx > 10) idx = (idx - 10);
if (idx < 1 || idx > 9)return 0;
idx = (idx -1); /*adjust for base 0 */

row = sprow[idx];

/* set defaults */
rows = 2;
cols = sp1cols;

    switch(idx) {
/* the first section of pipe is 3 rows high */
/* the next 7 are 2 rows high */
case 0: rows = 3;
        break;
/* the bottom of the spout is a special case */
case 8:
        rows = sp2rows;
        cols = sp2cols;
        break;
}

    if (onoff == 0) color = tc2;
else color = tvram;

palset(vram,row,0,rows,cols,color,0);

}


/* special purpose function for the blue wave */
/* do on from the bottom */
/* do off from the top */
/* this is almost imperceptible due to the speed of the palette set */
/* but this is the way it would really work with real water */
dowave(onoff)
int onoff;
{

int color, rows, cols;

/* blue is color 1 */
/* black is color 0 */
/* set blue off by registering black as color1 in the wave area */
/* this will not affect the other colors */
    /* the blue wave is positioned at 14, 14 */


if (onoff == 0) {
color = tc2;
    cols = splcols - 10; /* blue must be on in the clockface area */
rows = 1;
        palset(vram,14,24,rows,cols,color,onoff);
}
else {
color = tvram;
onoff = 1;
}

cols = splcols;
rows = splrows;

palset(vram,15,14,rows,cols,color,onoff);

if (onoff != 0) {
    cols = splcols - 10; /* blue must be on in the clockface area */
rows = 1;
        palset(vram,14,24,rows,cols,color,onoff);
}

}


/* the reward function for this module */
reward()
{
int idx, vc = V_COL; /* colliape */
char *ptr;

/* time to drain the pipe */
    if (sndflag != 0)harmony();
for (idx = 0; idx < 6; idx ++) {
switch(idx) {
    case 0: /* here we go lubey-loo */
            dospout(1,0);
            ptr = (char *)&lub0[0];
            break;

    case 1: /* here we go lubey-lie */
            dospout(2,0);
            dospout(3,0);
            ptr = (char *)&lub1[0];
            break;

    case 2: /* here we go lubey-loo */
            dospout(4,0);
            dospout(5,0);
            ptr = (char *)&lub0[0];
            break;

    case 3: /* all on a saturday */
            dospout(6,0);
            dospout(7,0);
            ptr = (char *)&lub3[0];
            break;

    case 4: /* all on a saturday */
            dospout(8,0);
            ptr = (char *)&lub3[0];
            break;

    case 5: /* all on a saturday night */
            dospout(9,0);
            ptr = (char *)&lub4[0];
            break;
}

dowave(1);
if (sndflag != 0)play(ptr,vc,vc,vc);
    else playnote(255,2000,0,0,0);
dowave(0);

}
if (sndflag != 0)unison();
}


While this does not exhaust the topic by any means this overview is quite large enough, thank you very much. There is info here that should probably help you in some way or another unless you know what I know and in that case there is, unfortunately, no help for you.

Continued Next Message...

BillBuckels

#9
Finally - Some Words about The Architecture

We have been reviewing some of the ways a programmer can use bit-mapped graphics on the C64 and C128. I used one of my products as an example for this discussion, and to bring all this to some kind of closure, I'll do a little post-mortem on the "What Time Is It?" product itself.

The TIME program for the Commodore 64 contains a completely rewritten English Language version of an application that I originally developed and published for the Apple IIe in 1991. The formal title of this program is "What Time Is It?".

The goal of the application is to teach Elementary School Children how to tell time. Regardless, my own goal in producing this program was to provide a full-blown application that demonstrates what a seasoned expert programmer can do in the Aztec C Environment for the Commodore 64

Now if all you are in this for is run programs and not to make them the TIME directory like all my other program directories contains the finished programs including a diskimage called time.d64. These programs are preloaded on the diskimage and run nicely in the vice emulator. If you are using these in WinVICE remember that while graphics load quickly in Warp Mode, the sound routines are time-based and you should take your emulator out-of Warp Mode for proper sound playback and time-based events.

Introduction

If you are reading this but have not reviewed all of the samples and all the projects in this programming environment please do not be offended if most of this goes completely over your head, or worse yet sounds like a nattering old man (which it should if it's flying high enough, since that was my intent).

Take comfort in the fact that I am giving you all the source code and graphics images that I used to produce the TIME application. All this is completely transparent. There are no trade secrets here and no TIME deadlines so take your TIME and enjoy the confusion because it's part of the game. It feels so good when you finally understand, for a moment... 'nuff said.

So let's get started and talk about the architecture and I am assuming that you have read the other make files and gained an understanding that memory management and mapping is "Job One".


Since this is quite a large overlay program, the MAKEFILE should prove quite interesting.

Balancing the TIME Overlays

I really enjoyed this part. Some of you can imagine how I hurried through getting all my samples and library routines written and tested so I could actually do something more-or-less meaningful.

I wondered myself at times whether I would be able to fit all the stuff I needed to into memory. My work on this particular application on the Apple IIe using Aztec C was in the PRODOS 128K environment which allowed me to store data in auxilliary memory. Even in that environment which is about the same size in conventional memory as this one, I needed to break down the Apple IIe version of TIME into more overlays than I did here and to keep the graphics data in upper memory... an option I don't have here.

So when I did all this and it just barely fit I knew I could show the rest of you how far this can go without breaking, Like I said above; memory management and mapping is "Job One" and showing someone what can be done makes the job fun.

You should have already figured-out from my other programs that I have beenplaying around with program memory holes, and sticking data into bits of memory that I couldn't run my programs in.

This is the way we do it. You should also have figured-out by now that the linker outputs the code and data sizes, and that my make files can be redirected to disk file so you can review errors and do something about them, or to examine actual data and code size and adjust the memory usage until there is barely any wasted space.

When I do overlays I am always trading-off what to put into the main (root) module and what to link into the overlays. If the main module gets too bloated and the overlay wipes-out the upper ram the program will finish but never get back to the BASIC prompt. My goal is always to get the user back to the OS whether I program for Windows, Linux, MS-DOS, Apple IIe ProDOS, or the C64. One must therefore consider all the overlays at once and realize where one must put what and when to discard and when not to.

In making TIME fit into SPACE I created some pretty neat tools to help save memory, and kept the code that I could in the main module, and the code that I couldn't in the overlays.

I run-length encoded my graphics and re-used buffers as well. The C64 disk drive is notoriously slow, so it is bad enough that I needed to read these overlays from disk but it would have been much worse if I needed to read additional graphics from disk, or worse yet, to read more overlays (like I needed to on the Apple IIe).

My comments are pretty good in the TIME modules, but sorry kids, they are intended for experts. So become one yourself if you aren't already and read the code and the MAKEFILE and run the thing and have some fun with it.

'Nuff Said on the balancing of overlays... some additional eulogies on the topic are in the TIME source code.



# ---------------------------------------------------------------------
# Aztec C64 makefile by bill buckels 2008
# Use this as the basis for your own C64 overlay programs
# ---------------------------------------------------------------------

PRG=time
OV1=cinit
OV2=mainmenu
OV3=t640
OV4=t641
OV5=t642

# I am using my usual nonsense goal of a B64 whatever that is.
# The real goal is of course a native mode C64 PRG
# That will run when loaded in BASIC 2 and return to the
# interpreter when done with the minor caveat that you
# will need to load it from disk each time you run it.
# As I remember, that was pretty well-behaved for a machine
# language program on the C64 back in those days.

# allowing 1.5K (1536 bytes) for data, hopefully enough
# 1.5K following default screen area for data
# in addition each overlay has its own data area
# which is swapped in and out when the overlay is loaded and discarded


$(PRG).B64: $(PRG).asm $(OV1).asm $(OV2).asm $(OV3).asm $(OV4).asm $(OV5).asm MAKEFILE
   as65 $(PRG).asm
   del $(PRG).asm
   as65 $(OV1).asm
   del $(OV1).asm
   as65 $(OV2).asm
   del $(OV2).asm
   as65 $(OV3).asm
   del $(OV3).asm   
   as65 $(OV4).asm
   del $(OV4).asm   
   as65 $(OV5).asm
   del $(OV5).asm   
   copy $(CLIB65)B64NAT.LIB .
   copy $(CLIB65)C64NAT.LIB .
   copy $(CLIB65)FLTNAT.LIB .
   copy $(CR65)ovloader.rel .
   copy $(CR65)ovbgn.rel .
   ln65 -b 810 -d 4000 -c 4480 -r $(PRG).rel ovloader.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB
   del $(PRG).rel
   del ovloader.rel
   ln65 $(OV1).rel $(PRG).rsm ovbgn.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB 
   ln65 $(OV2).rel $(PRG).rsm ovbgn.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB 
   ln65 $(OV3).rel $(PRG).rsm ovbgn.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB
   ln65 $(OV4).rel $(PRG).rsm ovbgn.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB   
   ln65 $(OV5).rel $(PRG).rsm ovbgn.rel B64NAT.LIB FLTNAT.LIB C64NAT.LIB 
   del $(PRG).rsm
   del $(OV1).rel
   del $(OV2).rel
   del $(OV3).rel 
   del $(OV4).rel
   del $(OV5).rel 
   del ovbgn.rel
   del C64NAT.LIB
   del B64NAT.LIB
   del FLTNAT.LIB
   ADDLOGO $(PRG)
   MKBASIC $(PRG).sys $(PRG).prg
   del $(PRG)
   del $(PRG).sys
     
# this pass converts the C programs to assembly language     
$(PRG).asm: $(PRG).c $(OV1).c $(OV2).c $(OV3).c $(OV4).c $(OV5).c MAKEFILE
    copy $(INCL65)stdio.h .
    copy $(INCL65)poke.h .
    copy $(INCL65)colors.h .
    copy $(INCL65)math.h .
    copy $(INCL65)sid.h .
    c65 $(PRG).c
    c65 $(OV1).c
    c65 $(OV2).c
    c65 $(OV3).c
    c65 $(OV4).c
    c65 $(OV5).c
    del stdio.h
    del poke.h
    del colors.h 
    del math.h
    del sid.h



Using The Graphics and Sound Routines

If you have looked at my graphics routines you know by now that I could have gone much further, but that was never my goal. I just wanted to have a little fun with this old compiler and show-off a little bit and leave the field wide-open for competition.

I also could have optimized a little further, or a lot further. But I already know where all this breaks and by now I think I got some of my money's worth back on my original purchase price in enjoyment.

Part of my goal was to showcase the B64NAT.LIB in all of this. I think that the C64 routines that I am leaving you with are better than what I did on the Apple. The sound is better of course and the gameplay is without doubt the same since the processor is the same. The memory saving technique of run length encoding can be taken further, but I kept it simple. Still, by comparison the C64 stuff is easily as robust as the Apple IIe equivalent ofusing bitmap graphics from upper memory. I am satisfied and can now leave this alone.

So by all means change the code, and have some fun yourself.

My selection of multicolour mode was deliberate. The graphics are simple since I originally drew then for the Apple II to avoid aliasing which effectively puts them somewhere close the same coarse resolution as on the C64. There are strange considerations when comparing low resolution graphics on the IBM-PC and Apple IIe and C64 which I have discussed in length in my Wikipedia articles etc. But the common denominator that I mostly went with was 4 Colors, and 2 of them being Black and White, with the other two mainly Red and Blue, and I will leave the rest for you to figure-out on your own.

Read the code, run the program and have fun!

Over and Out.


Quote from: A Seasoned and Expert Programmer
Note: Some reference above was made to imply that I might be a seasoned and expert programmer. Seasoning, like the type used on Turkey and other types of fowl is usually used in the preparation and cooking of said fowl. While it might be a quaint notion that the 4 seasons and the passing of TIME would somehow have a magical effect and would imbibe wisdom or a heightened ability and so forth more probably like the seasoned Turkey in the hot oven, the seasoning would just make one smell a little better, and if one remained in the oven a little too long, ones crispiness would apparently be quite enhanced to the point where like a turkey it would be quite unpalatable and a little too crusty. As far as experts who know more and more about less and less go... the only thing better than an outside expert is an out of town expert. We need to leave it there.