Last active
April 10, 2021 16:21
-
-
Save randrews/702460c1c3986254d1811ba6774a4dd8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This will build and run on Borland Turbo C++ with the | |
// "small" memory model. The declaration of `screen` may | |
// need to be changed if you use a larger memory model. | |
// It also may need some changes to build under DJGPP; | |
// TC++ is... let's say "unique." | |
#include <conio.h> | |
#include <dos.h> | |
#include <mem.h> | |
// conio is for getch, to pause after it runs | |
// dos is for MK_FP. Also for the register structs | |
// mem is for _fmemset | |
typedef unsigned char byte; | |
void vgaMode(int mode); | |
inline int offset(int x, int y); | |
void px(int x, int y, byte c); | |
void hline(int x, int y, int len, byte c); | |
void drawSprite(int x, int y, int *type, byte fg, byte bg); | |
// It doesn't support binary literals but octal is just as good | |
int piece1[] = { | |
0, 0200, 0500, 01040, 02220, 04510, 011044, 022222, | |
011044, 04510, 02220, 01040, 0500, 0200, 0 | |
}; | |
int piece2[] = { | |
0, 025252, 012524, 025252, 012524, 025252, 012524, | |
025252, 012524, 025252, 012524, 025252, 012524, | |
025252, 0 | |
}; | |
int piece3[] = { | |
0, 01740, 0200, 0200, 0200, 020202, 020202, 037776, | |
020202, 020202, 0200, 0200, 0200, 01740, 0 | |
}; // Yes I did these by hand | |
// DOS is 16-bit but supports megs of memory. How? With a | |
// non-flat memory map. We want a pointer longer than 16 | |
// bits, which DOS calls a "far pointer." MK_FP makes one. | |
byte far *screen = (byte far *)MK_FP(0xa000, 0); | |
void main() { | |
vgaMode(0x13); // Into mode 13 | |
px(10, 10, 13); // A dot | |
hline(20, 20, 100, 15); // A line | |
drawSprite(50, 25, piece1, 15, 3); // Some two-color sprites | |
drawSprite(25, 50, piece2, 4, 0); | |
drawSprite(10, 60, piece3, 26, 1); | |
getch(); // Wait so we can look at it | |
vgaMode(3); // Back to text mode | |
} | |
// Set the VGA mode: put the new mode in AL and call int 10. | |
// Mode 0x13 is 320x200, 8-bit color. | |
void vgaMode(int mode){ | |
union REGS regs; | |
regs.h.ah = 0; | |
regs.h.al = mode & 0xff; | |
int86(16, ®s, ®s); | |
} | |
// This is faster than multiplying by 320: two shifts and two adds. | |
inline int offset(int x, int y) { | |
return x + (y << 8) + (y << 6); | |
} | |
// Linear memory for the screen, horizontal lines are just | |
// memset. But because it's in "far memory" it's _fmemset. | |
// Also note that we can quickly clear the screen with | |
// hline(0, 0, 64000, something); | |
void hline(int x, int y, int len, byte c) { | |
_fmemset(screen + offset(x, y), c, len); | |
} | |
// Setting a pixel. | |
void px(int x, int y, byte c) { | |
*(screen + offset(x, y)) = c; | |
} | |
// Draws a 15x15 2-color sprite, packed into an array of 15 ints, | |
// at the given coordinates, in the given colors. Why not 16x16? | |
// Because it's nice to have odd sizes so there's a center line | |
// for symmetry. | |
void drawSprite(int x, int y, int *type, byte fg, byte bg) { | |
for(int r = 0; r < 15; r++) | |
for(int c = 0; c < 15; c++) | |
px(x + c, y + r, (type[r] & (1 << c) ? fg : bg)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment