fsh update

This commit is contained in:
minjaesong
2022-04-29 15:06:55 +09:00
parent e7315834ae
commit 7737f65ea5
9 changed files with 206 additions and 159 deletions

View File

@@ -1,106 +0,0 @@
let CURRENT_DRIVE = "A";
let shell_pwd = [""];
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_prompt_text() {
// oh-my-zsh-like prompt
con.color_pair(239,161);
print(" "+CURRENT_DRIVE+":");
con.color_pair(161,253);
con.addch(16);con.curs_right();
con.color_pair(0,253);
print(" /"+shell_pwd.join("/")+" ");
con.color_pair(253,255);
con.addch(16);con.curs_right();
con.addch(32);con.curs_right();
con.color_pair(239,255);
}
function greet() {
con.color_pair(0,253);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
con.clear();
greet();
let cmdHistory = []; // zeroth element is the oldest
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
while (true) {
print_prompt_text();
let cmdbuf = "";
while (true) {
let key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
println("You entered: " + cmdbuf);
}
catch (e) {
println(e);
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
cmdHistoryScroll = 0;
break;
}
}
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
}
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
}
}
}
}

View File

@@ -1,4 +1,4 @@
graphics.setBackground(3,3,3);
graphics.setBackground(2,1,3);
graphics.resetPalette();
function captureUserInput() {
@@ -18,7 +18,15 @@ _fsh.brandName = "f\xb3Sh";
_fsh.brandLogoTexSmall = new GL.Texture(24, 14, gzip.decomp(base64.atob(
"H4sIAAAAAAAAAPv/Hy/4Qbz458+fIeILQQBIwoSh6qECuMVBukCmIJkDVQ+RQNgLE0MX/w+1lyhxqIUwTLJ/sQMAcIXsbVABAAA="
)));
_fsh.scrlayout = ["com.fsh.clock","com.fsh.calendar","com.fsh.apps_n_files"];
_fsh.scrlayout = ["com.fsh.clock","com.fsh.calendar","com.fsh.todo_list", "com.fsh.quick_access"];
_fsh.drawWallpaper = function() {
filesystem.open("A", "/tvdos/wall.bytes", "R")
let b = sys.malloc(250880)
dma.comToRam(0, 0, b, 250880)
dma.ramToFrame(b, 0, 250880)
sys.free(b)
};
_fsh.drawTitlebar = function(titletext) {
GL.drawTexPattern(_fsh.titlebarTex, 0, 0, 560, 14);
@@ -58,7 +66,7 @@ _fsh.registerNewWidget = function(widget) {
_fsh.widgets[widget.identifier] = widget;
}
var clockWidget = new _fsh.Widget("com.fsh.clock", _fsh.scrwidth - 8, 7);
var clockWidget = new _fsh.Widget("com.fsh.clock", _fsh.scrwidth - 8, 7*2);
clockWidget.numberSheet = new GL.SpriteSheet(19, 22, new GL.Texture(190, 22, gzip.decomp(base64.atob(
"H4sIAAAAAAAAAMWVW3LEMAgE739aHcFJJV5ZMD2I9ToVfcl4GBr80HF8r/FaR1ozMuIyoUu87lEXI0al5qVR5AebSwchSaNE6Nyo1Nw5HXF3SfPT4Bshl"+
"EycA8RD96mLlHbuhTgOrfLnUDZspafbSQWk56WEGvQEtWaWwgb8iz7a8AOXhsraO/q9Qw2/GnXovfVN+q2wM/p/oddn2cjF239GX3y11+SWCtc6FTHC1v"+
@@ -84,12 +92,12 @@ clockWidget.draw = function(charXoff, charYoff) {
if (ordinalDay == 119) dayName = 7; // Verddag
var years = ((timeInMinutes / (60*24*30*120))|0) + 125;
// draw timepiece
GL.drawSprite(clockWidget.numberSheet, (hours / 10)|0, 0, xoff, yoff);
GL.drawSprite(clockWidget.numberSheet, hours % 10, 0, xoff + 24, yoff);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 5);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 14);
GL.drawSprite(clockWidget.numberSheet, (mins / 10)|0, 0, xoff + 57, yoff);
GL.drawSprite(clockWidget.numberSheet, mins % 10, 0, xoff + 81, yoff);
GL.drawSprite(clockWidget.numberSheet, (hours / 10)|0, 0, xoff, yoff, 1);
GL.drawSprite(clockWidget.numberSheet, hours % 10, 0, xoff + 24, yoff, 1);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 5, 1);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 14, 1);
GL.drawSprite(clockWidget.numberSheet, (mins / 10)|0, 0, xoff + 57, yoff, 1);
GL.drawSprite(clockWidget.numberSheet, mins % 10, 0, xoff + 81, yoff, 1);
// print month and date
con.move(1 + charYoff, 17 + charXoff);
print(clockWidget.monthNames[months]+" "+visualDay);
@@ -100,24 +108,100 @@ clockWidget.draw = function(charXoff, charYoff) {
};
var calendarWidget = new _fsh.Widget("com.fsh.calendar", (_fsh.scrwidth - 8) / 2, 7*6)
calendarWidget.dayLabels = [
" 1 2 3 4 5 6 7 \xFA\xFA",
" 8 9 10 11 12 13 14 \xFA\xFA",
"15 16 17 18 19 20 21 \xFA\xFA",
"22 23 24 25 26 27 28 \xFA\xFA",
"29 30 1 2 3 4 5 \xFA\xFA",
" 6 7 8 9 10 11 12 \xFA\xFA",
"13 14 15 16 17 18 19 \xFA\xFA",
"20 21 22 23 24 25 26 \xFA\xFA",
"27 28 29 30 1 2 3 \xFA\xFA",
" 4 5 6 7 8 9 10 \xFA\xFA",
"11 12 13 14 15 16 17 \xFA\xFA",
"18 19 20 21 22 23 24 \xFA\xFA",
"25 26 27 28 29 30 1 \xFA\xFA",
" 2 3 4 5 6 7 8 \xFA\xFA",
" 9 10 11 12 13 14 15 \xFA\xFA",
"16 17 18 19 20 21 22 \xFA\xFA",
"23 24 25 26 27 28 29 30"
]
calendarWidget.seasonCols = [229,39,215,73,253]
calendarWidget.draw = function(charXoff, charYoff) {
con.color_pair(254, 255)
let xoff = charXoff * 7
let yoff = charYoff * 14 + 3
let timeInMinutes = ((sys.currentTimeInMills() / 60000)|0)
let ordinalDay = ((timeInMinutes / (60*24))|0) % 120
let offset = (ordinalDay / 7)|0
con.move(charXoff, charYoff)
print("Mo Ty Mi To Fr La Su Ve")
for (let i = -3; i <= 3; i++) {
let lineOff = (offset + i) % 17
let line = calendarWidget.dayLabels[lineOff]
let textCol = 0
con.move(charXoff + 4 + i, charYoff)
for (let x = 0; x <= 23; x++) {
let paintingDayOrd = lineOff*7 + ((x/3)|0)
if (x >= 21 && lineOff != 16) textCol = calendarWidget.seasonCols[4]
else textCol = calendarWidget.seasonCols[(paintingDayOrd / 30)|0]
// special colour for spaces between numbers
if (x % 3 == 2) con.color_pair(255,255)
// mark today
else if (paintingDayOrd == ordinalDay) con.color_pair(0,textCol)
// paint normal day number with seasonal colour
else con.color_pair(textCol,255)
con.addch(line.charCodeAt(x))
con.curs_right()
}
}
}
// change graphics mode and check if it's supported
graphics.setGraphicsMode(3)
if (graphics.getGraphicsMode() == 0) {
printerrln("Insufficient VRAM")
return 1
}
// register widgets
_fsh.registerNewWidget(clockWidget);
_fsh.registerNewWidget(clockWidget)
_fsh.registerNewWidget(calendarWidget)
// screen init
con.color_pair(254, 255);
con.clear();
con.curs_set(0);
_fsh.drawTitlebar();
con.color_pair(254, 255)
con.clear()
con.curs_set(0)
graphics.clearPixels(255)
graphics.clearPixels2(255)
graphics.setFramebufferScroll(0,0)
_fsh.drawWallpaper()
_fsh.drawTitlebar()
// TEST
con.move(2,1);
print("Hit backspace to exit");
print("Hit backspace to exit")
// TODO update for events: key down (updates some widgets), timer (updates clock and calendar widgets)
while (true) {
captureUserInput();
if (getKeyPushed(0) == 67) break;
_fsh.widgets["com.fsh.clock"].draw(25, 2);
_fsh.widgets["com.fsh.clock"].draw(25, 3);
_fsh.widgets["com.fsh.calendar"].draw(8, 12);
sys.spin();sys.spin()
}
con.move(3,1);

View File

@@ -35,33 +35,34 @@ GL.SpriteSheet = function(tilew, tileh, tex) {
}
this.getOffX = function(x) { // THIS, or: GL.SpriteSheet.prototype.getOffX
var tx = this.tileWidth * (x|0);
let tx = this.tileWidth * (x|0);
if (tx + this.tileWidth > this.texture.width) throw "Sprite x-offset of "+tx+" is greater than sprite width "+this.texture.width;
return tx;
};
this.getOffY = function(y) {
var ty = this.tileHeight * (y|0);
let ty = this.tileHeight * (y|0);
if (ty + this.tileHeight > this.texture.height) throw "Sprite y-offset of "+ty+" is greater than sprite height "+this.texture.height;
return ty;
};
};
GL.drawTexPattern = function(texture, x, y, width, height, fgcol, bgcol) {
GL.drawTexPattern = function(texture, x, y, width, height, framebuffer, fgcol, bgcol) {
if (!(texture instanceof GL.Texture) && !(texture instanceof GL.MonoTex)) throw Error("Texture is not a GL Texture types");
let paint = (!framebuffer) ? graphics.plotPixel : graphics.plotPixel2
for (let yy = 0; yy < height; yy++) {
for (let xx = 0; xx < width;) {
let tx = xx % texture.width;
let ty = yy % texture.height;
if (texture instanceof GL.Texture) {
let c = texture.texData[ty * texture.width + tx];
graphics.plotPixel(x + xx, y + yy, c);
paint(x + xx, y + yy, c);
}
else if (texture instanceof GL.MonoTex) {
let octet = texture.texData[ty * (texture.width >> 3) + (tx >> 3)];
for (let i = 0; i < 8; i++) {
let bit = ((octet >>> (7 - i)) & 1 != 0)
graphics.plotPixel(x + xx + i, y + yy, bit ? bgcol : fgcol);
paint(x + xx + i, y + yy, bit ? bgcol : fgcol);
}
}
@@ -69,24 +70,25 @@ GL.drawTexPattern = function(texture, x, y, width, height, fgcol, bgcol) {
}
}
};
GL.drawTexPatternOver = function(texture, x, y, width, height, fgcol) {
GL.drawTexPatternOver = function(texture, x, y, width, height, framebuffer, fgcol) {
if (!(texture instanceof GL.Texture) && !(texture instanceof GL.MonoTex)) throw Error("Texture is not a GL Texture types");
let paint = (!framebuffer) ? graphics.plotPixel : graphics.plotPixel2
for (let yy = 0; yy < height; yy++) {
for (let xx = 0; xx < width;) {
let tx = xx % texture.width;
let ty = yy % texture.height;
if (texture instanceof GL.Texture) {
let c = texture.texData[ty * texture.width + tx];
if ((c & 255) != 255) {
let c = texture.texData[ty * texture.width + tx];
graphics.plotPixel(x + xx, y + yy, c);
paint(x + xx, y + yy, c);
}
}
else if (texture instanceof GL.MonoTex) {
let octet = texture.texData[ty * (texture.width >> 3) + (tx >> 3)];
for (let i = 0; i < 8; i++) {
let bit = ((octet >>> (7 - i)) & 1 != 0)
if (bit) graphics.plotPixel(x + xx + i, y + yy, fgcol);
if (bit) paint(x + xx + i, y + yy, fgcol);
}
}
@@ -97,14 +99,14 @@ GL.drawTexPatternOver = function(texture, x, y, width, height, fgcol) {
/*
* Draws a texture verbatim - color of 255 will be written to the screen buffer
*/
GL.drawTexImage = function(texture, x, y, fgcol, bgcol) {
GL.drawTexPattern(texture, x, y, texture.width, texture.height, fgcol, bgcol);
GL.drawTexImage = function(texture, x, y, framebuffer, fgcol, bgcol) {
GL.drawTexPattern(texture, x, y, texture.width, texture.height, framebuffer, fgcol, bgcol);
};
/*
* Draws texture with blitting - color of 255 will pass-thru what's already on the screen buffer
*/
GL.drawTexImageOver = function(texture, x, y, fgcol) {
GL.drawTexPatternOver(texture, x, y, texture.width, texture.height, fgcol);
GL.drawTexImageOver = function(texture, x, y, framebuffer, fgcol) {
GL.drawTexPatternOver(texture, x, y, texture.width, texture.height, framebuffer, fgcol);
};
/*
* @param xi x-index in the spritesheet, ZERO-BASED INDEX
@@ -114,16 +116,17 @@ GL.drawTexImageOver = function(texture, x, y, fgcol) {
* @param overrideFG if the value is set and the current pixel of the sheet is not 255, plots this colour instead
* @param overrideBG if the value is set and the current pixel of the sheet is 255, plots this colour instead
*/
GL.drawSprite = function(sheet, xi, yi, x, y, overrideFG, overrideBG) {
var offx = sheet.getOffX(xi);
var offy = sheet.getOffY(yi);
for (var ty = 0; ty < sheet.tileHeight; ty++) {
for (var tx = 0; tx < sheet.tileWidth; tx++) {
var c = sheet.texture.texData[(ty + offy) * sheet.texture.width + (tx + offx)];
GL.drawSprite = function(sheet, xi, yi, x, y, framebuffer, overrideFG, overrideBG) {
let paint = (!framebuffer) ? graphics.plotPixel : graphics.plotPixel2
let offx = sheet.getOffX(xi);
let offy = sheet.getOffY(yi);
for (let ty = 0; ty < sheet.tileHeight; ty++) {
for (let tx = 0; tx < sheet.tileWidth; tx++) {
let c = sheet.texture.texData[(ty + offy) * sheet.texture.width + (tx + offx)];
if ((c & 255) == 255)
graphics.plotPixel(x + tx, (y + ty)|0, (overrideBG !== undefined) ? overrideBG : c);
paint(x + tx, (y + ty)|0, (overrideBG !== undefined) ? overrideBG : c);
else
graphics.plotPixel(x + tx, (y + ty)|0, (overrideFG !== undefined) ? overrideFG : c);
paint(x + tx, (y + ty)|0, (overrideFG !== undefined) ? overrideFG : c);
}
}
};
@@ -134,14 +137,15 @@ GL.drawSprite = function(sheet, xi, yi, x, y, overrideFG, overrideBG) {
* @param y y-position on the framebuffer where the sprite will be drawn
* @param overrideFG if the value is set and the current pixel of the sheet is not 255, plots this colour instead
*/
GL.drawSpriteOver = function(sheet, xi, yi, x, y, overrideFG) {
var offx = sheet.getOffX(xi);
var offy = sheet.getOffY(yi);
for (var ty = 0; ty < sheet.tileHeight; ty++) {
for (var tx = 0; tx < sheet.tileWidth; tx++) {
var c = sheet.texture.texData[(ty + offy) * sheet.texture.width + (tx + offx)];
GL.drawSpriteOver = function(sheet, xi, yi, x, y, framebuffer, overrideFG) {
let paint = (!framebuffer) ? graphics.plotPixel : graphics.plotPixel2
let offx = sheet.getOffX(xi);
let offy = sheet.getOffY(yi);
for (let ty = 0; ty < sheet.tileHeight; ty++) {
for (let tx = 0; tx < sheet.tileWidth; tx++) {
let c = sheet.texture.texData[(ty + offy) * sheet.texture.width + (tx + offx)];
if ((c & 255) != 255) {
graphics.plotPixel(x + tx, (y + ty)|0, overrideFG || c);
paint(x + tx, (y + ty)|0, overrideFG || c);
}
}
}

BIN
assets/disk0/tvdos/wall.bytes LFS Normal file

Binary file not shown.

BIN
assets/disk0/tvdos/wall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/fsh_wallpaper.kra LFS Normal file

Binary file not shown.

View File

@@ -155,8 +155,9 @@ From the start of the memory space:
1 byte
command (writing to this memory address changes the status)
1: reset palette to default
2: fill framebuffer with given colour (arg1). If framebuffer 2 is there, it will be filled with arg2
3: do '1' then do '2'
2: fill framebuffer with given colour (arg1)
3: do '1' then do '2' (with arg1) then do '4' (with arg2)
4: fill framebuffer2 with given colour (arg1)
16: copy Low Font ROM (char 0127) to mapping area
17: copy High Font ROM (char 128255) to mapping area

View File

@@ -52,6 +52,14 @@ class GraphicsJSR223Delegate(val vm: VM) {
}
}
fun plotPixel2(x: Int, y: Int, color: Int) {
getFirstGPU()?.let {
if (x in 0 until it.config.width && y in 0 until it.config.height) {
it.poke(262144 + y.toLong() * it.config.width + x, color.toByte())
}
}
}
/**
* Sets absolute position of scrolling
*/
@@ -136,6 +144,11 @@ class GraphicsJSR223Delegate(val vm: VM) {
getFirstGPU()?.poke(250883L, 2)
}
fun clearPixels2(col: Int) {
getFirstGPU()?.poke(250884L, col.toByte())
getFirstGPU()?.poke(250883L, 4)
}
/**
* prints a char as-is; won't interpret them as an escape sequence
*/
@@ -211,7 +224,7 @@ class GraphicsJSR223Delegate(val vm: VM) {
pixmap.dispose()
UnsafeHelper.memcpyRaw(outData, UnsafeHelper.getArrayOffset(outData), null, vm.usermem.ptr + destPixmapPtr, outData.size.toLong())
return intArrayOf(width, height, destPixmapPtr)
return intArrayOf(width, height, destPixmapPtr, outData.size / (width * height))
}
/**

View File

@@ -326,7 +326,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
}
2 -> {
framebuffer.fillWith(arg1.toByte())
framebuffer2?.fillWith(arg2.toByte())
}
4 -> {
framebuffer2?.fillWith(arg1.toByte())
}
3 -> {
for (it in 0 until 1024) {
@@ -784,6 +786,54 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
}
}
}
else if (graphicsMode == 3 && framebuffer2 != null) {
val layerOrder = (if (graphicsMode == 1) LAYERORDERS4 else LAYERORDERS2)[layerArrangement]
val fb1 = if (layerOrder[0] == 0) framebuffer else framebuffer2
val fb2 = if (layerOrder[0] == 0) framebuffer2 else framebuffer
for (y in 0 until HEIGHT) {
var xoff = scanlineOffsets[2L * y].toUint() or scanlineOffsets[2L * y + 1].toUint().shl(8)
if (xoff.and(0x8000) != 0) xoff = xoff or 0xFFFF0000.toInt()
val xs = (0 + xoff).coerceIn(0, WIDTH - 1)..(WIDTH - 1 + xoff).coerceIn(0, WIDTH - 1)
if (xoff in -(WIDTH - 1) until WIDTH) {
for (x in xs) {
val colourIndex1 = fb1[y.toLong() * WIDTH + (x - xoff)].toUint()
val colourIndex2 = fb2[y.toLong() * WIDTH + (x - xoff)].toUint()
val colour1 = Color(
paletteOfFloats[4 * colourIndex1],
paletteOfFloats[4 * colourIndex1 + 1],
paletteOfFloats[4 * colourIndex1 + 2],
paletteOfFloats[4 * colourIndex1 + 3]
)
val colour2 = Color(
paletteOfFloats[4 * colourIndex2],
paletteOfFloats[4 * colourIndex2 + 1],
paletteOfFloats[4 * colourIndex2 + 2],
paletteOfFloats[4 * colourIndex2 + 3]
)
val colour = listOf(colour1, colour2).fold(Color(0)) { dest, src ->
// manually alpha compositing
// out_color = {src_color * src_alpha + dest_color * dest_alpha * (1-src_alpha)} / out_alpha
// see https://gamedev.stackexchange.com/a/115786
val outAlpha = (dest.a + (1f - dest.a) * src.a).coerceIn(0.0001f, 1f) // identical to 1 - (1 - dest.a) * (1 - src.a) but this is more optimised form
// src.a + dest.a - src.a*dest.a)
Color(
(src.r * src.a + dest.r * dest.a * (1f - src.a)) / outAlpha,
(src.g * src.a + dest.g * dest.a * (1f - src.a)) / outAlpha,
(src.b * src.a + dest.b* dest.a * (1f - src.a)) / outAlpha,
outAlpha
)
}
framebufferOut.setColor(colour)
framebufferOut.drawPixel(x, y)
}
}
}
}
else if (isRefSize && (graphicsMode == 1 || graphicsMode == 2)) {
val layerOrder = (if (graphicsMode == 1) LAYERORDERS4 else LAYERORDERS2)[layerArrangement]
for (y in 0..223) {
@@ -849,11 +899,6 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
if (xoff in -(WIDTH - 1) until WIDTH) {
for (x in xs) {
// this only works because framebuffer is guaranteed to be 8bpp
/*framebuffer2.pixels.put(
y * WIDTH + x,
framebuffer.pixels.get(y * WIDTH + (x - xoff)) // coerceIn not required as (x - xoff) never escapes 0..559
)*/
val colourIndex = framebuffer[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
framebufferOut.setColor(paletteOfFloats[4*colourIndex], paletteOfFloats[4*colourIndex+1], paletteOfFloats[4*colourIndex+2], paletteOfFloats[4*colourIndex+3])
framebufferOut.drawPixel(x, y)