#include "vga.h" #include "pc_stuff.h" #include #include #include #include #include #include #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; } }