init
This commit is contained in:
commit
0d6bed04f7
|
@ -0,0 +1,5 @@
|
||||||
|
*.zip
|
||||||
|
*.OBJ
|
||||||
|
*.ERR
|
||||||
|
*.EXE
|
||||||
|
.ccls-cache/
|
|
@ -0,0 +1,135 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <dos.h>
|
||||||
|
|
||||||
|
#include "bmp_loader.h"
|
||||||
|
#include "pc_stuff.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
||||||
|
int sizeOfHeader;
|
||||||
|
unsigned int numberOfUsedColors;
|
||||||
|
|
||||||
|
if ((fgetc(fh) != 'B') || (fgetc(fh) != 'M')) {
|
||||||
|
printf("Not a BMP file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fh, 12, SEEK_CUR);
|
||||||
|
|
||||||
|
fread(&sizeOfHeader, sizeof(int), 1, fh);
|
||||||
|
fread(&info->width, sizeof(int), 1, fh);
|
||||||
|
fread(&info->height, sizeof(int), 1, fh);
|
||||||
|
fseek(fh, 2, SEEK_CUR);
|
||||||
|
fread(&info->bpp, sizeof(word), 1, fh);
|
||||||
|
|
||||||
|
// for gimp, you need to add colors to the color map until it hits
|
||||||
|
// 16 colors, then the image will be a 256 color, 8 bpp image
|
||||||
|
//
|
||||||
|
// https://www.gimp-forum.net/Thread-indexing-into-8-bit?pid=13233#pid13233
|
||||||
|
if (info->bpp != 8) return 1;
|
||||||
|
|
||||||
|
fseek(fh, 16, SEEK_CUR);
|
||||||
|
fread(&numberOfUsedColors, sizeof(unsigned int), 1, fh);
|
||||||
|
if (numberOfUsedColors > 256) return 1;
|
||||||
|
|
||||||
|
// get down to color data
|
||||||
|
fseek(fh, 14 + sizeOfHeader, SEEK_SET);
|
||||||
|
|
||||||
|
fread(info->colors, sizeof(struct BMPColor), numberOfUsedColors, fh);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readBMPIntoMemory(FILE *fh, struct BMPImage *info) {
|
||||||
|
int x, y, plane;
|
||||||
|
int result;
|
||||||
|
byte *currentPointer;
|
||||||
|
|
||||||
|
result = readBMPHeader(fh, info);
|
||||||
|
if (result) return result;
|
||||||
|
|
||||||
|
currentPointer = info->memoryStart;
|
||||||
|
|
||||||
|
for (y = 0; y < info->height; ++y) {
|
||||||
|
for (x = 0; x < info->width; ++x) {
|
||||||
|
currentPointer[(info->height - 1 - y) * info->width + x] = fgetc(fh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readBMPIntoUnchainedMemory(FILE *fh, struct BMPImage* info) {
|
||||||
|
int x, y, plane;
|
||||||
|
int writeX, writeY, offset;
|
||||||
|
int unchainedLineWidth;
|
||||||
|
int result;
|
||||||
|
byte *rowHolder;
|
||||||
|
|
||||||
|
result = readBMPHeader(fh, info);
|
||||||
|
if (result) return result;
|
||||||
|
|
||||||
|
unchainedLineWidth = info->width / 4;
|
||||||
|
|
||||||
|
// reserve a row's worth of data
|
||||||
|
// read the bitmap data into the row, interleaving for planes
|
||||||
|
// for each plane, memcpy the data to the plane
|
||||||
|
for (y = 0; y < info->height; ++y) {
|
||||||
|
writeY = ((info->height - 1) - y) * unchainedLineWidth;
|
||||||
|
|
||||||
|
for (x = 0; x < info->width; ++x) {
|
||||||
|
plane = x & 0x03;
|
||||||
|
writeX = (x >> 2);
|
||||||
|
|
||||||
|
offset = plane * (unchainedLineWidth * info->height);
|
||||||
|
|
||||||
|
info->memoryStart[offset + writeY + writeX] = fgetc(fh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readBMPIntoUnchainedVGAMemory(FILE *fh, struct BMPImage* info) {
|
||||||
|
int x, y, plane;
|
||||||
|
int unchainedLineWidth;
|
||||||
|
int result;
|
||||||
|
byte *rowHolder;
|
||||||
|
|
||||||
|
result = readBMPHeader(fh, info);
|
||||||
|
if (result) return result;
|
||||||
|
|
||||||
|
rowHolder = malloc(info->width);
|
||||||
|
unchainedLineWidth = info->width / 4;
|
||||||
|
|
||||||
|
// reserve a row's worth of data
|
||||||
|
// read the bitmap data into the row, interleaving for planes
|
||||||
|
// for each plane, memcpy the data to the plane
|
||||||
|
for (y = 0; y < info->height; ++y) {
|
||||||
|
for (x = 0; x < info->width; ++x) {
|
||||||
|
rowHolder[((x & 3) * 80) + (x >> 2)] = fgetc(fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (plane = 0; plane < 4; ++plane) {
|
||||||
|
setActiveVGAMemoryPlanes(1 << plane);
|
||||||
|
|
||||||
|
memcpy(info->memoryStart + ((info->height - 1) - y) * info->width / 4, rowHolder + unchainedLineWidth * plane, unchainedLineWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rowHolder);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bmp256ColorPaletteToVGAColorPalette(struct BMPImage* bmpImage, struct VGAColor colors[]) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) {
|
||||||
|
colors[i].red = bmpImage->colors[i].red >> 2;
|
||||||
|
colors[i].green = bmpImage->colors[i].green >> 2;
|
||||||
|
colors[i].blue = bmpImage->colors[i].blue >> 2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
struct BMPColor {
|
||||||
|
byte blue;
|
||||||
|
byte green;
|
||||||
|
byte red;
|
||||||
|
byte _a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BMPImage {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
word bpp;
|
||||||
|
struct BMPColor colors[256];
|
||||||
|
byte *memoryStart;
|
||||||
|
};
|
||||||
|
|
||||||
|
int readBMPIntoUnchainedMemory(FILE *, struct BMPImage *);
|
||||||
|
int readBMPIntoMemory(FILE *, struct BMPImage *);
|
||||||
|
void bmp256ColorPaletteToVGAColorPalette(struct BMPImage*, struct VGAColor[]);
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
wcc386.exe -q bmp_loader.c
|
||||||
|
wcc386.exe -q mouse_io.c
|
||||||
|
wcc386.exe -q pc_stuff.c
|
||||||
|
wcc386.exe -q vga.c
|
||||||
|
wcc386.exe -q keyboard.c
|
||||||
|
wcl386.exe -q unch1.c bmp_load.obj mouse_io.obj pc_stuff.obj vga.obj keyboard.obj
|
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
#include "vga.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "mouse_io.h"
|
||||||
|
|
||||||
|
struct VGAColor colors[4] = {
|
||||||
|
{ 0, 0, 0 }, { 255, 255, 255 }, { 255, 0, 0 }, { 0, 0, 255 }
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int keepRunning = 1;
|
||||||
|
struct MouseStatus mouseStatus;
|
||||||
|
|
||||||
|
installKeyboardHandler();
|
||||||
|
activateMouse(&mouseStatus);
|
||||||
|
|
||||||
|
while (keepRunning) {
|
||||||
|
|
||||||
|
}
|
||||||
|
// states:
|
||||||
|
// * main menu
|
||||||
|
// * play
|
||||||
|
// * quit
|
||||||
|
// * play
|
||||||
|
// * draw base map
|
||||||
|
// * draw sidebar
|
||||||
|
// * Game loop
|
||||||
|
// * get mouse
|
||||||
|
// * get keyboard
|
||||||
|
// * set character position
|
||||||
|
// * check for enemy spawn and spawn enemy if needed
|
||||||
|
// * check for character firing and able to fire, spawn bullet if allowed
|
||||||
|
// * check for each enemy firing and able to fire, spawn enemy bullet if allowed
|
||||||
|
// * check for bullet collisions
|
||||||
|
// * enemies are destroyed
|
||||||
|
// * character is damaged
|
||||||
|
// * check for bullets hitting the edges of the screen and remove
|
||||||
|
// *
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
* Preserve video mode
|
||||||
|
* Rename files to 8.3
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include <conio.h>
|
||||||
|
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
unsigned char keystateBits[16];
|
||||||
|
struct KeyboardKeydownState keyboardKeydownState;
|
||||||
|
|
||||||
|
void far (interrupt *int9Save)();
|
||||||
|
|
||||||
|
void populateKeyboardKeydownState() {
|
||||||
|
keyboardKeydownState.KEY_W = keystateBits[2] & 0x02;
|
||||||
|
keyboardKeydownState.KEY_A = keystateBits[3] & 0x40;
|
||||||
|
keyboardKeydownState.KEY_S = keystateBits[3] & 0x80;
|
||||||
|
keyboardKeydownState.KEY_D = keystateBits[4] & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
void far interrupt keyboardHandler(void) {
|
||||||
|
unsigned char rawcode, scancode, ksbByte, temp;
|
||||||
|
unsigned char mask = 1;
|
||||||
|
|
||||||
|
_disable();
|
||||||
|
|
||||||
|
rawcode = inp(0x60);
|
||||||
|
|
||||||
|
scancode = rawcode & 0x7f;
|
||||||
|
mask = 1 << (scancode & 0x07);
|
||||||
|
ksbByte = scancode >> 3;
|
||||||
|
|
||||||
|
// https://github.com/id-Software/wolf3d/blob/05167784ef009d0d0daefe8d012b027f39dc8541/WOLFSRC/ID_IN.C#L152-L154
|
||||||
|
outp(0x61, (temp = inp(0x61)) | 0x80);
|
||||||
|
outp(0x61, temp);
|
||||||
|
|
||||||
|
/* break */
|
||||||
|
if (rawcode & 0x80) {
|
||||||
|
mask = 0xff - mask;
|
||||||
|
keystateBits[ksbByte] &= mask;
|
||||||
|
/* make */
|
||||||
|
} else {
|
||||||
|
keystateBits[ksbByte] |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// acknowledge we're done with the interrupt
|
||||||
|
outp(0x20, 0x20);
|
||||||
|
|
||||||
|
_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void installKeyboardHandler() {
|
||||||
|
int9Save = _dos_getvect(9);
|
||||||
|
_dos_setvect(9, keyboardHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstallKeyboardHandler() {
|
||||||
|
_dos_setvect(9, int9Save);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef __KEYBOARD_H__
|
||||||
|
#define __KEYBOARD_H__ 1
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
extern unsigned char keystateBits[];
|
||||||
|
|
||||||
|
struct KeyboardKeydownState {
|
||||||
|
byte KEY_W;
|
||||||
|
byte KEY_A;
|
||||||
|
byte KEY_S;
|
||||||
|
byte KEY_D;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct KeyboardKeydownState keyboardKeydownState;
|
||||||
|
|
||||||
|
void installKeyboardHandler();
|
||||||
|
void uninstallKeyboardHandler();
|
||||||
|
void populateKeyboardKeydownState();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <dos.h>
|
||||||
|
#include <conio.h>
|
||||||
|
|
||||||
|
#include "mouse_io.h"
|
||||||
|
|
||||||
|
int activateMouse(struct MouseStatus *status) {
|
||||||
|
union REGS regs;
|
||||||
|
int mouseActivated;
|
||||||
|
|
||||||
|
regs.w.ax = MOUSE_DRIVER_RESET;
|
||||||
|
int386(MOUSE_DRIVER_INTERRUPT, ®s, ®s);
|
||||||
|
|
||||||
|
mouseActivated = regs.w.ax;
|
||||||
|
|
||||||
|
if (mouseActivated) {
|
||||||
|
status->isActive = regs.w.ax;
|
||||||
|
status->buttonCount = regs.w.bx;
|
||||||
|
|
||||||
|
// set horiz and vert range
|
||||||
|
regs.w.ax = 0x07;
|
||||||
|
regs.w.cx = 0;
|
||||||
|
regs.w.dx = VGA_DISPLAY_WIDTH - 1;
|
||||||
|
int386(MOUSE_DRIVER_INTERRUPT, ®s, ®s);
|
||||||
|
|
||||||
|
regs.w.ax = 0x08;
|
||||||
|
regs.w.cx = 0;
|
||||||
|
regs.w.dx = VGA_DISPLAY_HEIGHT - 1;
|
||||||
|
int386(MOUSE_DRIVER_INTERRUPT, ®s, ®s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mouseActivated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readMouse(struct MouseStatus *status) {
|
||||||
|
union REGS regs;
|
||||||
|
int buttonStatus;
|
||||||
|
|
||||||
|
regs.w.ax = MOUSE_DRIVER_READ_STATE;
|
||||||
|
int386(MOUSE_DRIVER_INTERRUPT, ®s, ®s);
|
||||||
|
|
||||||
|
buttonStatus = regs.w.bx;
|
||||||
|
status->xPosition = regs.w.cx;
|
||||||
|
status->yPosition = regs.w.dx;
|
||||||
|
|
||||||
|
status->leftButtonDown = buttonStatus & 1;
|
||||||
|
status->rightButtonDown = (buttonStatus >> 1) & 1;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
typedef struct MouseStatus {
|
||||||
|
int isActive;
|
||||||
|
int buttonCount;
|
||||||
|
int xPosition;
|
||||||
|
int yPosition;
|
||||||
|
int leftButtonDown;
|
||||||
|
int rightButtonDown;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MOUSE_DRIVER_INTERRUPT (0x33)
|
||||||
|
#define MOUSE_DRIVER_RESET (0x00)
|
||||||
|
#define MOUSE_DRIVER_READ_DELTA_MOTION (0x0B)
|
||||||
|
#define MOUSE_DRIVER_READ_STATE (0x03);
|
||||||
|
|
||||||
|
int activateMouse(struct MouseStatus *);
|
||||||
|
void readMouse(struct MouseStatus *);
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "pc_stuff.h"
|
||||||
|
|
||||||
|
#define INPUT_STATUS (0x03da)
|
||||||
|
#define VBLANK (0x08)
|
||||||
|
#define BIOS_SET_VIDEO_MODE (0x00)
|
||||||
|
|
||||||
|
byte *VGA = (byte *)0xA0000;
|
||||||
|
|
||||||
|
void setVideoMode(byte videoMode) {
|
||||||
|
union REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = BIOS_SET_VIDEO_MODE;
|
||||||
|
regs.h.al = videoMode;
|
||||||
|
int386(BIOS_VIDEO_INTERRUPT, ®s, ®s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitStartVbl() {
|
||||||
|
while (inp(INPUT_STATUS) & VBLANK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitEndVbl() {
|
||||||
|
while (!(inp(INPUT_STATUS) & VBLANK));
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef __PC_STUFF_H__
|
||||||
|
#define __PC_STUFF_H__
|
||||||
|
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
extern byte *VGA;
|
||||||
|
|
||||||
|
#define BIOS_GET_VIDEO_MODE (0x0F)
|
||||||
|
#define BIOS_VIDEO_INTERRUPT (0x10)
|
||||||
|
|
||||||
|
#define VIDEO_MODE_VGA_256 (0x13)
|
||||||
|
#define VIDEO_MODE_80x25_TEXT (0x03)
|
||||||
|
|
||||||
|
// remember, little endian, so the "first" value is "last"
|
||||||
|
#define outpw_to_register(indexPort, dataRegister, data) \
|
||||||
|
outpw(indexPort, (((word)(data) << 8)) + (dataRegister))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setVideoMode(byte);
|
||||||
|
void waitStartVbl();
|
||||||
|
void waitEndVbl();
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short int word;
|
||||||
|
typedef unsigned long int ulong;
|
|
@ -0,0 +1,155 @@
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "mouse_io.h"
|
||||||
|
#include "pc_stuff.h"
|
||||||
|
#include "bmp_loader.h"
|
||||||
|
#include "vga.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
byte MOUSE_POINTER[8][8] = {
|
||||||
|
{ 2, 2, 2, 2, 2, 0, 0, 0 },
|
||||||
|
{ 2, 1, 1, 1, 2, 0, 0, 0 },
|
||||||
|
{ 2, 1, 1, 1, 2, 0, 0, 0 },
|
||||||
|
{ 2, 1, 1, 1, 2, 0, 0, 0 },
|
||||||
|
{ 2, 2, 2, 255, 1, 2, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0, 2, 1, 2, 0 },
|
||||||
|
{ 0, 0, 0, 0, 0, 2, 1, 2 },
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 2, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
byte WALKER[9][8] = {
|
||||||
|
{ 0, 0, 0, 4, 4, 0, 0, 0 },
|
||||||
|
{ 0, 0, 4, 5, 5, 4, 0, 0 },
|
||||||
|
{ 0, 4, 5, 5, 5, 5, 4, 0 },
|
||||||
|
{ 0, 0, 0, 4, 4, 0, 0, 0 },
|
||||||
|
{ 0, 0, 4, 5, 255, 4, 0, 0 },
|
||||||
|
{ 0, 4, 5, 5, 5, 5, 4, 0 },
|
||||||
|
{ 0, 0, 0, 4, 4, 0, 0, 0 },
|
||||||
|
{ 0, 0, 4, 5, 5, 4, 0, 0 },
|
||||||
|
{ 0, 4, 5, 5, 5, 5, 4, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
FILE *fh;
|
||||||
|
struct BMPImage bmpImage, spriteSheetImage;
|
||||||
|
struct MouseStatus mouseStatus = { .xPosition = 0, .yPosition = 0, .leftButtonDown = 0 };
|
||||||
|
struct VGAColor colors[256];
|
||||||
|
byte *spriteSheet, *chicken, *drawBuffer;
|
||||||
|
int i, x, y;
|
||||||
|
|
||||||
|
int currentMouseSprite = 0;
|
||||||
|
int mouseSpriteDelayCount = 0;
|
||||||
|
|
||||||
|
float measuredTime;
|
||||||
|
|
||||||
|
int walkerX = 0, walkerY = 0;
|
||||||
|
int yOffset;
|
||||||
|
|
||||||
|
struct SpriteRender mousePointer = {
|
||||||
|
.data = (byte *)MOUSE_POINTER,
|
||||||
|
.transparentColor = 0,
|
||||||
|
.width = 8,
|
||||||
|
.height = 8,
|
||||||
|
.modulo = 48
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpriteRender walker = {
|
||||||
|
.data = (byte *)WALKER,
|
||||||
|
.transparentColor = 0,
|
||||||
|
.width = 8,
|
||||||
|
.height = 9,
|
||||||
|
.modulo = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
installKeyboardHandler();
|
||||||
|
|
||||||
|
initializeDrawBuffer();
|
||||||
|
|
||||||
|
spriteSheet = malloc(64 * 64);
|
||||||
|
spriteSheetImage.memoryStart = spriteSheet;
|
||||||
|
|
||||||
|
fh = fopen("sprtsht.bmp", "rb");
|
||||||
|
if (readBMPIntoMemory(fh, &spriteSheetImage)) return 1;
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
setVideoMode(VIDEO_MODE_VGA_256);
|
||||||
|
|
||||||
|
chicken = malloc(320 * 256);
|
||||||
|
bmpImage.memoryStart = chicken;
|
||||||
|
|
||||||
|
fh = fopen("chicken.bmp", "rb");
|
||||||
|
readBMPIntoMemory(fh, &bmpImage);
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
mousePointer.data = spriteSheet;
|
||||||
|
mousePointer.width = 16;
|
||||||
|
mousePointer.height = 16;
|
||||||
|
mousePointer.modulo = 48;
|
||||||
|
|
||||||
|
bmp256ColorPaletteToVGAColorPalette(&bmpImage, colors);
|
||||||
|
setVGAColors(colors);
|
||||||
|
|
||||||
|
activateMouse(&mouseStatus);
|
||||||
|
readMouse(&mouseStatus);
|
||||||
|
|
||||||
|
while (!mouseStatus.leftButtonDown) {
|
||||||
|
readMouse(&mouseStatus);
|
||||||
|
|
||||||
|
populateKeyboardKeydownState();
|
||||||
|
|
||||||
|
if (keyboardKeydownState.KEY_W) walkerY -= 1;
|
||||||
|
if (keyboardKeydownState.KEY_S) walkerY += 1;
|
||||||
|
if (keyboardKeydownState.KEY_A) walkerX -= 1;
|
||||||
|
if (keyboardKeydownState.KEY_D) walkerX += 1;
|
||||||
|
|
||||||
|
|
||||||
|
drawBuffer = getDrawBuffer();
|
||||||
|
|
||||||
|
memcpy(drawBuffer, chicken, 320 * 200);
|
||||||
|
|
||||||
|
mousePointer.x = mouseStatus.xPosition;
|
||||||
|
mousePointer.y = mouseStatus.yPosition;
|
||||||
|
drawSprite(&mousePointer);
|
||||||
|
|
||||||
|
for (i = 0; i < 100; ++i) {
|
||||||
|
walker.x = walkerX + i;
|
||||||
|
walker.y = walkerY + i;
|
||||||
|
drawSprite(&walker);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitStartVbl();
|
||||||
|
memcpy((byte *)0xa0000, drawBuffer, 320 * 200);
|
||||||
|
waitEndVbl();
|
||||||
|
|
||||||
|
//drawBufferToUnchainedMemory();
|
||||||
|
|
||||||
|
|
||||||
|
//copyUnchainedMemoryToActive(chicken);
|
||||||
|
|
||||||
|
//swapPlanes();
|
||||||
|
|
||||||
|
mouseSpriteDelayCount += 1;
|
||||||
|
if (mouseSpriteDelayCount >= 15) {
|
||||||
|
currentMouseSprite = 1 - currentMouseSprite;
|
||||||
|
mousePointer.data = spriteSheet + (currentMouseSprite * 16);
|
||||||
|
mouseSpriteDelayCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstallKeyboardHandler();
|
||||||
|
setVideoMode(VIDEO_MODE_80x25_TEXT);
|
||||||
|
free(spriteSheet);
|
||||||
|
free(chicken);
|
||||||
|
|
||||||
|
freeDrawBuffer();
|
||||||
|
|
||||||
|
fprintf(stderr, "%lu %lu %lu\n", startTime, endTime, (clock_t)(endTime - startTime));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,456 @@
|
||||||
|
#include "vga.h"
|
||||||
|
#include "pc_stuff.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_INDEX (0x03C4)
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_DATA (0x03C5)
|
||||||
|
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_MEMORY_MODE (0x04)
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_ODD_EVEN_SEQUENTIAL_ACCESS (0x04)
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_EXTENDED_MEMORY (0x02)
|
||||||
|
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE (0x02)
|
||||||
|
#define VGA_SEQUENCE_CONTROLLER_ALL_PLANES (0xff)
|
||||||
|
|
||||||
|
#define VGA_GRAPHICS_REGISTERS_INDEX (0x03CE)
|
||||||
|
#define VGA_GRAPHICS_REGISTERS_DATA (0x03CF)
|
||||||
|
|
||||||
|
#define VGA_GRAPHICS_DATA_ROTATE (0x03)
|
||||||
|
|
||||||
|
#define VGA_CRT_CONTROLLER_INDEX (0x03d4)
|
||||||
|
#define VGA_CRT_CONTROLLER_DATA (0x03d5)
|
||||||
|
|
||||||
|
#define VGA_CRT_CONTROLLER_UNDERLINE_MODE (0x14)
|
||||||
|
#define VGA_CRT_CONTROLLER_MODE_CONTROL (0x17)
|
||||||
|
|
||||||
|
#define VGA_CRT_CONTROLLER_DISPLAY_HIGH_ADDRESS (0x0c)
|
||||||
|
#define VGA_CRT_CONTROLLER_DISPLAY_LOW_ADDRESS (0x0d)
|
||||||
|
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_RETRACE_START (0x10)
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_RETRACE_END (0x11)
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_DISPLAY_END (0x12)
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_BLANK_START (0x15)
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_BLANK_END (0x16)
|
||||||
|
#define VGA_CRT_CONTROLLER_VERTICAL_TOTAL (0x06)
|
||||||
|
#define VGA_CRT_CONTROLLER_OVERFLOW (0x07)
|
||||||
|
|
||||||
|
int activePage = 0;
|
||||||
|
byte *drawBuffer, *displayMirrorBuffer;
|
||||||
|
|
||||||
|
void initializeDrawBuffer() {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
drawBuffer = (byte *)malloc(VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
|
||||||
|
displayMirrorBuffer = (byte *)malloc(VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
|
||||||
|
|
||||||
|
for (i = 0; i < VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT; ++i) {
|
||||||
|
drawBuffer[i] = 0;
|
||||||
|
displayMirrorBuffer[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeDrawBuffer() {
|
||||||
|
free(drawBuffer);
|
||||||
|
free(displayMirrorBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setActiveVGAMemoryPlanes(int planes) {
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
planes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *getDrawBuffer() {
|
||||||
|
return drawBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t startTime, endTime;
|
||||||
|
|
||||||
|
void drawBufferToUnchainedMemory() {
|
||||||
|
int x, y, plane, pageOffset, yOffset, yDisplayOffset;
|
||||||
|
byte *vgaStart;
|
||||||
|
unsigned long data;
|
||||||
|
|
||||||
|
int rowsToCopy[VGA_DISPLAY_HEIGHT], minRow = -1, maxRow = 0;
|
||||||
|
|
||||||
|
unsigned long *drawBufferLong = (unsigned long *)drawBuffer,
|
||||||
|
*displayMirrorBufferLong = (unsigned long *)displayMirrorBuffer;
|
||||||
|
|
||||||
|
byte copyRow[VGA_DISPLAY_WIDTH];
|
||||||
|
|
||||||
|
startTime = clock();
|
||||||
|
|
||||||
|
pageOffset = activePage * PAGE_SIZE;
|
||||||
|
vgaStart = (byte *)(VGA + pageOffset);
|
||||||
|
|
||||||
|
for (y = 0; y < VGA_DISPLAY_HEIGHT; ++y) {
|
||||||
|
rowsToCopy[y] = 0;
|
||||||
|
yOffset = y * VGA_UNCHAINED_LINE_WIDTH;
|
||||||
|
|
||||||
|
for (x = 0; x < VGA_UNCHAINED_LINE_WIDTH; x++) {
|
||||||
|
data = *(drawBufferLong++);
|
||||||
|
|
||||||
|
if (displayMirrorBufferLong[yOffset] != data) {
|
||||||
|
rowsToCopy[y] = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
yOffset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(displayMirrorBuffer, drawBuffer, VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
|
||||||
|
|
||||||
|
for (y = 0; y < VGA_DISPLAY_HEIGHT; ++y) {
|
||||||
|
if (rowsToCopy[y]) {
|
||||||
|
if (minRow == -1) minRow = y;
|
||||||
|
maxRow = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (minRow == -1) return;
|
||||||
|
|
||||||
|
drawBufferLong = (unsigned long *)drawBuffer;
|
||||||
|
|
||||||
|
for (y = minRow; y <= maxRow; ++y) {
|
||||||
|
if (!rowsToCopy[y]) continue;
|
||||||
|
|
||||||
|
yOffset = y * VGA_UNCHAINED_LINE_WIDTH;
|
||||||
|
|
||||||
|
for (x = 0; x < VGA_UNCHAINED_LINE_WIDTH; ++x) {
|
||||||
|
data = drawBufferLong[yOffset + x];
|
||||||
|
|
||||||
|
for (plane = 0; plane < 4; plane++) {
|
||||||
|
copyRow[x + (plane * VGA_UNCHAINED_LINE_WIDTH)] = data & 0xff;
|
||||||
|
data >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (plane = 0; plane < 4; ++plane) {
|
||||||
|
setActiveVGAMemoryPlanes(1 << plane);
|
||||||
|
|
||||||
|
memcpy(vgaStart + yOffset, copyRow + (plane * VGA_UNCHAINED_LINE_WIDTH), VGA_UNCHAINED_LINE_WIDTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endTime = clock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableUnchainedVGAMode() {
|
||||||
|
word clearOffset;
|
||||||
|
|
||||||
|
// convert VGA pointer into a word sized
|
||||||
|
ulong *ptr = (ulong *)VGA;
|
||||||
|
|
||||||
|
// The VGA registers are (mostly) byte sized, and are grouped
|
||||||
|
// logically behind a pair of index/data ports.
|
||||||
|
// To access them, you prep the index port on the VGA card
|
||||||
|
// for the register you want to access, then do that access
|
||||||
|
// via the data port.
|
||||||
|
//
|
||||||
|
// Visual: VGA has pouches which contain organization boxes of
|
||||||
|
// registers.
|
||||||
|
|
||||||
|
// target the Sequence Memory Mode Register for Memory Mode
|
||||||
|
// enable sequential access and extended memory
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MEMORY_MODE,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_EXTENDED_MEMORY | VGA_SEQUENCE_CONTROLLER_ODD_EVEN_SEQUENTIAL_ACCESS
|
||||||
|
);
|
||||||
|
|
||||||
|
// target the Sequence Memory Mode Register for map mask
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_ALL_PLANES
|
||||||
|
);
|
||||||
|
|
||||||
|
for (clearOffset = 0; clearOffset < PAGE_SIZE; ++clearOffset) {
|
||||||
|
*ptr++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's a way to address memory as words or longs, but we're
|
||||||
|
// going to set it to byte addressing because it makes mroe sense.
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_UNDERLINE_MODE,
|
||||||
|
0x00
|
||||||
|
);
|
||||||
|
|
||||||
|
// * enable hsync and vsync
|
||||||
|
// * activate byte Mode
|
||||||
|
// * ...something with address wrapping that I don't quite understand yet...
|
||||||
|
// * ...even more with address funkiness that I don't understand
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_MODE_CONTROL,
|
||||||
|
0xe3
|
||||||
|
);
|
||||||
|
|
||||||
|
outp(0x3c2, 0xe3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable320x256VGAMode() {
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_RETRACE_END,
|
||||||
|
0x2c
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_TOTAL,
|
||||||
|
0x0d
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_OVERFLOW,
|
||||||
|
0x3e
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_RETRACE_START,
|
||||||
|
0xea
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_RETRACE_END,
|
||||||
|
0xac
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_DISPLAY_END,
|
||||||
|
0xdf
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_BLANK_START,
|
||||||
|
0xe7
|
||||||
|
);
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_CRT_CONTROLLER_INDEX,
|
||||||
|
VGA_CRT_CONTROLLER_VERTICAL_BLANK_END,
|
||||||
|
0x06
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearWithColor(byte color) {
|
||||||
|
int x, y;
|
||||||
|
int pageOffset, drawY;
|
||||||
|
long *start;
|
||||||
|
long newColor = (color << 24) + (color << 16) + (color << 8) + (color);
|
||||||
|
|
||||||
|
// write to all planes
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
0xff
|
||||||
|
);
|
||||||
|
|
||||||
|
pageOffset = activePage * PAGE_SIZE;
|
||||||
|
start = (long *)(VGA + pageOffset);
|
||||||
|
|
||||||
|
for (y = 0; y < VGA_DISPLAY_HEIGHT; ++y) {
|
||||||
|
for (x = 0; x < VGA_UNCHAINED_LINE_WIDTH / 4; ++x) {
|
||||||
|
*(start++) = newColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this is very temporary
|
||||||
|
*/
|
||||||
|
void copyUnchainedMemoryToActive(byte *src) {
|
||||||
|
int y, plane, _testSize, _testOffset;
|
||||||
|
|
||||||
|
_testSize = 80 * 240;
|
||||||
|
_testOffset = 80 * 256;
|
||||||
|
|
||||||
|
for (plane = 0; plane < 4; ++plane) {
|
||||||
|
// copying to/from VGA memory requires setting the plane to write to...
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
1 << plane
|
||||||
|
);
|
||||||
|
|
||||||
|
memcpy(VGA + activePage * PAGE_SIZE, src + plane * _testOffset, _testSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyScratchPlanesToActive() {
|
||||||
|
int y, plane;
|
||||||
|
|
||||||
|
for (plane = 0; plane < 4; ++plane) {
|
||||||
|
// copying to/from VGA memory requires setting the plane to write to...
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
1 << plane
|
||||||
|
);
|
||||||
|
|
||||||
|
// and to read from
|
||||||
|
outpw_to_register(
|
||||||
|
0x3ce,
|
||||||
|
0x04,
|
||||||
|
plane
|
||||||
|
);
|
||||||
|
|
||||||
|
memcpy(VGA + activePage * PAGE_SIZE, VGA + SCRATCH_PAGE, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyScratchPlanesToActiveViaLatches() {
|
||||||
|
int pixel;
|
||||||
|
byte *src, *dest;
|
||||||
|
|
||||||
|
// TODO: VGA latches
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
0xff
|
||||||
|
);
|
||||||
|
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_GRAPHICS_REGISTERS_INDEX,
|
||||||
|
VGA_GRAPHICS_DATA_ROTATE,
|
||||||
|
0x10
|
||||||
|
);
|
||||||
|
|
||||||
|
src = VGA + SCRATCH_PAGE;
|
||||||
|
dest = VGA + activePage * PAGE_SIZE;
|
||||||
|
|
||||||
|
for (pixel = 0; pixel < PAGE_SIZE; ++pixel) {
|
||||||
|
volatile char _temp = *(src++);
|
||||||
|
*(dest++) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_GRAPHICS_REGISTERS_INDEX,
|
||||||
|
VGA_GRAPHICS_DATA_ROTATE,
|
||||||
|
0x00
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawSprite(struct SpriteRender* sprite) {
|
||||||
|
int x, y;
|
||||||
|
byte pixel;
|
||||||
|
|
||||||
|
byte* spriteData = sprite->data;
|
||||||
|
byte* drawBufferPos = drawBuffer + sprite->x + (sprite->y * VGA_DISPLAY_WIDTH);
|
||||||
|
|
||||||
|
for (y = 0; y < sprite->height; ++y) {
|
||||||
|
for (x = 0; x < sprite->width; ++x) {
|
||||||
|
pixel = *(spriteData++);
|
||||||
|
if (pixel != sprite->transparentColor) {
|
||||||
|
*(drawBufferPos) = pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawBufferPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawBufferPos += (VGA_DISPLAY_WIDTH - sprite->width);
|
||||||
|
spriteData += sprite->modulo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawUnchainedSprite(struct SpriteRender* sprite) {
|
||||||
|
int dataX, dataY, currentPlane;
|
||||||
|
int drawX, drawY, vgaWriteYStart;
|
||||||
|
int startY, endY;
|
||||||
|
int nextStartX = 1;
|
||||||
|
int planeSampleX = 0, readPositionOffset;
|
||||||
|
int vgaWritePosition, readPosition, spriteAdvance;
|
||||||
|
int activePageOffset, alwaysVGAWriteStart, startVGAWritePosition;
|
||||||
|
byte readResult;
|
||||||
|
|
||||||
|
// precalculate sprite sheet handling and VGA plane
|
||||||
|
currentPlane = sprite->x & 3;
|
||||||
|
spriteAdvance = sprite->width + sprite->modulo;
|
||||||
|
|
||||||
|
outpw_to_register(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||||
|
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||||
|
1 << currentPlane
|
||||||
|
);
|
||||||
|
|
||||||
|
// precalculate x pixel drawing
|
||||||
|
activePageOffset = activePage * PAGE_SIZE;
|
||||||
|
|
||||||
|
alwaysVGAWriteStart = sprite->y;
|
||||||
|
if (alwaysVGAWriteStart < 0) alwaysVGAWriteStart = 0;
|
||||||
|
alwaysVGAWriteStart *= VGA_DISPLAY_WIDTH;
|
||||||
|
|
||||||
|
// precalculate y pixel drawing
|
||||||
|
startY = sprite->y;
|
||||||
|
endY = sprite->y + sprite->height;
|
||||||
|
readPositionOffset = 0;
|
||||||
|
|
||||||
|
if (startY < 0) {
|
||||||
|
readPositionOffset = (spriteAdvance * (-startY));
|
||||||
|
startY = 0;
|
||||||
|
}
|
||||||
|
if (endY > VGA_DISPLAY_HEIGHT) { endY = VGA_DISPLAY_HEIGHT; }
|
||||||
|
|
||||||
|
startVGAWritePosition = activePageOffset + (sprite->x + alwaysVGAWriteStart) / PLANE_PIXEL_DISTANCE;
|
||||||
|
|
||||||
|
for (dataX = 0; dataX < sprite->width; ++dataX) {
|
||||||
|
if (planeSampleX >= sprite->width) {
|
||||||
|
planeSampleX = nextStartX;
|
||||||
|
nextStartX++;
|
||||||
|
currentPlane = (currentPlane + 1) & 3;
|
||||||
|
|
||||||
|
startVGAWritePosition = activePageOffset + (planeSampleX + sprite->x + alwaysVGAWriteStart) / PLANE_PIXEL_DISTANCE;
|
||||||
|
|
||||||
|
// save a second out
|
||||||
|
outp(
|
||||||
|
VGA_SEQUENCE_CONTROLLER_DATA,
|
||||||
|
1 << currentPlane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawX = planeSampleX + sprite->x;
|
||||||
|
if (drawX >= 0 && drawX < VGA_DISPLAY_WIDTH) {
|
||||||
|
vgaWritePosition = startVGAWritePosition;
|
||||||
|
readPosition = planeSampleX + readPositionOffset;
|
||||||
|
|
||||||
|
for (drawY = startY; drawY < endY; ++drawY) {
|
||||||
|
readResult = sprite->data[readPosition];
|
||||||
|
if (readResult != sprite->transparentColor) {
|
||||||
|
VGA[vgaWritePosition] = readResult;
|
||||||
|
}
|
||||||
|
vgaWritePosition += VGA_UNCHAINED_LINE_WIDTH;
|
||||||
|
readPosition += spriteAdvance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startVGAWritePosition++;
|
||||||
|
planeSampleX += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void swapPlanes() {
|
||||||
|
outpw(VGA_CRT_CONTROLLER_INDEX, VGA_CRT_CONTROLLER_DISPLAY_HIGH_ADDRESS | ((PAGE_SIZE * activePage) & 0xff00));
|
||||||
|
outpw(VGA_CRT_CONTROLLER_INDEX, VGA_CRT_CONTROLLER_DISPLAY_LOW_ADDRESS | ((PAGE_SIZE * activePage) << 8));
|
||||||
|
|
||||||
|
activePage = 1 - activePage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVGAColors(struct VGAColor colors[], int totalColors) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
outp(0x3c8,0);
|
||||||
|
for (i = 0; i < totalColors; ++i) {
|
||||||
|
outp(0x3c9, colors[i].red);
|
||||||
|
outp(0x3c9, colors[i].green);
|
||||||
|
outp(0x3c9, colors[i].blue);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef __VGA_H__
|
||||||
|
#define __VGA_H__
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define PLANE_PIXEL_DISTANCE (4)
|
||||||
|
#define VGA_DISPLAY_WIDTH (320)
|
||||||
|
#define VGA_DISPLAY_HEIGHT (200)
|
||||||
|
#define VGA_UNCHAINED_LINE_WIDTH (VGA_DISPLAY_WIDTH / PLANE_PIXEL_DISTANCE)
|
||||||
|
|
||||||
|
// there are four of these in a row
|
||||||
|
#define PAGE_SIZE (VGA_DISPLAY_WIDTH*VGA_DISPLAY_HEIGHT/4)
|
||||||
|
#define SCRATCH_PAGE (PAGE_SIZE * 2)
|
||||||
|
|
||||||
|
struct VGAColor {
|
||||||
|
byte red;
|
||||||
|
byte green;
|
||||||
|
byte blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpriteRender {
|
||||||
|
byte* data;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
int transparentColor;
|
||||||
|
unsigned int modulo;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern clock_t startTime, endTime;
|
||||||
|
|
||||||
|
void enableUnchainedVGAMode();
|
||||||
|
void enable320x256VGAMode();
|
||||||
|
void setVGAColors(struct VGAColor[], int);
|
||||||
|
void copyUnchainedMemoryToActive();
|
||||||
|
void copyScratchPlanesToActive();
|
||||||
|
void copyScratchPlanesToActiveViaLatches();
|
||||||
|
void drawSprite(struct SpriteRender *sprite);
|
||||||
|
void swapPlanes();
|
||||||
|
void setActiveVGAMemoryPlanes(int);
|
||||||
|
void clearWithColor(byte);
|
||||||
|
|
||||||
|
void initializeDrawBuffer();
|
||||||
|
void freeDrawBuffer();
|
||||||
|
void drawBufferToUnchainedMemory();
|
||||||
|
|
||||||
|
byte *getDrawBuffer();
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue