more prep stuff
This commit is contained in:
parent
0d6bed04f7
commit
d52426a877
|
@ -3,3 +3,4 @@
|
||||||
*.ERR
|
*.ERR
|
||||||
*.EXE
|
*.EXE
|
||||||
.ccls-cache/
|
.ccls-cache/
|
||||||
|
*.LNK
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
|
|
||||||
#include "bmp_loader.h"
|
#include "bmpload.h"
|
||||||
#include "pc_stuff.h"
|
#include "pc_stuff.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
|
||||||
int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
||||||
int sizeOfHeader;
|
int sizeOfHeader;
|
||||||
|
char value;
|
||||||
unsigned int numberOfUsedColors;
|
unsigned int numberOfUsedColors;
|
||||||
|
|
||||||
if ((fgetc(fh) != 'B') || (fgetc(fh) != 'M')) {
|
if ((fgetc(fh) != 'B') || (fgetc(fh) != 'M')) {
|
||||||
|
@ -42,14 +43,26 @@ int readBMPHeader(FILE *fh, struct BMPImage *info) {
|
||||||
return 0;
|
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 readBMPIntoMemory(FILE *fh, struct BMPImage *info) {
|
||||||
int x, y, plane;
|
int x, y, plane;
|
||||||
int result;
|
int result;
|
||||||
byte *currentPointer;
|
byte *currentPointer;
|
||||||
|
|
||||||
result = readBMPHeader(fh, info);
|
|
||||||
if (result) return result;
|
|
||||||
|
|
||||||
currentPointer = info->memoryStart;
|
currentPointer = info->memoryStart;
|
||||||
|
|
||||||
for (y = 0; y < info->height; ++y) {
|
for (y = 0; y < info->height; ++y) {
|
||||||
|
@ -61,69 +74,6 @@ int readBMPIntoMemory(FILE *fh, struct BMPImage *info) {
|
||||||
return 0;
|
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[]) {
|
void bmp256ColorPaletteToVGAColorPalette(struct BMPImage* bmpImage, struct VGAColor colors[]) {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef __BMP_LOADER_H__
|
||||||
|
#define __BMP_LOADER_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -15,9 +18,12 @@ struct BMPImage {
|
||||||
word bpp;
|
word bpp;
|
||||||
struct BMPColor colors[256];
|
struct BMPColor colors[256];
|
||||||
byte *memoryStart;
|
byte *memoryStart;
|
||||||
|
|
||||||
|
int transparentColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
int readBMPIntoUnchainedMemory(FILE *, struct BMPImage *);
|
|
||||||
int readBMPIntoMemory(FILE *, struct BMPImage *);
|
int readBMPIntoMemory(FILE *, struct BMPImage *);
|
||||||
|
int readBMPIntoNewMemory(FILE *, struct BMPImage *);
|
||||||
void bmp256ColorPaletteToVGAColorPalette(struct BMPImage*, struct VGAColor[]);
|
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 pc_stuff.c
|
||||||
wcc386.exe -q vga.c
|
wcc386.exe -q vga.c
|
||||||
wcc386.exe -q keyboard.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 "vga.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "mouse_io.h"
|
#include "mouse_io.h"
|
||||||
|
#include "pc_stuff.h"
|
||||||
|
#include "bmpload.h"
|
||||||
|
|
||||||
struct VGAColor colors[4] = {
|
struct BMPImage spritesheetImage;
|
||||||
{ 0, 0, 0 }, { 255, 255, 255 }, { 255, 0, 0 }, { 0, 0, 255 }
|
struct VGAColor vgaColors[256];
|
||||||
}
|
|
||||||
|
struct SpriteRender arenaWallTop, arenaWallSide, arenaFloor;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
FILE *fh;
|
||||||
int keepRunning = 1;
|
int keepRunning = 1;
|
||||||
struct MouseStatus mouseStatus;
|
struct MouseStatus mouseStatus;
|
||||||
|
|
||||||
installKeyboardHandler();
|
installKeyboardHandler();
|
||||||
activateMouse(&mouseStatus);
|
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) {
|
while (keepRunning) {
|
||||||
|
arenaWallTop.x = 0;
|
||||||
|
arenaWallTop.y = 0;
|
||||||
|
|
||||||
|
drawSprite(&arenaWallTop);
|
||||||
|
|
||||||
|
waitStartVbl();
|
||||||
|
|
||||||
|
copyDrawBufferToDisplay();
|
||||||
|
|
||||||
|
waitEndVbl();
|
||||||
}
|
}
|
||||||
// states:
|
// states:
|
||||||
// * main menu
|
// * main menu
|
||||||
|
@ -35,4 +69,7 @@ int main(void) {
|
||||||
// * character is damaged
|
// * character is damaged
|
||||||
// * check for bullets hitting the edges of the screen and remove
|
// * 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"
|
#include "vga.h"
|
||||||
|
|
||||||
typedef struct MouseStatus {
|
struct MouseStatus {
|
||||||
int isActive;
|
int isActive;
|
||||||
int buttonCount;
|
int buttonCount;
|
||||||
int xPosition;
|
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 <stdio.h>
|
||||||
#include <time.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;
|
int activePage = 0;
|
||||||
byte *drawBuffer, *displayMirrorBuffer;
|
byte *drawBuffer;
|
||||||
|
|
||||||
void initializeDrawBuffer() {
|
byte *initializeDrawBuffer() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
drawBuffer = (byte *)malloc(VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
|
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) {
|
for (i = 0; i < VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT; ++i) {
|
||||||
drawBuffer[i] = 0;
|
drawBuffer[i] = 0;
|
||||||
displayMirrorBuffer[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return drawBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyDrawBufferToDisplay() {
|
||||||
|
memcpy(VGA, drawBuffer, 320 * 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeDrawBuffer() {
|
void freeDrawBuffer() {
|
||||||
free(drawBuffer);
|
free(drawBuffer);
|
||||||
free(displayMirrorBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setActiveVGAMemoryPlanes(int planes) {
|
|
||||||
outpw_to_register(
|
|
||||||
VGA_SEQUENCE_CONTROLLER_INDEX,
|
|
||||||
VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE,
|
|
||||||
planes
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *getDrawBuffer() {
|
byte *getDrawBuffer() {
|
||||||
|
@ -72,273 +35,19 @@ byte *getDrawBuffer() {
|
||||||
|
|
||||||
clock_t startTime, endTime;
|
clock_t startTime, endTime;
|
||||||
|
|
||||||
void drawBufferToUnchainedMemory() {
|
void buildSpriteFromSpritesheet(
|
||||||
int x, y, plane, pageOffset, yOffset, yDisplayOffset;
|
struct BMPImage *spritesheetImage,
|
||||||
byte *vgaStart;
|
struct SpriteRender *spriteRender,
|
||||||
unsigned long data;
|
int positionX,
|
||||||
|
int positionY,
|
||||||
int rowsToCopy[VGA_DISPLAY_HEIGHT], minRow = -1, maxRow = 0;
|
int width,
|
||||||
|
int height
|
||||||
unsigned long *drawBufferLong = (unsigned long *)drawBuffer,
|
) {
|
||||||
*displayMirrorBufferLong = (unsigned long *)displayMirrorBuffer;
|
spriteRender->data = spritesheetImage->memoryStart + positionY * spritesheetImage->width + positionX;
|
||||||
|
spriteRender->modulo = spritesheetImage->width - width;
|
||||||
byte copyRow[VGA_DISPLAY_WIDTH];
|
spriteRender->width = width;
|
||||||
|
spriteRender->height = height;
|
||||||
startTime = clock();
|
spriteRender->transparentColor = spritesheetImage->transparentColor;
|
||||||
|
|
||||||
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) {
|
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) {
|
void setVGAColors(struct VGAColor colors[], int totalColors) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
31
vga.h
31
vga.h
|
@ -1,17 +1,13 @@
|
||||||
#ifndef __VGA_H__
|
#ifndef __VGA_H__
|
||||||
#define __VGA_H__
|
#define __VGA_H__
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define PLANE_PIXEL_DISTANCE (4)
|
#include "types.h"
|
||||||
|
#include "bmpload.h"
|
||||||
|
|
||||||
#define VGA_DISPLAY_WIDTH (320)
|
#define VGA_DISPLAY_WIDTH (320)
|
||||||
#define VGA_DISPLAY_HEIGHT (200)
|
#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 {
|
struct VGAColor {
|
||||||
byte red;
|
byte red;
|
||||||
|
@ -29,23 +25,14 @@ struct SpriteRender {
|
||||||
unsigned int modulo;
|
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 drawSprite(struct SpriteRender *sprite);
|
||||||
void swapPlanes();
|
void buildSpriteFromSpritesheet(struct BMPImage*, struct SpriteRender*, int, int, int, int);
|
||||||
void setActiveVGAMemoryPlanes(int);
|
|
||||||
void clearWithColor(byte);
|
|
||||||
|
|
||||||
void initializeDrawBuffer();
|
|
||||||
void freeDrawBuffer();
|
|
||||||
void drawBufferToUnchainedMemory();
|
|
||||||
|
|
||||||
|
byte *initializeDrawBuffer();
|
||||||
byte *getDrawBuffer();
|
byte *getDrawBuffer();
|
||||||
|
void freeDrawBuffer();
|
||||||
|
void copyDrawBufferToDisplay();
|
||||||
|
|
||||||
|
void setVGAColors(struct VGAColor[], int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue