+++ /dev/null
-////////////////////////////////////////\r
-// Graph.h\r
-// Coded by Denn Man\r
-//\r
-// Licensed under the Academic Free License version 1.2\r
-//\r
-// *Special thanks to Micheal Abrash\r
-// and his columns in Dr. Dobbs Journal\r
-// (Jul91 and Aug91) documenting\r
-// ModeX\r
-//\r
-// For use with Turbo-C\r
-// Uses as much assembly as possible\r
-// in order to optimize drawing speed\r
-// Self-sufficient: Nothing else needed\r
-////////////////////////////////////////\r
-\r
-#include <alloc.h>\r
-#include <dos.h>\r
-#include <math.h>\r
-#include <stdio.h>\r
-\r
-\r
-// Start of video memory (SEGMENT)\r
-#define MCGA_MEM 0xA000\r
-// Video Digital-Analog-Converter Port\r
-#define VIDEO_DAC 0x03C8\r
-// Video DAC Read Port\r
-#define DAC_READ 0x03C7\r
-// Video Data Port\r
-#define VIDEO_DATA 0x03C9\r
-// VGA Sequence Controller\r
-#define SC_INDEX 0x03C4\r
-// CRT Control Register\r
-#define CRTC_INDEX 0x03D4\r
-// Miscellaneous Output Register\r
-#define MISC_OUTPUT 0x03C2\r
-// VGA Map Mask Register\r
-#define MAP_MASK 0x02\r
-// Screen Width\r
-#define SCR_WIDTH 80\r
-// VGA Graphics Controller Register\r
-#define GC_INDEX 0x03CE\r
-// VGA Read Map Register\r
-#define READ_MAP 0x04\r
-// PI\r
-#define PI 3.14159265358\r
-\r
-// Datatypes\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long dword;\r
-\r
-typedef struct tagTILE {\r
- word height;\r
- word width;\r
- byte *data;\r
-} TILE;\r
-\r
-// FOR BITMAP FILES!!!\r
-typedef struct tagBITMAPFILEHEADER {\r
- word bfType;\r
- dword bfSize;\r
- word bfReserved1;\r
- word bfReserved2;\r
- dword bfOffBits;\r
-} BITMAPFILEHEADER;\r
-\r
-typedef struct tagBITMAPINFOHEADER {\r
- dword biSize;\r
- dword biWidth;\r
- dword biHeight;\r
- word biPlanes;\r
- word biBitCount;\r
- dword biCompression;\r
- dword biSizeImage;\r
- dword biXPelsPerMeter;\r
- dword biYPelsPerMeter;\r
- dword biClrUsed;\r
- dword biClrImportant;\r
-} BITMAPINFOHEADER;\r
-\r
-typedef struct tagRGBQUAD {\r
- byte rgbBlue;\r
- byte rgbGreen;\r
- byte rgbRed;\r
- byte rgbReserved;\r
-} RGBQUAD;\r
-\r
-typedef struct tagBITMAPINFO {\r
- BITMAPINFOHEADER bmiHeader;\r
- RGBQUAD bmiColors[256];\r
-} BITMAPINFO;\r
-\r
-typedef struct tagBITMAP {\r
- BITMAPFILEHEADER bmFileHeader;\r
- BITMAPINFO bmInfo;\r
- byte *bmData;\r
-} BITMAP;\r
-// DONE WITH BITMAP FILE INFO\r
-\r
-// Monitor settings for ModeX\r
-struct tagCRTParms {\r
- word V_Total; // Vertical Total\r
- word OverFlow; // Overflow\r
- word CellHeight; // Cell Height\r
- word V_Sync_Start; // Vertical Sync Start\r
- word V_Sync_End; // Vertical Sync End\r
- word V_Disp; // Vertical Displayed\r
- word D_Off; // Turn off dword mode\r
- word V_Blank_Start; // Vertical Blank Start\r
- word V_Blank_End; // Vertical Blank End\r
- word B_On; // Turn byte mode on\r
-} CRTParms;\r
-\r
-byte VIDEO_MODE; // The current video mode\r
-word MAX_X; // Last available X\r
-word MAX_Y; // Last available Y\r
-word SCREEN_WIDTH;\r
-word SCREEN_HEIGHT;\r
-byte MAX_COLORS; // Last available color\r
-byte FG_COLOR; // For text and mono stuff\r
-byte BG_COLOR;\r
-word CUR_X; // Current X\r
-word CUR_Y; // Current Y\r
-word visibleStart;// Start offset in video memory of screen\r
-word activeStart; // Start offset in video memory to write to\r
-\r
-// For rectangle filling (ModeX)\r
-byte LeftClipPlaneMask[] = { 0x0F, 0x0E, 0x0C, 0x08 };\r
-byte RightClipPlaneMask[] = { 0x0F, 0x01, 0x03, 0x07 };\r
-\r
-// In case things go awry\r
-char msg_error[81];\r
-\r
-void exit_error(void)\r
-{\r
- printf("%s\a\n", msg_error);\r
-}\r
-\r
-////////////////////////////////////////\r
-// init_modeX\r
-//\r
-// -Initialized modeX 320x240x256 graphics\r
-// -Clears video memory\r
-// -Sets page 1 active at offset 0\r
-////////////////////////////////////////\r
-void init_modeX(void)\r
-{\r
- // Fill the CRT Parameters\r
- CRTParms.V_Total = 0x0D06;\r
- CRTParms.OverFlow = 0x3E07;\r
- CRTParms.CellHeight = 0x4109;\r
- CRTParms.V_Sync_Start = 0xEA10;\r
- CRTParms.V_Sync_End = 0xAC11;\r
- CRTParms.V_Disp = 0xDF12;\r
- CRTParms.D_Off = 0x0014;\r
- CRTParms.V_Blank_Start = 0xE715;\r
- CRTParms.V_Blank_End = 0x0616;\r
- CRTParms.B_On = 0xE317;\r
-\r
- asm {\r
- mov ax, 0x0013 // Start in mode 13h\r
- int 0x10 // Call interrupt\r
-\r
- mov dx, SC_INDEX // Disable Chain-4 Memory model\r
- mov ax, 0x0604\r
- out dx, ax\r
- mov ax, 0x0100 // Synchronous reset while switching clocks\r
- out dx, ax\r
-\r
- mov dx, MISC_OUTPUT // Select 28MHz dot clock, 60 Hz scan rate\r
- mov al, 0xE3\r
- out dx, al\r
-\r
- mov dx, SC_INDEX // Restart Sequencer\r
- mov ax, 0x0300\r
- out dx, ax\r
-\r
- mov dx, CRTC_INDEX // Reprogram the CRT Controller\r
- mov al, 0x11 // Select Write-Protect bit\r
- out dx, al\r
- inc dx // CRT-Data register into DX now\r
- in al, dx // Get current VSync End Register setting\r
- and al, 0x7F // Remove write-protect on various registers\r
- out dx, al\r
- dec dx // CRT-Controller\r
- cld // Clear the direction\r
- mov si, OFFSET CRTParms // Load settings\r
- mov cx, 20 // 20 Entries\r
- }\r
- SetCRTParmsLoop:asm {\r
- lodsw // Load the addr:data pair\r
- out dx, ax // Send them out\r
- loop SetCRTParmsLoop // Do it for each one\r
-\r
- mov dx, SC_INDEX // Enable write to all bitplanes\r
- mov ax, 0x0F02\r
- out dx, ax\r
- mov ax, MCGA_MEM // Load video memory\r
- mov es, ax\r
- mov di, 0 // Start at the top\r
- mov ax, 0 // Store 0's\r
- mov cx, 0x8000 // Do it 8000h times\r
- rep stosw // Store them\r
- }\r
-\r
- // Fill globals\r
- VIDEO_MODE = 0xFF;\r
- MAX_X = 319;\r
- MAX_Y = 239;\r
- SCREEN_WIDTH = 320;\r
- SCREEN_HEIGHT = 240;\r
- MAX_COLORS = 255;\r
- FG_COLOR = 15;\r
- BG_COLOR = 0;\r
- CUR_X = 0;\r
- CUR_Y = 0;\r
-\r
- activeStart = 0; // Write to Page 0\r
- visibleStart = 0; // Read from Page 0\r
-}\r
-\r
-////////////////////////////////////////\r
-// close_graph\r
-//\r
-// -Shuts down graphics, sets text mode,\r
-// and fills appropriate variables\r
-// -Frees memory taken by video buffers\r
-////////////////////////////////////////\r
-void close_graph(void)\r
-{\r
- asm {\r
- mov ax, 0x0003\r
- int 0x10\r
- }\r
-\r
- VIDEO_MODE = 0x03;\r
- MAX_X = 80;\r
- MAX_Y = 25;\r
- SCREEN_WIDTH = 80;\r
- SCREEN_HEIGHT = 25;\r
- MAX_COLORS = 15;\r
- FG_COLOR = 7;\r
- BG_COLOR = 0;\r
- CUR_X = 1;\r
- CUR_Y = 1;\r
-}\r
-\r
-void cleargraph(void)\r
-{\r
- asm {\r
- pusha\r
- push es\r
- push di\r
-\r
- mov ax, MCGA_MEM\r
- mov es, ax\r
- mov di, 0\r
-\r
- mov dx, SC_INDEX // Enable write to all bitplanes\r
- mov ax, 0x0F02\r
- out dx, ax\r
-\r
- mov cx, 0x8000\r
- mov ax, 0x0000\r
- rep stosw\r
-\r
- pop di\r
- pop es\r
- popa\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// setActiveStart\r
-//\r
-// -Sets the starting memory address\r
-// at which graphics are written to\r
-////////////////////////////////////////\r
-void setActiveStart(word PageBase)\r
-{\r
- activeStart = PageBase;\r
-}\r
-\r
-////////////////////////////////////////\r
-// setVisibleStart\r
-//\r
-// -Sets the starting memory address\r
-// at which graphics are displayed from\r
-////////////////////////////////////////\r
-void setVisibleStart(word PageBase)\r
-{\r
- visibleStart = PageBase;\r
-\r
- asm {\r
- pusha // Dont touch!\r
-\r
- mov bx, PageBase // Load the offset into BX\r
- mov dx, CRTC_INDEX // Load the CRT Index Port into DX\r
- mov al, 0x0C // Function 0Ch, High Byte of addres\r
- mov ah, bh // Load the high byte\r
- out dx, ax // Send it\r
- inc al // Function 0Dh, Low Byte of address\r
- mov ah, bl // Load the low byte\r
- out dx, ax // Send it\r
-\r
- popa // We were never here\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// setActivePage\r
-//\r
-// -Sets page in which graphics are\r
-// written\r
-////////////////////////////////////////\r
-void setActivePage(byte Page)\r
-{\r
- // Page = (Page Offset * Width of Screen (Bytes) * Screen Height (Rows))\r
- setActiveStart(Page * SCR_WIDTH * SCREEN_HEIGHT);\r
-}\r
-\r
-////////////////////////////////////////\r
-// setVisiblePage\r
-//\r
-// -Sets page from which graphics are\r
-// drawn\r
-////////////////////////////////////////\r
-void setVisiblePage(byte Page)\r
-{\r
- // Page = (Page Offset * Width of Screen (Bytes) * Screen Height (Rows))\r
- setVisibleStart(Page * SCR_WIDTH * SCREEN_HEIGHT);\r
-}\r
-\r
-void vScroll(int rows)\r
-{\r
- // Scrolling = current start + (rows * bytes in a row)\r
- setVisibleStart(visibleStart + (rows * SCR_WIDTH));\r
-}\r
-\r
-void read_palette(byte *pal)\r
-{\r
- int i;\r
-\r
- for (i = 0; i < 256; i++)\r
- {\r
- asm cli\r
- outportb(DAC_READ, i);\r
- pal[(i * 3) + 0] = inportb(VIDEO_DATA);\r
- pal[(i * 3) + 1] = inportb(VIDEO_DATA);\r
- pal[(i * 3) + 2] = inportb(VIDEO_DATA);\r
- asm sti\r
- }\r
-}\r
-\r
-void load_palette(byte *pal)\r
-{\r
- int i;\r
-\r
- for (i = 0; i < 256; i++)\r
- {\r
- asm cli\r
- outportb(VIDEO_DAC, i);\r
- outportb(VIDEO_DATA, pal[(i * 3) + 0]);\r
- outportb(VIDEO_DATA, pal[(i * 3) + 1]);\r
- outportb(VIDEO_DATA, pal[(i * 3) + 2]);\r
- asm sti\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// setpalette\r
-//\r
-// -Self explanatory, sets the color\r
-// of a given index in 256 MCGA mode\r
-////////////////////////////////////////\r
-void setpalette(byte index, byte red, byte green, byte blue)\r
-{\r
- outportb(VIDEO_DAC, index);\r
- outportb(VIDEO_DATA, red);\r
- outportb(VIDEO_DATA, green);\r
- outportb(VIDEO_DATA, blue);\r
-}\r
-\r
-////////////////////////////////////////\r
-// putpixel\r
-//\r
-// -Puts a pixel (in modeX) at (X, Y)\r
-// in active page\r
-////////////////////////////////////////\r
-void putpixel(word x, word y, byte Color)\r
-{\r
- asm {\r
- pusha\r
- push es\r
- push di\r
-\r
- mov ax, SCR_WIDTH // Load screen width, in bytes\r
- mul y // Multiply it by Y to get row\r
- mov di, x // Load X into BX\r
- shr di, 2 // Divide X by 4 to get plane\r
- add di, ax // Add to col offset, row offset\r
- add di, activeStart // Add the page offset\r
- mov ax, MCGA_MEM // Load video memory into AX\r
- mov es, ax // Then ES\r
-\r
- mov cx, x // Get X pos\r
- and cl, 0x03 // Get X plane\r
- mov ax, 0x0100 + MAP_MASK // Load Map-Mask register\r
- shl ah, cl // Write to only the desired plane\r
- mov dx, SC_INDEX // Tell the Map-Mask to do the same\r
- out dx, ax // Do it\r
-\r
- mov al, Color // Load the color\r
- stosb // Store it\r
-\r
- pop di\r
- pop es\r
- popa\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// getpixel\r
-//\r
-// -Returns color of pixel (in ModeX)\r
-// at (x, y)\r
-////////////////////////////////////////\r
-byte getpixel(word x, word y)\r
-{\r
- byte returnvalue; // To hold color\r
-\r
- asm {\r
- pusha // Dont touch anything\r
- push es\r
- push di\r
- mov ax, SCR_WIDTH // Move screen width (in bytes) into AX\r
- mul y // Multiply by y to get row\r
- mov bx, x // Move x into BX\r
- shr bx, 2 // Divide by 4 to get plane\r
- add bx, ax // Add the two offsets together\r
- add bx, activeStart // Add the PageBase\r
- mov ax, MCGA_MEM // Video Memory into AX\r
- mov es, ax // Now into ES\r
-\r
- mov ah, byte ptr x // X into AH\r
- and ah, 0x03 // Get Plane\r
- mov al, READ_MAP // Tell the Video Card\r
- mov dx, GC_INDEX\r
- out dx, ax // Do it\r
-\r
- mov al, es:[bx] // Get the color\r
- sub ah, ah // Clear AH\r
- mov returnvalue, al // Store the color into returnvalue\r
- pop di\r
- pop es\r
- popa // Put everything back\r
- }\r
-\r
- return returnvalue; // Return color\r
-}\r
-\r
-////////////////////////////////////////\r
-// vline\r
-//\r
-// -Draws a vertical line from (x,y1)-(x,y2)\r
-// of color in activePage\r
-////////////////////////////////////////\r
-void vline(word y1, word y2, word x, byte color)\r
-{\r
- asm {\r
- pusha // Dont touch anything here\r
- push es\r
- push di\r
- push si // For lowY\r
-\r
- mov si, y1 // Move y1 into SI\r
- mov bx, y2 // y2 into BX\r
- cmp si, bx // Compare the two\r
- jle vline_ordered // IF y1 <= y2, skip the next lines\r
-\r
- xchg si, bx // ELSE switch them\r
- }\r
- vline_ordered:asm {\r
- mov ax, MCGA_MEM // Load the video memory into AX\r
- mov es, ax // then into ES\r
- mov ax, SCR_WIDTH // Load screen width (bytes) into AX\r
- mul si // and Multiply by the y1 value\r
- mov di, ax // Move it into DI\r
- mov ax, x // x into AX\r
- shr ax, 2 // Divided by 4\r
- add di, ax // and added to get first point offset\r
-\r
- mov dx, SC_INDEX // Point to Sequence Controller\r
- mov al, MAP_MASK // Select Map Mask Register (0x02)\r
- out dx, al // Do it\r
- inc dx // Next Register (SC Data)\r
- mov cl, byte ptr x // x into CL\r
- and cl, 0x03 // x & 0011b to get plane\r
- mov al, 0x01 // Only one plane, so load 0001b\r
- shl ax, cl // Shift it left by the plane number\r
- out dx, al // Send it\r
-\r
- mov cx, bx // Load highY into CX\r
- sub cx, si // Subtract lowY to get ydelta\r
- inc cx // Add one\r
-\r
- mov al, color // Load the color into AL\r
- }\r
- vline_row_top:asm {\r
- stosb // Store the color\r
- add di, SCR_WIDTH // Add a row\r
- dec di // Subtract one, because STO incs DI\r
- loop vline_row_top // Loop until done\r
-\r
- pop si\r
- pop di\r
- pop es\r
- popa // Put everything back\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// hline\r
-//\r
-// -Draws a horizontal line from\r
-// (x1, y)-(x2, y) of color in activePage\r
-// -Faster than a speeding bullet! (Draws\r
-// four pixels at a time by turning on\r
-// all bitplanes for read at once.\r
-// -This function is ALL MINE!!! Not one\r
-// bit of a copy. :)\r
-////////////////////////////////////////\r
-void hline(word x1, word x2, word y, byte color)\r
-{\r
- asm {\r
- pusha // Dont touch anything\r
- push es\r
- push di\r
- push si // For lowX\r
-\r
- mov ax, MCGA_MEM // Load the graphics memory\r
- mov es, ax\r
-\r
- mov ax, SCR_WIDTH // Screen width (bytes) into AX\r
- mul y // Multiply by y to get row offset\r
- mov di, ax // Move row offset into DI\r
-\r
- mov si, x1 // This was a pain to order the variables\r
- mov cx, x2 // Load x1 into SI, x2 into CX\r
- cmp si, cx // Compare them\r
- jle hline_ordered // If x1 is <= x2, skip the next stuff\r
-\r
- xchg si, cx // ELSE switch them\r
- }\r
- hline_ordered:asm {\r
- mov ax, si // lowX into AX\r
- shr ax, 2 // Divided by 4\r
- add di, ax // Add the lowX offset to DI\r
-\r
- mov ax, si // lowX back into AX\r
- and ax, 0x0003 // lowX AND 0011b to get left bit planes\r
- }\r
- _BH = LeftClipPlaneMask[_AX]; // Load the left mask into BH\r
- asm {\r
- mov dx, SC_INDEX // Sequence Controller into DX\r
- mov al, MAP_MASK // Map Mask (Function 0Ch) into AL\r
- out dx, al // Send it\r
- inc dx // SC Data Register\r
- mov al, bh // Load the mask into AL\r
- out dx, al // Send it\r
-\r
- mov al, color // Load color into AL\r
- stosb // Store the first byte of line\r
-\r
- mov dx, SC_INDEX // Loading a mask again\r
- mov al, MAP_MASK // ...\r
- out dx, al // ...\r
- inc dx // ... as before\r
- mov al, 0x0F // Turn all bits on, we want MAX SPEED!\r
- out dx, al // Send it\r
-\r
- push cx // Store the highX\r
- sub cx, si // Subtract the lowX from highX\r
- shr cx, 2 // Divide it by 4\r
- dec cx // Minus the last byte\r
-\r
- mov al, color // Load the color into AL\r
- rep stosb // Repeat the storing of color\r
-\r
- pop cx // Get out highX back\r
- inc cl // Increment, BUG FIX : Not sure why\r
- and cl, 0x03 // AND 0011b to get bit planes\r
- }\r
- _BL = RightClipPlaneMask[_CL];// Load the right mask into BL\r
- asm {\r
- mov dx, SC_INDEX // Again, we send the mask to the\r
- mov al, MAP_MASK // VGA card\r
- out dx, al // ...\r
- inc dx // ...\r
- mov al, bl // ...\r
- out dx, al // ... We have seen this already...\r
-\r
- mov al, color // Load the color into AL\r
- stosb // Store the last byte\r
-\r
- pop si\r
- pop di\r
- pop es\r
- popa // Put everything back, we're done!\r
- }\r
-}\r
-\r
-////////////////////////////////////////\r
-// line\r
-//\r
-// -Draws a line from (x1, y1)-(x2, y2)\r
-// of color in the active page\r
-// -Uses Bresenhem's Line routine\r
-////////////////////////////////////////\r
-void line(word x1, word y1, word x2, word y2, byte color)\r
-{\r
- int dx, dy;\r
- int xinc, yinc;\r
- int P_right;\r
- int P_right_up;\r
- int P;\r
-\r
- if (x1 == x2)\r
- vline(y1, y2, x1, color);\r
-// if (y1 == y2)\r
-// hline(x1, x1, y1, 0, color);\r
-\r
- dx = abs(x2 - x1);\r
- dy = abs(y2 - y1);\r
-\r
- xinc = (x1 > x2) ? -1 : 1;\r
- yinc = (y1 > y2) ? -1 : 1;\r
-\r
- if (dx > dy)\r
- {\r
- P_right = (2 * dy);\r
- P_right_up = P_right - (2 * dx);\r
- P = P_right - dx;\r
-\r
- for (; dx >= 0; dx--)\r
- {\r
- putpixel(x1, y1, color);\r
- if (P > 0)\r
- {\r
- x1 += xinc;\r
- y1 += yinc;\r
- P += P_right_up;\r
- }\r
- else\r
- {\r
- x1 += xinc;\r
- P += P_right;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- P_right = (2 * dx);\r
- P_right_up = P_right - (2 * dy);\r
- P = P_right - dy;\r
-\r
- for (; dy >= 0; dy--)\r
- {\r
- putpixel(x1, y1, color);\r
- if (P > 0)\r
- {\r
- x1 += xinc;\r
- y1 += yinc;\r
- P += P_right_up;\r
- }\r
- else\r
- {\r
- y1 += yinc;\r
- P += P_right;\r
- }\r
- }\r
- }\r
-}\r
-\r
-void rect(word x1, word y1, word x2, word y2, byte color)\r
-{\r
- // Just draw the four lines, x is longer because hline is a\r
- // faster routine than vline.\r
- hline(x1, x2, y1, color);\r
- hline(x1, x2, y2, color);\r
- vline(y1 + 1, y2 - 1, x1, color);\r
- vline(y1 + 1, y2 - 1, x2, color);\r
-}\r
-\r
-////////////////////////////////////////\r
-// fillrect\r
-//\r
-// -Fills a rectangle (in ModeX) of color\r
-// from (x1, y1) to (x2, y2)\r
-//\r
-// *Adopted from Dr. Dobbs Journal Sep 91\r
-////////////////////////////////////////\r
-void fillrect(word x1, word y1, word x2, word y2, byte color)\r
-{\r
- asm {\r
- pusha // Dont touch anything\r
- push ds\r
- push si\r
- push es\r
- push di\r
- push bp\r
-\r
- cld // Clear direction flag (left to right)\r
- mov ax, SCR_WIDTH // Screen Width (bytes) into AX\r
- mul y1 // Times y1 value\r
- mov di, x1 // x1 into DI\r
- shr di, 2 // Divided by four to get plane\r
- add di, ax // Add the y offset\r
- add di, activeStart // Add the PageBase\r
- mov ax, MCGA_MEM // Now set up the video memory\r
- mov es, ax // into ES\r
- mov dx, SC_INDEX // Point to Sequence Controller\r
- mov al, MAP_MASK // Select Map Mask Register (0x02)\r
- out dx, al // Do it\r
- inc dx // Next Register (SC Data)\r
- mov si, x1 // x1 into SI\r
- and si, 0x0003 // x1 & 0011b to get plane\r
- }\r
- _BH = LeftClipPlaneMask[_SI]; // Select appropriate mask\r
- asm {\r
- mov si, x2 // Do the same for x2\r
- and si, 0x0003 // x2 & 0011b\r
- }\r
- _BL = RightClipPlaneMask[_SI]; // Mask select\r
- asm {\r
- mov cx, x2 // x2 into CX\r
- mov si, x1 // x1 into SI\r
- cmp cx, si // Compare them\r
- jle FillDone // IF CX <= SI jump to FillDone\r
- dec cx // Decrement CX\r
- and si, 0xFFFC // x1 & 1111111111111100\r
- sub cx, si // Subtract x1 from x2\r
- shr cx, 2 // Divide CX by 4\r
- jnz MasksSet // Jump if not zero to MasksSet\r
- and bh, bl // BH = BH and BL\r
- }\r
- MasksSet:asm {\r
- mov si, y2 // y2 into SI\r
- sub si, y1 // Subtract y1\r
- jle FillDone // IF SI <= 0 jump to FillDone\r
- mov ah, byte ptr color // Load color\r
- mov bp, SCR_WIDTH // Load screen width (bytes)\r
- sub bp, cx // Subtract xdelta from width\r
- dec bp // Minus 1\r
- }\r
- FillRowsLoop:asm {\r
- push cx // Dont hurt CX\r
- mov al, bh // Left Clip Mask into AL\r
- out dx, al // Send it out\r
- mov al, ah // Color to AL\r
- stosb // Send it out\r
- dec cx // Minus left edge byte\r
- js FillLoopBottom // Jump if SIGNAL flag NOT set\r
- jz DoRightEdge // If that's it, do the right.\r
- mov al, 0x0F // Turn all bit planes on\r
- out dx, al // Do it\r
- mov al, ah // Load color into AL\r
- rep stosb // Store it over and over\r
- }\r
- DoRightEdge:asm {\r
- mov al, bl // Right Clip Mask into AL\r
- out dx, al // Do it\r
- mov al, ah // Load color into AL\r
- stosb // Store it\r
- }\r
- FillLoopBottom:asm {\r
- add di, bp // Next scan line\r
- pop cx // What row?\r
- dec si // One less row\r
- jnz FillRowsLoop // If not zero, go again\r
- }\r
- FillDone:asm {\r
- pop bp\r
- pop di\r
- pop es\r
- pop si\r
- pop ds\r
- popa // All done, put everything back\r
- }\r
-}\r
-\r
-void circle(word x, word y, word radius, byte color)\r
-{\r
- float angle;\r
- float ainc = 1;\r
- word xc, yc;\r
-\r
- if (radius > 119) // IF the radius is greater than 119, make the\r
- ainc = 0.25; // increment smaller\r
- if (radius > 61) // IF it's bigger than 61\r
- ainc = 0.5; // do the same\r
-\r
-\r
- // Only calculate 1/8th of the circle\r
- // Four quadrants = (x, y), (-x, y), (-x, -y), (x, -y)\r
- // Eight octants are made by switching x's and y's.\r
- // Draw eight pixels per iteration and make the circle\r
- // eight times faster than conventional routines.\r
- for (angle = 0; angle <= 45; angle += ainc)\r
- {\r
- xc = (word)floor(cos((angle * PI) / 180) * radius);\r
- yc = (word)floor(sin((angle * PI) / 180) * radius);\r
-\r
- putpixel(x + xc, y + yc, color);\r
- putpixel(x + xc, y - yc, color);\r
- putpixel(x - xc, y + yc, color);\r
- putpixel(x - xc, y - yc, color);\r
-\r
- putpixel(x + yc, y + xc, color);\r
- putpixel(x + yc, y - xc, color);\r
- putpixel(x - yc, y + xc, color);\r
- putpixel(x - yc, y - xc, color);\r
- }\r
-}\r
-\r
-void load_BMP_palette(BITMAP *s)\r
-{\r
- int i;\r
-\r
- for (i = 0; i < 256; i++)\r
- setpalette(i, (byte)floor((s->bmInfo.bmiColors[i].rgbRed / 63) * 255),\r
- (byte)floor((s->bmInfo.bmiColors[i].rgbGreen / 63) * 255),\r
- (byte)floor((s->bmInfo.bmiColors[i].rgbBlue / 63) * 255));\r
-}\r
-\r
-////////////////////////////////////////\r
-// load_BMP\r
-//\r
-// -Opens a bitmap (Non-Compressed) and\r
-// stores the data into a given BITMAP\r
-// variable\r
-// -Allocate memory BEFORE calling this\r
-// function for the BITMAP structure\r
-// -Must be 256 Color, Columns divisible\r
-// by four\r
-////////////////////////////////////////\r
-void load_BMP(char *filename, TILE *target)\r
-{\r
- FILE *inBMP; // Create file handle\r
- BITMAP *tempBMP;\r
- int color;\r
-\r
- if ((inBMP = fopen(filename, "r+b")) == NULL)// Open it\r
- {\r
- sprintf(msg_error, "Cannot open %s", filename);\r
- atexit(exit_error); // IF error, exit and\r
- exit(1); // tell user.\r
- }\r
-\r
- tempBMP = (BITMAP *)malloc(sizeof(BITMAP) - 1);\r
-\r
- fseek(inBMP, 0, 0); // Goto the beginning\r
- fread(tempBMP, sizeof(BITMAP) - 1, 1, inBMP); // And load it all into\r
- // the given variable\r
-\r
- fseek(inBMP, 54, 0); // Goto color offset\r
- for (color = 0; color < 256; color++) // and read 'em in.\r
- {\r
- tempBMP->bmInfo.bmiColors[color].rgbBlue = fgetc(inBMP);\r
- tempBMP->bmInfo.bmiColors[color].rgbGreen = fgetc(inBMP);\r
- tempBMP->bmInfo.bmiColors[color].rgbRed = fgetc(inBMP);\r
- tempBMP->bmInfo.bmiColors[color].rgbReserved = fgetc(inBMP);\r
- }\r
-\r
- load_BMP_palette(tempBMP);\r
-\r
- // Allocate space for the data to hold the pixels\r
- // Goto the pixel offset in the file\r
- // Read in the pixels\r
- target->data = (byte *)calloc((tempBMP->bmFileHeader.bfSize - tempBMP->bmFileHeader.bfOffBits), 1);\r
- target->height = tempBMP->bmInfo.bmiHeader.biHeight;\r
- target->width = tempBMP->bmInfo.bmiHeader.biWidth;\r
- fseek(inBMP, tempBMP->bmFileHeader.bfOffBits, 0);\r
- fread(target->data, target->height * target->width, 1, inBMP);\r
-\r
- free(tempBMP);\r
- fclose(inBMP); // Dont forget to close\r
-}\r
-\r
-void show_BMP(TILE *source, word x, word y)\r
-{\r
- word row, col, offset = 0;\r
-\r
- for (row = source->height; row > 0; row--)\r
- {\r
- for (col = 0; col < source->height; col++)\r
- {\r
- if (source->data[offset] != 255)\r
- putpixel(x + col, y + row, source->data[offset]);\r
- offset++;\r
- }\r
- }\r
-}\r
-\r
-void show_tile(TILE *tile, word x, word y)\r
-{\r
- word cx, cy;\r
-\r
- for (cy = 1; cy <= tile->height; cy++)\r
- for (cx = 0; cx < tile->width; cx++)\r
- if (tile->data[cx + (cy * tile->width)] != 255)\r
- putpixel(x + cx, y + cy, tile->data[cx + (cy * tile->width)]);\r
-}\r
-\r
-void make_tile(TILE *target, TILE *source)\r
-{\r
- int row, col, offset = 0;\r
-\r
- target->data = (byte *)malloc(source->height * source->width + source->width);\r
-\r
- target->height = source->height;\r
- target->width = source->width;\r
-\r
- for (row = source->height * source->width; row >= 0; row -= source->width)\r
- {\r
- for (col = 0; col < source->width; col++)\r
- {\r
- target->data[offset] = source->data[col + row];\r
- offset++;\r
- }\r
- }\r
-}\r
-\r
-void get_tile(word x1, word y1, word x2, word y2, TILE *target)\r
-{\r
- int cx, cy, offset = 0;\r
-\r
- target->height = abs(y2 - y1);\r
- target->width = abs(x2 - x1);\r
-\r
- target->data = (byte *)malloc(target->height * target->width + target->width);\r
-\r
- for (cy = 0; cy <= target->height; cy++)\r
- for (cx = 0; cx < target->width; cx++)\r
- {\r
- target->data[offset] = getpixel(x1 + cx, y1 + cy);\r
- offset++;\r
- }\r
-}\r