Commit Graph
305 Commits
Author SHA1 Message Date
TermiNexus 3cd28b9925 perf(scene3d): cap render loop at ~60 FPS to keep UI responsive 2026-10-29 01:34:32 +08:00
TermiNexus 65ad527eeb fix(paging): clone from kernel PML4 and isolate user stack tables for runtime spawn 2026-10-29 01:31:33 +08:00
TermiNexus 51287eb1a0 perf(explorer): per-frame window double buffering and present-aware FLUSH 2026-10-29 00:57:00 +08:00
TermiNexus 6f856992da feat: Linux ABI P0-P6, BMIDE DMA, ImageSee, 4KiB page pool and Explorer hardening 2026-10-29 00:42:21 +08:00
TermiNexus ebd43ef9da fix(explorer): make window shadows follow rounded corners
_shadow_alpha() measured the distance to the window's bounding rectangle,
so WIN11/WIN7/WINXP shadows still had square corners: the rounded corner
notch stayed unshadowed and the outer iso-alpha lines met at a right
angle.

Measure against the rectangle inset by the window radius instead. The
corner arcs now shape both the notch and the outer falloff, while the
straight edges keep the previous values. Square styles pass r = 0 and
are unchanged.
2026-10-27 22:52:01 +08:00
TermiNexus 807c4207c0 chore: raise QEMU memory and extend the FontDemo sample
Give the guest 512 MiB so the full Noto Sans SC face and the fonttools
buffers fit, and render a mixed Chinese/Latin string in FontDemo.
2026-10-27 22:44:19 +08:00
TermiNexus 5d9df61de0 fix(fonttools): keep natural glyph proportions in the ASCII atlas
build_ascii_atlas() used to scale every glyph to fill its cw x ch cell,
so uppercase and lowercase had the same height and narrow shapes such as
i/l/o became solid blobs.

Use one uniform scale ((ch - 2) / units_per_em) for the whole font, keep
the real cap/x-height/descender ratios, and only squeeze glyphs whose ink
is wider than cw - 1. Center by ink width and place the baseline at ch - 4.
2026-10-27 22:21:41 +08:00
TermiNexus 9bfdaecc6b feat(vpui): support direct and Explorer-managed TTF text
vpui.set_text_mode selects:
- TEXT_MODE_DIRECT: vpui imports fonttools, loads /FONTS/FONT.TTF and
  builds the 8x16 atlas in-process.
- TEXT_MODE_MANAGED (default): text is queued per frame and drawn by
  Explorer through the new DESK_REQ_TEXT request; Explorer uses the same
  fonttools atlas.

Remove the fixed VPUI.ATL asset and its loader.
2026-10-27 22:08:16 +08:00
TermiNexus 5040149db8 feat(vpui): use a Noto Sans SC 8x16 atlas for UI text
Load /FONTS/VPUI.ATL once per process and alpha-blend its glyphs; keep the built-in 8x16 bitmap as fallback when the atlas is missing or the codepoint is non-ASCII.
2026-10-27 21:52:02 +08:00
TermiNexus 28a011ca9e fix(fonttools): stop the contour walk at the closing point
When an off-curve run ended on first_on, the walk set cur=first_on and
wrapped past it, repeating the contour and overflowing the edge table.
Break immediately after drawing the closing quadratic.
2026-10-27 21:42:19 +08:00
TermiNexus 6eba51701a fix(fonttools): record the TrueType on-curve flag per point
_pon was never written, so every point was treated as off-curve and all
straight edges/corners were flattened through the quadratic path. Set
_pon from bit 0 of each parsed glyph flag, including repeated flags.
2026-10-27 21:38:34 +08:00
TermiNexus 3145e38211 fix(fonttools): keep the second off-curve point as the next control
When two consecutive off-curve points were flattened via their midpoint,
the code advanced past the second point, so the following segment was a
line instead of a quadratic through that control. This rounded corners
and deformed glyphs. Advance only to the first control point.
2026-10-27 21:07:05 +08:00
TermiNexus 6a65d0a7f2 fix(fonttools): scale Bezier subdivision to the pixel error
Flatten each quadratic with a segment count derived from
|p0 - 2*p1 + p2| in pixel space, targeting < 0.5 px error. The count
grows with the rendered font size. All-off-curve contours now use
midpoint quadratics instead of polygon edges.
2026-10-27 21:00:07 +08:00
TermiNexus faab22c40e feat(font): use the full Noto Sans SC font and enlarge the disk
- FontDemo points at /FONTS/FONT.TTF
- build.py installs NotoSansSC-6.ttf as disk/fonts/font.ttf
- grow disk.img from 64 MiB to 256 MiB
2026-10-27 20:45:27 +08:00
TermiNexus e6e5763ded chore(build): allow QEMU to reboot on guest reset
Keep -no-reboot disabled so the reboot command restarts the VM.
2026-10-27 20:41:07 +08:00
TermiNexus 585d3a8215 feat(font): add Brotli/WOFF2 and TrueType text rendering
- vpsdk/brotli: Brotli decoder with the static dictionary
- vpsdk/fonttools: TTF/WOFF2 loading, cmap, glyf/composite glyphs and
  anti-aliased rasterization
