<feed xmlns='http://www.w3.org/2005/Atom'>
<title>gbos.git/src/blk.asm, branch master</title>
<subtitle>gbos - a tiny Unix-flavored OS for the Game Boy Color (kernel, shell, coreutils in C, RAM filesystem)</subtitle>
<id>https://git.sl0p.foo/gbos.git/atom/src/blk.asm?h=master</id>
<link rel='self' href='https://git.sl0p.foo/gbos.git/atom/src/blk.asm?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/'/>
<updated>2026-07-18T08:10:17Z</updated>
<entry>
<title>kernel: a real timer source (64 Hz tick IRQ) + uptime(1)</title>
<updated>2026-07-18T08:10:17Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-18T08:10:04Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=0cc9b0a8bdf774ee376937d5a6767ccdced51245'/>
<id>urn:sha1:0cc9b0a8bdf774ee376937d5a6767ccdced51245</id>
<content type='text'>
The kernel had no clock: TimerISR was a reti stub, IEF_TIMER masked, and
IME was never enabled - the vectors were decorative. sys_sleep just polls
DIV deltas per-process; nothing counted globally.

Now: TAC runs the hardware timer at 16384 Hz with TMA=0, so TIMA overflows
at exactly 64 Hz; TimerISR increments a monotonic 32-bit wTicks (wraps
after ~2.1 years). Scheduling stays cooperative - the ISR is transparent.

Enabling IME in a kernel written for zero interrupts needs care wherever
SP points into memory whose bank is being switched (an IRQ pushes onto SP):
  - read_block/write_block map the disk bank over the $A000 window that
    holds the caller's stack -&gt; di/ei around the transfer (~2ms, well under
    the 15.6ms tick period, so no tick is ever lost)
  - hSwitchTo switches SVBK + cart-RAM banks under the outgoing stack -&gt;
    di on entry, ei once the incoming stack is mapped
  - fork already runs on KSTACK_TOP2 (fixed WRAM) - safe as-is
  - term_putc's SVBK switch only remaps $Dxxx, stacks live in $Axxx/$Cxxx

SYS_UPTIME (36) copies the counter (4B LE, di/ei so the read can't tear)
to a user buffer; libc gticks(); usr/uptime.c formats 'up [Nd] H:MM:SS'.
uptime avoids SDCC long div/shift entirely: sm83.lib modules link into
their own areas that land in the $A000 RAM window (latent build.sh trap,
documented there) - bytewise &gt;&gt;6 plus bounded subtraction loops instead.
</content>
</entry>
<entry>
<title>fs rewrite stage 2: inodes + root directory (block-based, persistent)</title>
<updated>2026-07-16T10:20:57Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T10:20:57Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=4f2d40ca35e0e39886dc881d06256fc25ba27a77'/>
<id>urn:sha1:4f2d40ca35e0e39886dc881d06256fc25ba27a77</id>
<content type='text'>
- fs.asm: a real block filesystem on the persistent block device - superblock,
  block/inode bitmaps, a 32-entry inode table (type, size, 8 direct block
  pointers -&gt; files up to 2 KiB), and a root directory of 16-byte entries.
  Metadata cached in WRAMX; one-block data cache streams file/dir blocks.
- same syscall interface (open/getb/putb/list/remove) -&gt; tools unchanged;
  ls now enumerates until flist() runs out (16 files, was hardcoded 8).
- old 8-slot WRAM FS removed; cart RAM partitioned: process banks 0-7, disk 8-11.
- two register-clobber bugs fixed: alloc_block/alloc_inode returned the
  bitmap-block number (write_bitmap clobbers C); db_use loaded the wrong block
  on a transition (db_flush-&gt;write_block clobbers C) -&gt; multi-block files broke.
- verified: 10+ files, multi-block (300-byte) files, delete, and persistence
  across reboots. Debug 'blk' disk tool retained (fill/peek).
- README: document the block filesystem.
</content>
</entry>
<entry>
<title>fs rewrite stage 1: persistent block device (bounce buffer, cart SRAM)</title>
<updated>2026-07-16T09:42:38Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T09:42:38Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=057e5377af2d086917b9cd0ffb336231d7d098cb'/>
<id>urn:sha1:057e5377af2d086917b9cd0ffb336231d7d098cb</id>
<content type='text'>
- blk.asm: read_block/write_block move 256-byte blocks between battery-backed
  cart-RAM banks (8-11, the 'disk') and a WRAM bounce buffer. Banking is hidden
  in those two routines; they inline the 'restore my bank' step so they never
  touch the stack while the disk bank is mapped over the process's $A000 window
  (the stack lives there too -- a call/ret would rug-pull it).
- format-on-first-boot: superblock magic in block 0; otherwise the disk persists.
- cart RAM bumped to 128 KiB (-r 4); process banks 0-7, disk banks 8-11.
- debug tool 'blk fill/peek' + syscalls to validate round-trip and persistence.
- verified: round-trip incl. cross-bank (block 100 -&gt; bank 11); block survives a
  reboot via .sav; magic intact (no reformat on 2nd boot).
- old WRAM 8-slot FS still backs the tools until stages 2-3.
</content>
</entry>
</feed>
