dos-vga-arena-shooter-game/system/vga.c

197 lines
4.4 KiB
C

#include "vga.h"
#include "pc_stuff.h"
#include <malloc.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "../font8x8_basic.h"
int activePage = 0;
byte *drawBuffer;
byte *initializeDrawBuffer() {
int i;
drawBuffer = (byte *)malloc(VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
for (i = 0; i < VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT; ++i) {
drawBuffer[i] = 0;
}
return drawBuffer;
}
void copyDrawBufferToDisplay() {
memcpy(VGA, drawBuffer, VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
}
void freeDrawBuffer() {
free(drawBuffer);
}
byte *getDrawBuffer() {
return drawBuffer;
}
clock_t startTime, endTime;
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 buildCompiledSprite(
void (*code)(byte *),
struct CompiledSpriteRender *compiledSpriteRender,
int width,
int height,
int offsetX,
int offsetY
) {
compiledSpriteRender->code = code;
compiledSpriteRender->width = width;
compiledSpriteRender->height = height;
compiledSpriteRender->offsetX = offsetX;
compiledSpriteRender->offsetY = offsetY;
}
void drawPixel(int x, int y, int color) {
drawBuffer[y * VGA_DISPLAY_WIDTH + x] = color;
}
void drawSprite(struct SpriteRender* sprite) {
int x, y;
byte pixel;
int modulo = VGA_DISPLAY_WIDTH - sprite->width;
byte* spriteData = sprite->data;
byte* drawBufferPos =
drawBuffer +
sprite->x -
sprite->offsetX +
(
(sprite->y - sprite->offsetY) * 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 += modulo;
spriteData += sprite->modulo;
}
}
void drawCompiledSprite(struct CompiledSpriteRender* compiledSprite) {
byte *drawBufferPos = drawBuffer +
compiledSprite->x + compiledSprite->y * VGA_DISPLAY_WIDTH;
compiledSprite->code(drawBufferPos);
}
void getSpriteBounds(struct CompiledSpriteRender *sprite, struct SpriteBounds *bounds) {
bounds->top = sprite->y - sprite->offsetY;
bounds->bottom = bounds->top + sprite->height;
bounds->left = sprite->x - sprite->offsetX;
bounds->right = bounds->left + sprite->width;
}
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);
}
}
#define RENDER_STRING_FAILSAFE (80)
struct CharRowDetails {
char c;
char color;
char backgroundColor;
char writeBackgroundColor;
char* pos;
} charRowDetails;
// Write this in inline assembler for practice!
void plotCharRow();
#pragma aux plotCharRow = \
"mov al, [edi]" \
"mov ah, 8" \
"mov bl, [edi+1]" \
"mov bh, [edi+2]" \
"mov cl, [edi+3]" \
"mov edi, [edi + 4]" \
"nextBit: mov ch, al" \
"and ch,1" \
"cmp ch,1" \
"jne background" \
"mov [edi], bl" \
"jmp maybeKeepGoing" \
"background: cmp cl,0" \
"je maybeKeepGoing" \
"mov [edi], bh" \
"maybeKeepGoing: ror al, 1" \
"inc edi" \
"dec ah" \
"jnz nextBit" \
parm [edi] \
modify [eax ebx ecx edi];
void renderStringToDrawBuffer(char* buffer, int color, int backgroundColor, int x, int y) {
char *bufferPos = buffer, currentCharacter, charRow;
int i, fontX, fontY, currentX = x;
int charX, fontYs[8];
charRowDetails.color = color;
if (backgroundColor == -1) {
charRowDetails.backgroundColor = 0;
}
charRowDetails.writeBackgroundColor = backgroundColor != -1;
for (fontY = 0; fontY < 8; ++fontY) {
fontYs[fontY] = (y + fontY) * VGA_DISPLAY_WIDTH;
}
charX = x;
for (i = 0; i < RENDER_STRING_FAILSAFE; ++i) {
currentCharacter = *(bufferPos++);
if (!currentCharacter) break;
for (fontY = 0; fontY < 8; ++fontY) {
charRowDetails.c = font8x8_basic[currentCharacter][fontY];
charRowDetails.pos = drawBuffer + fontYs[fontY] + charX;
plotCharRow(&charRowDetails);
}
charX += 8;
}
}