- Apps/FontDemo: render 你好,世界 from a fixed font path
- autostart FontDemo and copy the Brotli dictionary into disk/libs
- build with the fixed ViperC compiler that zero-extends unsigned types
2026-10-27 20:26:05 +08:00
TermiNexus 93a4f5bdcb chore(explorer): remove [explorer] debug output
Drop startup/input/frame tracing from the desktop shell and window
server, including the one-shot diagnostic counters.
2026-10-27 17:54:06 +08:00
TermiNexus 976b8307f9 chore(scene3d): remove [s3d] debug output
Drop the serial tracing from startup, the render thread and the
pre-render loop.
2026-10-27 17:52:32 +08:00
TermiNexus 28d1a23677 chore(vpui): remove [vpui] debug output
Drop the first-redraw/first-flush/canvas-draw debug tracing and the
related counters.
2026-10-27 17:51:46 +08:00
TermiNexus 4abb0ef3f6 chore(devfs): remove [serial0] debug output
Keep the data written to /dev/serial0, drop the open/close/read/write
debug tags.
2026-10-27 17:50:41 +08:00
TermiNexus cec0647708 fix(acpi): read S5 sleep types from the DSDT _S5 object
The FADT signature constant was byte-swapped ("FCAP"), so FADT lookup
always failed. Correct it to "FACP".

SLP_TYP is platform-defined and must come from the DSDT _S5 package.
QEMU/OVMF defines _S5 as 0, so the previous hardcoded value 5 never
triggered S5. Parse _S5 and use its SLP_TYPa/SLP_TYPb for PM1a/PM1b.
2026-10-27 17:36:35 +08:00
TermiNexus b33fbb75dc fix(boot): read the ACPI RSDP before taking the memory-map key
ExitBootServices failed with EFI_INVALID_PARAMETER because Print ran
after GetMemoryMap, so the console output could change the memory map
and invalidate MapKey. Locate the RSDP and print it before GetMemoryMap.
2026-10-27 17:14:51 +08:00
TermiNexus 7e0aa5c7af feat(acpi): power off via the ACPI FADT
Pass the firmware ACPI RSDP through boot_info so the kernel can locate
the FADT. Shutdown now writes the S5 sleep type to the PM1a/PM1b control
blocks advertised by the FADT instead of fixed QEMU/Bochs/VirtualBox
ports.

- boot: capture the ACPI 2.0/1.0 RSDP from the UEFI configuration table
- kernel: add platform/acpi; walk RSDP -> RSDT/XSDT -> FADT
- syscall: power_shutdown calls acpi.poweroff()
2026-10-27 17:05:05 +08:00
TermiNexus 925e0ffaea feat(power): add reboot and shutdown syscalls and terminal commands
- REBOOT (0x1008): 8042 reset with PCI 0xCF9 fallback
- SHUTDOWN (0x1009): ACPI S5 writes to the common QEMU/Bochs/VBox
  PM1a control ports, then halt
