From 20b00236a2338faf3ba2d0e9bc180946cf8e0699 Mon Sep 17 00:00:00 2001 From: otya128 Date: Fri, 30 Dec 2016 16:42:30 +0900 Subject: [PATCH] Implement FONTDEF (1)(2) --- SMILEBASIC/builtinfunctions.d | 117 ++++++++++++++++++++++++++++++++++ SMILEBASIC/console.d | 50 ++++++++++++++- 2 files changed, 164 insertions(+), 3 deletions(-) diff --git a/SMILEBASIC/builtinfunctions.d b/SMILEBASIC/builtinfunctions.d index d269ef2..8df923b 100644 --- a/SMILEBASIC/builtinfunctions.d +++ b/SMILEBASIC/builtinfunctions.d @@ -3245,6 +3245,123 @@ class BuiltinFunction { return p.program.name(slot); } + static auto split2(R)(R range, size_t size) + { + return Split2!R(range, size); + } + unittest + { + struct IR + { + void popFront() + { + } + bool empty() + { + return true; + } + int front() + { + return 1; + } + } + static assert(isInputRange!(Split2!IR)); + static assert(isInputRange!(Split2!(int[]))); + } + struct Split2(R) + if (isInputRange!R) + { + R range; + size_t size; + ElementType!(R)[] item; + bool isEmpty; + this(R range, size_t size) + { + this.range = range; + this.size = size; + popFront(); + } + void popFront() + { + isEmpty = range.empty; + if (isEmpty) + return; + static if (hasSlicing!R && is(range[0..size] == item)) + { + item = range[0..size]; + popFrontN(item, size); + } + else + { + item = new ElementType!(R)[size]; + for (size_t i = 0; i < size; i++) + { + item[i] = range.front(); + range.popFront(); + } + } + } + auto front() + { + return item; + } + bool empty() + { + return isEmpty; + } + } + static void FONTDEF(PetitComputer p, int icode, Value array) + { + if (icode < 0 || icode > 0xFFFF) + { + throw new OutOfRange("FONTDEF", 1); + } + ushort code = cast(ushort)icode; + if (!p.console.canDefine(code)) + { + throw new IllegalFunctionCall("FONTDEF"/*, 1*/); + } + int color = 4; + if (array.isString) + { + wstring definition = array.castDString; + //FONTDEF 0,"0000"*65'=>OK + if (definition.length < p.console.fontDefWidth * p.console.fontDefHeight * color) + { + throw new IllegalFunctionCall("FONTDEF", 2); + } + int[] font = new int[p.console.fontDefWidth * p.console.fontDefHeight * color]; + try + { + p.console.define(code, split2(definition, 4).map!(x => x.to!int(16)).array); + } + catch (ConvException) + { + throw new IllegalFunctionCall("FONTDEF", 2); + } + return; + } + //DIM A$[63] + //FONTDEF 0,A$'=>Subscript out of range(FONTDEF:2) + //DIM A$[64] + //FONTDEF 0,A$'=>Type mismatch(FONTDEF:2) + //FONTDEF 0,1'=>Type mismatch(FONTDEF:2) + + if (!array.isArray) + throw new TypeMismatch("FONTDEF", 2); + if (array.length < p.console.fontDefWidth * p.console.fontDefHeight) + throw new SubscriptOutOfRange("FONTDEF", 2); + if (!array.isNumberArray) + throw new TypeMismatch("FONTDEF", 2); + if (array.type == ValueType.IntegerArray) + { + p.console.define(code, array.integerArray.array); + } + else if (array.type == ValueType.DoubleArray) + { + p.console.define(code, array.doubleArray.array); + } + } //alias void function(PetitComputer, Value[], Value[]) BuiltinFunc; static BuiltinFunctions[wstring] builtinFunctions; static wstring getBasicName(BFD)(const wstring def) diff --git a/SMILEBASIC/console.d b/SMILEBASIC/console.d index 3e5295e..4412d17 100644 --- a/SMILEBASIC/console.d +++ b/SMILEBASIC/console.d @@ -30,9 +30,24 @@ enum ConsoleAttribute TREVV = 8, } +struct FontRect +{ + int x, y, w, h; + bool define = true; +} + class Console { + //width 16,16 => return 16 + int fontDefWidth() + { + return 8; + } + int fontDefHeight() + { + return 8; + } int[2] fontWidths; int[2] fontHeights; int consoleWidthDisplay1; @@ -125,7 +140,7 @@ class Console bool showCursor; bool animationCursor; - SDL_Rect[] fontTable = new SDL_Rect[65536]; + FontRect[] fontTable = new FontRect[65536]; GraphicPage GRPF; PetitComputer petitcom; bool[2] visibles = [true, true]; @@ -202,7 +217,7 @@ class Console void createFontTable() { auto file = File(petitcom.fontTableFile, "w"); - std.algorithm.fill(fontTable, SDL_Rect(488,120, 8, 8));//TODO:480,120とどっちが使われているかは要調査 + std.algorithm.fill(fontTable, FontRect(488,120, 8, 8, false));//TODO:480,120とどっちが使われているかは要調査 for (int i = 1; i <= 16; i++) { string html = cast(string)get("http://smilebasic.com/supplements/unicode" ~ format("%02d",i)); @@ -229,6 +244,7 @@ class Console file.write(fontTable[index].y, '\n'); fontTable[index].w = 8; fontTable[index].h = 8; + fontTable[index].define = true; } } } @@ -236,7 +252,7 @@ class Console { import std.csv; import std.typecons; - std.algorithm.fill(fontTable, SDL_Rect(488,120, 8, 8));//TODO:480,120とどっちが使われているかは要調査 + std.algorithm.fill(fontTable, FontRect(488,120, 8, 8, false));//TODO:480,120とどっちが使われているかは要調査 auto csv = csvReader!(Tuple!(int,int,int))(readText(petitcom.fontTableFile)); foreach(record; csv) { @@ -244,6 +260,7 @@ class Console fontTable[record[0]].y = record[2]; fontTable[record[0]].w = 8; fontTable[record[0]].h = 8; + fontTable[record[0]].define = true; } } void cls() @@ -480,4 +497,31 @@ class Console consoleC[consoleHeightC - 1] = tmp; tmp[] = ConsoleCharacter(0, foreColor, backColor, attr, CSRZ); } + bool canDefine(ushort a) + { + return fontTable[a].define; + } + void define(T)(ushort code, T[] array) + { + import otya.smilebasic.graphic; + if (!canDefine(code)) + { + return; + } + auto buffer = cast(int*)GRPF.surface.pixels; + auto w = GRPF.surface.w; + auto h = GRPF.surface.h; + auto font = fontTable[code]; + for (int y = 0; y < font.h; y++) + { + for (int x = 0; x < font.w; x++) + { + buffer[x + font.x + (font.y + y) * w] = Graphic.RGBA16ToARGB32Color(cast(int)array[x + y * font.w]); + } + } + //update texture + glBindTexture(GL_TEXTURE_2D, GRPF.glTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, buffer); + glFlush(); + } } \ No newline at end of file