fixing black screen bug

This commit is contained in:
minjaesong
2020-04-24 10:20:14 +09:00
parent 280b4148d9
commit 344c35ed9b
11 changed files with 224 additions and 84 deletions

BIN
FontROM7x14.kra Normal file

Binary file not shown.

BIN
FontROM7x14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
smpte_bars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,28 @@
package net.torvald.tsvm
import net.torvald.tsvm.peripheral.GraphicsAdapter
class GraphicsJSR223Delegate(val vm: VM) {
private fun getFirstGPU(): GraphicsAdapter? {
return vm.peripheralTable[vm.findPeribyType("gpu") ?: return null].peripheral as? GraphicsAdapter
}
fun resetPalette() {
getFirstGPU()?.poke(250883L, 1)
}
/**
* @param index which palette number to modify, 0-255
* @param r g - b - a - RGBA value, 0-15
*/
fun setPalette(index: Int, r: Int, g: Int, b: Int, a: Int = 16) {
getFirstGPU()?.let {
it.paletteOfFloats[index * 4] = (r and 15) / 15f
it.paletteOfFloats[index * 4 + 1] = (g and 15) / 15f
it.paletteOfFloats[index * 4 + 2] = (b and 15) / 15f
it.paletteOfFloats[index * 4 + 3] = (a and 15) / 15f
}
}
}

View File