- vpsdk.process.reboot()/shutdown()
- Terminal commands: reboot, shutdown (help updated)
2026-10-27 16:56:26 +08:00
TermiNexus f9cf26e59a fix(paging): validate non-leaf page-table entries before dereference
_set_page_writable / MakePTWritable derived table pointers with
entry & ~0xFFF, which keeps reserved bits 52..62 and NX. An invalid
entry (P=1, PS=0, reserved bits set) produced 0xfffffffffffff000 and
a boot-time #PF in _set_page_writable.

Add _table_phys: keep address bits 12..51 and require reserved bits
52..62 to be zero. Use it at every non-leaf level in both walkers.
2026-10-27 16:35:06 +08:00
TermiNexus da4b0e47b7 fix(input): 修正 PS/2 滚轮方向
IntelliMouse 第 4 字节的 Z 符号与“向上 = 正值”的事件约定相反,
在驱动层统一翻符号;下游按正值表示滚轮向上处理,Terminal 的
scroll_offset -= w * 3 无需改动。
2026-10-27 16:19:37 +08:00
TermiNexus 395e5eefab feat(terminal): 去掉提示符/光标/输入文字的颜色
Text 默认的 prompt/cursor 由绿色改为与普通文本一致的 0xCCCCCC,
输入文字也不再硬编码白色;终端整体保持单色。
2026-10-27 14:54:00 +08:00
TermiNexus c379cadc38 feat(terminal): 日志与输入行之间留空行
- Text._exec_input 在本命令确实产生输出时追加一个空行,
  提示符与最后一条日志之间保持一个空行;无输出的命令不补
- 用实际 line_count 判断,clear 后不会被误补空行
- Terminal 启动时的介绍日志后也插入一个空行
2026-10-27 14:52:09 +08:00
TermiNexus 99c8cea8ee feat(window): 滚轮事件下传与 Terminal 滚动
- desk 协议新增 DESK_MOUSE_WHEEL;window 新增 EVENT_TYPE_WHEEL
- Explorer 汇总一批鼠标包的 wheel 增量,投给光标下的窗口
  (窗口内坐标;任务栏区域不投递)
- InputEvent.button 承载滚轮有符号增量(uint8 编码,消费方按 int8 解码)
- vpui.Text 处理 WHEEL:每次滚动 3 行,按“输出行 + 输入行”总行数钳制,
  并同步滚动条;输入行仍保持在可视区内
2026-10-27 14:50:04 +08:00
TermiNexus 5405a34a24 feat(input): PS/2 鼠标启用 IntelliMouse 滚轮
- init 发送 200/100/80 魔数并读取设备 ID;ID=3/4 时切到 4 字节包
- IRQ 的 4 字节模式解析第 4 字节低 4 位为有符号 Z 增量;
  标准 3 字节模式 wheel 恒 0
- mouse_packet 增加 wheel:int8
- /dev/input/mouse 布局扩展:[9] = wheel(int8),read 返回 10;
  调用方缓冲不足 10 字节时仍返回旧的 9 字节布局
2026-10-27 14:50:03 +08:00
TermiNexus 5e2598a992 feat(terminal): 输入行跟随输出并显示当前路径
- Text 不再把输入行固定在控件底部:输入行紧跟在最后一条输出之后,
  输出增加时随之下移;超出可视区时 scroll_offset 保持输入行可见
- Text 增加 prompt 字段 / set_prompt;点击定位、光标、_exec_input、
  滚动条计算都按实际 prompt 长度和总行数(输出行 + 输入行)计算
- Terminal 的提示符改为“归一化路径 + /> ”:
  根目录是 "/> ",/apps 是 "/apps/> "
- cd 成功后更新提示符;裸 cd 仍打印当前路径
2026-10-27 14:41:35 +08:00
TermiNexus ab18afd26e feat(window): WIN7 关闭按钮红底改为圆形
WIN7 样式的关闭按钮仍保留 28×20 的命中区,但红色背景改为
区域内居中的 20×20 圆,圆心与 X 图标中心重合;
hover / 按下时的颜色变化规则不变。
2026-10-27 14:40:48 +08:00
TermiNexus b94de46ce5 feat(window): 任务栏层级提升到窗口之上
- render_range 顺序改为:背景 → 窗口 → 任务栏 → 光标,
  窗口拖到任务栏区域时会被任务栏盖住
