Apps/Explorer:复制标准 app 骨架(main.vp / linker.ld / project.vpj,链接地址 0x400000)。启动流程:open /dev/fb0 → ioctl(FB_GET_INFO) 打几何 → mmap 拿到线性地址 → 等约 2 秒(等内核桌面首屏全量重绘过去)→ 画一条渐变横条验证像素真上屏 → open /dev/input/keyboard|mouse 验证输入设备可达 → 常驻不退出。 vpsdk/devfs.vp(新增 SDK 设备层):设备路径常量(与内核注册名逐字一致)、FB_GET_INFO 与 FbInfo 镜像(packed,与内核同布局)、fb_open/fb_get_info/fb_map/kbd_open/mouse_open。 build.py:把 Explorer 加进 required_apps 清单与完整构建分支;内核 main.vp 在四个 app 之后 spawn /APPS/explorer.elf。内核 desktop 与 explorer 并存属迁移中间态,S3 会把窗口合成整体交出去。
72 lines
2.4 KiB
Plaintext
72 lines
2.4 KiB
Plaintext
import vpsdk.devfs as devfs
|
||
import vpsdk.process as process
|
||
import vpsdk.syscall as syscall
|
||
from stdint import *
|
||
import viperlib
|
||
|
||
|
||
def _dbg(msg: const str):
|
||
syscall._syscall1(uint64(syscall.Syscall.SERIAL_PUTS), uint64(msg))
|
||
|
||
|
||
@__attribute__(section(".text.startup"), aligned(16))
|
||
export def _start() -> int:
|
||
_dbg("[explorer] start\n")
|
||
|
||
# 1) 打开 framebuffer 设备,问几何,再映射成线性地址
|
||
fb_fd: int = devfs.fb_open()
|
||
if fb_fd < 0:
|
||
_dbg("[explorer] open /dev/fb0 FAILED\n")
|
||
process.exit(1)
|
||
return 0
|
||
|
||
info: devfs.FbInfo = devfs.fb_get_info(fb_fd)
|
||
buf: [160]char
|
||
viperlib.snprintf(&buf, 160,
|
||
"[explorer] fb %ux%u pitch=%u fmt=%u size=%lu phys=0x%lx\n",
|
||
info.width, info.height, info.pitch, info.format, info.size, info.phys)
|
||
_dbg(&buf)
|
||
|
||
fb_va: uint64 = devfs.fb_map(fb_fd, info.size)
|
||
if fb_va == 0:
|
||
_dbg("[explorer] mmap /dev/fb0 FAILED\n")
|
||
process.exit(1)
|
||
return 0
|
||
|
||
buf2: [96]char
|
||
viperlib.snprintf(&buf2, 96, "[explorer] fb mapped at 0x%lx\n", fb_va)
|
||
_dbg(&buf2)
|
||
|
||
# 2) 等桌面把首屏全量重绘做完(否则刚写的像素会被 _mark_all_dirty 的首次重绘盖掉)。
|
||
# 这里没有时钟可用,就空转 yield:yield_cpu 约每 10ms 真让出一次,200 次约 2 秒。
|
||
for _i in range(200):
|
||
process.yield_cpu()
|
||
|
||
# 3) 画一条横贯屏幕的渐变条 —— 证明"用户态直接写 framebuffer 真的上屏"。
|
||
w: int = int(info.width)
|
||
h: int = int(info.height)
|
||
pitch_px: int = int(info.pitch) / 4
|
||
pixels: uint32* = uint32*(fb_va)
|
||
y0: int = h / 3
|
||
y1: int = y0 + h / 6
|
||
for y in range(y0, y1):
|
||
row: int = y * pitch_px
|
||
for x in range(w):
|
||
rr: int = (x * 255) / w
|
||
bb: int = 255 - rr
|
||
pixels[row + x] = uint32((rr << 16) | (0x78 << 8) | bb)
|
||
_dbg("[explorer] painted gradient band\n")
|
||
|
||
# 4) 输入设备可达性:能 open 到就说明 /dev/* 通路已打通
|
||
# (真正读事件、接管窗口合成放到 S3 —— 内核桌面此刻还在抢同一个 PS/2 口)。
|
||
kfd: int = devfs.kbd_open()
|
||
mfd: int = devfs.mouse_open()
|
||
buf3: [96]char
|
||
viperlib.snprintf(&buf3, 96, "[explorer] input: kbd=%d mouse=%d\n", kfd, mfd)
|
||
_dbg(&buf3)
|
||
|
||
# 图形壳暂时只是占位,常驻不退出(app 的 _start 绝不能再 return:栈顶下一格是 0)。
|
||
while True:
|
||
process.yield_cpu()
|
||
return 0
|