//======================================================================== // LSYSTEMS.C - Generates plant-like objects using an algorithm originally // coded in Turbo BASIC by Ramiro Perez // Translated to C by Fausto Barbuto // Fine-tuning and SVGA coding by Michael Sargent // // Runs in SVGA mode 102H (800 x 600 x 16), defaulting to VGA // (640 x 480 x 16) if VESA support is not detected. // Requires a math coprocessor to do the double-float trigonometric // calculations properly; the program will abort if a coprocessor is // not detected. // // DISCLAIMERS: Compile using large memory model or there will be plenty // of error messages. // If you modify this code, or use any of its routines for // your own programs, do so at your own risk. // // June 6, 1994 //======================================================================== #include #include #include #include #include #include #define plot16(i, j, c) { int mask; char far *address; \ address = (char far *) 0xA0000000L + (long)j * xres/8L + ((long)i/8L); \ mask = 0x8000 >> (i % 8); outport(0x3CE,mask | 8); \ outport(0x3CE,0x0205); *address = *address; \ *address = c; outport(0x3CE,0x0005); \ outport(0x3CE,0xFF08); } #define CHARPOINT 33 #define CHARPOUND 35 #define CHARPLUS 43 #define CHARMINUS 45 #define CHARZERO 48 #define CHARONE 49 void introscreen(void); void drawlsystem(void); int coprocessor(void); int initvesa(void); int checkmode(int test); void setmode(int mode); void cls(int color); double qsrandom(void); void drawline(int left, int top, int right, int bottom, int color); union REGS reg; struct SREGS seg; int continuous=0, vesa=0, memoryblocks, xres, yres; int xpos[2][2]={{320, 0}, {225, 575}}; int ypos[2][2]={{440, 0}, {500, 500}}; long int linetable[600]; unsigned int modetable[12]; //=========================================================================== // Main //=========================================================================== void main(int argc, char *argv[]) { if (argc > 0) if (argv[1][0] == 99 || argv[1][1] == 99) continuous = 1; if (!continuous) introscreen(); if (!coprocessor()) exit(1); if (initvesa()) { if (checkmode(0x102)) { setmode(0x102); vesa = 1; } else if (checkmode(0x12)) setmode(0x12); } else if (checkmode(0x12)) setmode(0x12); else exit(1); drawlsystem(); setmode(0x03); _setcursortype(_NORMALCURSOR); exit(0); } //=========================================================================== // DIsplay and scroll the introductory screen //=========================================================================== void introscreen(void) { int step; clrscr(); textcolor(YELLOW); textbackground(GREEN); _setcursortype(_NOCURSOR); gotoxy(18,4); cprintf(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» "); gotoxy(18,5); cprintf(" º Program LSYSTEMS.EXE º "); gotoxy(18,6); cprintf(" º By Ramiro Perez º "); gotoxy(18,7); cprintf(" º Original source code in TURBO BASIC º "); gotoxy(18,8); cprintf(" ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ "); gotoxy(18,9); cprintf(" º Translated to C by Fausto Barbuto º "); gotoxy(18,10); cprintf(" º º "); gotoxy(18,11); cprintf(" ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ "); gotoxy(18,12); cprintf(" º Adjustments and SVGA code º "); gotoxy(18,13); cprintf(" º by Michael Sargent º "); gotoxy(18,14); cprintf(" º º "); gotoxy(18,15); cprintf(" ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ "); gotoxy(18,16); cprintf(" º - Press any key to start or advance. º "); gotoxy(18,17); cprintf(" º - Press ESC to stop execution. º "); gotoxy(18,18); cprintf(" º - For continuous execution, enter º "); gotoxy(18,19); cprintf(" º lsystems c º "); gotoxy(18,20); cprintf(" º at the command prompt. º "); gotoxy(18,21); cprintf(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ "); textcolor(BLACK); textbackground(BLACK); getch(); for (step=0;step<18;step++) { reg.x.ax = 0x0601; reg.h.bh = 0x00; reg.x.cx = 0x0311; reg.x.dx = 0x1740; int86(0x10,®,®); delay(500); } } //=========================================================================== // The actual drawing function //=========================================================================== void drawlsystem(void) { unsigned char A[10000], B[10000], A1[10000], A0[10000], temp[1], key; double pi, s, s2, an, ang, ang1, sang, x, y, x1, y1, xp, yp, xp1, yp1; double ran1, ran2, zx, zy, sang1[20], xx[20], yy[20]; int Counter=0, Gen, k, Frw, cl, l, i, st, step, back, plant; pi = 3.141592653579793/180.0; for (step=0;step>3); do { back = random(4); if (back == 0) cls(YELLOW); else if (back == 1) cls(LIGHTCYAN); else if (back == 2) cls(BLACK); else cls(WHITE); randomize(); for (plant=0;plant 0x99 && modenumber < 0x10A) { modetable[count] = modenumber; count++; } (vb.videomode)++; } modetable[count] = 0xFFFF; return(1); } //=========================================================================== // Check for VGA/SVGA capability in mode "test". // If VESA SVGA modes are being tested, need to have called initvesa // with necessary global variables set. // Returns 1 if mode supported, or 0 if not. //=========================================================================== int checkmode(int test) { int count=0; if (test == 0x12) { reg.h.ah = 0x1B; int86(0x10,®,®); if (reg.h.al == 0x1B) /* VGA present */ { setmode(test); reg.h.ah = 0x0F; int86(0x10,®,®); if (reg.h.al != test) /* It didn't work */ { printf("\nUnable to initialize VGA 640 x 480 x 16 mode"); return(0); } else return (1); } else { printf("\nUnable to initialize VGA 640 x 480 x 16 mode"); return(0); } } else { while (modetable[count] != 0xFFFF) { if (modetable[count] == test) break; count++; } if (modetable[count] == 0xFFFF) /* Won't get to FFFFH if supported */ return(0); if ((test==0x105&&memoryblocks<12) || (test==0x106&&memoryblocks<10) || (test==0x107&&memoryblocks<20)) return(0); } return (1); } //=========================================================================== // Set video mode; set linetable[] array //=========================================================================== void setmode(int mode) { int flag=0; unsigned char set[13]={"Setting mode"}, number[2][5]={{" 12H"}, {"102H"}}, res[2][17]={{"(640 x 480 x 16)"}, {"(800 x 600 x 16)"}}; if (mode == 0x12) {xres = 640; yres = 480; flag = 1;} if (mode == 0x102) {xres = 800; yres = 600; flag = 2;} if (flag) { clrscr(); textcolor(LIGHTCYAN); textbackground(BLUE); _setcursortype(_NOCURSOR); gotoxy(29,10); cprintf(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» "); gotoxy(29,11); cprintf(" º º "); gotoxy(29,12); cprintf(" º %s %s º ",set,number[flag-1]); gotoxy(29,13); cprintf(" º %s º ",res[flag-1]); gotoxy(29,14); cprintf(" º º "); gotoxy(29,15); cprintf(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ "); delay(2000); textcolor(BLACK); textbackground(BLACK); clrscr(); } if (mode <= 0x13) /* VGA modes */ reg.x.ax = mode; else { reg.x.ax = 0x4F02; /* VESA SVGA modes */ reg.x.bx = mode; } int86(0x10,®,®); } //=========================================================================== // Clear screen to selected color - 16-color modes, write mode 2 //=========================================================================== void cls(int color) { char far *address; int i, j; for (i=0;i>3);j++) { outport(0x3CE,0xFF08); address[j] = address[j]; address[j] = color; } } outport(0x3CE,0x0005); } //=========================================================================== // Random generator //=========================================================================== double qsrandom(void) { int random_integer, temp_integer; double random_double, temp_double; random_integer = random(RAND_MAX); random_double = (double)random_integer / RAND_MAX; temp_integer = random(30519); temp_double = (double)temp_integer / 1000000000L; random_double += temp_double; return(random_double); } //=========================================================================== // Connect two pixels with a line using Bresenham's algorithm //=========================================================================== void drawline(int left, int top, int right, int bottom, int color) { int temp, dx, dy, i, x, y, x_sign, y_sign, decision; dx = abs(right - left); dy = abs(bottom - top); if (((dx >= dy) && (left > right)) || ((dy > dx) && (top > bottom))) { temp = left; left = right; right = temp; temp = top; top = bottom; bottom = temp; } if ((bottom - top) < 0) y_sign = -1; else y_sign = 1; if ((right - left) < 0) x_sign = -1; else x_sign = 1; if (dx >= dy) { for (x=left,y=top,decision=0; x<=right; x++,decision+=dy) { if (decision>=dx) { decision -= dx; y+= y_sign; } if (x>=0 && x<800) plot16(x,y,color); } } else { for (x=left,y=top,decision=0; y<=bottom; y++,decision+=dx) { if (decision>=dy) { decision -= dy; x += x_sign; } if (x>=0 && x<800) plot16(x,y,color); } } }