- hit_test 在任务栏高度内直接返回 -1,避免窗口视觉上被任务栏
  盖住后还能点到下面的窗口;任务栏图标仍由 _taskbar_icon_hit 处理
2026-10-27 14:35:38 +08:00
TermiNexus b6ea47277c fix(kernel): 用户异常终止不再提前 swapgs,避免拖垮整机
用户态 #PF 的终止路径直接从 ISR 调用 _yield,不经过 ISR 出口。
原实现在 _yield 前把 GS_BASE swap 回 0;但下一个被调度的线程如果是
从用户态 timer IRQ 或 syscall 挂起的,它的恢复路径会自己 swapgs 回 0。
提前 swap 会让它 swap 反,下一次系统调用用 gs:[8] 取内核栈时读到
线性地址 8,进而三重故障/整机卡死。

- 删除终止路径的 swapgs 块,保持 ISR 入口后的 GS 视图,与其他
  timer/syscall 让出路径一致
- 先置 THREAD_DONE 再 free_user_thread,与
  Scheduler.exit_current_thread 的次序一致,避免“资源已释放但
  state 仍是 RUNNING”的再调度窗口
2026-10-27 14:30:16 +08:00
TermiNexus f9e91a9d6e fix(gargantua): 调整窗口大小时不再改画布源尺寸
现象:计算过程中拖动/缩放 Gargantua 窗口,tid=2 以
[0E] rip=0x413f2f cr2=0x46c000 退出。

原因:RESIZE 处理器把 FBCanvas 的源尺寸用
set_fb(fb, new_w, new_h) 改成窗口内容尺寸,但 _fb_mem 仍是固定的
160×90。窗口变大后 FBCanvas.draw 会按新的 _cw 逐行读取
self._fb[py*_cw+px],越过 _fb_mem 末尾(0x46c000)触发用户态缺页。

修复:RESIZE 时不再改画布源尺寸,只调用 root.redraw() 按新窗口
尺寸重绘;超过源尺寸的部分由 FBCanvas 现有的 min(_cw,self.w)
裁剪逻辑处理。
2026-10-27 14:23:35 +08:00
TermiNexus 845633773b fix(window): 标题栏按钮保持方角,仅按窗口圆角裁剪
上一版把 WIN11 关闭按钮红底做了内收 + 按钮圆角,不符合预期:
窗口是全圆角,但按钮本身应当是方角,唯一需要丢弃的是与窗口
右上圆角重合的那部分像素。

- WIN11 关闭按钮红底恢复整块矩形,仅用 _window_round_keep 丢弃窗口圆角外像素
- WIN7/WINXP 按钮底色同样改为方角(r=0),仍做窗口轮廓裁剪
- 按钮命中区域保持不变(仍是完整方角矩形)
2026-10-27 13:25:41 +08:00
TermiNexus 8dc806e7e2 fix(window): WIN11 关闭按钮 hover 红底按圆角裁剪
WIN11 窗口是圆角样式,关闭按钮又紧贴右上角;此前 hover/按下直接
row_fill 整块矩形,红色会盖住窗口圆角外的区域。

- 新增 _window_round_keep:按窗口自身的圆角轮廓判断像素是否可画
- 新增 _close_fill_row:同时按“按钮圆角 + 窗口圆角”双重裁剪
- WIN11 关闭按钮红底向内收 2px、圆角 3px;WIN7/WINXP 也走窗口轮廓裁剪
- 移除不再使用的 _round_fill_row
2026-10-27 13:21:34 +08:00
TermiNexus b9efc30d71 feat(window): 标题栏 hover、最大化图标、边缘缩放与控件光标
1) 标题栏按钮 hover:min/max 背景按 alpha 压暗,close 变红、图标变白;
   按下态更深。新增 hover_btn_win/kind,仅在变化时重画标题栏。
2) 最大化图标改为单线方框(上边框不再两行加厚);最大化后显示
   两个错位重叠方框作为“还原”。
3) 窗口边缘 5px 热区支持拖拽缩放:左/右 ↔、上/下 ↕、四角斜向;
   缩放中实时更新几何与内容缓冲(按 1.5 倍扩容,避免 arena 抖动),
   并向 app 发 RESIZE。
4) 新增 DESK_REQ_CURSOR / window.set_cursor_type 真正下发光标类型;
   explorer 按窗口 cursor + 边缘热区选择箭头 / I 形 / 手指 / 缩放光标。
5) vpui.Tk 在 HOVER 时按最上层控件设置光标:Entry/Text → I 形,
   Button → 手指;Entry 自己的光标请求移除,避免与集中逻辑冲突。
2026-10-27 13:14:42 +08:00
TermiNexus 6ecd891f64 fix(desk): 清空共享区槽表并按版本拒绝旧 app
现场:所有窗口消失、任务栏多出若干图标,点击后 explorer 以
[0E] rip=0x4061e8 cr2=0x1207e8fff 缺页退出。

原因:desk_format 只清 DeskHeader,没有清 0x100 起的 WinSlot 表。
DESK_SHM_SIZE 从 8MB 提到 32MB 后,mm.malloc 拿到的内存不再恰好全零
(混入 bootloader/固件遗留数据),随机 used/active 被当成窗口,
合成时按垃圾 fb_off 越界读像素。

- desk_format 先 memset 整个控制区(0x000000 ~ 0x200000)
- 分配槽位时整槽清零,避免复用残留
- DESK_VERSION 1 → 2,desk_ready 校验版本:
  旧 app 按旧 WinSlot 偏移读写会写坏共享区,现在直接拒绝挂载
- render_window_rows 校验 fb_off 范围,坏槽位只跳过,不再拖崩合成器
2026-10-27 12:52:23 +08:00
TermiNexus 8e94458fc2 fix(window): 最大化窗口不绘制阴影
最大化后窗口底边正好贴住任务栏,阴影(下沿 14px)会盖在任务栏上。
最大化状态跳过阴影绘制。
2026-10-27 12:44:54 +08:00
TermiNexus 03a5738702 perf(window): 最小化窗口的 FLUSH 不再置脏
应用最小化后仍会继续绘制并发送 FLUSH;此前每条 FLUSH 都标脏窗口区域,
合成器于是每帧重画背景。最小化时直接忽略置脏即可。
2026-10-27 12:43:53 +08:00
TermiNexus 97ca7bbbdb chore(build): viperc 路径集中为 VIPERC 常量并切换 vpcbuild3
- BuildKernel / BuildLibs / BuildApps 共用 VIPERC,去掉三处硬编码
- 指向 ViperC/__vpcbuild3__/output/viperc.exe
2026-10-27 12:43:19 +08:00
TermiNexus 632bc877df feat(window): 鼠标捕获与窗口最小化/最大化
鼠标:
- 内容区按下后记录 capture_win,按住期间的移动仍投 HOVER、松开投 RELEASE
  (即使光标移出窗口)。此前 btn_down != 0 时完全不发 HOVER,滚动条
  拖动拿不到位置更新。
- 标题栏按钮按下态改为通用 btn_win/btn_kind,支持关闭/最小化/最大化。

窗口:
- WinSlot 新增 maximized、restore_*、fb_cap 字段
- 最小化:隐藏窗口并把焦点交给最高可见窗口;任务栏点击恢复,
  再点一次已聚焦窗口则最小化
- 最大化:保存还原几何,铺满工作区(不含任务栏)并发送 RESIZE 事件;
  再次点击还原;拖动最大化窗口会先还原
- 像素缓冲按 fb_cap 复用,仅在容量不足时从 arena 扩容,避免反复
  最大化/还原耗尽 bump arena
- 1920x1080 最大化需要约 7.3MB 内容缓冲:DESK_SHM_SIZE 8MB → 32MB
2026-10-27 12:43:19 +08:00
TermiNexus 859197e5e9 feat(kbd): USB 键盘按住自动重复
USB HID 键盘只在状态变化时上报;a3c1d22 为避免 Enter 洪流加入整份报告去重后,
按住不放不再产生任何字符。

