mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 17:13:31 +02:00
big progress
This commit is contained in:
parent
d4d84881ef
commit
9447da090b
5
TODO.md
5
TODO.md
@ -1,8 +1,8 @@
|
|||||||
# Parity with Vanilla OC (only the stuff that makes sense for an emulator)
|
# Parity with Vanilla OC (only the stuff that makes sense for an emulator)
|
||||||
|
|
||||||
- get rid of nn_busySleep
|
|
||||||
- rework literally all the costs to just be heat and amount per tick
|
- rework literally all the costs to just be heat and amount per tick
|
||||||
- change more methods to be direct but with buffered indirects.
|
- change more methods to be direct but with buffered indirects
|
||||||
|
- complete the GPU implementation (screen buffers and missing methods)
|
||||||
- `computer` component
|
- `computer` component
|
||||||
- `modem` component
|
- `modem` component
|
||||||
- `tunnel` component
|
- `tunnel` component
|
||||||
@ -10,6 +10,7 @@
|
|||||||
- `redstone` component
|
- `redstone` component
|
||||||
- `hologram` component
|
- `hologram` component
|
||||||
- `internet` component
|
- `internet` component
|
||||||
|
- use dynamic arrays for signals
|
||||||
|
|
||||||
# Bugfixes
|
# Bugfixes
|
||||||
|
|
||||||
|
@ -107,9 +107,9 @@ void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
size_t area = screen->width * screen->height;
|
size_t area = screen->width * screen->height;
|
||||||
nn_addHeat(computer, gpu->ctrl.pixelResetHeat * area);
|
nn_addHeat(computer, gpu->ctrl.heatPerPixelReset * area);
|
||||||
nn_callCost(computer, gpu->ctrl.pixelResetCost * area);
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenFillPerTick);
|
||||||
nn_removeEnergy(computer, gpu->ctrl.pixelResetEnergy * area);
|
nn_removeEnergy(computer, gpu->ctrl.energyPerPixelReset * area);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu->currentScreen = screen;
|
gpu->currentScreen = screen;
|
||||||
@ -118,10 +118,6 @@ void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
|
|||||||
}
|
}
|
||||||
gpu->screenAddress = nn_strdup(&gpu->alloc, addr);
|
gpu->screenAddress = nn_strdup(&gpu->alloc, addr);
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.bindHeat);
|
|
||||||
nn_callCost(computer, gpu->ctrl.bindCost);
|
|
||||||
nn_removeEnergy(computer, gpu->ctrl.bindEnergy);
|
|
||||||
|
|
||||||
nn_return(computer, nn_values_boolean(true));
|
nn_return(computer, nn_values_boolean(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +139,7 @@ void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co
|
|||||||
}
|
}
|
||||||
|
|
||||||
int current = 0;
|
int current = 0;
|
||||||
|
int len = 0;
|
||||||
while(s[current] != 0) {
|
while(s[current] != 0) {
|
||||||
int codepoint = nn_unicode_codepointAt(s, current);
|
int codepoint = nn_unicode_codepointAt(s, current);
|
||||||
nn_setPixel(gpu->currentScreen, x, y, nni_gpu_makePixel(gpu, s + current));
|
nn_setPixel(gpu->currentScreen, x, y, nni_gpu_makePixel(gpu, s + current));
|
||||||
@ -152,7 +149,10 @@ void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co
|
|||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
current += nn_unicode_codepointSize(codepoint);
|
current += nn_unicode_codepointSize(codepoint);
|
||||||
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenSetsPerTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||||
@ -243,9 +243,7 @@ void nni_gpu_setBackground(nni_gpu *gpu, void *_, nn_component *component, nn_co
|
|||||||
gpu->currentBg = color;
|
gpu->currentBg = color;
|
||||||
gpu->isBgPalette = isPalette;
|
gpu->isBgPalette = isPalette;
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.colorChangeHeat);
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenColorChangesPerTick);
|
||||||
nn_callCost(computer, gpu->ctrl.colorChangeCost);
|
|
||||||
nn_removeEnergy(computer, gpu->ctrl.colorChangeEnergy);
|
|
||||||
|
|
||||||
nn_return(computer, nn_values_integer(old));
|
nn_return(computer, nn_values_integer(old));
|
||||||
if(idx != -1) {
|
if(idx != -1) {
|
||||||
@ -277,9 +275,7 @@ void nni_gpu_setForeground(nni_gpu *gpu, void *_, nn_component *component, nn_co
|
|||||||
gpu->currentFg = color;
|
gpu->currentFg = color;
|
||||||
gpu->isFgPalette = isPalette;
|
gpu->isFgPalette = isPalette;
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.colorChangeHeat);
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenColorChangesPerTick);
|
||||||
nn_callCost(computer, gpu->ctrl.colorChangeCost);
|
|
||||||
nn_removeEnergy(computer, gpu->ctrl.colorChangeEnergy);
|
|
||||||
|
|
||||||
nn_return(computer, nn_values_integer(old));
|
nn_return(computer, nn_values_integer(old));
|
||||||
if(idx != -1) {
|
if(idx != -1) {
|
||||||
@ -331,13 +327,13 @@ void nni_gpu_fill(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes);
|
nn_addHeat(computer, gpu->ctrl.heatPerPixelChange * changes);
|
||||||
nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes);
|
nn_removeEnergy(computer, gpu->ctrl.energyPerPixelChange * changes);
|
||||||
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * changes);
|
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * clears);
|
nn_addHeat(computer, gpu->ctrl.heatPerPixelReset * clears);
|
||||||
nn_callCost(computer, gpu->ctrl.pixelChangeCost * clears);
|
nn_removeEnergy(computer, gpu->ctrl.energyPerPixelReset * clears);
|
||||||
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * clears);
|
|
||||||
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenFillPerTick);
|
||||||
|
|
||||||
nn_return(computer, nn_values_boolean(true));
|
nn_return(computer, nn_values_boolean(true));
|
||||||
}
|
}
|
||||||
@ -389,13 +385,13 @@ void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
|
|||||||
|
|
||||||
nn_dealloc(&gpu->alloc, tmpBuffer, sizeof(nn_scrchr_t) * w * h);
|
nn_dealloc(&gpu->alloc, tmpBuffer, sizeof(nn_scrchr_t) * w * h);
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes);
|
nn_addHeat(computer, gpu->ctrl.heatPerPixelChange * changes);
|
||||||
nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes);
|
nn_removeEnergy(computer, gpu->ctrl.energyPerPixelChange * changes);
|
||||||
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * changes);
|
|
||||||
|
|
||||||
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * clears);
|
nn_addHeat(computer, gpu->ctrl.heatPerPixelReset * clears);
|
||||||
nn_callCost(computer, gpu->ctrl.pixelChangeCost * clears);
|
nn_removeEnergy(computer, gpu->ctrl.energyPerPixelReset * clears);
|
||||||
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * clears);
|
|
||||||
|
nn_simulateBufferedIndirect(component, 1, gpu->ctrl.screenCopyPerTick);
|
||||||
|
|
||||||
nn_return(computer, nn_values_boolean(true));
|
nn_return(computer, nn_values_boolean(true));
|
||||||
}
|
}
|
||||||
@ -407,7 +403,43 @@ void nni_gpu_getViewport(nni_gpu *gpu, void *_, nn_component *component, nn_comp
|
|||||||
nn_return(computer, nn_values_integer(h));
|
nn_return(computer, nn_values_integer(h));
|
||||||
}
|
}
|
||||||
void nni_gpu_getDepth(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
void nni_gpu_getDepth(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||||
nn_return(computer, nn_values_integer(8));
|
if(gpu->currentScreen == NULL) return;
|
||||||
|
nn_return(computer, nn_values_integer(gpu->currentScreen->depth));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nn_depthName(int depth) {
|
||||||
|
if(depth == 1) return "OneBit";
|
||||||
|
if(depth == 4) return "FourBit";
|
||||||
|
if(depth == 8) return "EightBit";
|
||||||
|
if(depth == 16) return "SixteenBit";
|
||||||
|
if(depth == 24) return "TwentyFourBit";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nni_gpu_setDepth(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
if(gpu->currentScreen == NULL) return;
|
||||||
|
int depth = nn_toInt(nn_getArgument(computer, 0));
|
||||||
|
int maxDepth = nn_maxDepth(gpu->currentScreen);
|
||||||
|
|
||||||
|
if(nn_depthName(depth) == NULL) {
|
||||||
|
nn_setCError(computer, "invalid depth");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(depth > maxDepth) {
|
||||||
|
nn_setCError(computer, "depth out of range");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int old = nn_getDepth(gpu->currentScreen);
|
||||||
|
nn_setDepth(gpu->currentScreen, depth);
|
||||||
|
|
||||||
|
nn_return_cstring(computer, nn_depthName(depth));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nni_gpu_maxDepth(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
if(gpu->currentScreen == NULL) return;
|
||||||
|
nn_return(computer, nn_values_integer(gpu->currentScreen->maxDepth));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_loadGraphicsCardTable(nn_universe *universe) {
|
void nn_loadGraphicsCardTable(nn_universe *universe) {
|
||||||
@ -416,8 +448,8 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
|
|||||||
|
|
||||||
nn_defineMethod(gpuTable, "bind", false, (void *)nni_gpu_bind, NULL, "bind(addr: string[, reset: boolean = false]): boolean - Bind a GPU to a screen. Very expensive. If reset is true, it will clear the screen.");
|
nn_defineMethod(gpuTable, "bind", false, (void *)nni_gpu_bind, NULL, "bind(addr: string[, reset: boolean = false]): boolean - Bind a GPU to a screen. Very expensive. If reset is true, it will clear the screen.");
|
||||||
nn_defineMethod(gpuTable, "getScreen", true, (void *)nni_gpu_getScreen, NULL, "getScreen(): string");
|
nn_defineMethod(gpuTable, "getScreen", true, (void *)nni_gpu_getScreen, NULL, "getScreen(): string");
|
||||||
nn_defineMethod(gpuTable, "set", false, (void *)nni_gpu_set, NULL, "set(x: integer, y: integer, text: string[, vertical: boolean = false]) - Modifies the screen at a specific x or y. If vertical is false, it will display it horizontally. If it is true, it will display it vertically.");
|
nn_defineMethod(gpuTable, "set", true, (void *)nni_gpu_set, NULL, "set(x: integer, y: integer, text: string[, vertical: boolean = false]) - Modifies the screen at a specific x or y. If vertical is false, it will display it horizontally. If it is true, it will display it vertically.");
|
||||||
nn_defineMethod(gpuTable, "get", false, (void *)nni_gpu_get, NULL, "get(x: integer, y: integer): string, integer, integer, integer?, integer? - Returns the character, foreground color, background color, foreground palette index (if applicable), background palette index (if applicable) of a pixel");
|
nn_defineMethod(gpuTable, "get", true, (void *)nni_gpu_get, NULL, "get(x: integer, y: integer): string, integer, integer, integer?, integer? - Returns the character, foreground color, background color, foreground palette index (if applicable), background palette index (if applicable) of a pixel");
|
||||||
nn_defineMethod(gpuTable, "maxResolution", true, (void *)nni_gpu_maxResolution, NULL, "maxResolution(): integer, integer - Gets the maximum resolution supported by the bound screen.");
|
nn_defineMethod(gpuTable, "maxResolution", true, (void *)nni_gpu_maxResolution, NULL, "maxResolution(): integer, integer - Gets the maximum resolution supported by the bound screen.");
|
||||||
nn_defineMethod(gpuTable, "getResolution", true, (void *)nni_gpu_getResolution, NULL, "getResolution(): integer, integer - Gets the current resolution of the bound screen.");
|
nn_defineMethod(gpuTable, "getResolution", true, (void *)nni_gpu_getResolution, NULL, "getResolution(): integer, integer - Gets the current resolution of the bound screen.");
|
||||||
nn_defineMethod(gpuTable, "setResolution", true, (void *)nni_gpu_setResolution, NULL, "maxResolution(): integer, integer - Changes the resolution of the bound screen.");
|
nn_defineMethod(gpuTable, "setResolution", true, (void *)nni_gpu_setResolution, NULL, "maxResolution(): integer, integer - Changes the resolution of the bound screen.");
|
||||||
@ -425,7 +457,8 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
|
|||||||
nn_defineMethod(gpuTable, "setForeground", true, (void *)nni_gpu_setForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
|
nn_defineMethod(gpuTable, "setForeground", true, (void *)nni_gpu_setForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
|
||||||
nn_defineMethod(gpuTable, "getBackground", true, (void *)nni_gpu_getBackground, NULL, "setBackground(color: integer, isPalette: boolean): integer, integer? - Sets the current background color. Returns the old one and palette index if applicable.");
|
nn_defineMethod(gpuTable, "getBackground", true, (void *)nni_gpu_getBackground, NULL, "setBackground(color: integer, isPalette: boolean): integer, integer? - Sets the current background color. Returns the old one and palette index if applicable.");
|
||||||
nn_defineMethod(gpuTable, "getForeground", true, (void *)nni_gpu_getForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
|
nn_defineMethod(gpuTable, "getForeground", true, (void *)nni_gpu_getForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
|
||||||
nn_defineMethod(gpuTable, "getDepth", true, (void *)nni_gpu_getDepth, NULL, "getDepth(): number - The currently set color depth of the GPU/screen, in bits. Can be 1, 4 or 8.");
|
nn_defineMethod(gpuTable, "getDepth", true, (void *)nni_gpu_getDepth, NULL, "getDepth(): number - The currently set color depth of the screen, in bits. Can be 1, 4 or 8.");
|
||||||
|
nn_defineMethod(gpuTable, "setDepth", true, (void *)nni_gpu_setDepth, NULL, "setDepth(depth: integer): string - Changes the screen depth. Valid values can be 1, 4, 8, 16 or 24, however check maxDepth for the maximum supported value of the screen. Using a depth higher than what is supported by the screen will error. Returns the name of the new depth.");
|
||||||
nn_defineMethod(gpuTable, "fill", true, (void *)nni_gpu_fill, NULL, "fill(x: integer, y: integer, w: integer, h: integer, s: string)");
|
nn_defineMethod(gpuTable, "fill", true, (void *)nni_gpu_fill, NULL, "fill(x: integer, y: integer, w: integer, h: integer, s: string)");
|
||||||
nn_defineMethod(gpuTable, "copy", true, (void *)nni_gpu_copy, NULL, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
|
nn_defineMethod(gpuTable, "copy", true, (void *)nni_gpu_copy, NULL, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
|
||||||
nn_defineMethod(gpuTable, "getViewport", true, (void *)nni_gpu_getViewport, NULL, "getViewport(): integer, integer - Gets the current viewport resolution");
|
nn_defineMethod(gpuTable, "getViewport", true, (void *)nni_gpu_getViewport, NULL, "getViewport(): integer, integer - Gets the current viewport resolution");
|
||||||
|
@ -239,3 +239,74 @@ nn_component *nn_addScreen(nn_computer *computer, nn_address address, int slot,
|
|||||||
nn_componentTable *screenTable = nn_queryUserdata(nn_getUniverse(computer), "NN:SCREEN");
|
nn_componentTable *screenTable = nn_queryUserdata(nn_getUniverse(computer), "NN:SCREEN");
|
||||||
return nn_newComponent(computer, address, slot, screenTable, screen);
|
return nn_newComponent(computer, address, slot, screenTable, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_getStd4BitPalette(int color[16]) {
|
||||||
|
color[0] = 0xFFF9FE; // white
|
||||||
|
color[1] = 0xF9801D; // orange
|
||||||
|
color[2] = 0xC74EBD; // magenta
|
||||||
|
color[3] = 0x3AB3DA; // lightblue
|
||||||
|
color[4] = 0xFED83D; // yellow
|
||||||
|
color[5] = 0x80C71F; // lime
|
||||||
|
color[6] = 0xF38BAA; // pink
|
||||||
|
color[7] = 0x474F52; // gray
|
||||||
|
color[8] = 0x9D9D97; // silver
|
||||||
|
color[9] = 0x169C9C; // cyan
|
||||||
|
color[10] = 0x8932B8; // purple
|
||||||
|
color[11] = 0x3C44AA; // blue
|
||||||
|
color[12] = 0x835432; // brown
|
||||||
|
color[13] = 0x5E7C16; // green
|
||||||
|
color[14] = 0xB02E26; // red
|
||||||
|
color[15] = 0x1D1D21; // black
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_getStd8BitPalette(int color[256]) {
|
||||||
|
// source: https://ocdoc.cil.li/component:gpu
|
||||||
|
int reds[6] = {0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF};
|
||||||
|
int greens[8] = {0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF};
|
||||||
|
int blues[5] = {0x00, 0x40, 0x80, 0xC0, 0xFF};
|
||||||
|
|
||||||
|
for(int r = 0; r < 6; r++) {
|
||||||
|
for(int g = 0; g < 8; g++) {
|
||||||
|
for(int b = 0; b < 5; b++) {
|
||||||
|
int i = r * 8 * 5 + g * 5 + b;
|
||||||
|
color[i] = (reds[r] << 16) | (greens[g] << 8) | (blues[b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: turn into an algorithm
|
||||||
|
color[240] = 0x0F0F0F;
|
||||||
|
color[241] = 0x1E1E1E;
|
||||||
|
color[242] = 0x2D2D2D;
|
||||||
|
color[243] = 0x3C3C3C;
|
||||||
|
color[244] = 0x4B4B4B;
|
||||||
|
color[245] = 0x5A5A5A;
|
||||||
|
color[246] = 0x696969;
|
||||||
|
color[247] = 0x787878;
|
||||||
|
color[248] = 0x878787;
|
||||||
|
color[249] = 0x969696;
|
||||||
|
color[250] = 0xA5A5A5;
|
||||||
|
color[251] = 0xB4B4B4;
|
||||||
|
color[252] = 0xC3C3C3;
|
||||||
|
color[253] = 0xD2D2D2;
|
||||||
|
color[254] = 0xE1E1E1;
|
||||||
|
color[255] = 0xF0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nn_mapDepth(int color, int depth) {
|
||||||
|
if(depth == 1) {
|
||||||
|
if(color == 0) return 0;
|
||||||
|
return 0xFFFFFF;
|
||||||
|
}
|
||||||
|
if(depth == 4) {
|
||||||
|
int palette[16];
|
||||||
|
nn_getStd4BitPalette(palette);
|
||||||
|
return nn_mapColor(color, palette, 16);
|
||||||
|
}
|
||||||
|
if(depth == 8) {
|
||||||
|
int palette[256];
|
||||||
|
nn_getStd8BitPalette(palette);
|
||||||
|
return nn_mapColor(color, palette, 256);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
@ -597,31 +597,21 @@ int main() {
|
|||||||
nn_mountKeyboard(computer, "shitty keyboard", 2);
|
nn_mountKeyboard(computer, "shitty keyboard", 2);
|
||||||
nn_addScreen(computer, "Main Screen", 2, s);
|
nn_addScreen(computer, "Main Screen", 2, s);
|
||||||
|
|
||||||
|
// somewhat matches tier 3 in OC in terms of perTick
|
||||||
nn_gpuControl gpuCtrl = {
|
nn_gpuControl gpuCtrl = {
|
||||||
.maxWidth = 240,
|
.totalVRAM = 16*1024,
|
||||||
.maxHeight = 80,
|
.screenCopyPerTick = 4,
|
||||||
.maxDepth = 16,
|
.screenFillPerTick = 8,
|
||||||
|
.screenSetsPerTick = 16,
|
||||||
|
.screenColorChangesPerTick = 8,
|
||||||
|
|
||||||
.totalVRAM = 32*1024,
|
.heatPerPixelChange = 0.0005,
|
||||||
.vramByteChangeCost = 0,
|
.heatPerPixelReset = 0.0001,
|
||||||
.vramByteChangeEnergy = 0,
|
.heatPerVRAMChange = 0.000015,
|
||||||
.vramByteChangeHeat = 0,
|
|
||||||
.vramByteChangeLatency = 0,
|
|
||||||
|
|
||||||
.pixelChangeCost = 0,
|
.energyPerPixelChange = 0.05,
|
||||||
.pixelChangeEnergy = 0,
|
.energyPerPixelReset = 0.01,
|
||||||
.pixelChangeHeat = 0,
|
.energyPerVRAMChange = 0.0015,
|
||||||
.pixelChangeLatency = 0,
|
|
||||||
|
|
||||||
.pixelResetCost = 0,
|
|
||||||
.pixelResetEnergy = 0,
|
|
||||||
.pixelResetHeat = 0,
|
|
||||||
.pixelResetLatency = 0,
|
|
||||||
|
|
||||||
.colorChangeLatency = 0,
|
|
||||||
.colorChangeCost = 0,
|
|
||||||
.colorChangeEnergy = 0,
|
|
||||||
.colorChangeHeat = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nn_addGPU(computer, "RTX 6090", 3, &gpuCtrl);
|
nn_addGPU(computer, "RTX 6090", 3, &gpuCtrl);
|
||||||
@ -736,13 +726,15 @@ render:
|
|||||||
float spacing = (float)pixelHeight/10;
|
float spacing = (float)pixelHeight/10;
|
||||||
int pixelWidth = MeasureTextEx(unscii, "A", pixelHeight, spacing).x;
|
int pixelWidth = MeasureTextEx(unscii, "A", pixelHeight, spacing).x;
|
||||||
|
|
||||||
|
int depth = nn_getDepth(s);
|
||||||
|
|
||||||
for(size_t x = 0; x < scrW; x++) {
|
for(size_t x = 0; x < scrW; x++) {
|
||||||
for(size_t y = 0; y < scrH; y++) {
|
for(size_t y = 0; y < scrH; y++) {
|
||||||
nn_scrchr_t p = nn_getPixel(s, x, y);
|
nn_scrchr_t p = nn_getPixel(s, x, y);
|
||||||
|
|
||||||
// fuck palettes
|
// fuck palettes
|
||||||
Color fgColor = ne_processColor(p.fg);
|
Color fgColor = ne_processColor(nn_mapDepth(p.fg, depth));
|
||||||
Color bgColor = ne_processColor(p.bg);
|
Color bgColor = ne_processColor(nn_mapDepth(p.bg, depth));
|
||||||
DrawRectangle(x * pixelWidth, y * pixelHeight, pixelWidth, pixelHeight, bgColor);
|
DrawRectangle(x * pixelWidth, y * pixelHeight, pixelWidth, pixelHeight, bgColor);
|
||||||
DrawTextCodepoint(unscii, p.codepoint, (Vector2) {x * pixelWidth, y * pixelHeight}, pixelHeight - 5, fgColor);
|
DrawTextCodepoint(unscii, p.codepoint, (Vector2) {x * pixelWidth, y * pixelHeight}, pixelHeight - 5, fgColor);
|
||||||
}
|
}
|
||||||
|
@ -620,6 +620,14 @@ int nn_getPaletteCount(nn_screen *screen);
|
|||||||
int nn_maxDepth(nn_screen *screen);
|
int nn_maxDepth(nn_screen *screen);
|
||||||
int nn_getDepth(nn_screen *screen);
|
int nn_getDepth(nn_screen *screen);
|
||||||
void nn_setDepth(nn_screen *screen, int depth);
|
void nn_setDepth(nn_screen *screen, int depth);
|
||||||
|
const char *nn_depthName(int depth);
|
||||||
|
|
||||||
|
double nn_colorDistance(int colorA, int colorB);
|
||||||
|
int nn_mapColor(int color, int *palette, int paletteSize);
|
||||||
|
|
||||||
|
int nn_mapDepth(int color, int depth);
|
||||||
|
void nn_getStd4BitPalette(int color[16]);
|
||||||
|
void nn_getStd8BitPalette(int color[256]);
|
||||||
|
|
||||||
void nn_setPixel(nn_screen *screen, int x, int y, nn_scrchr_t pixel);
|
void nn_setPixel(nn_screen *screen, int x, int y, nn_scrchr_t pixel);
|
||||||
nn_scrchr_t nn_getPixel(nn_screen *screen, int x, int y);
|
nn_scrchr_t nn_getPixel(nn_screen *screen, int x, int y);
|
||||||
@ -636,41 +644,25 @@ void nn_setOn(nn_screen *buffer, bool on);
|
|||||||
nn_component *nn_addScreen(nn_computer *computer, nn_address address, int slot, nn_screen *screen);
|
nn_component *nn_addScreen(nn_computer *computer, nn_address address, int slot, nn_screen *screen);
|
||||||
|
|
||||||
typedef struct nn_gpuControl {
|
typedef struct nn_gpuControl {
|
||||||
// resolution and colors
|
|
||||||
int maxWidth;
|
|
||||||
int maxHeight;
|
|
||||||
int maxDepth;
|
|
||||||
|
|
||||||
// VRAM Buffers
|
// VRAM Buffers
|
||||||
int totalVRAM;
|
int totalVRAM;
|
||||||
|
|
||||||
// Energy costs
|
// Calls per tick, only applicable to screens
|
||||||
double bindEnergy;
|
double screenCopyPerTick;
|
||||||
double pixelChangeEnergy;
|
double screenFillPerTick;
|
||||||
double pixelResetEnergy;
|
double screenSetsPerTick;
|
||||||
double colorChangeEnergy;
|
double screenColorChangesPerTick;
|
||||||
double vramByteChangeEnergy;
|
double bitbltPerTick; // for bitblit
|
||||||
|
|
||||||
// Heat
|
// Heat
|
||||||
double bindHeat;
|
double heatPerPixelChange;
|
||||||
double pixelChangeHeat;
|
double heatPerPixelReset;
|
||||||
double pixelResetHeat;
|
double heatPerVRAMChange;
|
||||||
double colorChangeHeat;
|
|
||||||
double vramByteChangeHeat;
|
|
||||||
|
|
||||||
// Call budgets
|
// Energy
|
||||||
size_t bindCost;
|
double energyPerPixelChange;
|
||||||
size_t pixelChangeCost;
|
double energyPerPixelReset;
|
||||||
size_t pixelResetCost;
|
double energyPerVRAMChange;
|
||||||
size_t colorChangeCost;
|
|
||||||
size_t vramByteChangeCost;
|
|
||||||
|
|
||||||
// Latencies
|
|
||||||
double bindLatency;
|
|
||||||
double pixelChangeLatency;
|
|
||||||
double pixelResetLatency;
|
|
||||||
double colorChangeLatency;
|
|
||||||
double vramByteChangeLatency;
|
|
||||||
} nn_gpuControl;
|
} nn_gpuControl;
|
||||||
|
|
||||||
// the control is COPIED.
|
// the control is COPIED.
|
||||||
|
47
src/utils.c
47
src/utils.c
@ -114,3 +114,50 @@ double nn_realTimeClock(void *_) {
|
|||||||
return nn_realTime();
|
return nn_realTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use OKLAB the color space for more accurate results.
|
||||||
|
|
||||||
|
typedef struct nn_rgbColor {
|
||||||
|
double r, g, b;
|
||||||
|
} nn_rgbColor;
|
||||||
|
|
||||||
|
nn_rgbColor nni_splitColorToRgb(int color) {
|
||||||
|
double r = (color & 0xFF0000) >> 16;
|
||||||
|
double g = (color & 0x00FF00) >> 8;
|
||||||
|
double b = color & 0x0000FF;
|
||||||
|
|
||||||
|
int max = 0xFF;
|
||||||
|
return (nn_rgbColor) {
|
||||||
|
.r = r / max,
|
||||||
|
.g = g / max,
|
||||||
|
.b = b / max,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
double nn_colorDistance(int colorA, int colorB) {
|
||||||
|
if(colorA == colorB) return 0;
|
||||||
|
nn_rgbColor a = nni_splitColorToRgb(colorA);
|
||||||
|
nn_rgbColor b = nni_splitColorToRgb(colorB);
|
||||||
|
|
||||||
|
nn_rgbColor delta;
|
||||||
|
delta.r = a.r - b.r;
|
||||||
|
delta.g = a.g - b.g;
|
||||||
|
delta.b = a.b - b.b;
|
||||||
|
|
||||||
|
return delta.r*delta.r + delta.g*delta.g + delta.b*delta.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nn_mapColor(int color, int *palette, int paletteSize) {
|
||||||
|
if(paletteSize <= 0) return color;
|
||||||
|
int bestColor = palette[0];
|
||||||
|
double fitness = nn_colorDistance(color, bestColor);
|
||||||
|
|
||||||
|
for(int i = 1; i < paletteSize; i++) {
|
||||||
|
double dist = nn_colorDistance(color, palette[i]);
|
||||||
|
if(dist < fitness) {
|
||||||
|
bestColor = palette[i];
|
||||||
|
fitness = dist;
|
||||||
|
}
|
||||||
|
if(bestColor == color) return color;
|
||||||
|
}
|
||||||
|
return bestColor;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user