aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kdata.asm3
-rw-r--r--src/syscall.asm41
2 files changed, 44 insertions, 0 deletions
diff --git a/src/kdata.asm b/src/kdata.asm
index 6333f38..eece708 100644
--- a/src/kdata.asm
+++ b/src/kdata.asm
@@ -57,6 +57,9 @@ wFsSlashPtr::DS 2 ; last '/' seen while splitting a path
wListDir:: DS 1 ; directory sys_list enumerates
wKChar:: DS 1 ; scratch for KPutc
wConInSkip:: DS 1 ; console input: mid-SLIP-frame? (skip net packets)
+wSleepTarget::DS 1 ; sys_sleep: target in 1/64-second units
+wSleepAcc:: DS 2 ; sys_sleep: accumulated DIV ticks
+wSleepLastDiv::DS 1 ; sys_sleep: previous DIV reading
wKillParent::DS 1 ; scratch for sys_kill
wPsBuf:: DS 2 ; scratch for sys_ps
wPnStart:: DS 2 ; scratch for sys_progname
diff --git a/src/syscall.asm b/src/syscall.asm
index 04e9661..1051a4d 100644
--- a/src/syscall.asm
+++ b/src/syscall.asm
@@ -68,6 +68,7 @@ SyscallTable:
dw sys_srecv_nb ; 31 SRECVNB
dw sys_pollin ; 32 POLLIN
dw sys_net ; 33 NET
+ dw sys_sleep ; 34 SLEEP
; -----------------------------------------------------------------------------
sys_nosys:
@@ -279,6 +280,46 @@ sys_yield:
ret
; -----------------------------------------------------------------------------
+; sys_sleep(B = 1/64-second units) - cooperative delay driven by the DIV timer.
+; DIV (FF04) free-runs at 16384 Hz, so 256 ticks = 1/64 s. We accumulate DIV
+; deltas across SchedYields (other procs run) until enough units have elapsed.
+; -----------------------------------------------------------------------------
+sys_sleep:
+ ld a, b
+ or a
+ ret z ; sleep 0 = no-op
+ ld [wSleepTarget], a
+ xor a
+ ld [wSleepAcc], a
+ ld [wSleepAcc+1], a
+ ld a, [rDIV]
+ ld [wSleepLastDiv], a
+.loop
+ call SchedYield
+ ld a, [rDIV]
+ ld c, a ; current DIV
+ ld a, [wSleepLastDiv]
+ ld b, a ; previous DIV
+ ld a, c
+ ld [wSleepLastDiv], a
+ sub b ; A = DIV delta (mod 256)
+ ld e, a
+ ld a, [wSleepAcc] ; acc += delta
+ add e
+ ld [wSleepAcc], a
+ ld a, [wSleepAcc+1]
+ adc 0
+ ld [wSleepAcc+1], a ; acc high byte = elapsed 1/64-second units
+ ld b, a
+ ld a, [wSleepTarget]
+ cp b
+ jr z, .done ; elapsed == target
+ jr c, .done ; elapsed > target
+ jr .loop
+.done
+ ret
+
+; -----------------------------------------------------------------------------
; sys_exit(code=B) -- become a zombie awaiting reap; never returns.
; - store exit code, set PS_ZOMBIE
; - reparent any children to init (so they can still be waited on)