- 记录当前按住的非 CapsLock 键与下一次补发时刻
- 同一份报告重复到达(按键仍按住)时,按 500ms 首次延迟、33ms 间隔
  重新走 _decode_press,注入与按下沿相同的 ASCII/ANSI 字节
- 松开或换键时更新/清除重复目标;CapsLock 本身不重复
2026-10-27 12:43:19 +08:00
TermiNexus b8ca4826a9 chore(kernel): 移除帧缓冲参数的影子副本校验
fb/width/height/pitch 偶发被写坏的根因(页表/1GB 大页拆分时写坏内存)已修复,
不再需要 fail-fast 影子防御:

- 删除 _ShadowFb/_ShadowW/_ShadowH/_ShadowPitch 与 _SetFrameShadow、_CheckFrameLocals
- 删除 after_usb / after_vga / pre_devfs_fb0 / pre_explorer 四处校验调用
- devfs_register_fb0 恢复直接使用 __init__ 里的局部几何
  (原先为规避局部量被写坏,改为从 BootInfo 重取)
2026-10-27 11:54:41 +08:00
TermiNexus f43951c1f8 fix(fat32): 以 . / .. 结尾的路径会误开第一个子目录
dir_open_path 在 follow_path 返回后仍按“父目录中的最后一项”回读目录项。
当路径以 “.” 或 “..” 结尾时,follow_path 已经把 dp 打开成目标目录,
这段回读会把目标目录的第一个子项当成最终项再打开:

  根目录 cd .. → full=/.. → follow_path 打开根 → 回读根的第一项 APP
  → 实际进入 /APP,于是 ls 显示的是 app 里的 helloworld.asm。

现在检测末尾的 “.” / “..”,与根路径一样直接返回已打开的 dp。
2026-10-26 23:10:38 +08:00
TermiNexus 329a60b123 feat(terminal): 裸 cd 显示当前路径并归一化 cwd
- 只输入 cd 时不再重置到根目录,改为打印当前路径(pwd 语义)
- 新增 _normalize_path:折叠重复分隔符、去掉 .、处理 ..,
  根目录下 cd .. 仍为 /
- _cwd 保存归一化后的路径,pwd/ls 不再出现 /app/../.. 这类串,
  也避免路径越 cd 越长
2026-10-26 23:09:19 +08:00
TermiNexus 338472e304 fix(vpui): Label 自然尺寸与 pack 交叉轴居中
Input Demo 的两个显示问题:

- Label 没有显式 w/h,构造后 w/h 恒为 0:pack 时按 0 尺寸计算,
  PACK_BOTTOM 的标签被贴到内容区底边之外(字模被裁),且不占纵向空间,
  后面的按钮与 Name: 标签重叠。新增 _fit_natural() 按文本最长行/行数
  计算自然尺寸,__init__ 与 config() 时更新。
- pack 在未 fill 时原先一律贴左上,导致 Submit 按钮紧贴左边缘。
  改为与 tkinter 默认 anchor=center 一致:TOP/BOTTOM 横向居中、
  LEFT/RIGHT 纵向居中,沿 pack 方向仍保留 padx/pady。
- redraw 先刷新窗口尺寸再 _do_layout(),避免 resize 后布局滞后一帧。
2026-10-26 23:04:25 +08:00
TermiNexus ad6f0f68a2 chore(boot): GOP 显示模式改用 22
同时精简 GOP 初始化处的冗余注释。bootx64.efi 为编译产物,已停止跟踪,
需要时用 build.py --bootloader 重编。
2026-10-26 22:41:52 +08:00
TermiNexus ca448eee98 chore(build): 移除 VPUI64 动态库并调整构建入口
- 删除 Libs/VPUI64(linker.ld / project.vpj / vpui64.vp),同步 README
- viperc 路径改到 ViperC/__vpcbuild__/output
- 新增 --nokernel(显式 --kernel 优先,且与 --kernel-only 互斥)
- 未编内核时的提示改为「跳过内核编译」
2026-10-26 22:41:47 +08:00