more prep stuff
This commit is contained in:
parent
0d6bed04f7
commit
d52426a877
|
@ -3,3 +3,4 @@
|
|||
*.ERR
|
||||
*.EXE
|
||||
.ccls-cache/
|
||||
*.LNK
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
#include <malloc.h>
|
||||
#include <dos.h>
|
||||
|
||||
#include "bmp_loader.h"
|
||||
#include "bmpload.h"
|
||||
#include "pc_stuff.h"
|
||||
#include "vga.h"
|
||||
|
||||
int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
||||
int sizeOfHeader;
|
||||
char value;
|
||||
unsigned int numberOfUsedColors;
|
||||
|
||||
if ((fgetc(fh) != 'B') || (fgetc(fh) != 'M')) {
|
||||
|
@ -42,14 +43,26 @@ int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int readBMPIntoNewMemory(FILE *fh, struct BMPImage *info) {
|
||||
int result;
|
||||
|
||||
result = readBMPHeader(fh, info);
|
||||
if (result) return result;
|
||||
|
||||
info->memoryStart = malloc(info->width * info->height);
|
||||
|
||||
return readBMPIntoMemory(fh, info);
|
||||
}
|
||||
|
||||
void freeBMP(struct BMPImage *info) {
|
||||
free(info->memoryStart);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -61,69 +74,6 @@ int readBMPIntoMemory(FILE *fh, struct BMPImage *info) {
|
|||
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;
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
#ifndef __BMP_LOADER_H__
|
||||
#define __BMP_LOADER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
|
@ -15,9 +18,12 @@ struct BMPImage {
|
|||
word bpp;
|
||||
struct BMPColor colors[256];
|
||||
byte *memoryStart;
|
||||
|
||||
int transparentColor;
|
||||
};
|
||||
|
||||
int readBMPIntoUnchainedMemory(FILE *, struct BMPImage *);
|
||||
int readBMPIntoMemory(FILE *, struct BMPImage *);
|
||||
int readBMPIntoNewMemory(FILE *, struct BMPImage *);
|
||||
void bmp256ColorPaletteToVGAColorPalette(struct BMPImage*, struct VGAColor[]);
|
||||
|
||||
#endif
|
|
@ -3,4 +3,5 @@ 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
|
||||
wcl386.exe -q game.c bmp_load.obj mouse_io.obj pc_stuff.obj vga.obj keyboard.obj
|
||||
|
||||
|
|
43
game.c
43
game.c
|
@ -1,20 +1,54 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "vga.h"
|
||||
#include "keyboard.h"
|
||||
#include "mouse_io.h"
|
||||
#include "pc_stuff.h"
|
||||
#include "bmpload.h"
|
||||
|
||||
struct VGAColor colors[4] = {
|
||||
{ 0, 0, 0 }, { 255, 255, 255 }, { 255, 0, 0 }, { 0, 0, 255 }
|
||||
}
|
||||
struct BMPImage spritesheetImage;
|
||||
struct VGAColor vgaColors[256];
|
||||
|
||||
struct SpriteRender arenaWallTop, arenaWallSide, arenaFloor;
|
||||
|
||||
int main(void) {
|
||||
FILE *fh;
|
||||
int keepRunning = 1;
|
||||
struct MouseStatus mouseStatus;
|
||||
|
||||
installKeyboardHandler();
|
||||
activateMouse(&mouseStatus);
|
||||
initializeDrawBuffer();
|
||||
|
||||
fh = fopen("sprtsht.bmp", "rb");
|
||||
if (readBMPIntoNewMemory(fh, &spritesheetImage)) return 1;
|
||||
fclose(fh);
|
||||
|
||||
return 0;
|
||||
|
||||
spritesheetImage.transparentColor = 0;
|
||||
|
||||
buildSpriteFromSpritesheet(
|
||||
&spritesheetImage,
|
||||
&arenaWallTop,
|
||||
0, 0, 20, 20
|
||||
);
|
||||
|
||||
setVideoMode(VIDEO_MODE_VGA_256);
|
||||
bmp256ColorPaletteToVGAColorPalette(&spritesheetImage, vgaColors);
|
||||
setVGAColors(vgaColors, 256);
|
||||
|
||||
while (keepRunning) {
|
||||
arenaWallTop.x = 0;
|
||||
arenaWallTop.y = 0;
|
||||
|
||||
drawSprite(&arenaWallTop);
|
||||
|
||||
waitStartVbl();
|
||||
|
||||
copyDrawBufferToDisplay();
|
||||
|
||||
waitEndVbl();
|
||||
}
|
||||
// states:
|
||||
// * main menu
|
||||
|
@ -35,4 +69,7 @@ int main(void) {
|
|||
// * character is damaged
|
||||
// * check for bullets hitting the edges of the screen and remove
|
||||
// *
|
||||
//
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.c.obj
|
||||
wcc386 -q $<
|
||||
|
||||
game.exe: bmpload.obj mouse_io.obj pc_stuff.obj vga.obj keyboard.obj game.obj
|
||||
%write game.lnk NAME $@
|
||||
%write game.lnk SYSTEM DOS4G
|
||||
%write game.lnk FILE bmpload.obj
|
||||
%write game.lnk FILE mouse_io.obj
|
||||
%write game.lnk FILE pc_stuff.obj
|
||||
%write game.lnk FILE vga.obj
|
||||
%write game.lnk FILE keyboard.obj
|
||||
%write game.lnk FILE game.obj
|
||||
wlink @game.lnk
|
|
@ -1,6 +1,6 @@
|
|||
#include "vga.h"
|
||||
|
||||
typedef struct MouseStatus {
|
||||
struct MouseStatus {
|
||||
int isActive;
|
||||
int buttonCount;
|
||||
int xPosition;
|
||||
|
|
Binary file not shown.
BIN
sprtsht.bmp
BIN
sprtsht.bmp
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 39 KiB |
|
@ -0,0 +1,21 @@
|
|||
char canRenderFrame = 0;
|
||||
char elapsedTicks = 0;
|
||||
|
||||
void far (interrupt *oldTimer());
|
||||
|
||||
void far interrupt timerInterrupt() {
|
||||
_disable();
|
||||
|
||||
elapsedTicks++;
|
||||
if (elapsedTicks > SOME_THRESHOLD_FOR_30FPS) {
|
||||
canRenderFrame = 1;
|
||||
elapsedTicks = 0;
|
||||
}
|
||||
|
||||
oldTimer();
|
||||
|
||||
int(0x20, 0x20);
|
||||
_enable()
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
#define PLANE_PIXEL_DISTANCE (4)
|
||||
#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)
|
||||
|
||||
#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 readBMPIntoUnchainedMemory(FILE *, struct BMPImage *);
|
||||
|
||||
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 setActiveVGAMemoryPlanes(int planes) {
|
||||
outpw_to_register(
|
||||
VGA_SEQUENCE_CONTROLLER_INDEX,
|
||||
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
||||
planes
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
414
vga.c
414
vga.c
|
@ -6,64 +6,27 @@
|
|||
#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;
|
||||
byte *drawBuffer;
|
||||
|
||||
void initializeDrawBuffer() {
|
||||
byte *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;
|
||||
}
|
||||
|
||||
return drawBuffer;
|
||||
}
|
||||
|
||||
void copyDrawBufferToDisplay() {
|
||||
memcpy(VGA, drawBuffer, 320 * 200);
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -72,273 +35,19 @@ byte *getDrawBuffer() {
|
|||
|
||||
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 buildSpriteFromSpritesheet(
|
||||
struct BMPImage *spritesheetImage,
|
||||
struct SpriteRender *spriteRender,
|
||||
int positionX,
|
||||
int positionY,
|
||||
int width,
|
||||
int height
|
||||
) {
|
||||
spriteRender->data = spritesheetImage->memoryStart + positionY * spritesheetImage->width + positionX;
|
||||
spriteRender->modulo = spritesheetImage->width - width;
|
||||
spriteRender->width = width;
|
||||
spriteRender->height = height;
|
||||
spriteRender->transparentColor = spritesheetImage->transparentColor;
|
||||
}
|
||||
|
||||
void drawSprite(struct SpriteRender* sprite) {
|
||||
|
@ -363,87 +72,6 @@ void drawSprite(struct SpriteRender* sprite) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
31
vga.h
31
vga.h
|
@ -1,17 +1,13 @@
|
|||
#ifndef __VGA_H__
|
||||
#define __VGA_H__
|
||||
|
||||
#include "types.h"
|
||||
#include <time.h>
|
||||
|
||||
#define PLANE_PIXEL_DISTANCE (4)
|
||||
#include "types.h"
|
||||
#include "bmpload.h"
|
||||
|
||||
#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;
|
||||
|
@ -29,23 +25,14 @@ struct SpriteRender {
|
|||
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();
|
||||
void buildSpriteFromSpritesheet(struct BMPImage*, struct SpriteRender*, int, int, int, int);
|
||||
|
||||
byte *initializeDrawBuffer();
|
||||
byte *getDrawBuffer();
|
||||
void freeDrawBuffer();
|
||||
void copyDrawBufferToDisplay();
|
||||
|
||||
void setVGAColors(struct VGAColor[], int);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue