; ============================================================================= ; proc.asm - process table management, task creation, fork/exec (stubs) ; ============================================================================= INCLUDE "include/gbos.inc" SECTION "proc", ROM0 ; ----------------------------------------------------------------------------- ; ProcInit - table already zeroed by ClearKernelRAM (PS_FREE=0). Seed pids. ; ----------------------------------------------------------------------------- ProcInit:: ld a, 1 ld [wNextPid], a ret ; ----------------------------------------------------------------------------- ; PcbPtr - slot -> PCB pointer. in: A=slot out: DE=&PCB. preserves BC. ; ----------------------------------------------------------------------------- PcbPtr:: push bc ld hl, wProcTable ld bc, PROC_SIZE and a jr z, .done .mul add hl, bc dec a jr nz, .mul .done ld d, h ld e, l pop bc ret ; ----------------------------------------------------------------------------- ; ProcCreate - allocate a PCB and build an initial (runnable) task. ; in: HL = task entry, B = cart-RAM bank, C = SVBK u-area bank ; out: A = pid, or 0 if the table is full ; ----------------------------------------------------------------------------- ProcCreate:: ; stash params ld a, l ld [wTmpEntry], a ld a, h ld [wTmpEntry+1], a ld a, b ld [wTmpRamB], a ld a, c ld [wTmpWramB], a ; find a free slot ld c, 0 .find ld a, c call PcbPtr ; DE = &PCB[c] ld a, [de] cp PS_FREE jr z, .found inc c ld a, c cp MAX_PROCS jr c, .find xor a ; table full ret .found ld a, c ld [wTmpSlot], a ; fill fields; HL walks the PCB ld h, d ld l, e ld a, PS_READY ld [hl+], a ; PROC_STATE ld a, [wNextPid] ld [hl+], a ; PROC_PID ld [wTmpPid], a inc a ld [wNextPid], a inc hl ; skip PROC_SP (filled below) inc hl ld a, 1 ld [hl+], a ; PROC_ROMB lo (placeholder text bank) xor a ld [hl+], a ; PROC_ROMB hi ld a, [wTmpRamB] ld [hl+], a ; PROC_RAMB ld a, [wTmpWramB] ld [hl+], a ; PROC_WRAMB xor a ld [hl+], a ; PROC_PARENT ld [hl], a ; PROC_EXIT ; build the initial stack frame in the task's RAM bank ld a, [wTmpEntry] ld l, a ld a, [wTmpEntry+1] ld h, a ; HL = entry ld a, [wTmpRamB] ld b, a ; B = RAM bank call ProcSetupStack ; out: HL = initial SP ld a, l ld [wTmpSP], a ld a, h ld [wTmpSP+1], a ; store SP into PCB.PROC_SP ld a, [wTmpSlot] call PcbPtr ; DE = &PCB ld a, e add PROC_SP ld l, a ld a, d adc 0 ld h, a ; HL = &PROC_SP ld a, [wTmpSP] ld [hl+], a ld a, [wTmpSP+1] ld [hl], a ld a, [wTmpPid] ret ; ----------------------------------------------------------------------------- ; ProcSetupStack - lay a fresh switch-in frame at the top of a task RAM bank. ; in: HL = entry, B = cart-RAM bank ; out: HL = initial SP (points at the saved-HL slot) ; The frame matches hSwitchTo's restore sequence: ; [SP+0..1]=hl [+2..3]=de [+4..5]=bc [+6]=f [+7]=a [+8..9]=entry (ret target) ; ----------------------------------------------------------------------------- ProcSetupStack:: ld a, b ld [MBC5_RAMB], a ; map task's RAM bank into $A000-$BFFF push hl ; save entry ld hl, TASK_STACK_TOP - 9 ; frame base = $BFF6 xor a ld [hl+], a ; hl_lo ld [hl+], a ; hl_hi ld [hl+], a ; de_lo ld [hl+], a ; de_hi ld [hl+], a ; bc_lo ld [hl+], a ; bc_hi ld [hl+], a ; f ld [hl+], a ; a pop de ; DE = entry ld a, e ld [hl+], a ; entry lo (ret target) ld a, d ld [hl], a ; entry hi ld hl, TASK_STACK_TOP - 9 ; initial SP ret ; ----------------------------------------------------------------------------- ; sys_fork / sys_exec - TODO. Plan: ; fork: alloc slot, copy parent's 8 KiB RAM bank -> child bank, dup u-area, ; patch child's saved-A to 0 (child return), parent gets child pid. ; exec: point PROC_ROMB at a flashed program image, reset RAM-bank layout ; (copy .data from ROM, zero .bss, fresh heap/stack), longjmp in. ; -----------------------------------------------------------------------------