#include "screen.h"
#include "hankaku.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

BYTE Screen::buf[sizeof(Screen)];

Screen::Screen(BOOTINFO *binfo):binfo(binfo), pt(binfo){
	//printf("a");
}

void Screen::Init(BOOTINFO *binfo){
	new ((void *)buf) Screen(binfo);
}

void Screen::printf(const char *format, ...){
	va_list ap;

	va_start(ap, format);
	vprintf(format, ap);
	va_end(ap);
}

void Screen::vprintf(const char *format, va_list ap){
	char s[2048];
	vsprintf(s, format, ap);
	puts(s);
}

void Screen::puts(const char *s){
	for(; *s; s++){
		if(*s == '\n'){
			if(pt.NewLine()){
				Scroll();
			}
		}else{
			for(int i = 0; i < fonth; i++){
				BYTE b = hankakufont[*s][i];
				for(int j = 0; j < fontw; j++){
					if((b >> (7 - j)) & 1){
						SetPixel(pt.getx() + j, pt.gety() + i, RGB(0xff,0xff,0xff));
					}
				}
			}
			if(pt.NextChar()){
				Scroll();
			}
		}
	}
}

void Screen::SetPixel(int x, int y, const Screen::RGB &rgb){
	if(binfo->vmode == 8){
		binfo->vram[y * binfo->screenx + x] = rgb.col8();
	}else{
		BYTE *p = &binfo->vram[(y * binfo->screenx + x) * 3];
		p[0] = rgb.b;
		p[1] = rgb.g;
		p[2] = rgb.r;
	}
}

void Screen::Scroll(){
	unsigned int lines = binfo->screeny / fonth;
	unsigned int stride = binfo->screenx * binfo->vmode / 8;
	unsigned int cstride = stride * fonth;

	//1〜(lines - 1)行目を1行上へずらす
	memmove(binfo->vram
		, binfo->vram + cstride
		, cstride * (lines - 1));
	
	memset(binfo->vram + (lines - 1) * cstride, 0, cstride);
}
