mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
fsh update
This commit is contained in:
@@ -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 = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
if ((c & 255) != 255) {
|
||||
let c = texture.texData[ty * texture.width + tx];
|
||||
graphics.plotPixel(x + xx, y + yy, c);
|
||||
if ((c & 255) != 255) {
|
||||
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
BIN
assets/disk0/tvdos/wall.bytes
LFS
Normal file
Binary file not shown.
BIN
assets/disk0/tvdos/wall.png
Normal file
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
BIN
assets/fsh_wallpaper.kra
LFS
Normal file
Binary file not shown.
@@ -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 0–127) to mapping area
|
||||
17: copy High Font ROM (char 128–255) to mapping area
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user