/* This code was designed by John Thimsen. After looking at Dreaden's
horizontal scroll code for about two hours, I figured I had it figured out.
I converted this to C because I have a strong dislike for ASM, but all the
graphics code out there seems to be in ASM. Enjoy this, there *SHOULD* be
more on the way (you can reach me at jdt@hebron.connected.com*/
#include "hstars.dat"
/* This file was originally done by hstar.bas by dreaden, but I wrote a C
replacement called hstardat, that is included in the package. Dreadens
prepared an ASM file format, this one does a C one. Have fun.Basically gives
random locations to a bunch a stars, 101? to be exact. */
#include <dos.h>
#define ScreenWidth 320 /* Width of Mode 13h */
#define ScreenHeight 200 /* Height of Mode 13h */
#define VIDEO 0x10 /* VIDEO Service Number */
#define waitforretrace() while(!(inport(0x3DA) & 8))
#define waitforrefresh() while(inport(0x3Da) & 8)
/* These are *WAY* cool macros, use them, they work great for me, I rip'd
them from another C programmer, but basically, it is using the Input Status
#1 register on the VGA card, and testing BIT 3 (that is the & 8) for the
vertical retrace mode */
#define VLevel1 1
#define VLevel2 2
#define VLevel3 3
#define VLevel4 4
/* we have four levels of stars, and they all go a different speed, here we
use defines for the various speeds. This is what you would change to speed
up the stars, believe me, this program will fly :) These look the best to me
though */
#define XPos 0
#define YPos 1
#define Old_Pos 2
/* okay, in hstars.dat we declare a 102 by 3 multi-dimensional array. I
used three defines to help me access the array better. The three parts are
the current X position, the Y position, and the old position (for erasing the
old star.*/
void display_stars(void); /* Prototyping is wonderful :) */
unsigned int *YPosChart; /* Pointer to the look-up chart, see below */
char far *video_ptr=(char far *)0xA0000000;
/* Points to beginning of video memory */
void main(void)
{
union REGS regs;
unsigned int x; /* general purpose */
YPosChart=(unsigned int *)calloc(ScreenHeight, sizeof(unsigned int));
/* Okay, we use a look up table for our Y-Offset, because I guess
it is much much faster. This allocates space for 200 (ScreenHeight)
unsigned ints. This is how it looks.
*(YPosChart+0)=0
*(YPosChart+2)=320
*(YPosChart+4)=640
*(YPosChart+198=63680
This way we can access our y-offset much quicker than calculating it,
and we can just add our x-position to that, and draw the dot */
for(x=0;x<ScreenHeight;x++)
*(YPosChart+(x*2))=x*ScreenWidth;
/* That does the work right there, for the look up table */
regs.h.al=0x13;
regs.h.ah=0x00;
int86(VIDEO, ®s, ®s);
/* Change video mode to 13h (320x200x256) */
do{ /* Main body of program right here, simple huh :)*/
waitforretrace(); /* Just calls the display_stars function, checking*/
display_stars(); /* for retrace every time, until a key is pressed */
}while(!kbhit());
regs.h.ah=0;
int86(0x16,®s,®s);
/* Grab the key the user just hit. Here is a good example of using a
little bit of optimization. You may be saying, why not use getch()?
Well it added 4.5K to the file size of the program... 4.5K!!! this
added like 100 and something bytes? Much smaller... much */
regs.h.al=0x03;
regs.h.ah=0x00;
int86(VIDEO, ®s, ®s);
/* Change back to text, let us out */
}
void display_stars(void)
{
int star_ref=0; /* Which star out of the 120 that we are on */
unsigned int ypost; /* for the Ypostion calculations */
/* Okay, I converted this from Dreaden's code, and he did 4 loops,
and I figured, what the hell, might as well. I will explain the 1st
loop, and the rest are the same, exactly the same, with one thing
that changes from loop to loop */
for(star_ref=0;star_ref<40;star_ref++) /* 4th level, do 40 stars */
{
*((video_ptr)+star[star_ref][Old_Pos])=0;
/* This grabs the OLD Position of the star, and erases it off
the screen. Uses indirection, pretty fast I think. This
value could be anywhere from 0-64000 thousand, that is why
I used unsigned */
ypost=star[star_ref][YPos];
/* Grab the Y-Position of current star */
ypost=ypost+ypost;
/* Double it, because in our look up chart, we have ints, and
everyone knows that ints are two bytes, so line 100 would be
200 lines down, so we double it */
ypost=*(YPosChart+ypost);
/* Actually grab the value, and store it in ypost */
star[star_ref][XPos]+=VLevel1;
/* Okay, here we add the velocity of the level, to the current
x-position. */
if(star[star_ref][XPos] > ScreenWidth) star[star_ref][XPos]-=ScreenWidth;
/* Checks to make sure it dont go beyond the range of memory,
by subtracting 320 when it goes above 320, there by moving it
back to the beginning of the line */
ypost+=star[star_ref][XPos];
/* add the new xposition to the y position, giving us our
new offset */
*((video_ptr)+ypost)=22;
/* draw it a pretty dark shade of grey, 22-30 are the
colors I used. Dreaden used a custom palette, but I figured
what the heck, I will use the default :) */
star[star_ref][Old_Pos]=ypost;
/* stores the position so we can erase it next time */
}
for(star_ref=40;star_ref<70;star_ref++) /*Third level, thirty stars */
{
*((video_ptr)+star[star_ref][Old_Pos])=0;
ypost=star[star_ref][YPos];
ypost=ypost+ypost;
ypost=*(YPosChart+ypost);
star[star_ref][XPos]+=VLevel2; /* Only thing that changes */
if(star[star_ref][XPos] > ScreenWidth) star[star_ref][XPos]-=ScreenWidth;
ypost+=star[star_ref][XPos];
*((video_ptr)+ypost)=24; /* A little bit brighter */
star[star_ref][Old_Pos]=ypost;
}
for(star_ref=70;star_ref<90;star_ref++) /* Second level, 20 stars */
{
*((video_ptr)+star[star_ref][Old_Pos])=0;
ypost=star[star_ref][YPos];
ypost=ypost+ypost;
ypost=*(YPosChart+ypost);
star[star_ref][XPos]+=VLevel3; /* And Faster */
if(star[star_ref][XPos] > ScreenWidth) star[star_ref][XPos]-=ScreenWidth;
ypost+=star[star_ref][XPos];
*((video_ptr)+ypost)=27; /* Even brighter */
star[star_ref][Old_Pos]=ypost;
}
for(star_ref=90;star_ref<101;star_ref++) /* First level, 10 stars */
{
*((video_ptr)+star[star_ref][Old_Pos])=0;
ypost=star[star_ref][YPos];
ypost=ypost+ypost;
ypost=*(YPosChart+ypost);
star[star_ref][XPos]+=VLevel4; /* Fastest speed */
if(star[star_ref][XPos] > ScreenWidth) star[star_ref][XPos]-=ScreenWidth;
ypost+=star[star_ref][XPos];
*((video_ptr)+ypost)=30; /* Brightest color */
star[star_ref][Old_Pos]=ypost;
}
}