Download Game! Currently 73 players and visitors. Last logged in:JosimSolvikBrurinRequiem

Blitzer's Blog >> 71399

Back to blogs index
Posted: 12 Jul 2026 11:41 [ permalink ]
TC$mC$ on arkkitehtuurinen neronleimaus! Se, ettC$ tuot webistC$ tutut
DOM-tapahtumat (`onclick`, `onmousedown`) suoraan paljaan metallin ytimeesi,
on valtava etu. Ohjelmoit ikkunoita tismalleen samalla logiikalla kuin tekisit
React- tai Vanilla JS -webbisovelluksia, mutta ohitat selaimen massiivisen
muistinkulutuksen tC$ysin.

### Visio: Hauki OS huippunopeana Thin ClienttinC$

Thin Client -mallin toteuttaminen tC$lle arkkitehtuurille on itse asiassa
yllC$ttC$vC$n suoraviivaista The Mesh -verkossasi. Koska meillC$ on jo
salamannopea UDP-vastaanotto, voimme rakentaa "Virtual DOM over UDP"
-protokollan:

1. **Host-kone (Palvelin):** Ajaa raskasta sovellusta (esim. sC$hkC6postiohjelm
aa tai tekoC$lymallia). Se laskee, miltC$ ruudun pitC$isi nC$yttC$C$, ja
lC$hettC$C$ Hauki OS:lle pienen JSON-paketin: `[{id: "btn1", type: "button",
text: "Send", x: 10, y: 10}]`.
2. **Hauki OS (Thin Client):** Ei tiedC$ mitC$C$n sovelluksen logiikasta. Se
vain piirtC$C$ JSON-paketin mukaiset elementit ruudulle.
3. **Tapahtumien palautus:** Kun kC$yttC$jC$ klikkaa `btn1`-ikkunaa, Hauki
OS:n `onclick`-funktio lC$hettC$C$ takaisin isC$ntC$koneelle UDP-paketin:
`{"event": "click", "target": "btn1"}`.

Raskaampiin pC$ivityksiin voimme lisC$tC$ **"Dirty Rectangles"
(Muutosalueet)** -logiikan: Host lC$hettC$C$ NanoJPEG-pakattuna vain ne 20x20
pikselin alueet, jotka oikeasti muuttuivat, eikC$ koko ruutua. NC$in
sC$C$stC$mme verkkokaistaa massiivisesti.

---

### Vaihe 1: Hiiren laitteistokeskeytys C-ytimeen (`kernel_js.c`)

Jotta JS-tyC6pC6ytC$si voi reagoida hiireen, meidC$n on lisC$ttC$vC$ ytimeen
hiiren (IRQ12) keskeytyskC$sittelijC$, joka lukee PS/2-hiiren lC$hettC$mC$t
3-tavuiset paketit portista `0x60` ja vC$littC$C$ ne JS Event Loopiin.

LisC$C$ tC$mC$ **`kernel_js.c`** -tiedostoon nC$ppC$imistC6n (`kbd_interrupt_ha
ndler`) koodin alapuolelle:

```c
/ ==========================================
/ HIIREN KESKEYTYS (IRQ12 -> INT 44)
/ ==========================================
#define MOUSE_BUF_SIZE 256
volatile uint8_t mouse_ring[MOUSE_BUF_SIZE];
volatile uint8_t mouse_head = 0, mouse_tail = 0;

void mouse_interrupt_handler() {
    uint8_t status = inb(0x64);
    if (status & 0x20) { // Onko data varmasti hiireltC$? (Bitti 5)
        mouse_ring[mouse_head++] = inb(0x60);
    }
    outb(0xA0, 0x20); // Kuittaa Slave PIC
    outb(0x20, 0x20); // Kuittaa Master PIC
}
asm("
.global isr44
isr44:
 cli
 pusha
 call mouse_interrupt_handler
 popa
 iret
");
extern void isr44();

```

Etsi sitten `kmain()` -funktiosta kohta, jossa IDT asennetaan, ja kytke hiiri
pC$C$lle:

```c
idt_set_gate(44, (uint32_t)isr44, cs, 0x8E); // <-- LisC$C$ tC$mC$ muiden
idt_set_gate -kutsujen joukkoon

/ SALLITAAN IRQ12 Slave PICillC$ (bitti 4 nollataan)
outb(0xA1, inb(0xA1) & ~0x10); // <-- LisC$C$ tC$mC$ ennen init_rtl8139()
kutsua

```

Lopuksi, lisC$C$ `while(1)` -pC$C$luuppiin hiiridatan vC$litys JavaScriptille
(nC$ppC$imistC6luupin viereen):

```c
    // Hiiridata JavaScriptille
    if (!raw_kbd_mode) {
        while (mouse_tail != mouse_head) {
            uint8_t m_data = mouse_ring[mouse_tail++];
            JS_PushArg(ctx_os, JS_NewInt32(ctx_os, m_data));
            JS_PushArg(ctx_os, *mouse_func); // HUOM: Varmista ettC$ haet
"onMouseEvent" JSGCRefin kuten nC$ppC$imistC6lle!
            JS_PushArg(ctx_os, JS_UNDEFINED);
            JS_Call(ctx_os, 1);
        }
    }

```

---

### Vaihe 2: JS-DOM & Hiirimoottori (`DESK.JS`)

TC$ssC$ on tyC6pC6ytC$si uusi arkkitehtuuri. Se pitC$C$ sisC$llC$C$n
3-tavuisen PS/2-hiiren tulkitsijan, Z-indeksoinnin, `onclick` ja `onmousedown`
-handlerit, sekC$ tC$ydellisen ikkunoiden raahauksen (Drag & Drop)
"Maailma"-koordinaateissa!

```javascript
var DESK = {
    name: "InfiniteDesk",
    camX: 0, camY: 0,
    windows: {},   
    winOrder: [],  

    // Hiiren sisC$inen tila (PS/2 protokolla ja DOM-tila)
    mouse: { x: 160, y: 100, left: false, right: false, state: 0, bytes: [],
dragWin: null, dragOffX: 0, dragOffY: 0 },

    init: function() {
        sys.gfx_13h();
        this.camX = 0; this.camY = 0;
        
        // --- WEB-TYYLINEN DOM API TESTI ---
        this.addWin("btn_test", 100, 80, 120, 50, 42, 44);
        this.setContent("btn_test", "text", ["KLIKKAA MINUA!"]);
        
        var self = this;
        // MC$C$ritellC$C$n web-tyylinen onclick-handleri!
        this.windows["btn_test"].onclick = function() {
            self.setTheme("btn_test", 40, 45); // Muuttuu punaiseksi!
            self.setContent("btn_test", "text", ["KLIKATTU!", "KIITOS :)"]);
        };
        
        // Luodaan toinen ikkuna raahauksen testaamiseen
        this.addWin("syslog", 20, 20, 150, 80, 20, 22);
        this.setContent("syslog", "text", ["RAAHAA MINUA", "YLAPALKISTA!"]);
    },

    // ==========================================
    // DOM & WINDOW API
    // ==========================================

    addWin: function(id, x, y, w, h, bgCol, titleCol) {
        if (this.windows[id]) return;
        this.windows[id] = { 
            id: id, x: x, y: y, w: w, h: h, 
            bgCol: bgCol, titleCol: titleCol, tx: x, ty: y,
            type: "none", content: null,
            onclick: null, onmousedown: null