@@ -115,7 +115,7 @@ class VM(
} }
} }
fun poke(addr: Long, value: Byte) { internal fun poke(addr: Long, value: Byte) {
val (memspace, offset) = translateAddr(addr) val (memspace, offset) = translateAddr(addr)
if (memspace == null) if (memspace == null)
Firmware.errorIllegalAccess(addr) Firmware.errorIllegalAccess(addr)
@@ -125,7 +125,7 @@ class VM(
(memspace as PeriBase).poke(offset, value) (memspace as PeriBase).poke(offset, value)
} }
fun peek(addr:Long): Byte? { internal fun peek(addr:Long): Byte? {
val (memspace, offset) = translateAddr(addr) val (memspace, offset) = translateAddr(addr)
return if (memspace == null) return if (memspace == null)
null null

View File

@@ -70,21 +70,12 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
private var latch = true private var latch = true
private fun updateGame(delta: Float) { private fun updateGame(delta: Float) {
// black screening workaround
if (latch) {
latch = false
//paintTestPalette()
val peripheralSlot = vm.findPeribyType(VM.PERITYPE_GRAPHICS)!!
val hwoff = VM.HW_RESERVE_SIZE * peripheralSlot
for (i in 250880 until 250972) {
vm.poke(-(i + 1) - hwoff, 0)
}
}
} }
fun poke(addr: Long, value: Byte) = vm.poke(addr, value) fun poke(addr: Long, value: Byte) = vm.poke(addr, value)
private fun paintTestPalette() { private fun paintTestPalette() {
} }
private val gpuTestPaletteKt = """ private val gpuTestPaletteKt = """
@@ -101,30 +92,25 @@ fun inthash(x: Int): Int {
var rng = (Math.floor(Math.random() * 2147483647) + 1).toInt() var rng = (Math.floor(Math.random() * 2147483647) + 1).toInt()
bindings.forEach {
println(it)
}
println(zzz)
while (true) { while (true) {
val tstart: Long = System.nanoTime() val tstart: Long = System.nanoTime()
for (y1 in 0..359) { for (y1 in 0..359) {
for (x1 in 0 until w) { for (x1 in 0 until w) {
val palnum = 20 * (y1 / 30) + (x1 / 28) val palnum = 20 * (y1 / 30) + (x1 / 28)
vm.poke(-(y1 * w + x1 + 1L) - hwoff, inthash(palnum + rng).toByte()) vm.poke(-(y1 * w + x1 + 1) - hwoff, inthash(palnum + rng))
} }
} }
for (y2 in 360 until h) { for (y2 in 360 until h) {
for (x2 in 0 until w) { for (x2 in 0 until w) {
val palnum = 240 + x2 / 35 val palnum = 240 + x2 / 35
vm.poke(-(y2 * w + x2 + 1L) - hwoff, palnum.toByte()) vm.poke(-(y2 * w + x2 + 1) - hwoff, palnum)
} }
} }
for (k in 0..2239) {
vm.poke(-(254912L + k + 1) - hwoff, -2) // white for (k in 0 until 2560) {
vm.poke(-(254912L + 2240 + k + 1) - hwoff, -1) // transparent vm.poke(-(253952 + k + 1) - hwoff, -2) // white
vm.poke(-(254912L + 2240 * 2 + k + 1) - hwoff, Math.round(Math.random() * 255).toByte()) vm.poke(-(253952 + 2560 + k + 1) - hwoff, -1) // transparent
vm.poke(-(253952 + 2560 * 2 + k + 1) - hwoff, Math.round(Math.random() * 255).toInt())
} }
rng = inthash(rng) rng = inthash(rng)
@@ -133,6 +119,42 @@ while (true) {
} }
""".trimIndent() """.trimIndent()
private val gpuTestPaletteKt2 = """
val w = 560
val h = 448
val hwoff = 1048576
fun inthash(x: Int): Int {
var x = (x.shr(16) xor x) * 0x45d9f3b
x = (x.shr(16) xor x) * 0x45d9f3b
x = (x.shr(16) xor x)
return x
}
var rng = ((Math.random() * 2147483647) + 1).toInt()
while (true) {
for (y1 in 0..359) {
for (x1 in 0 until w) {
val palnum = 20 * (y1 / 30) + (x1 / 28)
vm.poke(-(y1 * w + x1 + 1) - hwoff, palnum)//inthash(palnum + rng))
}
}
for (y2 in 360 until h) {
for (x2 in 0 until w) {
val palnum = 240 + x2 / 35
vm.poke(-(y2 * w + x2 + 1) - hwoff, palnum)
}
}
for (k in 0 until 255) {
graphics.setPalette(k, (Math.random() * 15).toInt(), (Math.random() * 15).toInt(), (Math.random() * 15).toInt())
}
println("arst")
}
""".trimIndent()
private val gpuTestPalette = """ private val gpuTestPalette = """
local vm = require("rawmem") local vm = require("rawmem")
local bit = require("bit32") local bit = require("bit32")
@@ -150,7 +172,7 @@ end
local rng = math.floor(math.random() * 2147483647) local rng = math.floor(math.random() * 2147483647)
while true do while true do
local tstart = vm.nanotime() local tstart = vm.nanoTime()
for y = 0, 359 do for y = 0, 359 do
for x = 0, w - 1 do for x = 0, w - 1 do
@@ -167,14 +189,14 @@ while true do
end end
for k = 0, 2239 do for k = 0, 2239 do
vm.poke(-(254912 + k + 1) - hwoff, 254) vm.poke(-(253952 + k + 1) - hwoff, 254)
vm.poke(-(254912 + 2240 + k + 1) - hwoff, 255) vm.poke(-(253952 + 2560 + k + 1) - hwoff, 255)
vm.poke(-(254912 + 2240*2 + k + 1) - hwoff, math.floor(math.random() * 255.0)) vm.poke(-(253952 + 2560*2 + k + 1) - hwoff, math.floor(math.random() * 255.0))
end end
rng = inthash(rng) rng = inthash(rng)
local tend = vm.nanotime() local tend = vm.nanoTime()
print("Apparent FPS: "..tostring(1000000000.0 / (tend - tstart))) print("Apparent FPS: "..tostring(1000000000.0 / (tend - tstart)))
end end
@@ -186,7 +208,7 @@ var h = 448
var hwoff = 1048576 var hwoff = 1048576
print(typeof print) //function print(typeof print) //function
print(typeof poke.invoke) //function print(typeof vm.poke) //function
function inthash(x) { function inthash(x) {
x = ((x >> 16) ^ x) * 0x45d9f3b x = ((x >> 16) ^ x) * 0x45d9f3b
@@ -199,31 +221,31 @@ var rng = Math.floor(Math.random() * 2147483647) + 1
while (true) { while (true) {
var tstart = nanotime.invoke() var tstart = vm.nanoTime()
for (var y = 0; y < 360; y++) { for (var y = 0; y < 360; y++) {
for (var x = 0; x < w; x++) { for (var x = 0; x < w; x++) {
var palnum = 20 * Math.floor(y / 30) + Math.floor(x / 28) var palnum = 20 * Math.floor(y / 30) + Math.floor(x / 28)
poke.invoke(-(y * w + x + 1) - hwoff, inthash(palnum + rng)) vm.poke(-(y * w + x + 1) - hwoff, inthash(palnum + rng))
} }
} }
for (var y = 360; y < h; y++) { for (var y = 360; y < h; y++) {
for (var x = 0; x < w; x++) { for (var x = 0; x < w; x++) {
var palnum = 240 + Math.floor(x / 35) var palnum = 240 + Math.floor(x / 35)
poke.invoke(-(y * w + x + 1) - hwoff, palnum) vm.poke(-(y * w + x + 1) - hwoff, palnum)
} }
} }
for (var k = 0; k < 2240; k++) { for (var k = 0; k < 2560; k++) {
poke.invoke(-(254912 + k + 1) - hwoff, -2) // white vm.poke(-(253952 + k + 1) - hwoff, -2) // white
poke.invoke(-(254912 + 2240 + k + 1) - hwoff, -1) // transparent vm.poke(-(253952 + 2560 + k + 1) - hwoff, -1) // transparent
poke.invoke(-(254912 + 2240*2 + k + 1) - hwoff, Math.round(Math.random() * 255)) vm.poke(-(253952 + 2560*2 + k + 1) - hwoff, Math.round(Math.random() * 255))
} }
rng = inthash(rng) rng = inthash(rng)
var tend = nanotime.invoke() var tend = vm.nanoTime()
print("Apparent FPS: " + (1000000000 / (tend - tstart))) print("Apparent FPS: " + (1000000000 / (tend - tstart)))
} }
@@ -250,7 +272,7 @@ int rng = Math.floor(Math.random() * 2147483647) + 1;
while (true) { while (true) {
long tstart = nanotime.invoke(); long tstart = nanoTime.invoke();
for (int y1 = 0; y1 < 360; y1++) { for (int y1 = 0; y1 < 360; y1++) {
for (int x1 = 0; x1 < w; x1++) { for (int x1 = 0; x1 < w; x1++) {
@@ -266,15 +288,15 @@ while (true) {
} }
} }
for (int k = 0; k < 2240; k++) { for (int k = 0; k < 2560; k++) {
poke.invoke(-(254912 + k + 1) - hwoff, -2); // white poke.invoke(-(253952 + k + 1) - hwoff, -2); // white
poke.invoke(-(254912 + 2240 + k + 1) - hwoff, -1); // transparent poke.invoke(-(253952 + 2560 + k + 1) - hwoff, -1); // transparent
poke.invoke(-(254912 + 2240*2 + k + 1) - hwoff, Math.round(Math.random() * 255)); poke.invoke(-(253952 + 2560*2 + k + 1) - hwoff, Math.round(Math.random() * 255));
} }
rng = inthash(rng); rng = inthash(rng);
long tend = nanotime.invoke(); long tend = nanoTime.invoke();
System.out.println("Apparent FPS: " + (1000000000.0 / (tend - tstart))); System.out.println("Apparent FPS: " + (1000000000.0 / (tend - tstart)));
} }
@@ -301,7 +323,7 @@ rng = random.randint(1, 2147483647)
while True: while True:
tstart = nanotime.invoke() tstart = nanoTime.invoke()
for y1 in range(0, 360): for y1 in range(0, 360):
for x1 in range(0, w): for x1 in range(0, w):
@@ -313,14 +335,14 @@ while True:
palnum = 240 + int(x2 / 35) palnum = 240 + int(x2 / 35)
poke.invoke(-(y2 * w + x2 + 1) - hwoff, palnum) poke.invoke(-(y2 * w + x2 + 1) - hwoff, palnum)
for k in range(0, 2240): for k in range(0, 2560):
poke.invoke(-(254912 + k + 1) - hwoff, -2) poke.invoke(-(253952 + k + 1) - hwoff, -2)
poke.invoke(-(254912 + 2240 + k + 1) - hwoff, -1) poke.invoke(-(253952 + 2560 + k + 1) - hwoff, -1)
poke.invoke(-(254912 + 2240*2 + k + 1) - hwoff, random.randint(0, 255)) poke.invoke(-(253952 + 2560*2 + k + 1) - hwoff, random.randint(0, 255))
rng = inthash(rng) rng = inthash(rng)
tend = nanotime.invoke() tend = nanoTime.invoke()
print("Apparent FPS: " + str(1000000000.0 / (tend - tstart))) print("Apparent FPS: " + str(1000000000.0 / (tend - tstart)))

View File

@@ -0,0 +1,22 @@
package net.torvald.tsvm
import net.torvald.tsvm.peripheral.GraphicsAdapter
/**
* Pass the instance of the class to the ScriptEngine's binding, preferably under the namespace of "vm"
*/
class VMJSR223Delegate(val vm: VM) {
fun poke(addr: Int, value: Int) = vm.poke(addr.toLong(), value.toByte())
fun peek(addr: Int) = vm.peek(addr.toLong())
fun nanoTime() = System.nanoTime()
fun dmagload(from: Int, to: Int, length: Int) {
val periid = vm.findPeribyType("gpu")
if (periid == null)
throw IllegalStateException("GPU not found")
else {
(vm.peripheralTable[periid].peripheral as GraphicsAdapter).bulkLoad(vm, from.toLong(), to.toLong(), length.toLong())
}
}
}

View File

@@ -1,10 +0,0 @@
package net.torvald.tsvm
class VMKotlinAdapter(val vm: VM) {
/*fun getClassLoader(): ClassLoader {
val cl = object : ClassLoader() {
}
}*/
}

View File

@@ -52,10 +52,10 @@ object VMRunnerFactory {
private val bind = context.getBindings(ScriptContext.ENGINE_SCOPE) private val bind = context.getBindings(ScriptContext.ENGINE_SCOPE)
init { init {
bind.put("zzz", 42) bind.put("vm", VMJSR223Delegate(vm)) // TODO use delegator class to access peripheral (do not expose VM itself)
bind.put("vm", vm) // TODO use delegator class to access peripheral (do not expose VM itself) bind.put("graphics", GraphicsJSR223Delegate(vm))
bind.put("poke", { a: Long, b: Byte -> vm.poke(a, b) }) // kts: lambda does not work... //bind.put("poke", { a: Long, b: Byte -> vm.poke(a, b) }) // kts: lambda does not work...
bind.put("nanotime", { System.nanoTime() }) //bind.put("nanotime", { System.nanoTime() })
} }
override fun executeCommand(command: String) { override fun executeCommand(command: String) {

View File

@@ -1,15 +1,14 @@
package net.torvald.tsvm.peripheral package net.torvald.tsvm.peripheral
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.UnsafeHelper import net.torvald.UnsafeHelper
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import net.torvald.tsvm.AppLoader import net.torvald.tsvm.AppLoader
import net.torvald.tsvm.VM import net.torvald.tsvm.VM
import net.torvald.tsvm.kB import net.torvald.tsvm.kB
import sun.nio.ch.DirectBuffer
import kotlin.experimental.and import kotlin.experimental.and
class GraphicsAdapter : PeriBase { class GraphicsAdapter : PeriBase {
@@ -21,7 +20,7 @@ class GraphicsAdapter : PeriBase {
val channel = it % 4 val channel = it % 4
rgba.shr((3 - channel) * 8).and(255) / 255f rgba.shr((3 - channel) * 8).and(255) / 255f
} }
private val chrrom0 = Texture("./EGA8x14.png") private val chrrom0 = Texture("./FontROM7x14.png")
private val faketex: Texture private val faketex: Texture
private val spriteAndTextArea = UnsafeHelper.allocate(10660L) private val spriteAndTextArea = UnsafeHelper.allocate(10660L)
@@ -34,11 +33,11 @@ class GraphicsAdapter : PeriBase {
private var graphicsUseSprites = false private var graphicsUseSprites = false
private var lastUsedColour = (-1).toByte() private var lastUsedColour = (-1).toByte()
private var currentChrRom = 0 private var currentChrRom = 0
private var chrWidth = 8f private var chrWidth = 7f
private var chrHeight = 14f private var chrHeight = 14f
private var ttyFore = 254 private var ttyFore: Int = 254 // cannot be Byte
private var ttyBack = 255 private var ttyBack: Int = 255 // cannot be Byte
private val textForePixmap = Pixmap(TEXT_COLS, TEXT_ROWS, Pixmap.Format.RGBA8888) private val textForePixmap = Pixmap(TEXT_COLS, TEXT_ROWS, Pixmap.Format.RGBA8888)
private val textBackPixmap = Pixmap(TEXT_COLS, TEXT_ROWS, Pixmap.Format.RGBA8888) private val textBackPixmap = Pixmap(TEXT_COLS, TEXT_ROWS, Pixmap.Format.RGBA8888)
@@ -48,7 +47,13 @@ class GraphicsAdapter : PeriBase {
private var textBackTex = Texture(textBackPixmap) private var textBackTex = Texture(textBackPixmap)
private var textTex = Texture(textPixmap) private var textTex = Texture(textPixmap)
private fun getTtyCursorPos() = spriteAndTextArea.getShort(3938L) % TEXT_COLS to spriteAndTextArea.getShort(3938L) / TEXT_COLS private val memTextCursorPosOffset = 2978L
private val memTextForeOffset = 2980L
private val memTextBackOffset = 2980L + 2560
private val memTextOffset = 2980L + 2560 + 2560
private fun getTtyCursorPos() = spriteAndTextArea.getShort(memTextCursorPosOffset) % TEXT_COLS to spriteAndTextArea.getShort(3938L) / TEXT_COLS
private fun toTtyTextOffset(x: Int, y: Int) = y * TEXT_COLS + x
init { init {
framebuffer.blending = Pixmap.Blending.None framebuffer.blending = Pixmap.Blending.None
@@ -62,7 +67,10 @@ class GraphicsAdapter : PeriBase {
faketex = Texture(pm) faketex = Texture(pm)
pm.dispose() pm.dispose()
spriteAndTextArea.fillWith(0) // initialise with NONZERO value; value zero corresponds with opaque black, and it will paint the whole screen black
// when in text mode, and that's undesired behaviour
// -1 is preferred because it points to the colour CLEAR, and it's constant.
spriteAndTextArea.fillWith(-1)
} }
override fun peek(addr: Long): Byte? { override fun peek(addr: Long): Byte? {
@@ -88,6 +96,10 @@ class GraphicsAdapter : PeriBase {
lastUsedColour = byte lastUsedColour = byte
framebuffer.drawPixel(adi % WIDTH, adi / WIDTH, bi.shl(24)) framebuffer.drawPixel(adi % WIDTH, adi / WIDTH, bi.shl(24))
} }
250883L -> {
unusedArea[adi - 250880] = byte
runCommand(byte)
}
in 250880 until 250972 -> unusedArea[adi - 250880] = byte in 250880 until 250972 -> unusedArea[adi - 250880] = byte
in 250972 until 261632 -> spriteAndTextArea[addr - 250972] = byte in 250972 until 261632 -> spriteAndTextArea[addr - 250972] = byte
in 261632 until 262144 -> pokePalette(adi - 261632, byte) in 261632 until 262144 -> pokePalette(adi - 261632, byte)
@@ -132,6 +144,64 @@ class GraphicsAdapter : PeriBase {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
private fun runCommand(opcode: Byte) {
val arg1 = unusedArea[4].toInt().and(255)
val arg2 = unusedArea[5].toInt().and(255)
when (opcode.toInt()) {
1 -> {
for (it in 0 until 1024) {
val rgba = DEFAULT_PALETTE[it / 4]
val channel = it % 4
rgba.shr((3 - channel) * 8).and(255) / 255f
}
}
2 -> {
framebuffer.setColor(
paletteOfFloats[arg1 * 4],
paletteOfFloats[arg1 * 4 + 1],
paletteOfFloats[arg1 * 4 + 2],
paletteOfFloats[arg1 * 4 + 3]
)
framebuffer.fill()
}
}
}
/**
* @param from memory address (pointer) on the VM's user memory. Because of how the VM is coded, only the user space is eligible for move.
* @param to memory "offset" in Graphics Adapter's memory space, starts from zero.
* @param length how many bytes should be moved
*/
fun bulkLoad(vm: VM, from: Long, to: Long, length: Long) {
UnsafeHelper.unsafe.copyMemory(null, vm.usermem.ptr + from, (framebuffer.pixels as DirectBuffer).address(), to, length)
}
private fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte = ttyFore.toByte(), backColour: Byte = ttyBack.toByte()) {
val textOff = toTtyTextOffset(x, y)
spriteAndTextArea[memTextForeOffset + textOff] = foreColour
spriteAndTextArea[memTextBackOffset + textOff] = backColour
spriteAndTextArea[memTextOffset + textOff] = text
}
private fun advanceCursor() {
spriteAndTextArea.setShort(
memTextCursorPosOffset,
((spriteAndTextArea.getShort(memTextCursorPosOffset) + 1) % (TEXT_COLS * TEXT_ROWS)).toShort()
)
}
// how TTY should work with all those ASCII control characters
fun print(char: Byte) {
val (cx, cy) = getTtyCursorPos()
when (char) {
in 0x20..0x7E, in 0x80..0xFF -> {
putChar(cx, cy, char)
advanceCursor()
}
}
}
override fun dispose() { override fun dispose() {
framebuffer.dispose() framebuffer.dispose()
rendertex.dispose() rendertex.dispose()
@@ -178,7 +248,6 @@ class GraphicsAdapter : PeriBase {
// draw framebuffer // draw framebuffer
batch.draw(rendertex, x, y) batch.draw(rendertex, x, y)
// draw texts or sprites // draw texts or sprites
batch.color = Color.WHITE batch.color = Color.WHITE
@@ -190,9 +259,9 @@ class GraphicsAdapter : PeriBase {
for (y in 0 until TEXT_ROWS) { for (y in 0 until TEXT_ROWS) {
for (x in 0 until TEXT_COLS) { for (x in 0 until TEXT_COLS) {
val addr = y.toLong() * TEXT_COLS + x val addr = y.toLong() * TEXT_COLS + x
val char = spriteAndTextArea[3940 + 2240 + 2240 + addr].toInt().and(255) val char = spriteAndTextArea[memTextOffset + addr].toInt().and(255)
val back = spriteAndTextArea[3940 + 2240 + addr].toInt().and(255) val back = spriteAndTextArea[memTextBackOffset + addr].toInt().and(255)
val fore = spriteAndTextArea[3940 + addr].toInt().and(255) val fore = spriteAndTextArea[memTextForeOffset + addr].toInt().and(255)
textPixmap.setColor(Color(0f, 0f, char / 255f, 1f)) textPixmap.setColor(Color(0f, 0f, char / 255f, 1f))
textPixmap.drawPixel(x, y) textPixmap.drawPixel(x, y)
@@ -232,7 +301,7 @@ class GraphicsAdapter : PeriBase {
batch.shader = null batch.shader = null
if (textCursorIsOn) { /*if (textCursorIsOn) {
batch.color = Color( batch.color = Color(
paletteOfFloats[4 * ttyFore], paletteOfFloats[4 * ttyFore],
paletteOfFloats[4 * ttyFore + 1], paletteOfFloats[4 * ttyFore + 1],
@@ -241,7 +310,7 @@ class GraphicsAdapter : PeriBase {
) )
val (cursorx, cursory) = getTtyCursorPos() val (cursorx, cursory) = getTtyCursorPos()
batch.draw(faketex, cursorx * chrWidth, (TEXT_ROWS - cursory - 1) * chrHeight, chrWidth, chrHeight) batch.draw(faketex, cursorx * chrWidth, (TEXT_ROWS - cursory - 1) * chrHeight, chrWidth, chrHeight)
} }*/
} }
else { else {
// draw sprites // draw sprites
@@ -293,7 +362,7 @@ class GraphicsAdapter : PeriBase {
companion object { companion object {
const val WIDTH = 560 const val WIDTH = 560
const val HEIGHT = 448 const val HEIGHT = 448
const val TEXT_COLS = 70 const val TEXT_COLS = 80
const val TEXT_ROWS = 32 const val TEXT_ROWS = 32
val VRAM_SIZE = 256.kB() val VRAM_SIZE = 256.kB()

View File

@@ -44,7 +44,16 @@ Endianness: little
From the start of the memory space: From the start of the memory space:
250880 bytes 250880 bytes
Framebuffer Framebuffer
92 bytes 3 bytes
*reserved for future use*
1 byte
command (writing to this memory address changes the status)
1: reset palette to default
2: fill framebuffer with given colour (arg1)
2 bytes
argument for "command" (arg1: Byte, arg2: Byte)
write to this address FIRST and then write to "command" to execute the command
86 bytes
*Unused* *Unused*
IF graphics_mode THEN IF graphics_mode THEN
(41 sprites : 260 bytes each -> 10660 bytes) (41 sprites : 260 bytes each -> 10660 bytes)
@@ -56,15 +65,15 @@ IF graphics_mode THEN
256 bytes 256 bytes
16x16 texture for the sprite 16x16 texture for the sprite
ELSE ELSE
3938 bytes 2978 bytes
*Unused* *Unused*
2 bytes 2 bytes
Cursor position in: (y*32 + x) Cursor position in: (y*32 + x)
2240 bytes 2560 bytes
Text foreground colours Text foreground colours
2240 bytes 2560 bytes
Text background colours Text background colours
2240 bytes 2560 bytes
Text buffer of 70x32 (8x14 character size, and yes: actual character data is on the bottom) Text buffer of 70x32 (8x14 character size, and yes: actual character data is on the bottom)
FI FI
512 bytes 512 bytes