296 lines
8.3 KiB
D
296 lines
8.3 KiB
D
module otya.smilebasic.bg;
|
|
import otya.smilebasic.petitcomputer;
|
|
import otya.smilebasic.error;
|
|
import derelict.sdl2.sdl;
|
|
import derelict.opengl3.gl;
|
|
|
|
struct BGChip
|
|
{
|
|
int i;
|
|
int screenData()
|
|
{
|
|
return i;
|
|
}
|
|
void screenData(int a)
|
|
{
|
|
i = a;
|
|
}
|
|
}
|
|
//912枚まで描画されるみたい
|
|
//->899枚まで描画してその後は一番下のみ描画の様子
|
|
//縦から描画していそう
|
|
class BG
|
|
{
|
|
BGChip[16384] chip;
|
|
int offsetx, offsety, offsetz;
|
|
int clipx, clipy, clipx2, clipy2;
|
|
double scalex, scaley;
|
|
double r;
|
|
int homex, homey;
|
|
int width, height;
|
|
int rendermax = 899;
|
|
PetitComputer petitcom;
|
|
bool show;
|
|
int chipWidth = 16;
|
|
int chipHeight = 16;
|
|
int display;
|
|
int bgcolor;
|
|
this(PetitComputer pc)
|
|
{
|
|
chip[] = BGChip(0);
|
|
width = 25;
|
|
height = 35;
|
|
petitcom = pc;
|
|
scalex = 1;
|
|
scaley = 1;
|
|
r = 0;
|
|
show = true;
|
|
bgcolor = 0xffffffff;
|
|
}
|
|
void render(int display, float disw, float dish)
|
|
{
|
|
if (!show)
|
|
return;
|
|
float aspect = disw / dish;
|
|
disw /= 2;
|
|
dish /= 2;
|
|
float z = offsetz;
|
|
{
|
|
ubyte r, g, b, a;
|
|
petitcom.RGBRead(bgcolor, r, g, b, a);
|
|
glColor4ub(r, g, b, 255);
|
|
}
|
|
petitcom.chRenderingDisplay(display, clipx, clipx, clipx2 - clipx + 1, clipy2 - clipy + 1);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(homex, homey, 0);
|
|
glScalef(scalex, scaley, 1f);
|
|
glRotatef( r, 0.0f, 0.0f, 1.0f );
|
|
glTranslatef(-offsetx, -offsety, z);
|
|
version(test) glRotatef(rot_test_deg, rot_test_x, rot_test_y, rot_test_z);
|
|
//viewport
|
|
//clipx,clipy
|
|
int bgchipwidth = 512 / chipWidth;
|
|
int bgchipheight = 512 / chipHeight;
|
|
int bgchipwidth2 = petitcom.graphic.width / chipWidth;
|
|
int bgchipheight2 = petitcom.graphic.height / chipHeight;
|
|
int chipNumberMax = bgchipwidth * bgchipheight;
|
|
int chipNumberMax2 = bgchipwidth2 * bgchipheight2;
|
|
bool isHR = (petitcom.graphic.width > 512) || (petitcom.graphic.height > 512);
|
|
glBegin(GL_QUADS);
|
|
int rendercount = 0;
|
|
for(int x = 0; x < width; x++)
|
|
{
|
|
version(none)
|
|
{
|
|
for(int y = 0; y < height; y++){}
|
|
}
|
|
for(int y = height - 1; y >= 0; y--)//下から描画してるのか?
|
|
{
|
|
BGChip bgc = chip[x + y * width];
|
|
if(!bgc.i) continue;
|
|
int u = (bgc.i % bgchipwidth) * chipWidth;
|
|
int v = (bgc.i / bgchipheight) * chipHeight;
|
|
if (bgc.i >= chipNumberMax)
|
|
{
|
|
if (isHR)
|
|
{
|
|
if (bgc.i >= bgchipheight2 * bgchipwidth)
|
|
{
|
|
u += 512;
|
|
v %= petitcom.graphic.height;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
u = ((bgc.i % chipNumberMax) % bgchipwidth) * chipWidth;
|
|
v = ((bgc.i % chipNumberMax) / bgchipheight) * chipHeight;
|
|
}
|
|
}
|
|
int u2 = u + chipWidth;
|
|
int v2 = v + chipHeight;
|
|
int w = chipWidth;
|
|
int h = chipHeight;
|
|
glTexCoord2f(u / (cast(float)petitcom.graphic.width) - 1 , v2 / (cast(float)petitcom.graphic.height) - 1);
|
|
glVertex3f((x * w), (y * h + h), 0);
|
|
glTexCoord2f(u / (cast(float)petitcom.graphic.width) - 1, v / (cast(float)petitcom.graphic.height) - 1);
|
|
glVertex3f((x * w), (y * h), 0);
|
|
glTexCoord2f(u2 / (cast(float)petitcom.graphic.width) - 1, v / (cast(float)petitcom.graphic.height) - 1);
|
|
glVertex3f((x * w + w), (y * h), 0);
|
|
glTexCoord2f(u2 / (cast(float)petitcom.graphic.width) - 1, v2 / (cast(float)petitcom.graphic.height) - 1);
|
|
glVertex3f((x * w + w), (y * h + h), 0);
|
|
rendercount++;
|
|
/*if(rendercount >= 899)
|
|
{
|
|
break;
|
|
}*/
|
|
}
|
|
}
|
|
glEnd();
|
|
glLoadIdentity();
|
|
}
|
|
void put(int x, int y, int screendata)
|
|
{
|
|
int i = screendata & 4095;
|
|
chip[x + y * width].i = i;
|
|
}
|
|
void clear()
|
|
{
|
|
chip[0 .. width * height] = BGChip(0);
|
|
}
|
|
void screen(int w, int h)
|
|
{
|
|
rot = 0;
|
|
scalex = 1;
|
|
scaley = 1;
|
|
homex = 0;
|
|
homey = 0;
|
|
chipWidth = 16;
|
|
chipHeight = 16;
|
|
offsetx = offsety = offsetz = 0;
|
|
//BGCLIP is not initialized
|
|
this.width = w;
|
|
this.height = h;
|
|
this.clear();
|
|
}
|
|
void ofs(int x, int y, int z)
|
|
{
|
|
this.offsetx = x;
|
|
this.offsety = y;
|
|
this.offsetz = z;
|
|
}
|
|
void clip(int x, int y, int x2, int y2)
|
|
{
|
|
import std.algorithm : swap;
|
|
if (x > x2)
|
|
{
|
|
swap(x, x2);
|
|
}
|
|
if (y > y2)
|
|
{
|
|
swap(y, y2);
|
|
}
|
|
this.clipx = x;
|
|
this.clipy = y;
|
|
this.clipx2 = x2;
|
|
this.clipy2 = y2;
|
|
}
|
|
void clip()
|
|
{
|
|
this.clipx = 0;
|
|
this.clipy = 0;
|
|
this.clipx2 = petitcom.currentDisplay.rect[display].w - 1;
|
|
this.clipy2 = petitcom.currentDisplay.rect[display].h - 1;
|
|
}
|
|
void home(int x, int y)
|
|
{
|
|
homex = x;
|
|
homey = y;
|
|
}
|
|
void scale(double x, double y)
|
|
{
|
|
this.scalex = x;
|
|
this.scaley = y;
|
|
}
|
|
void getScale(out double x, out double y)
|
|
{
|
|
x = this.scalex;
|
|
y = this.scaley;
|
|
}
|
|
void rot(int rot)
|
|
{
|
|
this.r = rot;
|
|
}
|
|
int rot()
|
|
{
|
|
return cast(int)r;
|
|
}
|
|
void fill(int x, int y, int x2, int y2, int screendata)
|
|
{
|
|
import std.algorithm;
|
|
int id = screendata & 4095;
|
|
if(x > x2) swap(x, x2);
|
|
if(y > y2) swap(y, y2);
|
|
for(; y <= y2; y++)
|
|
chip[x + y * width .. x2 + y * width] = BGChip(id);
|
|
/*for(int i = x; i <= x2; i++)
|
|
{
|
|
chip[i + y * width].i = id;
|
|
}*/
|
|
}
|
|
void fill(int x, int y, int x2, int y2, ushort[] screendata)
|
|
{
|
|
import std.algorithm;
|
|
if(x > x2) swap(x, x2);
|
|
if(y > y2) swap(y, y2);
|
|
int index = 0;
|
|
if (screendata.length == 0)
|
|
{
|
|
fill(x, y, x2, y2, 0);
|
|
return;
|
|
}
|
|
for(; y <= y2; y++)
|
|
for(int i = x; i <= x2; i++)
|
|
{
|
|
chip[i + y * width] = BGChip(screendata[index] & 4095);
|
|
index = (index + 1) % screendata.length;
|
|
}
|
|
}
|
|
int get(int x, int y, int flag)
|
|
{
|
|
if (flag)
|
|
{
|
|
return chip[x / chipWidth + y / chipHeight * width].screenData;
|
|
}
|
|
else
|
|
{
|
|
return chip[x + y * width].screenData;
|
|
}
|
|
}
|
|
void save(T)(int x, int y, int w, int h, T[] array)
|
|
if (is(T == int) || is(T == double))
|
|
{
|
|
int desti;
|
|
for (int i = x; i < x + w; i++)
|
|
{
|
|
for (int j = y; j < y + h; j++)
|
|
{
|
|
desti++;
|
|
int index = i + j * width;
|
|
if (index < 0)
|
|
continue;
|
|
array[desti - 1] = cast(int)chip[index].screenData;
|
|
}
|
|
}
|
|
}
|
|
void load(T)(int x, int y, int w, int h, T[] array, int charoff)
|
|
if (is(T == int) || is(T == double))
|
|
{
|
|
int srci;
|
|
for (int i = x; i < x + w; i++)
|
|
{
|
|
for (int j = y; j < y + h; j++)
|
|
{
|
|
srci++;
|
|
int index = i + j * width;
|
|
if (index < 0)
|
|
continue;
|
|
auto scr = cast(int)array[srci - 1];
|
|
auto chr = ((scr & 0xFFF) + charoff) & /*mask?*/0xFFF;
|
|
chip[index].screenData = (scr & 0xF000) | chr;
|
|
}
|
|
}
|
|
}
|
|
import otya.smilebasic.vm;
|
|
Callback callback;
|
|
public void color(int color)
|
|
{
|
|
this.bgcolor = color;
|
|
}
|
|
public int color()
|
|
{
|
|
return this.bgcolor;
|
|
}
|
|
}
|