I saw Oliver Schmidt's announcement about CC65 having just recently
added some AUX memory routines.
This can be useful to limit DISK I/O especially for graphics programs.
The strategy here is to load your graphics into AUX memory at the
beginning of your program
When I added my production library routines for doing so to my Aztec-C
ProDOS 8 G2.LIB back in 1990 it was with this express purpose in mind.
I also created several tools to produce graphics libraries of Apple II
screens and image fragments and in fact mixing all these with other
binary data files which are ideally suited to AUXMEM storage.
Back to CC65 and AUXMEM... Imitation is the sincerest form of flattery
so thank you for the compliment CC65 guys:)
Oliver, FYI, I ran into another CC65 guy over on the C64 comp.sys.cbm
forum who extolled the virtues of the CC65 compiler and criticized my
style for not being C-like which is more than a little like telling
Papa how to make babies:)
And it turned-out he was working in linux (LOL) and hadn't even taken
a look at my C64 Aztec-C cross-compiler libraries and my Windows XP
build environment... just hammered away about Aztec-C being a dead
compiler and CC65 being better because the source was open. Well it's
not better... it's just different (I thought I should just clear that
up) and not to belittle anything that CC65 guys are doing, the support
that I have added is more than just adding a library to these Aztec-C
compilers that I am preparing and putting online so read-on. There is
a challenge for CC65 Guys at the end of this all simply because CC65
guys have earned a challenge.
Everything that I am talking about here can be downloaded from my
Clipshop and Aztec C websites and you can see how it really was done,
and if you follow the link below the memory map displayed on the
website will also tell you what I am doing with those memory
addresses :
http://www.clipshop.ca/Aztec/index.htm#apple
http://www.clipshop.ca/Aztec/AppleX.zip
A Fullblown ProDOS 8 Production Program complete with Aztec-C source
using AUXMEM as well as overlays with Aztec-C is also there to show
you how it is done and if you are not so much into re-inventing the
wheel and you would like to use a complete suite of tools that have
passed the test of time to practically use AUXMEM in your own C
programs for ProDOS graphics just give the following a whirl:
http://www.clipshop.ca/Aztec/timex.zip
Available for download since last year along with the ProDOS Aztec-C
build environment for XP from my Aztec-C website is a utility called
RIBCOOK which I have already covered in a recent thread which is part
of making it easy for a Aztec-C ProDOS programmer to build and use
these AUXMEM graphics libraries from the comfort of Windows XP.
Here's the general gist of doing so:
1. Create your graphics on the IBM-PC in 4-Color CGA Mode as an IBM
BSAVE graphics image. The easiest way to do that is to use my ClipShop
program for Windows XP to just use Windows Paint or whatever to create
these then remap and save these as IBM BSaved Images in ClipShop.
http://www.clipshop.ca/index.htm
2. Then use my TOPRAG.EXE Utility to cut your Apple II graphics image
fragments to the size that you wish to use in your Apple II program
for animation sequences or whatever from IBM BSaved Graphics Images.
http://www.clipshop.ca/Aztec/appletools.zip
3. Then (Finally) Cook-Up those RIBs using RIBCOOK and the RAGS that
you have created from the IBM Images that you have created in Windows.
http://www.clipshop.ca/Aztec/appletools.zip
This utility creates binary libraries that can be loaded into the
apple IIe's auxilliary memory which is supported in my G2.LIB in
AppleX.
It is a programmer's tool and not good for much else.This is pretty
advanced, but a tremendous time saver at runtime since all your
graphics and other stuff can be pre-loaded from disk into auxilliary
memory in the form of one of these libraries and then accessed from
auxilliary memory in the upper ram of the IIe thereby avoiding further
(slow) disk IO.
RIBCOOK is incremental and libraries can be appended to. I am not
going into great detail about all this. The G2 library source is there
for anyone who wants to take this further, and image loaders etc. are
supported from auxilliary memory in G2.LIB so you can do animation
with library images etc.
For Image Data:
Usage is: RIBCOOK MYLIBRARY.RIB MY.RAG
Output is: MYLIBRARY.RIB and MYLIBRARY.RAP
For Binary Data:
Alternate Usage: RIBCOOK MYLIBRARY.RIB MY.BIN BIN
Output is: MYLIBRARY.RIB and MYLIBRARY.RAP
You can use the BIN option as noted to put anything you wish into this
library.
The output files should be kept paired because you need the info in
the RAP file to include in your program.
In simple terms:
RAP - Map file to include in your Aztec C ProDOS program
RIB - Binary Data File (AKA Library File) to distribute with your
program.
Have Fun!
The CC65 Guy Challenge from the Aztec-C Guy
And if you are a CC65 guy, try recompiling my Overlay project noted
above without using any of my Aztec-C library routines and let us all
know relatively speaking what advantages in whatever your deal has
over Aztec-C, leaving the stuff about almost ANSI and open source out
of it, and also the stuff about having a structure for this or a
structure for that (unless you truly believe that what Goodnow and
Fenwick did can be topped. I don't.)
As far as library stuff etc. If you like you can compare the CC65
Apple II library music playback and putimage routines and the CC65
font stuff to mine as well and let us all know what kind of cool tools
CC65 offers. No peeking at my stuff either:)
And soon the CP/M 80 and CPM/86 "full-meal deal" Aztec-C cross-
compilers will be coming to the Aztec-C Website with samples and tools
and other goodies. Yay!
Bill Buckels
bbuc...@escape.ca
It might seem that I believe AUXMEM is better suited to storing data
than running code. I wonder why that would be?
An overlay like this one takes up just a little more space than an 8K
HIRES screen on disk. Some other overlays in the same project take up
half of this. It just depends on how you balance your application.
Overlays load reasonably quickly.
One other nice thing about overlays as opposed to using AUXMEM to
break a larger program down is that you don't need to depend on AUXMEM
to run big programs.
Whether we code in Aztec-C on older CPM machines, on the Commodore 64,
or on the Apple II, etc, the use of overlays is roughly the same. When
I ported this same program to the C64 I needed to conform to that
particular architecture and did not have the AUXMEM to depend on. But
I did have the overlay structure in place which made doing the port
quite easy since that part remained almost unchanged. Instead of using
AUXMEM to store graphics I used run-length encoding and some other
tricks.
OK so having said that most of what I said is really just chatter
until one gets down to the nitty-gritty of piecing a large application
together. The application that the following is from and that I am
recommending you read and try etc. uses lots of little graphics and
but they all still fit into 28K of AUXMEM. Once loaded they remain
there and are available to all the overlay programs that come and go
without accessing the disk drive continually. Overlays are only loaded
once in a while but readonly data can be really disk intensive so
logically from that POV 'tis better to put the data up on top than the
code.
The offset info into AUXMEM is autogenerated by RIBCOOK as previously
noted and this is how it all goes together...
emsputimage() was already posted in here in another thread as were the
AUXMEM routines for loading this stuff into there in the first place.
An overlay module from...
http://www.clipshop.ca/Aztec/timex.zip
Later,
Bill
x--- snip ---x
/* (C) Copyright 2008 Bill Buckels */
/*
TIME0.c by bill buckels
June 1991
*/
#include <stdio.h>
#include <fcntl.h>
#include <prodos.h>
#include <sgtty.h>
#include <device.h>
#include <sysfunc.h>
/* the auxmem (ems) library info */
/* graphics library map for library TIME.RIB */
/* lib info for character array created from fragment HOURMENU.BOT */
#define HOURMENU_SIZE 7680
#define HOURMENU_WIDTH 40
#define HOURMENU_HEIGHT 192
#define HOURMENU_OFFSET 0
/* lib info for character array created from fragment TIME0A.RAG */
#define TIME0A_SIZE 1296
#define TIME0A_WIDTH 16
#define TIME0A_HEIGHT 81
#define TIME0A_OFFSET 7680
/* lib info for character array created from fragment TIME1A.RAG */
#define TIME1A_SIZE 3276
#define TIME1A_WIDTH 26
#define TIME1A_HEIGHT 126
#define TIME1A_OFFSET 8976
/* lib info for character array created from fragment TIME2A.RAG */
#define TIME2A_SIZE 3264
#define TIME2A_WIDTH 24
#define TIME2A_HEIGHT 136
#define TIME2A_OFFSET 12252
/* lib info for character array created from fragment ELBOW.RAG */
#define ELBOW_SIZE 96
#define ELBOW_WIDTH 4
#define ELBOW_HEIGHT 24
#define ELBOW_OFFSET 15516
/* lib info for character array created from fragment ELBOW2.RAG */
#define ELBOW2_SIZE 96
#define ELBOW2_WIDTH 4
#define ELBOW2_HEIGHT 24
#define ELBOW2_OFFSET 15612
/* lib info for character array created from fragment DOWNPIPE.RAG */
#define DOWNPIPE_SIZE 64
#define DOWNPIPE_WIDTH 4
#define DOWNPIPE_HEIGHT 16
#define DOWNPIPE_OFFSET 15708
/* lib info for character array created from fragment DOWN2.RAG */
#define DOWN2_SIZE 64
#define DOWN2_WIDTH 4
#define DOWN2_HEIGHT 16
#define DOWN2_OFFSET 15772
/* lib info for character array created from fragment SPOUT.RAG */
#define SPOUT_SIZE 496
#define SPOUT_WIDTH 16
#define SPOUT_HEIGHT 31
#define SPOUT_OFFSET 15836
/* lib info for character array created from fragment SPOUT2.RAG */
#define SPOUT2_SIZE 496
#define SPOUT2_WIDTH 16
#define SPOUT2_HEIGHT 31
#define SPOUT2_OFFSET 16332
/* lib info for character array created from fragment WAVE.RAG */
#define WAVE_SIZE 1704
#define WAVE_WIDTH 24
#define WAVE_HEIGHT 71
#define WAVE_OFFSET 16828
/* lib info for character array created from fragment WAVENO.RAG */
#define WAVENO_SIZE 1704
#define WAVENO_WIDTH 24
#define WAVENO_HEIGHT 71
#define WAVENO_OFFSET 18532
int getch();
int randomval();
#define clearscreen() setmem(0x4000,0x2000,0x80)
/* the coordinates for the spout sections */
int spoutrasters[11]=
{
24,
48,
64,
80,
96,
112,
128,
144,
160,
120,
157};
/* special keys as noted */
/* note that none of the special keys used are affected by caps lock
*/
#define ESCKEY 27 /* exit current module */
#define ENTERKEY 13 /* initialize command */
#define SPACEBAR 32 /* same as ENTERKEY */
#define SOUNDKEY 19 /* sound toggle */
#define THREE 51
#define FIVE 53
extern int multiples;
char *timebuf=" :00"; /* digital clock text */
/* the limits for the multiple choices - default is set to 3 boxes */
/* pressing the number 3 or 5 prior to pressing the spacebar */
/* or the enter key will flipflop between levels */
#define BACKSPACE 8
#define LEFTARROW 8
#define RIGHTARROW 21
#define UPARROW 11
#define DOWNARROW 10
#define DELETE 127
#define CTRLKEY -64 /* toupper - 64 = ctrl value of a key press */
extern int hourslimit; /* set to 12 for M0 or 24 for M1 and M2
*/
extern int randomhours[5];
extern int randomminutes[5];
#define ON 1
#define OFF 0
extern int soundflag;
#define PUT 0 /* action verbs for putimage */
#define GET 1
#define P_AND 5
/* locations for the digital clock on the right */
/* dimension = byte x raster */
/* multiply x 7 to use pixel plotting functions */
int boxcords[6][6]={
/* box cords */ /* textcords */
32,5, 39, 25, 33, 10,
32,40, 39, 60, 33, 45,
32,75, 39, 95, 33, 80,
32,110, 39, 130, 33, 115,
32,145, 39, 165, 33, 150,
32,156, 0, 0, 0, 0};
/* use a buffer directly beneath the program */
/* to back-up the clock face */
/* buffer size is 640 bytes.... */
extern char *cleanface;
#define FACEX 12
#define FACEY 56
#define FACEHEIGHT 56
#define FACEWIDTH 10
ovmain(answers)
int answers;
{
/* position markers */
int pos=5, oldpos=5;
/* a pointer to the library buffer in memory */
extern char *SNAIL;
#define SNL_SIZE 350
#define SNL_WIDTH 10
#define SNL_HEIGHT 35
extern char *SNLBACK;
extern char *LEFTSNL;
extern char *RIGHTSNL;
int done = 0;
int c, choice,temp=0;
if(!answers)
{
clearscreen();
lbox(0,0,279,191,0);
emsputimage(TIME0A_OFFSET,
TIME0A_WIDTH,TIME0A_HEIGHT,
8,40,0);
/* make the drain spout */
dospout(0);
/* store the clock face in a buffer */
putimage(cleanface,FACEWIDTH,FACEHEIGHT,FACEX,FACEY,GET);
/* store the snail position in a buffer */
/* and put up the first snail */
putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos][1],GET);
/* put the musical note up */
noteworthy(1);
}
putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);
hourslimit=12;
choice=randomval();
/* draw the boxes on the right side */
c=0;
while(c<multiples)
{
if(!answers || c>2 )
lbox(boxcords[c][0],boxcords[c][1],boxcords[c][2],boxcords[c]
[3],1);
randomminutes[c]=0;
c++;
}
dohands(randomhours[choice],randomminutes[choice]);
do
{
/* for test purposes */
/* on every key press */
/* display a new time */
c=getch();
switch(c)
{
case SOUNDKEY: noteworthy(0);break;
case UPARROW: if(pos==0)
{
if(soundflag)sound(0,0,3);
}
else pos--;
if(pos>=multiples)pos=multiples-1;
break;
case DOWNARROW: if(pos>=(multiples-1))
{
if(soundflag)sound(0,0,3);
}
else pos++;
break;
case 27: return 0;
case SPACEBAR:
case ENTERKEY:
if(choice!=pos || pos==5)
{
if(soundflag)sound(0,0,3);
break;
}
/* erase the other times */
for(c=0;c<multiples;c++)
{
if(c!=oldpos)
plots2(timebuf,boxcords[c][4],boxcords[c][5],
0);
}
/* move the snail down */
putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],PUT);
pos=5;
oldpos=5;
putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],GET);
putimage(RIGHTSNL,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],PUT);
if(soundflag)choice=3;
else choice=7;
answers++;
temp++;
/* get a reward every 10 times */
if(answers==10||answers==20)return answers;
/* count off the answers */
/* fill the pipe */
dospout(answers);
for(c=0;c<temp;c++)
sound((char)choice,(char)c,1);
/* wait for a moment */
sound(7,0,10);
/* do the next clock in the series */
choice=randomval();
for(c=0;c<multiples;c++)randomminutes[c]=0;
dohands(randomhours[choice],randomminutes[choice]);
putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],PUT);
}
/* if our position has changed update the snail */
if(pos!=oldpos)
{
putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],PUT);
oldpos=pos;
putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],GET);
putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
boxcords[oldpos][0]-10,boxcords[oldpos]
[1],P_AND);
}
}
while(!(done));
}
dospout(answers)
int answers;
{
int i;
if(answers>9)answers-=10;
switch(answers)
{
case 0 : /* do the whole spout */
emsputimage(ELBOW_OFFSET,
ELBOW_WIDTH,ELBOW_HEIGHT,
0,spoutrasters[0],PUT);
for(i=1;i<8;i++)
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[i],PUT);
emsputimage(SPOUT_OFFSET,
SPOUT_WIDTH,SPOUT_HEIGHT,
0,spoutrasters[8],PUT);
break;
case 1 : /* fill the elbow */
emsputimage(ELBOW2_OFFSET,
ELBOW2_WIDTH,ELBOW2_HEIGHT,
0,spoutrasters[0],P_AND);
break;
case 9 : /* fill the bottom */
emsputimage(SPOUT2_OFFSET,
SPOUT2_WIDTH,SPOUT2_HEIGHT,
0,spoutrasters[8],P_AND);
break;
default :
/* fill a single segment */
emsputimage(DOWN2_OFFSET,
DOWN2_WIDTH,DOWN2_HEIGHT,
0,spoutrasters[answers-1],P_AND);
}
}
dohands(hour,minute)
int hour, minute;
{
/* centre of the circle */
int x1=116, y1=84, x2,y2;
/* length of the hands */
int hourbase=20, minutebase=26;
/* variables for time update */
int temp;
int part1;
int part2;
double hourdegrees;
double minutedegrees;
/* erase the old hands */
putimage(cleanface,FACEWIDTH,FACEHEIGHT,FACEX,FACEY,PUT);
/* update the time */
temp=0;
while(temp<multiples)
{
/* the old time is erased first for smooth sequencing */
plots2(timebuf,boxcords[temp][4],boxcords[temp][5],0);
temp++;
}
temp=0;
while(temp<multiples)
{
/* convert hours to ascii and plot in the appropriate box */
part1=randomhours[temp]/10;
part2=randomhours[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=(randomminutes[temp]/10)+48;
part2=(randomminutes[temp]%10)+48;
timebuf[3]=(char)part1;
timebuf[4]=(char)part2;
plots2(timebuf,boxcords[temp][4],boxcords[temp][5],1);
temp++;
}
minutedegrees=(double)6*minute;
while(hour>11)hour-=12;
hourdegrees= (double)30*hour;
hourdegrees+= (double).5*minute; /* adjust for between hours */
/* draw the new hands */
x2=x1;
y2=y1;
circlepoints(&x2,&y2,minutebase,minutedegrees);
/* draw the minute hand */
drawline(x1,y1,x2,y2,0);
x2=x1-2;
y2=y1;
circlepoints(&x2,&y2,hourbase,hourdegrees);
/* draw the hour hand */
drawline(x1-2,y1,x2,y2,3,0);
}
extern int sine_cosine[46][2];
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;
}
x--- snip ---x
/* (C) Copyright 2008 Bill Buckels */
/*
TIME0A.c by bill buckels
reward module for module 0 of "What Time is It"
June 1991
*/
#include <stdio.h>
#include <fcntl.h>
#include <prodos.h>
#include <sgtty.h>
#include <device.h>
#include <sysfunc.h>
/* the auxmem (ems) library info */
/* graphics library map for library TIME.RIB */
/* lib info for character array created from fragment ELBOW.RAG */
#define ELBOW_SIZE 96
#define ELBOW_WIDTH 4
#define ELBOW_HEIGHT 24
#define ELBOW_OFFSET 15516
/* lib info for character array created from fragment ELBOW2.RAG */
#define ELBOW2_SIZE 96
#define ELBOW2_WIDTH 4
#define ELBOW2_HEIGHT 24
#define ELBOW2_OFFSET 15612
/* lib info for character array created from fragment DOWNPIPE.RAG */
#define DOWNPIPE_SIZE 64
#define DOWNPIPE_WIDTH 4
#define DOWNPIPE_HEIGHT 16
#define DOWNPIPE_OFFSET 15708
/* lib info for character array created from fragment DOWN2.RAG */
#define DOWN2_SIZE 64
#define DOWN2_WIDTH 4
#define DOWN2_HEIGHT 16
#define DOWN2_OFFSET 15772
/* lib info for character array created from fragment SPOUT.RAG */
#define SPOUT_SIZE 496
#define SPOUT_WIDTH 16
#define SPOUT_HEIGHT 31
#define SPOUT_OFFSET 15836
/* lib info for character array created from fragment SPOUT2.RAG */
#define SPOUT2_SIZE 496
#define SPOUT2_WIDTH 16
#define SPOUT2_HEIGHT 31
#define SPOUT2_OFFSET 16332
/* lib info for character array created from fragment WAVE.RAG */
#define WAVE_SIZE 1704
#define WAVE_WIDTH 24
#define WAVE_HEIGHT 71
#define WAVE_OFFSET 16828
/* lib info for character array created from fragment WAVENO.RAG */
#define WAVENO_SIZE 1704
#define WAVENO_WIDTH 24
#define WAVENO_HEIGHT 71
#define WAVENO_OFFSET 18532
/* the coordinates for the spout sections */
int spoutrasters[10]=
{
24,
48,
64,
80,
96,
112,
128,
144,
160,
120};
extern int soundflag;
#define PUT 0 /* action verbs for putimage */
#define GET 1 /* expand as required */
#define P_STIX 2
#define P_BLACK 3
#define P_WHITE 4
#define P_AND 5
#define P_XOR 6
/* here we go lubey loo */
char loobey1[]={
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x05, 0x05,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x08, 0x0B,
0xff, 0xff, 0xff};
char loobey2[]={
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x05, 0x05,
0x07, 0x00, 0x01,
0x03, 0x01, 0x02,
0x07, 0x00, 0x01,
0x03, 0x03, 0x0B,
0xff, 0xff, 0xff};
char loobey3[]={
0x03, 0x08, 0x02,
0x07, 0x00, 0x01,
0x03, 0x0A, 0x02,
0x07, 0x00, 0x01,
0x03, 0x08, 0x02,
0x07, 0x00, 0x01,
0x03, 0x06, 0x02,
0x07, 0x00, 0x01,
0x03, 0x05, 0x02,
0x07, 0x00, 0x01,
0x03, 0x03, 0x02,
0xff, 0xff, 0xff};
char loobey4[]={
0x03, 0x08, 0x02,
0x07, 0x00, 0x01,
0x03, 0x0A, 0x02,
0x07, 0x00, 0x01,
0x03, 0x08, 0x02,
0x07, 0x00, 0x01,
0x03, 0x06, 0x02,
0x07, 0x00, 0x01,
0x03, 0x05, 0x02,
0x07, 0x00, 0x01,
0x03, 0x03, 0x02,
0x07, 0x00, 0x01,
0x03, 0x01, 0x0B,
0xff, 0xff, 0xff};
ovmain()
{
int answers=0;
char *temp;
unsigned char octave,note;
/* backup the screen */
emsputimage(WAVENO_OFFSET,
WAVENO_WIDTH,WAVENO_HEIGHT,
16,spoutrasters[9],GET);
/* make waves */
do
{
dospout(answers);
emsupimage(WAVE_OFFSET,
WAVE_WIDTH,WAVE_HEIGHT,
16,spoutrasters[9],P_AND);
if(!soundflag)sound(7,0,10);
else
{
switch(answers)
{
case 0:
case 2: temp=(char *)&loobey1[0];break;
case 1: temp=(char *)&loobey2[0];break;
case 5: temp=(char *)&loobey4[0];break;
default :temp=(char *)&loobey3[0];
}
while((octave=*temp++)!=0xFF)
{
note=*temp++;
sound(octave,note,*temp);
*temp++;
}
}
/*clean up the wave */
emsputimage(WAVENO_OFFSET,
WAVENO_WIDTH,WAVENO_HEIGHT,
16,spoutrasters[9],PUT);
answers++;
}while(answers<6);
return(0);
}
dospout(answers)
int answers;
{
int i;
switch(answers)
{
case 0 : /* empty the elbow */
emsputimage(ELBOW_OFFSET,
ELBOW_WIDTH,ELBOW_HEIGHT,
0,spoutrasters[0],PUT);
break;
case 1 :
/* empty a single segment */
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[1],PUT);
/* empty a single segment */
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[2],PUT);
break;
/* empty a single segment */
case 2 : emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[3],PUT);
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[4],PUT);
break;
case 3 :
/* empty a single segment */
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[5],PUT);
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[6],PUT);
break;
case 4 :
/* empty a single segment */
emsputimage(DOWNPIPE_OFFSET,
DOWNPIPE_WIDTH,DOWNPIPE_HEIGHT,
0,spoutrasters[7],PUT);
break;
case 5 : /* empty the bottom */
emsputimage(SPOUT_OFFSET,
SPOUT_WIDTH,SPOUT_HEIGHT,
0,spoutrasters[8],PUT);
break;
}
}
/* special version of putimage loads from the bottom up */
/* emsupimage() */
/* handles screen manipulation of image fragments */
/* both gets and puts and uses auxmem (ems) memory for the IO buffer
*/
/* for screen puts other than memory moves a buffer is used */
/* since a full screen stored in our .BOT format has a
file size of 7680 bytes there is room in the upper ram bank
to store 6 full screens (6x7680=46080 bytes) */
extern unsigned HB[];
emsupimage(emsarraybase,width,height,xorg,yorg,action)
unsigned emsarraybase;
int width,height,xorg,yorg,action;
{
int ctr;
char *ptr,*ptr2;
int temp;
/* the auxmem (ems) buffer starts above the 2nd page of text screen
*/
/* in auxilliary memory */
unsigned hitemp=emsarraybase+0x0C00+(width*height)-width;
int bos=yorg+height-1;
char tempbyte='\x00';
char arrayname[40] ;
if(action==P_WHITE)tempbyte='\xff';
while(bos>=yorg)
{
temp = HB[bos];
ptr = (char *)&arrayname[0];
ptr2 = (char *)(temp+xorg);
/* expand action verbs as required */
switch(action)
{
case P_XOR : /* reverse video */
auxtomain(hitemp,hitemp+width-1,&arrayname[0]);
for(ctr=0;ctr<width;ctr++)
{
*ptr2=(*ptr^0x7f);
*ptr2++;
*ptr++;
}
break;
/* bitwise ANDing the background... */
/* works best with white */
case P_AND :
auxtomain(hitemp,hitemp+width-1,&arrayname[0]);
for(ctr=0;ctr<width;ctr++)
{
*ptr2|=*ptr;
*ptr2++;
*ptr++;
}
break;
/* if the image byte is black don't erase the */
/* background */
case P_STIX :
auxtomain(hitemp,hitemp+width-1,&arrayname[0]);
for(ctr=0;ctr<width;ctr++)
{
tempbyte=*ptr++;
if(tempbyte=='\x80'||tempbyte=='\x00')*ptr2++;
else *ptr2++=tempbyte;
}
break;
/* clear an area the size of the image fragment */
/* to black or white */
case P_BLACK:
case P_WHITE:
for(ctr=0;ctr<width;ctr++)*ptr2+
+=tempbyte;break;
/* read each raster into auxmem (ems) */
case GET: maintoaux((temp+xorg),(temp+xorg+width-1),hitemp);
break;
case PUT: /* read each raster to the screen */
default : auxtomain(hitemp,hitemp+width-1,(temp+xorg));
break;
}
bos--;
hitemp-=width;
}
}