197 lines
4.4 KiB
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;
|
|
}
|
|
}
|