diff --git a/.gitignore b/.gitignore index 813ef6d..1b7978a 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ ViperTemplateProject/ StandardTemplateProject/ # ViperOS 编译产物(每个子项目内的 output/ 和 temp/) +**/.tpv_build/ **/output/ **/temp/ **/*.deps.json diff --git a/Apps/Gargantua/main.vp b/Apps/Gargantua/main.vp index 2b758da..70988ad 100644 --- a/Apps/Gargantua/main.vp +++ b/Apps/Gargantua/main.vp @@ -25,9 +25,9 @@ YIELD_ROWS: t.CDefine = 4 V3_POOL_SIZE: t.CDefine = 8192 V3_POOL_BYTES: t.CDefine = V3_POOL_SIZE * 24 + 512 -_v3_mem: t.CArray[t.CUInt8T, V3_POOL_BYTES] +_v3_mem: t.CArray[uint8, V3_POOL_BYTES] _v3_pool: memhub.MemPool | t.CPtr -_fb_mem: t.CArray[t.CUInt32T, GW * GH] +_fb_mem: t.CArray[uint32, GW * GH] class V3: x: t.CFloat64T @@ -35,7 +35,7 @@ class V3: z: t.CFloat64T def __new__() -> 'V3' | t.CPtr: - return t.CVoid(t.CUInt64T(_v3_pool.alloc(24)), t.CPtr) + return t.CVoid(uint64(_v3_pool.alloc(24)), t.CPtr) def __init__(self, x: t.CFloat64T, y: t.CFloat64T, z: t.CFloat64T): self.x = x @@ -124,7 +124,7 @@ def hash3(x: t.CFloat64T, y: t.CFloat64T, z: t.CFloat64T) -> t.CFloat64T: def stars(d: V3 | t.CPtr) -> V3 | t.CPtr: col: V3 | t.CPtr = V3(0.0, 0.0, 0.0) - i: t.CInt = 0 + i: int = 0 while i < 3: s: t.CFloat64T = 80.0 + t.CFloat64T(i) * 90.0 px: t.CFloat64T = d.x * s @@ -185,7 +185,7 @@ def trace(dir_v: V3 | t.CPtr, gT: t.CFloat64T) -> V3 | t.CPtr: T: t.CFloat64T = 1.0 col: V3 | t.CPtr = V3(0.0, 0.0, 0.0) - i: t.CInt = 0 + i: int = 0 while i < MAX_STEPS: r2: t.CFloat64T = pos.dot(pos) r: t.CFloat64T = vm.sqrt(r2) @@ -238,7 +238,7 @@ def trace(dir_v: V3 | t.CPtr, gT: t.CFloat64T) -> V3 | t.CPtr: i += 1 return col -def shade_pixel(px: t.CInt, py: t.CInt, gT: t.CFloat64T) -> t.CUInt32T: +def shade_pixel(px: int, py: int, gT: t.CFloat64T) -> uint32: aspect: t.CFloat64T = GW_F / GH_F sx: t.CFloat64T = (2.0 * (t.CFloat64T(px) + 0.5) / GW_F - 1.0) * aspect * FOVF sy: t.CFloat64T = (1.0 - 2.0 * (t.CFloat64T(py) + 0.5) / GH_F) * FOVF @@ -252,13 +252,13 @@ def shade_pixel(px: t.CInt, py: t.CInt, gT: t.CFloat64T) -> t.CUInt32T: c.x = vm.pow(c.x, 1.0 / 2.2) c.y = vm.pow(c.y, 1.0 / 2.2) c.z = vm.pow(c.z, 1.0 / 2.2) - R: t.CInt = t.CInt(clmp(c.x, 0.0, 1.0) * 255.0) - G: t.CInt = t.CInt(clmp(c.y, 0.0, 1.0) * 255.0) - B: t.CInt = t.CInt(clmp(c.z, 0.0, 1.0) * 255.0) - return t.CUInt32T((R << 16) | (G << 8) | B) + R: int = int(clmp(c.x, 0.0, 1.0) * 255.0) + G: int = int(clmp(c.y, 0.0, 1.0) * 255.0) + B: int = int(clmp(c.z, 0.0, 1.0) * 255.0) + return uint32((R << 16) | (G << 8) | B) @c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) -def _start() -> t.CInt | t.CExport: +def _start() -> int | t.CExport: global _v3_pool _v3_pool = memhub.MemPool(c.Addr(_v3_mem), V3_POOL_BYTES) setup_camera() @@ -266,7 +266,7 @@ def _start() -> t.CInt | t.CExport: root: vpui.Tk = vpui.Tk() root.title("Gargantua") root.set_style(window.STYLE_WIN7) - root.bg_color = t.CUInt32T(0x000000) + root.bg_color = uint32(0x000000) master: vpui.Tk | t.CPtr = c.Addr(root) canvas: vpui.FBCanvas = vpui.FBCanvas(master, GW, GH) @@ -279,33 +279,33 @@ def _start() -> t.CInt | t.CExport: root.geometry(100, 30, GW, GH + 32) gT: t.CFloat64T = 0.0 - rendered: t.CInt = 0 + rendered: int = 0 evt: window.InputEvent while window.is_active(root.win_id): - result: t.CInt = window.poll_event(c.Addr(evt)) + result: int = window.poll_event(c.Addr(evt)) if result != 0: if evt.type == window.EVENT_TYPE_PING: window.flush(root.win_id) elif evt.type == window.EVENT_TYPE_RESIZE: - sz: t.CInt = window.get_win_size(root.win_id) - new_w: t.CInt = sz >> 16 - new_h: t.CInt = sz & 0xFFFF + sz: int = window.get_win_size(root.win_id) + new_w: int = sz >> 16 + new_h: int = sz & 0xFFFF canvas.set_fb(fb, new_w, new_h) if rendered == 0: - y: t.CInt = 0 + y: int = 0 while y < GH: - x: t.CInt = 0 + x: int = 0 while x < GW: - pixel: t.CUInt32T = shade_pixel(x, y, gT) + pixel: uint32 = shade_pixel(x, y, gT) fb[y * GW + x] = pixel x += 1 y += 1 if y % YIELD_ROWS == 0: root.redraw() process.yield_cpu() - result2: t.CInt = window.poll_event(c.Addr(evt)) + result2: int = window.poll_event(c.Addr(evt)) if result2 != 0: if evt.type == window.EVENT_TYPE_PING: window.flush(root.win_id) diff --git a/Apps/HelloWorld/main.vp b/Apps/HelloWorld/main.vp index 99a33df..5dc02f1 100644 --- a/Apps/HelloWorld/main.vp +++ b/Apps/HelloWorld/main.vp @@ -1,53 +1,53 @@ -import vpsdk.vpui as vpui -import vpsdk.window as window -import vpsdk.process as process -import vpsdk.dynlib as dynlib -import vpsdk.stdlib as stdlib -import vpsdk.stdio as stdio -from stdint import * -import t, c - -@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) -def _start() -> t.CInt | t.CExport: - base: t.CUInt64T = dynlib.load_so("/LIBS/SLOG.SO") - if base != 0: - dynlib.so_call1("log_info", "Hello from dynamic library!") - - root: vpui.Tk = vpui.Tk() - root.title("Input Demo") - root.set_style(window.STYLE_WIN7) - root.geometry(290, 30, 300, 200) - root.bg_color = t.CUInt32T(0x1E1E32) - master: vpui.Tk | t.CPtr = c.Addr(root) - - entry: vpui.Entry = vpui.Entry(master, 260, 28) - root.pack(0, vpui.PACK_TOP, vpui.FILL_X, 0, 20, 10) - result: vpui.Label = vpui.Label(master, "", t.CUInt32T(0x00FF00)) - root.pack(1, vpui.PACK_BOTTOM, 0, 0, 0, 10) - - def _on_submit() -> t.CInt: - text: t.CConst | str = entry.get() - result.config(text) - entry.delete(0, -1) - return 0 - - lbl: vpui.Label = vpui.Label(master, "Name:", 0xFFFFFFFF) - root.pack(2, vpui.PACK_TOP, 0, 0, 20, 0) - btn: vpui.Button = vpui.Button(master, 100, 36, "Submit", c.Addr(_on_submit)) - root.pack(3, vpui.PACK_TOP, 0, 0, 0, 10) - - root2: vpui.Tk = vpui.Tk() - root2.title("Test No-Resp") - root2.set_style(window.STYLE_WIN10) - root2.geometry(200, 50, 300, 150) - root2.bg_color = t.CUInt32T(0x1E1E32) - master2: vpui.Tk | t.CPtr = c.Addr(root2) - - lbl2: vpui.Label = vpui.Label(master2, "This window will NOT respond!", 0xFFFFFFFF) - lbl2.place(10, 10) - - root2.update() - - root.mainloop() - process.exit(0) - return 0 +import vpsdk.vpui as vpui +import vpsdk.window as window +import vpsdk.process as process +import vpsdk.dynlib as dynlib +import vpsdk.stdlib as stdlib +import vpsdk.stdio as stdio +from stdint import * +import t, c + +@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) +def _start() -> int | t.CExport: + base: uint64 = dynlib.load_so("/LIBS/SLOG.SO") + if base != 0: + dynlib.so_call1("log_info", "Hello from dynamic library!") + + root: vpui.Tk = vpui.Tk() + root.title("Input Demo") + root.set_style(window.STYLE_WIN7) + root.geometry(290, 30, 300, 200) + root.bg_color = uint32(0x1E1E32) + master: vpui.Tk | t.CPtr = c.Addr(root) + + entry: vpui.Entry = vpui.Entry(master, 260, 28) + root.pack(0, vpui.PACK_TOP, vpui.FILL_X, 0, 20, 10) + result: vpui.Label = vpui.Label(master, "", uint32(0x00FF00)) + root.pack(1, vpui.PACK_BOTTOM, 0, 0, 0, 10) + + def _on_submit() -> int: + text: t.CConst | str = entry.get() + result.config(text) + entry.delete(0, -1) + return 0 + + lbl: vpui.Label = vpui.Label(master, "Name:", 0xFFFFFFFF) + root.pack(2, vpui.PACK_TOP, 0, 0, 20, 0) + btn: vpui.Button = vpui.Button(master, 100, 36, "Submit", c.Addr(_on_submit)) + root.pack(3, vpui.PACK_TOP, 0, 0, 0, 10) + + root2: vpui.Tk = vpui.Tk() + root2.title("Test No-Resp") + root2.set_style(window.STYLE_WIN10) + root2.geometry(200, 50, 300, 150) + root2.bg_color = uint32(0x1E1E32) + master2: vpui.Tk | t.CPtr = c.Addr(root2) + + lbl2: vpui.Label = vpui.Label(master2, "This window will NOT respond!", 0xFFFFFFFF) + lbl2.place(10, 10) + + root2.update() + + root.mainloop() + process.exit(0) + return 0 diff --git a/Apps/Scene3D/gfx.vp b/Apps/Scene3D/gfx.vp index e89591b..a19c719 100644 --- a/Apps/Scene3D/gfx.vp +++ b/Apps/Scene3D/gfx.vp @@ -1,305 +1,305 @@ -from stdint import * -import vipermath -import string -import t, c - - -PI: t.CDefine = float(3.14159265358979323846) - -SPHERE_SLICES: t.CDefine = (24 * 1) -SPHERE_STACKS: t.CDefine = (16 * 1) -SIN_WAVE_GRID: t.CDefine = (40 * 1) - -def COLOR_RGB(r: int, g: int, b: int) -> t.CInline | t.CInt: - return (255 << 24) | (r << 16) | (g << 8) | (b) - -@t.Object -class Vec3: - x: float - y: float - z: float - def __init__(self, x: float, y: float, z: float): - self.x = x - self.y = y - self.z = z - def Sub(self, b: 'Vec3') -> 'Vec3': - return Vec3(self.x - b.x, self.y - b.y, self.z - b.z) - def Cross(self, b: 'Vec3') -> 'Vec3': - return Vec3(self.y * b.z - self.z * b.y, self.z * b.x - self.x * b.z, self.x * b.y - self.y * b.x) - def Dot(self, b: 'Vec3') -> float: - return self.x * b.x + self.y * b.y + self.z * b.z - def Norm(self) -> 'Vec3': - l = vipermath.sqrtf(self.Dot(self)) - return Vec3(self.x / l, self.y / l, self.z / l) - -class Mat4: - m: t.CArray[t.CArray[float, 4], 4] - -def Mat4_Identity() -> Mat4: - m: Mat4 = Mat4() - string.memset(c.Addr(m), 0, Mat4.__sizeof__()) - m.m[0][0] = 1; m.m[1][1] = 1; m.m[2][2] = 1; m.m[3][3] = 1 - return m - -def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4: - res: Mat4 = Mat4() - string.memset(c.Addr(res), 0, Mat4.__sizeof__()) - for i in range(4): - for j in range(4): - for k in range(4): - res.m[i][j] += a.m[i][k] * b.m[k][j] - return res - -def Mat4_MulVec(m: Mat4, v: Vec3) -> Vec3: - x: float = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] - y: float = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] - z: float = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] - w: float = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] - if w != 0: - x /= w; y /= w; z /= w - return Vec3(x, y, z) - -def Mat4_Perspective(fov: float, aspect: float, zn: float, zf: float) -> Mat4: - m: Mat4 = Mat4() - string.memset(c.Addr(m), 0, Mat4.__sizeof__()) - f: float = float(1.0) / vipermath.tanf(fov / float(2.0)) - m.m[0][0] = f / aspect; m.m[1][1] = f - m.m[2][2] = zf / (zn - zf); m.m[2][3] = (zf * zn) / (zn - zf); m.m[3][2] = -1 - return m - -def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4: - zaxis: Vec3 = eye.Sub(target).Norm() - xaxis: Vec3 = up.Cross(zaxis).Norm() - yaxis: Vec3 = zaxis.Cross(xaxis) - m: Mat4 = Mat4_Identity() - m.m[0][0]=xaxis.x; m.m[0][1]=xaxis.y; m.m[0][2]=xaxis.z; m.m[0][3]= -xaxis.Dot(eye) - m.m[1][0]=yaxis.x; m.m[1][1]=yaxis.y; m.m[1][2]=yaxis.z; m.m[1][3]= -yaxis.Dot(eye) - m.m[2][0]=zaxis.x; m.m[2][1]=zaxis.y; m.m[2][2]=zaxis.z; m.m[2][3]= -zaxis.Dot(eye) - m.m[3][3] = 1 - return m - -def Mat4_Translate(x: float, y: float, z: float) -> Mat4: - m: Mat4 = Mat4_Identity() - m.m[0][3] = x; m.m[1][3] = y; m.m[2][3] = z - return m - -def Mat4_RotateY(a: float) -> Mat4: - m: Mat4 = Mat4_Identity() - m.m[0][0] = vipermath.cosf(a); m.m[0][2] = vipermath.sinf(a) - m.m[2][0] = -vipermath.sinf(a); m.m[2][2] = vipermath.cosf(a) - return m - - -@t.Object -class Surface: - fb: UINT32PTR - zb: float | t.CPtr - w: int - h: int - def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): - self.fb = fb - self.zb = zb - self.w = w - self.h = h - -@t.Object -class Renderer: - _fb: UINT32PTR - _zb: float | t.CPtr - _w: int - _h: int - - def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): - self._fb = fb - self._zb = zb - self._w = w - self._h = h - - def Clear(self, color: t.CUInt32T): - fb: UINT32PTR = self._fb - zb: float | t.CPtr = self._zb - size: int = self._w * self._h - for i in range(size): - fb[i] = color - zb[i] = float(1.0) - - def DrawLine2D(self, x0: int, y0: int, x1: int, y1: int, col: t.CUInt32T): - fb: UINT32PTR = self._fb - w: int = self._w; h: int = self._h - dx: int = abs(x1-x0); dy: int = abs(y1-y0) - sx: int = 1 if x0 < x1 else -1; sy: int = 1 if y0 < y1 else -1 - err: int = dx - dy - while True: - if x0 >= 0 and x0 < w and y0 >= 0 and y0 < h: fb[y0 * w + x0] = col - if x0 == x1 and y0 == y1: break - e2: int = 2 * err - if e2 > -dy: err -= dy; x0 += sx - if e2 < dx: err += dx; y0 += sy - - def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: t.CUInt32T): - if v0.z < float(0.0) or v1.z < float(0.0) or v2.z < float(0.0): return - if (v0.x > float(10.0) or v0.x < float(-10.0) or v0.y > float(10.0) or v0.y < float(-10.0) or - v1.x > float(10.0) or v1.x < float(-10.0) or v1.y > float(10.0) or v1.y < float(-10.0) or - v2.x > float(10.0) or v2.x < float(-10.0) or v2.y > float(10.0) or v2.y < float(-10.0)): return - - fb: UINT32PTR = self._fb - zb: float | t.CPtr = self._zb - w: int = self._w - h: int = self._h - - sx0: float = (v0.x + float(1.0)) * float(0.5) * w; sy0: float = (float(1.0) - v0.y) * float(0.5) * h - sx1: float = (v1.x + float(1.0)) * float(0.5) * w; sy1: float = (float(1.0) - v1.y) * float(0.5) * h - sx2: float = (v2.x + float(1.0)) * float(0.5) * w; sy2: float = (float(1.0) - v2.y) * float(0.5) * h - - minX: int = max(0, int(vipermath.floorf(min(min(sx0, sx1), sx2)))) - maxX: int = min(w - 1, int(vipermath.ceilf(max(max(sx0, sx1), sx2)))) - minY: int = max(0, int(vipermath.floorf(min(min(sy0, sy1), sy2)))) - maxY: int = min(h - 1, int(vipermath.ceilf(max(max(sy0, sy1), sy2)))) - - dx12: float = sx1 - sx2; dy12: float = sy1 - sy2 - dx02: float = sx0 - sx2; dy02: float = sy0 - sy2 - denom: float = dx12 * dy02 - dy12 * dx02 - if denom < float(0.001) and denom > float(-0.001): return - invDenom: float = float(1.0) / denom - - row_dxP_start: float = float(minX) - sx2 - for y in range(minY, maxY + 1): - dyP: float = float(y) - sy2 - dxP: float = row_dxP_start - row_base: int = y * w - for x in range(minX, maxX + 1): - w0: float = (dx12 * dyP - dy12 * dxP) * invDenom - w1: float = (dxP * dy02 - dyP * dx02) * invDenom - w2: float = float(1.0) - w0 - w1 - if w0 >= 0 and w1 >= 0 and w2 >= 0: - z: float = w0 * v0.z + w1 * v1.z + w2 * v2.z - idx: int = row_base + x - if z < zb[idx]: - zb[idx] = z - fb[idx] = col - dxP += float(1.0) - - def DrawGlowDot(self, x: float, y: float, radius: float, core_col: t.CUInt32T, intensity: float): - fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h - r: int = int(radius) + 4 - ix: int = int(x); iy: int = int(y) - for dy in range(-r, r + 1): - py: int = iy + dy - if py < 0 or py >= h: continue - for dx in range(-r, r + 1): - px: int = ix + dx - if px < 0 or px >= w: continue - dist: float = vipermath.sqrtf(float(dx*dx + dy*dy)) - if dist < radius: - self.BlendPixel(px, py, core_col, intensity) - elif dist < float(r): - fade: float = 1.0 - (dist - radius) / 4.0 - self.BlendPixel(px, py, core_col, intensity * fade * 0.5) - - def BlendPixel(self, x: int, y: int, col: t.CUInt32T, alpha: float): - if alpha <= 0.0: return - fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h - if x < 0 or x >= w or y < 0 or y >= h: return - - idx: int = y * w + x - bg: t.CUInt32T = fb[idx] - bg_b: int = bg & 0xFF; bg_g: int = (bg >> 8) & 0xFF; bg_r: int = (bg >> 16) & 0xFF - f_b: int = col & 0xFF; f_g: int = (col >> 8) & 0xFF; f_r: int = (col >> 16) & 0xFF - - a: int = int(alpha * 255.0) - inv_a: int = 255 - a - nr: int = (f_r * a + bg_r * inv_a) >> 8 - ng: int = (f_g * a + bg_g * inv_a) >> 8 - nb: int = (f_b * a + bg_b * inv_a) >> 8 - - fb[idx] = COLOR_RGB(255 if (nr > 255) else nr, - 255 if (ng > 255) else ng, - 255 if (nb > 255) else nb) - - -@t.Object -class Scene3D: - renderer: Renderer - - def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): - self.renderer = Renderer(fb, zb, w, h) - - def Render(self, time: float): - rw: int = self.renderer._w - rh: int = self.renderer._h - self.renderer.Clear(COLOR_RGB(15, 15, 25)) - - yaw: float = float(45.0) * PI / float(180.0); pitch: float = float(45.0) * PI / float(180.0); radius: float = float(10.0) - eye: Vec3 = Vec3(radius*vipermath.cosf(pitch)*vipermath.cosf(yaw), radius*vipermath.sinf(pitch), radius*vipermath.cosf(pitch)*vipermath.sinf(yaw)) - target: Vec3 = Vec3(0, 0, 0); up: Vec3 = Vec3(0, 1, 0) - view: Mat4 = Mat4_LookAt(eye, target, up) - proj: Mat4 = Mat4_Perspective(PI / float(3.0), float(rw)/float(rh), float(0.1), float(100.0)) - vp: Mat4 = Mat4_Mul(proj, view) - - cubeX: float = float(-3.5) - cubeMVP: Mat4 = Mat4_Mul(vp, Mat4_Translate(cubeX, 0, 0)) - self._DrawCube(cubeMVP, COLOR_RGB(180, 180, 180)) - - colors: t.CArray[t.CUInt32T, 4] = [COLOR_RGB(255,50,50), COLOR_RGB(50,50,255), COLOR_RGB(255,255,50), COLOR_RGB(50,255,255)] - for i in range(4): - a: float = time * float(1.5) + i * (PI / float(2.0)); r: float = float(3.0) - pos: Vec3 = Vec3(vipermath.cosf(a) * r + cubeX, 0, vipermath.sinf(a) * r) - sphereMVP: Mat4 = Mat4_Mul(vp, Mat4_Translate(pos.x, pos.y, pos.z)) - self._DrawSphere(sphereMVP, Vec3(0,0,0), float(0.5), colors[i]) - - self._Draw3DSinWave(vp, Vec3(float(3.5), 0, 0), time) - - self.renderer.DrawLine2D(50, rh - 150, rw - 50, rh - 150, COLOR_RGB(80, 80, 80)) - self.renderer.DrawLine2D(50, rh - 50, 50, rh - 250, COLOR_RGB(80, 80, 80)) - wave_shift: float = time * float(2.0) - prev_x: int = 50; prev_y: int = rh - 150 - int(vipermath.sinf(0 - wave_shift) * float(100.0)) - for i in range(1, rw - 100): - tr: float = float(i) / float(rw-100) * float(4.0) * PI - cx: int = 50 + i; cy: int = rh - 150 - int(vipermath.sinf(tr - wave_shift) * float(100.0)) - self.renderer.DrawLine2D(prev_x, prev_y, cx, cy, COLOR_RGB(0, 255, 100)) - prev_x = cx; prev_y = cy - - def _DrawCube(self, mvp: Mat4, col: t.CUInt32T): - v: t.CArray[Vec3, 8] = [ - Vec3(-1, -1, -1), Vec3(-1, -1, 1), Vec3(-1, 1, -1), Vec3(-1, 1, 1), - Vec3( 1, -1, -1), Vec3( 1, -1, 1), Vec3( 1, 1, -1), Vec3( 1, 1, 1) - ] - for i in range(8): v[i] = Mat4_MulVec(mvp, v[i]) - faces: t.CArray[t.CArray[int, 3], 12] = [ - [0, 2, 1], [1, 2, 3], [4, 1, 5], [4, 0, 1], [6, 3, 2], [6, 7, 3], - [4, 6, 0], [0, 6, 2], [5, 7, 4], [4, 7, 6], [1, 3, 5], [5, 3, 7] - ] - for i in range(12): self.renderer.DrawTriangle(v[faces[i][0]], v[faces[i][1]], v[faces[i][2]], col) - - def _DrawSphere(self, mvp: Mat4, center: Vec3, radius: float, col: t.CUInt32T): - step_pi: float = PI / SPHERE_STACKS; step_2pi: float = float(2.0) * PI / SPHERE_SLICES - for i in range(SPHERE_STACKS): - for j in range(SPHERE_SLICES): - theta1: float = i * step_pi; theta2: float = (i + 1) * step_pi - phi1: float = j * step_2pi; phi2: float = (j + 1) * step_2pi - v: t.CArray[Vec3, 4] - v[0] = Vec3(center.x+radius*vipermath.sinf(theta1)*vipermath.cosf(phi1), center.y+radius*vipermath.cosf(theta1), center.z+radius*vipermath.sinf(theta1)*vipermath.sinf(phi1)) - v[1] = Vec3(center.x+radius*vipermath.sinf(theta1)*vipermath.cosf(phi2), center.y+radius*vipermath.cosf(theta1), center.z+radius*vipermath.sinf(theta1)*vipermath.sinf(phi2)) - v[2] = Vec3(center.x+radius*vipermath.sinf(theta2)*vipermath.cosf(phi1), center.y+radius*vipermath.cosf(theta2), center.z+radius*vipermath.sinf(theta2)*vipermath.sinf(phi1)) - v[3] = Vec3(center.x+radius*vipermath.sinf(theta2)*vipermath.cosf(phi2), center.y+radius*vipermath.cosf(theta2), center.z+radius*vipermath.sinf(theta2)*vipermath.sinf(phi2)) - for k in range(4): v[k] = Mat4_MulVec(mvp, v[k]) - self.renderer.DrawTriangle(v[0], v[1], v[2], col) - self.renderer.DrawTriangle(v[1], v[3], v[2], col) - - def _Draw3DSinWave(self, vp: Mat4, pos: Vec3, time: float): - _range: float = float(2.0) * PI; step: float = _range / SIN_WAVE_GRID; scale: float = float(0.5) - mvp: Mat4 = Mat4_Mul(vp, Mat4_Mul(Mat4_Translate(pos.x, pos.y, pos.z), Mat4_RotateY(time * float(1.0)))) - for i in range(SIN_WAVE_GRID): - for j in range(SIN_WAVE_GRID): - x0: float = -PI + i * step; z0 = -PI + j * step; x1: float = x0 + step; z1 = z0 + step - y00: float = vipermath.sinf(x0) * vipermath.cosf(z0) * scale; y10: float = vipermath.sinf(x1) * vipermath.cosf(z0) * scale - y01: float = vipermath.sinf(x0) * vipermath.cosf(z1) * scale; y11: float = vipermath.sinf(x1) * vipermath.cosf(z1) * scale - - t1: float = (y00 / scale + float(1.0)) * float(0.5); r1: int = int(50 + 205 * t1); g1: int = int(80 + 120 * vipermath.sinf(t1 * PI)); b1: int = int(255 - 205 * t1) - col1: t.CUInt32T = COLOR_RGB(255 if (r1 > 255) else (0 if (r1 < 0) else r1), 255 if (g1 > 255) else (0 if (g1 < 0) else g1), 255 if (b1 > 255) else (0 if (b1 < 0) else b1)) - t2: float = (y11 / scale + float(1.0)) * float(0.5); r2: int = int(50 + 205 * t2); g2: int = int(80 + 120 * vipermath.sinf(t2 * PI)); b2: int = int(255 - 205 * t2) - col2: t.CUInt32T = COLOR_RGB(255 if (r2 > 255) else (0 if (r2 < 0) else r2), 255 if (g2 > 255) else (0 if (g2 < 0) else g2), 255 if (b2 > 255) else (0 if (b2 < 0) else b2)) - - v00: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y00, z0)); v10: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y10, z0)) - v01: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y01, z1)); v11: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y11, z1)) - self.renderer.DrawTriangle(v00, v10, v11, col1); self.renderer.DrawTriangle(v00, v11, v01, col2) +from stdint import * +import vipermath +import string +import t, c + + +PI: t.CDefine = float(3.14159265358979323846) + +SPHERE_SLICES: t.CDefine = (24 * 1) +SPHERE_STACKS: t.CDefine = (16 * 1) +SIN_WAVE_GRID: t.CDefine = (40 * 1) + +def COLOR_RGB(r: int, g: int, b: int) -> t.CInline | int: + return (255 << 24) | (r << 16) | (g << 8) | (b) + +@t.Object +class Vec3: + x: float + y: float + z: float + def __init__(self, x: float, y: float, z: float): + self.x = x + self.y = y + self.z = z + def Sub(self, b: 'Vec3') -> 'Vec3': + return Vec3(self.x - b.x, self.y - b.y, self.z - b.z) + def Cross(self, b: 'Vec3') -> 'Vec3': + return Vec3(self.y * b.z - self.z * b.y, self.z * b.x - self.x * b.z, self.x * b.y - self.y * b.x) + def Dot(self, b: 'Vec3') -> float: + return self.x * b.x + self.y * b.y + self.z * b.z + def Norm(self) -> 'Vec3': + l = vipermath.sqrtf(self.Dot(self)) + return Vec3(self.x / l, self.y / l, self.z / l) + +class Mat4: + m: t.CArray[t.CArray[float, 4], 4] + +def Mat4_Identity() -> Mat4: + m: Mat4 = Mat4() + string.memset(c.Addr(m), 0, Mat4.__sizeof__()) + m.m[0][0] = 1; m.m[1][1] = 1; m.m[2][2] = 1; m.m[3][3] = 1 + return m + +def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4: + res: Mat4 = Mat4() + string.memset(c.Addr(res), 0, Mat4.__sizeof__()) + for i in range(4): + for j in range(4): + for k in range(4): + res.m[i][j] += a.m[i][k] * b.m[k][j] + return res + +def Mat4_MulVec(m: Mat4, v: Vec3) -> Vec3: + x: float = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] + y: float = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] + z: float = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] + w: float = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] + if w != 0: + x /= w; y /= w; z /= w + return Vec3(x, y, z) + +def Mat4_Perspective(fov: float, aspect: float, zn: float, zf: float) -> Mat4: + m: Mat4 = Mat4() + string.memset(c.Addr(m), 0, Mat4.__sizeof__()) + f: float = float(1.0) / vipermath.tanf(fov / float(2.0)) + m.m[0][0] = f / aspect; m.m[1][1] = f + m.m[2][2] = zf / (zn - zf); m.m[2][3] = (zf * zn) / (zn - zf); m.m[3][2] = -1 + return m + +def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4: + zaxis: Vec3 = eye.Sub(target).Norm() + xaxis: Vec3 = up.Cross(zaxis).Norm() + yaxis: Vec3 = zaxis.Cross(xaxis) + m: Mat4 = Mat4_Identity() + m.m[0][0]=xaxis.x; m.m[0][1]=xaxis.y; m.m[0][2]=xaxis.z; m.m[0][3]= -xaxis.Dot(eye) + m.m[1][0]=yaxis.x; m.m[1][1]=yaxis.y; m.m[1][2]=yaxis.z; m.m[1][3]= -yaxis.Dot(eye) + m.m[2][0]=zaxis.x; m.m[2][1]=zaxis.y; m.m[2][2]=zaxis.z; m.m[2][3]= -zaxis.Dot(eye) + m.m[3][3] = 1 + return m + +def Mat4_Translate(x: float, y: float, z: float) -> Mat4: + m: Mat4 = Mat4_Identity() + m.m[0][3] = x; m.m[1][3] = y; m.m[2][3] = z + return m + +def Mat4_RotateY(a: float) -> Mat4: + m: Mat4 = Mat4_Identity() + m.m[0][0] = vipermath.cosf(a); m.m[0][2] = vipermath.sinf(a) + m.m[2][0] = -vipermath.sinf(a); m.m[2][2] = vipermath.cosf(a) + return m + + +@t.Object +class Surface: + fb: UINT32PTR + zb: float | t.CPtr + w: int + h: int + def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): + self.fb = fb + self.zb = zb + self.w = w + self.h = h + +@t.Object +class Renderer: + _fb: UINT32PTR + _zb: float | t.CPtr + _w: int + _h: int + + def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): + self._fb = fb + self._zb = zb + self._w = w + self._h = h + + def Clear(self, color: uint32): + fb: UINT32PTR = self._fb + zb: float | t.CPtr = self._zb + size: int = self._w * self._h + for i in range(size): + fb[i] = color + zb[i] = float(1.0) + + def DrawLine2D(self, x0: int, y0: int, x1: int, y1: int, col: uint32): + fb: UINT32PTR = self._fb + w: int = self._w; h: int = self._h + dx: int = abs(x1-x0); dy: int = abs(y1-y0) + sx: int = 1 if x0 < x1 else -1; sy: int = 1 if y0 < y1 else -1 + err: int = dx - dy + while True: + if x0 >= 0 and x0 < w and y0 >= 0 and y0 < h: fb[y0 * w + x0] = col + if x0 == x1 and y0 == y1: break + e2: int = 2 * err + if e2 > -dy: err -= dy; x0 += sx + if e2 < dx: err += dx; y0 += sy + + def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: uint32): + if v0.z < float(0.0) or v1.z < float(0.0) or v2.z < float(0.0): return + if (v0.x > float(10.0) or v0.x < float(-10.0) or v0.y > float(10.0) or v0.y < float(-10.0) or + v1.x > float(10.0) or v1.x < float(-10.0) or v1.y > float(10.0) or v1.y < float(-10.0) or + v2.x > float(10.0) or v2.x < float(-10.0) or v2.y > float(10.0) or v2.y < float(-10.0)): return + + fb: UINT32PTR = self._fb + zb: float | t.CPtr = self._zb + w: int = self._w + h: int = self._h + + sx0: float = (v0.x + float(1.0)) * float(0.5) * w; sy0: float = (float(1.0) - v0.y) * float(0.5) * h + sx1: float = (v1.x + float(1.0)) * float(0.5) * w; sy1: float = (float(1.0) - v1.y) * float(0.5) * h + sx2: float = (v2.x + float(1.0)) * float(0.5) * w; sy2: float = (float(1.0) - v2.y) * float(0.5) * h + + minX: int = max(0, int(vipermath.floorf(min(min(sx0, sx1), sx2)))) + maxX: int = min(w - 1, int(vipermath.ceilf(max(max(sx0, sx1), sx2)))) + minY: int = max(0, int(vipermath.floorf(min(min(sy0, sy1), sy2)))) + maxY: int = min(h - 1, int(vipermath.ceilf(max(max(sy0, sy1), sy2)))) + + dx12: float = sx1 - sx2; dy12: float = sy1 - sy2 + dx02: float = sx0 - sx2; dy02: float = sy0 - sy2 + denom: float = dx12 * dy02 - dy12 * dx02 + if denom < float(0.001) and denom > float(-0.001): return + invDenom: float = float(1.0) / denom + + row_dxP_start: float = float(minX) - sx2 + for y in range(minY, maxY + 1): + dyP: float = float(y) - sy2 + dxP: float = row_dxP_start + row_base: int = y * w + for x in range(minX, maxX + 1): + w0: float = (dx12 * dyP - dy12 * dxP) * invDenom + w1: float = (dxP * dy02 - dyP * dx02) * invDenom + w2: float = float(1.0) - w0 - w1 + if w0 >= 0 and w1 >= 0 and w2 >= 0: + z: float = w0 * v0.z + w1 * v1.z + w2 * v2.z + idx: int = row_base + x + if z < zb[idx]: + zb[idx] = z + fb[idx] = col + dxP += float(1.0) + + def DrawGlowDot(self, x: float, y: float, radius: float, core_col: uint32, intensity: float): + fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h + r: int = int(radius) + 4 + ix: int = int(x); iy: int = int(y) + for dy in range(-r, r + 1): + py: int = iy + dy + if py < 0 or py >= h: continue + for dx in range(-r, r + 1): + px: int = ix + dx + if px < 0 or px >= w: continue + dist: float = vipermath.sqrtf(float(dx*dx + dy*dy)) + if dist < radius: + self.BlendPixel(px, py, core_col, intensity) + elif dist < float(r): + fade: float = 1.0 - (dist - radius) / 4.0 + self.BlendPixel(px, py, core_col, intensity * fade * 0.5) + + def BlendPixel(self, x: int, y: int, col: uint32, alpha: float): + if alpha <= 0.0: return + fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h + if x < 0 or x >= w or y < 0 or y >= h: return + + idx: int = y * w + x + bg: uint32 = fb[idx] + bg_b: int = bg & 0xFF; bg_g: int = (bg >> 8) & 0xFF; bg_r: int = (bg >> 16) & 0xFF + f_b: int = col & 0xFF; f_g: int = (col >> 8) & 0xFF; f_r: int = (col >> 16) & 0xFF + + a: int = int(alpha * 255.0) + inv_a: int = 255 - a + nr: int = (f_r * a + bg_r * inv_a) >> 8 + ng: int = (f_g * a + bg_g * inv_a) >> 8 + nb: int = (f_b * a + bg_b * inv_a) >> 8 + + fb[idx] = COLOR_RGB(255 if (nr > 255) else nr, + 255 if (ng > 255) else ng, + 255 if (nb > 255) else nb) + + +@t.Object +class Scene3D: + renderer: Renderer + + def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int): + self.renderer = Renderer(fb, zb, w, h) + + def Render(self, time: float): + rw: int = self.renderer._w + rh: int = self.renderer._h + self.renderer.Clear(COLOR_RGB(15, 15, 25)) + + yaw: float = float(45.0) * PI / float(180.0); pitch: float = float(45.0) * PI / float(180.0); radius: float = float(10.0) + eye: Vec3 = Vec3(radius*vipermath.cosf(pitch)*vipermath.cosf(yaw), radius*vipermath.sinf(pitch), radius*vipermath.cosf(pitch)*vipermath.sinf(yaw)) + target: Vec3 = Vec3(0, 0, 0); up: Vec3 = Vec3(0, 1, 0) + view: Mat4 = Mat4_LookAt(eye, target, up) + proj: Mat4 = Mat4_Perspective(PI / float(3.0), float(rw)/float(rh), float(0.1), float(100.0)) + vp: Mat4 = Mat4_Mul(proj, view) + + cubeX: float = float(-3.5) + cubeMVP: Mat4 = Mat4_Mul(vp, Mat4_Translate(cubeX, 0, 0)) + self._DrawCube(cubeMVP, COLOR_RGB(180, 180, 180)) + + colors: t.CArray[uint32, 4] = [COLOR_RGB(255,50,50), COLOR_RGB(50,50,255), COLOR_RGB(255,255,50), COLOR_RGB(50,255,255)] + for i in range(4): + a: float = time * float(1.5) + i * (PI / float(2.0)); r: float = float(3.0) + pos: Vec3 = Vec3(vipermath.cosf(a) * r + cubeX, 0, vipermath.sinf(a) * r) + sphereMVP: Mat4 = Mat4_Mul(vp, Mat4_Translate(pos.x, pos.y, pos.z)) + self._DrawSphere(sphereMVP, Vec3(0,0,0), float(0.5), colors[i]) + + self._Draw3DSinWave(vp, Vec3(float(3.5), 0, 0), time) + + self.renderer.DrawLine2D(50, rh - 150, rw - 50, rh - 150, COLOR_RGB(80, 80, 80)) + self.renderer.DrawLine2D(50, rh - 50, 50, rh - 250, COLOR_RGB(80, 80, 80)) + wave_shift: float = time * float(2.0) + prev_x: int = 50; prev_y: int = rh - 150 - int(vipermath.sinf(0 - wave_shift) * float(100.0)) + for i in range(1, rw - 100): + tr: float = float(i) / float(rw-100) * float(4.0) * PI + cx: int = 50 + i; cy: int = rh - 150 - int(vipermath.sinf(tr - wave_shift) * float(100.0)) + self.renderer.DrawLine2D(prev_x, prev_y, cx, cy, COLOR_RGB(0, 255, 100)) + prev_x = cx; prev_y = cy + + def _DrawCube(self, mvp: Mat4, col: uint32): + v: t.CArray[Vec3, 8] = [ + Vec3(-1, -1, -1), Vec3(-1, -1, 1), Vec3(-1, 1, -1), Vec3(-1, 1, 1), + Vec3( 1, -1, -1), Vec3( 1, -1, 1), Vec3( 1, 1, -1), Vec3( 1, 1, 1) + ] + for i in range(8): v[i] = Mat4_MulVec(mvp, v[i]) + faces: t.CArray[t.CArray[int, 3], 12] = [ + [0, 2, 1], [1, 2, 3], [4, 1, 5], [4, 0, 1], [6, 3, 2], [6, 7, 3], + [4, 6, 0], [0, 6, 2], [5, 7, 4], [4, 7, 6], [1, 3, 5], [5, 3, 7] + ] + for i in range(12): self.renderer.DrawTriangle(v[faces[i][0]], v[faces[i][1]], v[faces[i][2]], col) + + def _DrawSphere(self, mvp: Mat4, center: Vec3, radius: float, col: uint32): + step_pi: float = PI / SPHERE_STACKS; step_2pi: float = float(2.0) * PI / SPHERE_SLICES + for i in range(SPHERE_STACKS): + for j in range(SPHERE_SLICES): + theta1: float = i * step_pi; theta2: float = (i + 1) * step_pi + phi1: float = j * step_2pi; phi2: float = (j + 1) * step_2pi + v: t.CArray[Vec3, 4] + v[0] = Vec3(center.x+radius*vipermath.sinf(theta1)*vipermath.cosf(phi1), center.y+radius*vipermath.cosf(theta1), center.z+radius*vipermath.sinf(theta1)*vipermath.sinf(phi1)) + v[1] = Vec3(center.x+radius*vipermath.sinf(theta1)*vipermath.cosf(phi2), center.y+radius*vipermath.cosf(theta1), center.z+radius*vipermath.sinf(theta1)*vipermath.sinf(phi2)) + v[2] = Vec3(center.x+radius*vipermath.sinf(theta2)*vipermath.cosf(phi1), center.y+radius*vipermath.cosf(theta2), center.z+radius*vipermath.sinf(theta2)*vipermath.sinf(phi1)) + v[3] = Vec3(center.x+radius*vipermath.sinf(theta2)*vipermath.cosf(phi2), center.y+radius*vipermath.cosf(theta2), center.z+radius*vipermath.sinf(theta2)*vipermath.sinf(phi2)) + for k in range(4): v[k] = Mat4_MulVec(mvp, v[k]) + self.renderer.DrawTriangle(v[0], v[1], v[2], col) + self.renderer.DrawTriangle(v[1], v[3], v[2], col) + + def _Draw3DSinWave(self, vp: Mat4, pos: Vec3, time: float): + _range: float = float(2.0) * PI; step: float = _range / SIN_WAVE_GRID; scale: float = float(0.5) + mvp: Mat4 = Mat4_Mul(vp, Mat4_Mul(Mat4_Translate(pos.x, pos.y, pos.z), Mat4_RotateY(time * float(1.0)))) + for i in range(SIN_WAVE_GRID): + for j in range(SIN_WAVE_GRID): + x0: float = -PI + i * step; z0 = -PI + j * step; x1: float = x0 + step; z1 = z0 + step + y00: float = vipermath.sinf(x0) * vipermath.cosf(z0) * scale; y10: float = vipermath.sinf(x1) * vipermath.cosf(z0) * scale + y01: float = vipermath.sinf(x0) * vipermath.cosf(z1) * scale; y11: float = vipermath.sinf(x1) * vipermath.cosf(z1) * scale + + t1: float = (y00 / scale + float(1.0)) * float(0.5); r1: int = int(50 + 205 * t1); g1: int = int(80 + 120 * vipermath.sinf(t1 * PI)); b1: int = int(255 - 205 * t1) + col1: uint32 = COLOR_RGB(255 if (r1 > 255) else (0 if (r1 < 0) else r1), 255 if (g1 > 255) else (0 if (g1 < 0) else g1), 255 if (b1 > 255) else (0 if (b1 < 0) else b1)) + t2: float = (y11 / scale + float(1.0)) * float(0.5); r2: int = int(50 + 205 * t2); g2: int = int(80 + 120 * vipermath.sinf(t2 * PI)); b2: int = int(255 - 205 * t2) + col2: uint32 = COLOR_RGB(255 if (r2 > 255) else (0 if (r2 < 0) else r2), 255 if (g2 > 255) else (0 if (g2 < 0) else g2), 255 if (b2 > 255) else (0 if (b2 < 0) else b2)) + + v00: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y00, z0)); v10: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y10, z0)) + v01: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y01, z1)); v11: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y11, z1)) + self.renderer.DrawTriangle(v00, v10, v11, col1); self.renderer.DrawTriangle(v00, v11, v01, col2) diff --git a/Apps/Scene3D/main.vp b/Apps/Scene3D/main.vp index 26e5b67..66c14cc 100644 --- a/Apps/Scene3D/main.vp +++ b/Apps/Scene3D/main.vp @@ -1,66 +1,66 @@ -import vpsdk.window as window -import vpsdk.process as process -import vpsdk.vpui as vpui -import vpsdk.stdlib as stdlib -import vpsdk.stdio as stdio -import viperstring as string -import vipermath -from stdint import * -import gfx -import t, c - -SCENE_W: t.CDefine = 640 -SCENE_H: t.CDefine = 360 - -_zbuf_mem: t.CArray[t.CUInt8T, SCENE_W * SCENE_H * 8] -_fb_mem: t.CArray[t.CUInt32T, SCENE_W * SCENE_H] - -_root_ptr: vpui.Tk | t.CPtr -_canvas_ptr: vpui.FBCanvas | t.CPtr -_s3d_ptr: gfx.Scene3D | t.CPtr -_time_val: float = float(0.0) - -def _render_thread(arg: t.CVoid | t.CPtr) -> t.CVoid: - root: vpui.Tk | t.CPtr = _root_ptr - canvas: vpui.FBCanvas | t.CPtr = _canvas_ptr - s3d: gfx.Scene3D | t.CPtr = _s3d_ptr - while root.winfo_exists(): - s3d.Render(_time_val) - _time_val += float(0.02) - root.update() - process.yield_cpu() - -@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) -def _start() -> t.CInt | t.CExport: - root: vpui.Tk = vpui.Tk() - root.title("3D Scene") - root.set_style(window.STYLE_WIN11) - root.bg_color = t.CUInt32T(0x0F0F19) - master: vpui.Tk | t.CPtr = c.Addr(root) - - canvas: vpui.FBCanvas = vpui.FBCanvas(master, SCENE_W, SCENE_H) - root.pack(0, vpui.PACK_TOP, vpui.FILL_BOTH, 1, 0, 0) - - zbuf: float | t.CPtr = t.CVoid(c.Addr(_zbuf_mem), t.CPtr) - string.memset(zbuf, 0, SCENE_W * SCENE_H * 8) - - fb: UINT32PTR = c.Addr(_fb_mem) - string.memset(fb, 0, SCENE_W * SCENE_H * 4) - canvas.set_fb(fb, SCENE_W, SCENE_H) - - s3d: gfx.Scene3D = gfx.Scene3D(fb, zbuf, SCENE_W, SCENE_H) - - root.geometry(100, 30, SCENE_W, SCENE_H + 32) - - global _root_ptr, _canvas_ptr, _s3d_ptr - - _root_ptr = c.Addr(root) - _canvas_ptr = c.Addr(canvas) - _s3d_ptr = c.Addr(s3d) - - process.thread_create(_render_thread, None) - - root.mainloop() - - process.exit(0) - return 0 +import vpsdk.window as window +import vpsdk.process as process +import vpsdk.vpui as vpui +import vpsdk.stdlib as stdlib +import vpsdk.stdio as stdio +import viperstring as string +import vipermath +from stdint import * +import gfx +import t, c + +SCENE_W: t.CDefine = 640 +SCENE_H: t.CDefine = 360 + +_zbuf_mem: t.CArray[uint8, SCENE_W * SCENE_H * 8] +_fb_mem: t.CArray[uint32, SCENE_W * SCENE_H] + +_root_ptr: vpui.Tk | t.CPtr +_canvas_ptr: vpui.FBCanvas | t.CPtr +_s3d_ptr: gfx.Scene3D | t.CPtr +_time_val: float = float(0.0) + +def _render_thread(arg: t.CPtr) -> t.CVoid: + root: vpui.Tk | t.CPtr = _root_ptr + canvas: vpui.FBCanvas | t.CPtr = _canvas_ptr + s3d: gfx.Scene3D | t.CPtr = _s3d_ptr + while root.winfo_exists(): + s3d.Render(_time_val) + _time_val += float(0.02) + root.update() + process.yield_cpu() + +@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) +def _start() -> int | t.CExport: + root: vpui.Tk = vpui.Tk() + root.title("3D Scene") + root.set_style(window.STYLE_WIN11) + root.bg_color = uint32(0x0F0F19) + master: vpui.Tk | t.CPtr = c.Addr(root) + + canvas: vpui.FBCanvas = vpui.FBCanvas(master, SCENE_W, SCENE_H) + root.pack(0, vpui.PACK_TOP, vpui.FILL_BOTH, 1, 0, 0) + + zbuf: float | t.CPtr = t.CVoid(c.Addr(_zbuf_mem), t.CPtr) + string.memset(zbuf, 0, SCENE_W * SCENE_H * 8) + + fb: UINT32PTR = c.Addr(_fb_mem) + string.memset(fb, 0, SCENE_W * SCENE_H * 4) + canvas.set_fb(fb, SCENE_W, SCENE_H) + + s3d: gfx.Scene3D = gfx.Scene3D(fb, zbuf, SCENE_W, SCENE_H) + + root.geometry(100, 30, SCENE_W, SCENE_H + 32) + + global _root_ptr, _canvas_ptr, _s3d_ptr + + _root_ptr = c.Addr(root) + _canvas_ptr = c.Addr(canvas) + _s3d_ptr = c.Addr(s3d) + + process.thread_create(_render_thread, None) + + root.mainloop() + + process.exit(0) + return 0 diff --git a/Apps/Terminal/main.vp b/Apps/Terminal/main.vp index d04a98e..637cd4c 100644 --- a/Apps/Terminal/main.vp +++ b/Apps/Terminal/main.vp @@ -1,327 +1,327 @@ -import vpsdk.vpui as vpui -import vpsdk.window as window -import vpsdk.process as process -import vpsdk.fs as fs -import vpsdk.syscall as _syscall -import vpsdk.stdlib as stdlib -import vpsdk.stdio as stdio -import string -import viperlib -from stdint import * -import t, c - -@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) -def _start() -> t.CInt | t.CExport: - root: vpui.Tk = vpui.Tk() - root.title("Terminal") - root.set_style(window.STYLE_WIN7) - root.geometry(80, 30, 640, 480) - root.bg_color = t.CUInt32T(0x0C0C0C) - master: vpui.Tk | t.CPtr = c.Addr(root) - - def _sdbg(msg: str): - _syscall._syscall1(t.CUInt64T(18), t.CUInt64T(msg)) - - _sdbg("[term] start\n") - - _cwd: t.CArray[t.CChar, 64] - _cwd[0] = 47 - for i in range(1, 64): - _cwd[i] = 0 - - sbar: vpui.Scrollbar = vpui.Scrollbar(master, 16, 446, vpui.VERTICAL) - root.pack(0, vpui.PACK_RIGHT, vpui.FILL_Y, 0, 0, 0) - - term: vpui.Text = vpui.Text(master, 624, 446) - root.pack(1, vpui.PACK_LEFT, vpui.FILL_BOTH, 1, 0, 0) - term.insert("ViperOS Terminal v1.1") - term.insert("Type 'help' for commands.") - term.insert("") - - term.yscrollbar = t.CType(sbar, vpui.Widget, t.CPtr) - - def _on_scroll(): - act: t.CInt = sbar.action - if act == 1: - term.scroll_offset -= 1 - elif act == 2: - term.scroll_offset += 1 - elif act == 3: - vis: t.CInt = term._visible_lines() - term.scroll_offset -= vis - elif act == 4: - vis2: t.CInt = term._visible_lines() - term.scroll_offset += vis2 - elif act == 5: - aval: t.CInt = sbar.action_value - if term.line_count > 0: - term.scroll_offset = aval * term.line_count / 1000 - vis3: t.CInt = term._visible_lines() - max_off: t.CInt = term.line_count - vis3 - if max_off < 0: max_off = 0 - if term.scroll_offset < 0: term.scroll_offset = 0 - if term.scroll_offset > max_off: term.scroll_offset = max_off - term._update_scrollbar() - - sbar.command = c.Addr(_on_scroll) - - def _startswith(s: str, prefix: str) -> t.CInt: - plen: t.CSizeT = string.strlen(prefix) - if string.strncmp(s, prefix, plen) == 0: - return 1 - return 0 - - def _build_path(out: str, out_size: t.CInt, rel: str): - if c.Deref(rel) == 47: - string.strncpy(out, rel, out_size - 1) - else: - i: t.CInt = 0 - for i in range(63): - ch: t.CChar = _cwd[i] - c.DerefAs(out + i, ch) - if ch == 0: break - cwd_len: t.CInt = i - if cwd_len > 0 and _cwd[cwd_len - 1] != 47: - c.DerefAs(out + cwd_len, t.CChar(47)) - cwd_len += 1 - j: t.CInt = 0 - for j in range(out_size - 1 - cwd_len): - ch2: t.CChar = c.Deref(rel + j) - c.DerefAs(out + cwd_len + j, ch2) - if ch2 == 0: break - c.DerefAs(out + out_size - 1, t.CChar(0)) - - def _print_dir_entry(name: str, is_dir: t.CInt): - buf: t.CArray[t.CChar, 80] - j: t.CInt = 0 - for j in range(78): - ch: t.CChar = c.Deref(name + j) - buf[j] = ch - if ch == 0: break - if is_dir and j < 78: - buf[j] = 47 - j += 1 - buf[j] = 0 - term.insert_ptr(c.Addr(buf[0])) - - def _cmd_cd(path: str): - if path is None or c.Deref(path) == 0: - _cwd[0] = 47 - for i in range(1, 64): - _cwd[i] = 0 - return - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - dd: t.CInt = fs.opendir(c.Addr(full[0])) - if dd < 0: - term.insert("Error: dir not found") - return - fs.closedir(dd) - string.strncpy(c.Addr(_cwd[0]), c.Addr(full[0]), 63) - _cwd[63] = 0 - - def _cmd_ls(): - dd: t.CInt = fs.opendir(c.Addr(_cwd[0])) - if dd < 0: - term.insert("Error: cannot open dir") - return - info: t.CArray[t.CChar, 320] - string.memset(c.Addr(info[0]), 0, 320) - while True: - result: t.CInt = fs.readdir(dd, c.Addr(info[0])) - if result != 0: break - attr_val: t.CUInt8T = t.CUInt8T(c.Deref(c.Addr(info[4]))) - name_off: t.CInt = 16 - name_ptr: str = c.Addr(info[name_off]) - if c.Deref(name_ptr) == 0: break - if c.Deref(name_ptr) == 46: - if c.Deref(name_ptr + 1) == 0: - string.memset(c.Addr(info[0]), 0, 320) - continue - if c.Deref(name_ptr + 1) == 46 and c.Deref(name_ptr + 2) == 0: - string.memset(c.Addr(info[0]), 0, 320) - continue - if (attr_val & 0x10) != 0: - _print_dir_entry(name_ptr, 1) - else: - _print_dir_entry(name_ptr, 0) - string.memset(c.Addr(info[0]), 0, 320) - fs.closedir(dd) - - def _cmd_cat(path: str): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_RDONLY) - if fd < 0: - term.insert("Error: file not found") - return - buf: t.CArray[t.CChar, 80] - while True: - string.memset(c.Addr(buf[0]), 0, 80) - n: t.CInt = fs.read(fd, c.Addr(buf[0]), 78) - if n <= 0: break - if n > 78: n = 78 - buf[n] = 0 - term.insert_ptr(c.Addr(buf[0])) - fs.close(fd) - - def _cmd_mkdir(path: str): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - result: t.CInt = fs.mkdir(c.Addr(full[0])) - if result < 0: - term.insert("Error: mkdir failed") - else: - term.insert("Directory created") - - def _cmd_rm(path: str): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - result: t.CInt = fs.remove(c.Addr(full[0])) - if result < 0: - term.insert("Error: remove failed") - else: - term.insert("Removed") - - def _cmd_touch(path: str): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_WRONLY | fs.O_CREAT) - if fd < 0: - term.insert("Error: touch failed") - return - fs.close(fd) - term.insert("File created") - - def _cmd_sysinfo(): - term.insert("ViperOS v1.0 (x86_64)") - term.insert("Framebuffer: 32bpp") - term.insert("Compiler: TransPyC") - - def _cmd_hexdump(path: str): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_RDONLY) - if fd < 0: - term.insert("Error: file not found") - return - offset: t.CInt = 0 - buf: t.CArray[t.CChar, 16] - while True: - string.memset(c.Addr(buf[0]), 0, 16) - n: t.CInt = fs.read(fd, c.Addr(buf[0]), 16) - if n <= 0: break - if n > 16: n = 16 - line: t.CArray[t.CChar, 80] - string.memset(c.Addr(line[0]), 0, 80) - viperlib.snprintf(c.Addr(line[0]), 80, "%08x: ", offset) - pos: t.CInt = 10 - j: t.CInt = 0 - for j in range(16): - if j < n: - ub: t.CUInt32T = t.CUInt32T(buf[j]) & 0xFF - hi: t.CInt = t.CInt(ub >> 4) - lo: t.CInt = t.CInt(ub & 0xF) - if hi < 10: - line[pos] = t.CChar(48 + hi) - else: - line[pos] = t.CChar(65 + hi - 10) - pos += 1 - if lo < 10: - line[pos] = t.CChar(48 + lo) - else: - line[pos] = t.CChar(65 + lo - 10) - pos += 1 - else: - line[pos] = 32 - pos += 1 - line[pos] = 32 - pos += 1 - line[pos] = 32 - pos += 1 - if j == 7: - line[pos] = 32 - pos += 1 - line[pos] = 124 - pos += 1 - for j in range(n): - b2: t.CUInt32T = t.CUInt32T(buf[j]) & 0xFF - if b2 >= 32 and b2 < 127: - line[pos] = t.CChar(b2) - else: - line[pos] = 46 - pos += 1 - line[pos] = 0 - term.insert_ptr(c.Addr(line[0])) - offset += n - fs.close(fd) - - def _cmd_run(path: str, blocking: t.CInt): - full: t.CArray[t.CChar, 256] - _build_path(c.Addr(full[0]), 256, path) - pid: t.CInt = process.spawn(c.Addr(full[0]), blocking) - if pid < 0: - term.insert("Error: cannot spawn") - elif blocking: - term.insert("Process exited") - else: - msg: t.CArray[t.CChar, 32] - viperlib.snprintf(c.Addr(msg[0]), 32, "Spawned pid=%d", pid) - term.insert_ptr(c.Addr(msg[0])) - - def _on_command() -> t.CInt: - _sdbg("[cmd] enter\n") - text: str = term.get() - _sdbg("[cmd] text=") - _sdbg(text) - _sdbg("\n") - if _startswith(text, "echo "): - term.insert_ptr(text + 5) - elif string.samestr(text, "echo"): - pass - elif string.samestr(text, "clear"): - term.delete(0, -1) - elif string.samestr(text, "help"): - term.insert("File: ls cd cat pwd mkdir rm touch") - term.insert("Sys: ver about sysinfo reboot") - term.insert("Util: echo clear help hexdump run runb") - elif string.samestr(text, "ver"): - term.insert("ViperOS Terminal v1.1") - elif string.samestr(text, "about"): - term.insert("ViperOS - A tiny OS in Viper lang") - elif string.samestr(text, "pwd"): - term.insert_ptr(c.Addr(_cwd[0])) - elif string.samestr(text, "ls"): - _cmd_ls() - elif string.samestr(text, "cd"): - _cmd_cd("") - elif _startswith(text, "cd "): - _cmd_cd(text + 3) - elif _startswith(text, "cat "): - _cmd_cat(text + 4) - elif _startswith(text, "mkdir "): - _cmd_mkdir(text + 6) - elif _startswith(text, "rm "): - _cmd_rm(text + 3) - elif _startswith(text, "touch "): - _cmd_touch(text + 6) - elif string.samestr(text, "sysinfo"): - _cmd_sysinfo() - elif string.samestr(text, "reboot"): - process.exit(0) - elif _startswith(text, "hexdump "): - _cmd_hexdump(text + 8) - elif _startswith(text, "run "): - _cmd_run(text + 4, 0) - elif _startswith(text, "runb "): - _cmd_run(text + 5, 1) - else: - if text is not None and c.Deref(text) != 0: - term.insert("Unknown command. Type 'help'.") - return 0 - - term.on_command = c.Addr(_on_command) - - root.mainloop() - process.exit(0) - return 0 +import vpsdk.vpui as vpui +import vpsdk.window as window +import vpsdk.process as process +import vpsdk.fs as fs +import vpsdk.syscall as _syscall +import vpsdk.stdlib as stdlib +import vpsdk.stdio as stdio +import string +import viperlib +from stdint import * +import t, c + +@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) +def _start() -> int | t.CExport: + root: vpui.Tk = vpui.Tk() + root.title("Terminal") + root.set_style(window.STYLE_WIN7) + root.geometry(80, 30, 640, 480) + root.bg_color = uint32(0x0C0C0C) + master: vpui.Tk | t.CPtr = c.Addr(root) + + def _sdbg(msg: str): + _syscall._syscall1(uint64(18), uint64(msg)) + + _sdbg("[term] start\n") + + _cwd: t.CArray[t.CChar, 64] + _cwd[0] = 47 + for i in range(1, 64): + _cwd[i] = 0 + + sbar: vpui.Scrollbar = vpui.Scrollbar(master, 16, 446, vpui.VERTICAL) + root.pack(0, vpui.PACK_RIGHT, vpui.FILL_Y, 0, 0, 0) + + term: vpui.Text = vpui.Text(master, 624, 446) + root.pack(1, vpui.PACK_LEFT, vpui.FILL_BOTH, 1, 0, 0) + term.insert("ViperOS Terminal v1.1") + term.insert("Type 'help' for commands.") + term.insert("") + + term.yscrollbar = t.CType(sbar, vpui.Widget, t.CPtr) + + def _on_scroll(): + act: int = sbar.action + if act == 1: + term.scroll_offset -= 1 + elif act == 2: + term.scroll_offset += 1 + elif act == 3: + vis: int = term._visible_lines() + term.scroll_offset -= vis + elif act == 4: + vis2: int = term._visible_lines() + term.scroll_offset += vis2 + elif act == 5: + aval: int = sbar.action_value + if term.line_count > 0: + term.scroll_offset = aval * term.line_count / 1000 + vis3: int = term._visible_lines() + max_off: int = term.line_count - vis3 + if max_off < 0: max_off = 0 + if term.scroll_offset < 0: term.scroll_offset = 0 + if term.scroll_offset > max_off: term.scroll_offset = max_off + term._update_scrollbar() + + sbar.command = c.Addr(_on_scroll) + + def _startswith(s: str, prefix: str) -> int: + plen: t.CSizeT = string.strlen(prefix) + if string.strncmp(s, prefix, plen) == 0: + return 1 + return 0 + + def _build_path(out: str, out_size: int, rel: str): + if c.Deref(rel) == 47: + string.strncpy(out, rel, out_size - 1) + else: + i: int = 0 + for i in range(63): + ch: t.CChar = _cwd[i] + c.DerefAs(out + i, ch) + if ch == 0: break + cwd_len: int = i + if cwd_len > 0 and _cwd[cwd_len - 1] != 47: + c.DerefAs(out + cwd_len, t.CChar(47)) + cwd_len += 1 + j: int = 0 + for j in range(out_size - 1 - cwd_len): + ch2: t.CChar = c.Deref(rel + j) + c.DerefAs(out + cwd_len + j, ch2) + if ch2 == 0: break + c.DerefAs(out + out_size - 1, t.CChar(0)) + + def _print_dir_entry(name: str, is_dir: int): + buf: t.CArray[t.CChar, 80] + j: int = 0 + for j in range(78): + ch: t.CChar = c.Deref(name + j) + buf[j] = ch + if ch == 0: break + if is_dir and j < 78: + buf[j] = 47 + j += 1 + buf[j] = 0 + term.insert_ptr(c.Addr(buf[0])) + + def _cmd_cd(path: str): + if path is None or c.Deref(path) == 0: + _cwd[0] = 47 + for i in range(1, 64): + _cwd[i] = 0 + return + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + dd: int = fs.opendir(c.Addr(full[0])) + if dd < 0: + term.insert("Error: dir not found") + return + fs.closedir(dd) + string.strncpy(c.Addr(_cwd[0]), c.Addr(full[0]), 63) + _cwd[63] = 0 + + def _cmd_ls(): + dd: int = fs.opendir(c.Addr(_cwd[0])) + if dd < 0: + term.insert("Error: cannot open dir") + return + info: t.CArray[t.CChar, 320] + string.memset(c.Addr(info[0]), 0, 320) + while True: + result: int = fs.readdir(dd, c.Addr(info[0])) + if result != 0: break + attr_val: uint8 = uint8(c.Deref(c.Addr(info[4]))) + name_off: int = 16 + name_ptr: str = c.Addr(info[name_off]) + if c.Deref(name_ptr) == 0: break + if c.Deref(name_ptr) == 46: + if c.Deref(name_ptr + 1) == 0: + string.memset(c.Addr(info[0]), 0, 320) + continue + if c.Deref(name_ptr + 1) == 46 and c.Deref(name_ptr + 2) == 0: + string.memset(c.Addr(info[0]), 0, 320) + continue + if (attr_val & 0x10) != 0: + _print_dir_entry(name_ptr, 1) + else: + _print_dir_entry(name_ptr, 0) + string.memset(c.Addr(info[0]), 0, 320) + fs.closedir(dd) + + def _cmd_cat(path: str): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + fd: int = fs.open(c.Addr(full[0]), fs.O_RDONLY) + if fd < 0: + term.insert("Error: file not found") + return + buf: t.CArray[t.CChar, 80] + while True: + string.memset(c.Addr(buf[0]), 0, 80) + n: int = fs.read(fd, c.Addr(buf[0]), 78) + if n <= 0: break + if n > 78: n = 78 + buf[n] = 0 + term.insert_ptr(c.Addr(buf[0])) + fs.close(fd) + + def _cmd_mkdir(path: str): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + result: int = fs.mkdir(c.Addr(full[0])) + if result < 0: + term.insert("Error: mkdir failed") + else: + term.insert("Directory created") + + def _cmd_rm(path: str): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + result: int = fs.remove(c.Addr(full[0])) + if result < 0: + term.insert("Error: remove failed") + else: + term.insert("Removed") + + def _cmd_touch(path: str): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + fd: int = fs.open(c.Addr(full[0]), fs.O_WRONLY | fs.O_CREAT) + if fd < 0: + term.insert("Error: touch failed") + return + fs.close(fd) + term.insert("File created") + + def _cmd_sysinfo(): + term.insert("ViperOS v1.0 (x86_64)") + term.insert("Framebuffer: 32bpp") + term.insert("Compiler: TransPyC") + + def _cmd_hexdump(path: str): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + fd: int = fs.open(c.Addr(full[0]), fs.O_RDONLY) + if fd < 0: + term.insert("Error: file not found") + return + offset: int = 0 + buf: t.CArray[t.CChar, 16] + while True: + string.memset(c.Addr(buf[0]), 0, 16) + n: int = fs.read(fd, c.Addr(buf[0]), 16) + if n <= 0: break + if n > 16: n = 16 + line: t.CArray[t.CChar, 80] + string.memset(c.Addr(line[0]), 0, 80) + viperlib.snprintf(c.Addr(line[0]), 80, "%08x: ", offset) + pos: int = 10 + j: int = 0 + for j in range(16): + if j < n: + ub: uint32 = uint32(buf[j]) & 0xFF + hi: int = int(ub >> 4) + lo: int = int(ub & 0xF) + if hi < 10: + line[pos] = t.CChar(48 + hi) + else: + line[pos] = t.CChar(65 + hi - 10) + pos += 1 + if lo < 10: + line[pos] = t.CChar(48 + lo) + else: + line[pos] = t.CChar(65 + lo - 10) + pos += 1 + else: + line[pos] = 32 + pos += 1 + line[pos] = 32 + pos += 1 + line[pos] = 32 + pos += 1 + if j == 7: + line[pos] = 32 + pos += 1 + line[pos] = 124 + pos += 1 + for j in range(n): + b2: uint32 = uint32(buf[j]) & 0xFF + if b2 >= 32 and b2 < 127: + line[pos] = t.CChar(b2) + else: + line[pos] = 46 + pos += 1 + line[pos] = 0 + term.insert_ptr(c.Addr(line[0])) + offset += n + fs.close(fd) + + def _cmd_run(path: str, blocking: int): + full: t.CArray[t.CChar, 256] + _build_path(c.Addr(full[0]), 256, path) + pid: int = process.spawn(c.Addr(full[0]), blocking) + if pid < 0: + term.insert("Error: cannot spawn") + elif blocking: + term.insert("Process exited") + else: + msg: t.CArray[t.CChar, 32] + viperlib.snprintf(c.Addr(msg[0]), 32, "Spawned pid=%d", pid) + term.insert_ptr(c.Addr(msg[0])) + + def _on_command() -> int: + _sdbg("[cmd] enter\n") + text: str = term.get() + _sdbg("[cmd] text=") + _sdbg(text) + _sdbg("\n") + if _startswith(text, "echo "): + term.insert_ptr(text + 5) + elif string.samestr(text, "echo"): + pass + elif string.samestr(text, "clear"): + term.delete(0, -1) + elif string.samestr(text, "help"): + term.insert("File: ls cd cat pwd mkdir rm touch") + term.insert("Sys: ver about sysinfo reboot") + term.insert("Util: echo clear help hexdump run runb") + elif string.samestr(text, "ver"): + term.insert("ViperOS Terminal v1.1") + elif string.samestr(text, "about"): + term.insert("ViperOS - A tiny OS in Viper lang") + elif string.samestr(text, "pwd"): + term.insert_ptr(c.Addr(_cwd[0])) + elif string.samestr(text, "ls"): + _cmd_ls() + elif string.samestr(text, "cd"): + _cmd_cd("") + elif _startswith(text, "cd "): + _cmd_cd(text + 3) + elif _startswith(text, "cat "): + _cmd_cat(text + 4) + elif _startswith(text, "mkdir "): + _cmd_mkdir(text + 6) + elif _startswith(text, "rm "): + _cmd_rm(text + 3) + elif _startswith(text, "touch "): + _cmd_touch(text + 6) + elif string.samestr(text, "sysinfo"): + _cmd_sysinfo() + elif string.samestr(text, "reboot"): + process.exit(0) + elif _startswith(text, "hexdump "): + _cmd_hexdump(text + 8) + elif _startswith(text, "run "): + _cmd_run(text + 4, 0) + elif _startswith(text, "runb "): + _cmd_run(text + 5, 1) + else: + if text is not None and c.Deref(text) != 0: + term.insert("Unknown command. Type 'help'.") + return 0 + + term.on_command = c.Addr(_on_command) + + root.mainloop() + process.exit(0) + return 0 diff --git a/Libs/SerialLogger/serial_logger.vp b/Libs/SerialLogger/serial_logger.vp index 235a4a7..98c796c 100644 --- a/Libs/SerialLogger/serial_logger.vp +++ b/Libs/SerialLogger/serial_logger.vp @@ -1,12 +1,12 @@ -import vpsdk.syscall as syscall -import t, c - -def log_info(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CExport: - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T("[SerialLogger] ")) - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T(msg)) - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T("\n")) - -def log_warn(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CExport: - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T("[SerialLogger:WARN] ")) - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T(msg)) - syscall._syscall1(t.CUInt64T(syscall.SERIAL_PUTS), t.CUInt64T("\n")) +import vpsdk.syscall as syscall +import t, c + +def log_info(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CExport: + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64("[SerialLogger] ")) + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64(msg)) + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64("\n")) + +def log_warn(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CExport: + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64("[SerialLogger:WARN] ")) + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64(msg)) + syscall._syscall1(uint64(syscall.SERIAL_PUTS), uint64("\n")) diff --git a/Libs/VPUI64/vpui64.vp b/Libs/VPUI64/vpui64.vp index ff544f1..955b9b9 100644 --- a/Libs/VPUI64/vpui64.vp +++ b/Libs/VPUI64/vpui64.vp @@ -1,80 +1,80 @@ -import t -import vpsdk.syscall as syscall - -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr - -def color_rgb(r: t.CUInt8T, g: t.CUInt8T, b: t.CUInt8T) -> t.CUInt32T: - return t.CUInt32T(r) | (t.CUInt32T(g) << 8) | (t.CUInt32T(b) << 16) - -def get_winbuf(win_id: t.CInt) -> UINT32PTR: - return t.CVoid(syscall._syscall2(t.CUInt64T(syscall.GET_WINBUF), t.CUInt64T(win_id), 0), t.CPtr) - -def win_flush(win_id: t.CInt) -> t.CVoid: - syscall._syscall2(t.CUInt64T(syscall.WIN_FLUSH), t.CUInt64T(win_id), 0) - -def draw_pixel(buf: UINT32PTR, bw: t.CInt, x: t.CInt, y: t.CInt, color: t.CUInt32T) -> t.CVoid | t.CExport: - if x < 0 or y < 0: return - buf[y * bw + x] = color - -def draw_line(buf: UINT32PTR, bw: t.CInt, x0: t.CInt, y0: t.CInt, x1: t.CInt, y1: t.CInt, color: t.CUInt32T) -> t.CVoid | t.CExport: - dx: t.CInt = x1 - x0 - dy: t.CInt = y1 - y0 - sx: t.CInt = 1 - sy: t.CInt = 1 - if dx < 0: - dx = -dx - sx = -1 - if dy < 0: - dy = -dy - sy = -1 - err: t.CInt = dx - dy - while True: - if x0 >= 0 and y0 >= 0: - buf[y0 * bw + x0] = color - if x0 == x1 and y0 == y1: - break - e2: t.CInt = 2 * err - if e2 > -dy: - err -= dy - x0 += sx - if e2 < dx: - err += dx - y0 += sy - -def draw_rect(buf: UINT32PTR, bw: t.CInt, rx: t.CInt, ry: t.CInt, rw: t.CInt, rh: t.CInt, color: t.CUInt32T) -> t.CVoid | t.CExport: - draw_line(buf, bw, rx, ry, rx + rw - 1, ry, color) - draw_line(buf, bw, rx + rw - 1, ry, rx + rw - 1, ry + rh - 1, color) - draw_line(buf, bw, rx + rw - 1, ry + rh - 1, rx, ry + rh - 1, color) - draw_line(buf, bw, rx, ry + rh - 1, rx, ry, color) - -def fill_rect(buf: UINT32PTR, bw: t.CInt, rx: t.CInt, ry: t.CInt, rw: t.CInt, rh: t.CInt, color: t.CUInt32T) -> t.CVoid | t.CExport: - if rx < 0: rw += rx; rx = 0 - if ry < 0: rh += ry; ry = 0 - if rw <= 0 or rh <= 0: return - py: t.CInt = ry - while py < ry + rh: - px: t.CInt = rx - while px < rx + rw: - buf[py * bw + px] = color - px += 1 - py += 1 - -def draw_circle(buf: UINT32PTR, bw: t.CInt, cx: t.CInt, cy: t.CInt, r: t.CInt, color: t.CUInt32T) -> t.CVoid | t.CExport: - x: t.CInt = r - y: t.CInt = 0 - d: t.CInt = 1 - r - while x >= y: - if cx + x >= 0: buf[(cy + y) * bw + cx + x] = color - if cx + y >= 0: buf[(cy + x) * bw + cx + y] = color - if cx - y >= 0: buf[(cy + x) * bw + cx - y] = color - if cx - x >= 0: buf[(cy + y) * bw + cx - x] = color - if cx - x >= 0: buf[(cy - y) * bw + cx - x] = color - if cx - y >= 0: buf[(cy - x) * bw + cx - y] = color - if cx + y >= 0: buf[(cy - x) * bw + cx + y] = color - if cx + x >= 0: buf[(cy - y) * bw + cx + x] = color - y += 1 - if d <= 0: - d += 2 * y + 1 - else: - x -= 1 - d += 2 * (y - x) + 1 +import t +import vpsdk.syscall as syscall + +UINT32PTR: t.CTypedef = uint32 | t.CPtr + +def color_rgb(r: uint8, g: uint8, b: uint8) -> uint32: + return uint32(r) | (uint32(g) << 8) | (uint32(b) << 16) + +def get_winbuf(win_id: int) -> UINT32PTR: + return t.CVoid(syscall._syscall2(uint64(syscall.GET_WINBUF), uint64(win_id), 0), t.CPtr) + +def win_flush(win_id: int) -> t.CVoid: + syscall._syscall2(uint64(syscall.WIN_FLUSH), uint64(win_id), 0) + +def draw_pixel(buf: UINT32PTR, bw: int, x: int, y: int, color: uint32) -> t.CVoid | t.CExport: + if x < 0 or y < 0: return + buf[y * bw + x] = color + +def draw_line(buf: UINT32PTR, bw: int, x0: int, y0: int, x1: int, y1: int, color: uint32) -> t.CVoid | t.CExport: + dx: int = x1 - x0 + dy: int = y1 - y0 + sx: int = 1 + sy: int = 1 + if dx < 0: + dx = -dx + sx = -1 + if dy < 0: + dy = -dy + sy = -1 + err: int = dx - dy + while True: + if x0 >= 0 and y0 >= 0: + buf[y0 * bw + x0] = color + if x0 == x1 and y0 == y1: + break + e2: int = 2 * err + if e2 > -dy: + err -= dy + x0 += sx + if e2 < dx: + err += dx + y0 += sy + +def draw_rect(buf: UINT32PTR, bw: int, rx: int, ry: int, rw: int, rh: int, color: uint32) -> t.CVoid | t.CExport: + draw_line(buf, bw, rx, ry, rx + rw - 1, ry, color) + draw_line(buf, bw, rx + rw - 1, ry, rx + rw - 1, ry + rh - 1, color) + draw_line(buf, bw, rx + rw - 1, ry + rh - 1, rx, ry + rh - 1, color) + draw_line(buf, bw, rx, ry + rh - 1, rx, ry, color) + +def fill_rect(buf: UINT32PTR, bw: int, rx: int, ry: int, rw: int, rh: int, color: uint32) -> t.CVoid | t.CExport: + if rx < 0: rw += rx; rx = 0 + if ry < 0: rh += ry; ry = 0 + if rw <= 0 or rh <= 0: return + py: int = ry + while py < ry + rh: + px: int = rx + while px < rx + rw: + buf[py * bw + px] = color + px += 1 + py += 1 + +def draw_circle(buf: UINT32PTR, bw: int, cx: int, cy: int, r: int, color: uint32) -> t.CVoid | t.CExport: + x: int = r + y: int = 0 + d: int = 1 - r + while x >= y: + if cx + x >= 0: buf[(cy + y) * bw + cx + x] = color + if cx + y >= 0: buf[(cy + x) * bw + cx + y] = color + if cx - y >= 0: buf[(cy + x) * bw + cx - y] = color + if cx - x >= 0: buf[(cy + y) * bw + cx - x] = color + if cx - x >= 0: buf[(cy - y) * bw + cx - x] = color + if cx - y >= 0: buf[(cy - x) * bw + cx - y] = color + if cx + y >= 0: buf[(cy - x) * bw + cx + y] = color + if cx + x >= 0: buf[(cy - y) * bw + cx + x] = color + y += 1 + if d <= 0: + d += 2 * y + 1 + else: + x -= 1 + d += 2 * (y - x) + 1 diff --git a/VKernel/Kernel/bootinfo.vp b/VKernel/Kernel/bootinfo.vp index ccf06c6..94ec21a 100644 --- a/VKernel/Kernel/bootinfo.vp +++ b/VKernel/Kernel/bootinfo.vp @@ -1,17 +1,17 @@ import t, c -MEMORY_TYPE_AVAILABLE: t.CUInt64T = 7 -MEMORY_TYPE_RESERVED: t.CUInt64T = 0 -MEMORY_TYPE_LOADER_CODE: t.CUInt64T = 1 -MEMORY_TYPE_LOADER_DATA: t.CUInt64T = 2 -MEMORY_TYPE_BOOT_SERVICES_CODE: t.CUInt64T = 3 -MEMORY_TYPE_BOOT_SERVICES_DATA: t.CUInt64T = 4 -MEMORY_TYPE_RUNTIME_SERVICES_CODE: t.CUInt64T = 5 -MEMORY_TYPE_RUNTIME_SERVICES_DATA: t.CUInt64T = 6 -MEMORY_TYPE_ACPI_RECLAIMABLE: t.CUInt64T = 9 -MEMORY_TYPE_ACPI_NVS: t.CUInt64T = 10 -MEMORY_TYPE_BAD_MEMORY: t.CUInt64T = 8 +MEMORY_TYPE_AVAILABLE: uint64 = 7 +MEMORY_TYPE_RESERVED: uint64 = 0 +MEMORY_TYPE_LOADER_CODE: uint64 = 1 +MEMORY_TYPE_LOADER_DATA: uint64 = 2 +MEMORY_TYPE_BOOT_SERVICES_CODE: uint64 = 3 +MEMORY_TYPE_BOOT_SERVICES_DATA: uint64 = 4 +MEMORY_TYPE_RUNTIME_SERVICES_CODE: uint64 = 5 +MEMORY_TYPE_RUNTIME_SERVICES_DATA: uint64 = 6 +MEMORY_TYPE_ACPI_RECLAIMABLE: uint64 = 9 +MEMORY_TYPE_ACPI_NVS: uint64 = 10 +MEMORY_TYPE_BAD_MEMORY: uint64 = 8 @c.Attribute(t.attr.packed) class memory_map_entry: diff --git a/VKernel/Kernel/drivers/core/cpu/apic.vp b/VKernel/Kernel/drivers/core/cpu/apic.vp index d4ce7bd..eb7b729 100644 --- a/VKernel/Kernel/drivers/core/cpu/apic.vp +++ b/VKernel/Kernel/drivers/core/cpu/apic.vp @@ -1,257 +1,261 @@ -import asm -import intr.gdt as gdt -import intr.idt as idt -import drivers.serial.uart.serial as serial -import drivers.core.cpu.cpu as cpu -import mm.mm as mm -import platform.pch.timer as timer -import viperlib -import t, c - - -IA32_APIC_BASE: t.CDefine = 0x1B -APIC_BASE_MSR_ENABLE: t.CDefine = 0x800 -APIC_BASE_ADDR_MASK: t.CDefine = 0xFFFFF000 - -LAPIC_ID: t.CDefine = 0x020 -LAPIC_VERSION: t.CDefine = 0x030 -LAPIC_TPR: t.CDefine = 0x080 -LAPIC_EOI: t.CDefine = 0x0B0 -LAPIC_LDR: t.CDefine = 0x0D0 -LAPIC_SVR: t.CDefine = 0x0F0 -LAPIC_ISR0: t.CDefine = 0x100 -LAPIC_ICR_LOW: t.CDefine = 0x300 -LAPIC_ICR_HIGH: t.CDefine = 0x310 -LAPIC_LVT_TIMER: t.CDefine = 0x320 -LAPIC_LVT_LINT0: t.CDefine = 0x350 -LAPIC_LVT_LINT1: t.CDefine = 0x360 -LAPIC_LVT_ERROR: t.CDefine = 0x370 -LAPIC_TIMER_INIT: t.CDefine = 0x380 -LAPIC_TIMER_CURRENT: t.CDefine = 0x390 -LAPIC_TIMER_DIVIDE: t.CDefine = 0x3E0 - -LAPIC_SVR_ENABLE: t.CDefine = 0x100 -LAPIC_LVT_MASKED: t.CDefine = 0x10000 -LAPIC_LVT_DELIVERY_EXTINT: t.CDefine = 0x700 -LAPIC_LVT_DELIVERY_NMI: t.CDefine = 0x400 -LAPIC_LVT_TIMER_PERIODIC: t.CDefine = 0x20000 - -LAPIC_ICR_INIT: t.CDefine = 0x500 -LAPIC_ICR_STARTUP: t.CDefine = 0x600 -LAPIC_ICR_ASSERT: t.CDefine = 0x4000 -LAPIC_ICR_DEASSERT: t.CDefine = 0x8000 -LAPIC_ICR_LEVEL: t.CDefine = 0x8000 - -MAX_CPUS: t.CDefine = 8 +import asm +import intr.gdt as gdt +import intr.idt as idt +import drivers.serial.uart.serial as serial +import drivers.core.cpu.cpu as cpu +import mm.mm as mm +import platform.pch.timer as timer +import viperlib +import t, c + + +IA32_APIC_BASE: t.CDefine = 0x1B +APIC_BASE_MSR_ENABLE: t.CDefine = 0x800 +APIC_BASE_ADDR_MASK: t.CDefine = 0xFFFFF000 + +LAPIC_ID: t.CDefine = 0x020 +LAPIC_VERSION: t.CDefine = 0x030 +LAPIC_TPR: t.CDefine = 0x080 +LAPIC_EOI: t.CDefine = 0x0B0 +LAPIC_LDR: t.CDefine = 0x0D0 +LAPIC_SVR: t.CDefine = 0x0F0 +LAPIC_ISR0: t.CDefine = 0x100 +LAPIC_ICR_LOW: t.CDefine = 0x300 +LAPIC_ICR_HIGH: t.CDefine = 0x310 +LAPIC_LVT_TIMER: t.CDefine = 0x320 +LAPIC_LVT_LINT0: t.CDefine = 0x350 +LAPIC_LVT_LINT1: t.CDefine = 0x360 +LAPIC_LVT_ERROR: t.CDefine = 0x370 +LAPIC_TIMER_INIT: t.CDefine = 0x380 +LAPIC_TIMER_CURRENT: t.CDefine = 0x390 +LAPIC_TIMER_DIVIDE: t.CDefine = 0x3E0 + +LAPIC_SVR_ENABLE: t.CDefine = 0x100 +LAPIC_LVT_MASKED: t.CDefine = 0x10000 +LAPIC_LVT_DELIVERY_EXTINT: t.CDefine = 0x700 +LAPIC_LVT_DELIVERY_NMI: t.CDefine = 0x400 +LAPIC_LVT_TIMER_PERIODIC: t.CDefine = 0x20000 + +LAPIC_ICR_INIT: t.CDefine = 0x500 +LAPIC_ICR_STARTUP: t.CDefine = 0x600 +LAPIC_ICR_ASSERT: t.CDefine = 0x4000 +LAPIC_ICR_DEASSERT: t.CDefine = 0x8000 +LAPIC_ICR_LEVEL: t.CDefine = 0x8000 + +MAX_CPUS: t.CDefine = 8 AP_TRAMPOLINE_ADDR: t.CDefine = 0x7000 - -_lapic_base: t.CUInt64T = 0 -_cpu_count: t.CUInt32T = 1 -_bsp_lapic_id: t.CUInt32T = 0 -_ap_ready: t.CUInt32T = 0 - -def read(offset: t.CUInt32T) -> t.CUInt32T: - addr: t.CUInt64T = _lapic_base + t.CUInt64T(offset) - return c.Deref(t.CUInt32T(addr, t.CPtr)) - -def write(offset: t.CUInt32T, value: t.CUInt32T): - addr: t.CUInt64T = _lapic_base + t.CUInt64T(offset) - c.Set(c.Deref(t.CUInt32T(addr, t.CPtr)), value) - -def eoi(): - write(LAPIC_EOI, 0) - -def get_id() -> t.CUInt32T: - return read(LAPIC_ID) >> 24 - -@c.Attribute(t.attr.noinline) -def init(): - global _lapic_base, _bsp_lapic_id - msr_val: t.CUInt64T = cpu.msr_read(IA32_APIC_BASE) - _lapic_base = msr_val & APIC_BASE_ADDR_MASK - cpu.msr_write(IA32_APIC_BASE, msr_val | APIC_BASE_MSR_ENABLE) - _bsp_lapic_id = read(LAPIC_ID) >> 24 - write(LAPIC_SVR, LAPIC_SVR_ENABLE | 0xFF) - write(LAPIC_TPR, 0) - write(LAPIC_LVT_TIMER, LAPIC_LVT_MASKED) - write(LAPIC_LVT_LINT0, LAPIC_LVT_DELIVERY_EXTINT) - write(LAPIC_LVT_LINT1, LAPIC_LVT_DELIVERY_NMI) - write(LAPIC_LVT_ERROR, LAPIC_LVT_MASKED) - write(LAPIC_TIMER_DIVIDE, 0x0B) - write(LAPIC_LDR, 0x01000000) - eoi() - -@c.Attribute(t.attr.noinline) -def detect_cpu_count() -> t.CUInt32T: - res: cpu.cpuid_result - cpu.cpuid(0, c.Addr(res)) - max_leaf: t.CUInt32T = res.eax - - if max_leaf >= 0x0B: - cpu.cpuid_sub(0x0B, 0, c.Addr(res)) - num_threads: t.CUInt32T = res.ebx & 0xFFFF - if num_threads > 0 and num_threads <= MAX_CPUS: - return num_threads - - cpu.cpuid(1, c.Addr(res)) - if res.edx & cpu.CPU_FEATURE_HTT: - count: t.CUInt32T = (res.ebx >> 16) & 0xFF - if count > 0 and count <= MAX_CPUS: - return count - return 1 - -def _wait_icr(): - timeout: t.CUInt32T = 1000000 - while timeout > 0: - val: t.CUInt32T = read(LAPIC_ICR_LOW) - if (val & (1 << 12)) == 0: - return - timeout -= 1 - -def _send_ipi(apic_id: t.CUInt32T, vector: t.CUInt32T, delivery_mode: t.CUInt32T): - _wait_icr() - write(LAPIC_ICR_HIGH, apic_id << 24) - write(LAPIC_ICR_LOW, vector | delivery_mode | LAPIC_ICR_LEVEL | LAPIC_ICR_ASSERT) - _wait_icr() - -def ap_entry(): - global _ap_ready - my_id: t.CUInt32T = get_id() - buf: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(buf), 64, "[AP] core %u started (lapic=%u)\n", my_id, my_id) - serial.puts(buf) - _ap_ready = 1 - while True: - asm.sti() - asm.hlt() - -_trampoline_bin: t.CArray[t.CUInt8T, 128] = [ - 0xFA, # cli - 0x31, 0xC0, # xor ax, ax - 0x8E, 0xD8, # mov ds, ax - 0x8E, 0xC0, # mov es, ax - 0x0F, 0x01, 0x16, 0x00, 0x7E, # lgdt [0x7E00] - 0x0F, 0x20, 0xC0, # mov eax, cr0 - 0x83, 0xC8, 0x01, # or eax, 1 - 0x0F, 0x22, 0xC0, # mov cr0, eax - 0xEA, 0x1A, 0x07, 0x00, 0x00, 0x08, 0x00, # jmp 0x08:0x701A - - # 32-bit 保护模式开始 - 0xB8, 0x10, 0x00, 0x00, 0x00, # mov ax, 0x10 - 0x8E, 0xD8, # mov ds, ax - 0x8E, 0xC0, # mov es, ax - 0x8E, 0xE0, # mov fs, ax - 0x8E, 0xE8, # mov gs, ax - 0x8E, 0xD0, # mov ss, ax - 0x0F, 0x20, 0xE0, # mov eax, cr4 - 0x83, 0xC8, 0x20, # or eax, 0x20 (PAE) - 0x0F, 0x22, 0xE0, # mov cr4, eax - 0x8B, 0x04, 0x25, 0x00, 0x7F, 0x00, 0x00, # mov eax, [0x7F00] - 0x0F, 0x22, 0xD8, # mov cr3, eax - 0xB9, 0x80, 0x00, 0x00, 0xC0, # mov ecx, 0xC0000080 (EFER) - 0x0F, 0x32, # rdmsr - 0x83, 0xC8, 0x00, 0x01, 0x00, 0x00, # or eax, 0x100 (LME) - 0x0F, 0x79, # wrmsr - 0x0F, 0x20, 0xC0, # mov eax, cr0 - 0x0D, 0x00, 0x00, 0x00, 0x80, # or eax, 0x80000000 (PG) - 0x0F, 0x22, 0xC0, # mov cr0, eax - 0xEA, 0x5A, 0x07, 0x00, 0x00, 0x08, 0x00, # jmp 0x08:0x705A - - # 64-bit 长模式开始 - 0x48, 0x8B, 0x24, 0x25, 0x08, 0x7F, 0x00, 0x00, # mov rsp, [0x7F08] - 0x0F, 0x01, 0x16, 0x10, 0x7F, # lgdt [0x7F10] - 0x0F, 0x01, 0x1E, 0x20, 0x7F, # lidt [0x7F20] - 0xB8, 0x10, 0x00, 0x00, 0x00, # mov ax, 0x10 - 0x8E, 0xD8, # mov ds, ax - 0x8E, 0xC0, # mov es, ax - 0x8E, 0xE0, # mov fs, ax - 0x8E, 0xE8, # mov gs, ax - 0x8E, 0xD0, # mov ss, ax - 0x48, 0x8B, 0x04, 0x25, 0x28, 0x7F, 0x00, 0x00, # mov rax, [0x7F28] - 0xFF, 0xE0 # jmp rax -] - -def _setup_trampoline(entry_addr: t.CUInt64T, stack_addr: t.CUInt64T, cr3_val: t.CUInt64T): - dest: t.CUInt8T | t.CPtr = t.CUInt8T(AP_TRAMPOLINE_ADDR, t.CPtr) - src: t.CUInt8T | t.CPtr = c.Addr(_trampoline_bin) - i: t.CInt - for i in range(128): - c.Set(c.Deref(dest + t.CUInt64T(i)), c.Deref(src + t.CUInt64T(i))) - - gdt_ptr_addr: t.CUInt64T = AP_TRAMPOLINE_ADDR + 0x0E00 - c.Set(c.Deref(t.CUInt16T(gdt_ptr_addr, t.CPtr)), t.CUInt16T(23)) - c.Set(c.Deref(t.CUInt64T(gdt_ptr_addr + 2, t.CPtr)), t.CUInt64T(AP_TRAMPOLINE_ADDR + 0x0E10)) - - gdt_addr: t.CUInt64T = AP_TRAMPOLINE_ADDR + 0x0E10 - c.Set(c.Deref(t.CUInt64T(gdt_addr, t.CPtr)), t.CUInt64T(0)) - c.Set(c.Deref(t.CUInt64T(gdt_addr + 8, t.CPtr)), t.CUInt64T(0x00AF9A000000FFFF)) - c.Set(c.Deref(t.CUInt64T(gdt_addr + 16, t.CPtr)), t.CUInt64T(0x00CF92000000FFFF)) - - c.Set(c.Deref(t.CUInt32T(AP_TRAMPOLINE_ADDR + 0x0F00, t.CPtr)), t.CUInt32T(cr3_val)) - c.Set(c.Deref(t.CUInt64T(AP_TRAMPOLINE_ADDR + 0x0F08, t.CPtr)), stack_addr) - - gp_addr: t.CUInt64T = t.CUInt64T(c.Addr(gdt.gp)) - gdt_base: t.CUInt64T = c.Deref(t.CUInt64T(gp_addr + 2, t.CPtr)) - gdt_limit: t.CUInt16T = c.Deref(t.CUInt16T(gp_addr, t.CPtr)) - c.Set(c.Deref(t.CUInt16T(AP_TRAMPOLINE_ADDR + 0x0F10, t.CPtr)), gdt_limit) - c.Set(c.Deref(t.CUInt64T(AP_TRAMPOLINE_ADDR + 0x0F12, t.CPtr)), gdt_base) - - idt_addr: t.CUInt64T = t.CUInt64T(c.Addr(idt.idt)) - idt_base: t.CUInt64T = c.Deref(t.CUInt64T(idt_addr + 2, t.CPtr)) - idt_limit: t.CUInt16T = c.Deref(t.CUInt16T(idt_addr, t.CPtr)) - c.Set(c.Deref(t.CUInt16T(AP_TRAMPOLINE_ADDR + 0x0F20, t.CPtr)), idt_limit) - c.Set(c.Deref(t.CUInt64T(AP_TRAMPOLINE_ADDR + 0x0F22, t.CPtr)), idt_base) - - c.Set(c.Deref(t.CUInt64T(AP_TRAMPOLINE_ADDR + 0x0F28, t.CPtr)), entry_addr) - -def start_aps(): - global _cpu_count, _ap_ready - if _cpu_count <= 1: return - - cr3_val: t.CUInt64T = 0 - c.Asm(f"""mov rax, cr3 - mov {c.AsmOut(cr3_val, t.ASM_DESCR.OUTPUT_REG)}, rax""", - [t.ASM_DESCR.CLOBBER_RAX]) - - stack_size: t.CUInt64T = 8192 - i: t.CUInt32T - for i in range(1, _cpu_count): - _ap_ready = 0 - stack: t.CVoid | t.CPtr = mm.malloc(stack_size) - if stack is None: continue - stack_top: t.CUInt64T = t.CUInt64T(stack) + stack_size - stack_top = stack_top & ~t.CUInt64T(15) - - _setup_trampoline(t.CUInt64T(ap_entry), stack_top, cr3_val) - - _send_ipi(i, 0, LAPIC_ICR_INIT) - timer.timer_msleep(10) - _send_ipi(i, (AP_TRAMPOLINE_ADDR >> 12) & 0xFF, LAPIC_ICR_STARTUP) - timer.timer_msleep(1) - _send_ipi(i, (AP_TRAMPOLINE_ADDR >> 12) & 0xFF, LAPIC_ICR_STARTUP) - - wait: t.CUInt32T = 0 - while _ap_ready == 0 and wait < 5000: - timer.timer_msleep(1) - wait += 1 - -def early_init(): - global _cpu_count, _bsp_lapic_id - # 直接以 IA32_APIC_BASE 的 EN 位(bit 11)判断 APIC 是否可用: - # QEMU/OVMF 必启用,且 msr_read 路径已在前置流程验证可用; - # 比依赖 cpuid 特性位更可靠(避免 cpuid 包装被误判时静默跳过 init)。 - msr_val: t.CUInt64T = cpu.msr_read(IA32_APIC_BASE) - if msr_val & APIC_BASE_MSR_ENABLE: - init() - _cpu_count = detect_cpu_count() - else: - _cpu_count = 1 - -def get_cpu_count() -> t.CUInt32T: - return _cpu_count - -def get_base() -> t.CUInt64T: - return _lapic_base - -def get_lapic_id() -> t.CUInt32T: - return get_id() +# trampoline 机器码字节数(与下方 _trampoline_bin 初始化列表元素数一致) +AP_TRAMPOLINE_LEN: t.CDefine = 138 + +_lapic_base: uint64 = 0 +_cpu_count: uint32 = 1 +_bsp_lapic_id: uint32 = 0 +_ap_ready: uint32 = 0 + +def read(offset: uint32) -> uint32: + addr: uint64 = _lapic_base + uint64(offset) + return c.Deref(uint32(addr, t.CPtr)) + +def write(offset: uint32, value: uint32): + addr: uint64 = _lapic_base + uint64(offset) + c.Set(c.Deref(uint32(addr, t.CPtr)), value) + +def eoi(): + write(LAPIC_EOI, 0) + +def get_id() -> uint32: + return read(LAPIC_ID) >> 24 + +@c.Attribute(t.attr.noinline) +def init(): + global _lapic_base, _bsp_lapic_id + msr_val: uint64 = cpu.msr_read(IA32_APIC_BASE) + _lapic_base = msr_val & APIC_BASE_ADDR_MASK + cpu.msr_write(IA32_APIC_BASE, msr_val | APIC_BASE_MSR_ENABLE) + _bsp_lapic_id = read(LAPIC_ID) >> 24 + write(LAPIC_SVR, LAPIC_SVR_ENABLE | 0xFF) + write(LAPIC_TPR, 0) + write(LAPIC_LVT_TIMER, LAPIC_LVT_MASKED) + write(LAPIC_LVT_LINT0, LAPIC_LVT_DELIVERY_EXTINT) + write(LAPIC_LVT_LINT1, LAPIC_LVT_DELIVERY_NMI) + write(LAPIC_LVT_ERROR, LAPIC_LVT_MASKED) + write(LAPIC_TIMER_DIVIDE, 0x0B) + write(LAPIC_LDR, 0x01000000) + eoi() + +@c.Attribute(t.attr.noinline) +def detect_cpu_count() -> uint32: + res: cpu.cpuid_result + cpu.cpuid(0, c.Addr(res)) + max_leaf: uint32 = res.eax + + if max_leaf >= 0x0B: + cpu.cpuid_sub(0x0B, 0, c.Addr(res)) + num_threads: uint32 = res.ebx & 0xFFFF + if num_threads > 0 and num_threads <= MAX_CPUS: + return num_threads + + cpu.cpuid(1, c.Addr(res)) + if res.edx & cpu.CPU_FEATURE_HTT: + count: uint32 = (res.ebx >> 16) & 0xFF + if count > 0 and count <= MAX_CPUS: + return count + return 1 + +def _wait_icr(): + timeout: uint32 = 1000000 + while timeout > 0: + val: uint32 = read(LAPIC_ICR_LOW) + if (val & (1 << 12)) == 0: + return + timeout -= 1 + +def _send_ipi(apic_id: uint32, vector: uint32, delivery_mode: uint32): + _wait_icr() + write(LAPIC_ICR_HIGH, apic_id << 24) + write(LAPIC_ICR_LOW, vector | delivery_mode | LAPIC_ICR_LEVEL | LAPIC_ICR_ASSERT) + _wait_icr() + +def ap_entry(): + global _ap_ready + my_id: uint32 = get_id() + buf: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(buf), 64, "[AP] core %u started (lapic=%u)\n", my_id, my_id) + serial.puts(buf) + _ap_ready = 1 + while True: + asm.sti() + asm.hlt() + +_trampoline_bin: t.CArray[uint8, AP_TRAMPOLINE_LEN] = [ + 0xFA, # cli + 0x31, 0xC0, # xor ax, ax + 0x8E, 0xD8, # mov ds, ax + 0x8E, 0xC0, # mov es, ax + 0x0F, 0x01, 0x16, 0x00, 0x7E, # lgdt [0x7E00] + 0x0F, 0x20, 0xC0, # mov eax, cr0 + 0x83, 0xC8, 0x01, # or eax, 1 + 0x0F, 0x22, 0xC0, # mov cr0, eax + 0xEA, 0x1A, 0x07, 0x00, 0x00, 0x08, 0x00, # jmp 0x08:0x701A + + # 32-bit 保护模式开始 + 0xB8, 0x10, 0x00, 0x00, 0x00, # mov ax, 0x10 + 0x8E, 0xD8, # mov ds, ax + 0x8E, 0xC0, # mov es, ax + 0x8E, 0xE0, # mov fs, ax + 0x8E, 0xE8, # mov gs, ax + 0x8E, 0xD0, # mov ss, ax + 0x0F, 0x20, 0xE0, # mov eax, cr4 + 0x83, 0xC8, 0x20, # or eax, 0x20 (PAE) + 0x0F, 0x22, 0xE0, # mov cr4, eax + 0x8B, 0x04, 0x25, 0x00, 0x7F, 0x00, 0x00, # mov eax, [0x7F00] + 0x0F, 0x22, 0xD8, # mov cr3, eax + 0xB9, 0x80, 0x00, 0x00, 0xC0, # mov ecx, 0xC0000080 (EFER) + 0x0F, 0x32, # rdmsr + 0x83, 0xC8, 0x00, 0x01, 0x00, 0x00, # or eax, 0x100 (LME) + 0x0F, 0x79, # wrmsr + 0x0F, 0x20, 0xC0, # mov eax, cr0 + 0x0D, 0x00, 0x00, 0x00, 0x80, # or eax, 0x80000000 (PG) + 0x0F, 0x22, 0xC0, # mov cr0, eax + 0xEA, 0x5A, 0x07, 0x00, 0x00, 0x08, 0x00, # jmp 0x08:0x705A + + # 64-bit 长模式开始 + 0x48, 0x8B, 0x24, 0x25, 0x08, 0x7F, 0x00, 0x00, # mov rsp, [0x7F08] + 0x0F, 0x01, 0x16, 0x10, 0x7F, # lgdt [0x7F10] + 0x0F, 0x01, 0x1E, 0x20, 0x7F, # lidt [0x7F20] + 0xB8, 0x10, 0x00, 0x00, 0x00, # mov ax, 0x10 + 0x8E, 0xD8, # mov ds, ax + 0x8E, 0xC0, # mov es, ax + 0x8E, 0xE0, # mov fs, ax + 0x8E, 0xE8, # mov gs, ax + 0x8E, 0xD0, # mov ss, ax + 0x48, 0x8B, 0x04, 0x25, 0x30, 0x7F, 0x00, 0x00, # mov rax, [0x7F30] + 0xFF, 0xE0 # jmp rax +] + +def _setup_trampoline(entry_addr: uint64, stack_addr: uint64, cr3_val: uint64): + dest: uint8 | t.CPtr = uint8(AP_TRAMPOLINE_ADDR, t.CPtr) + src: uint8 | t.CPtr = c.Addr(_trampoline_bin) + i: int + for i in range(AP_TRAMPOLINE_LEN): + c.Set(c.Deref(dest + uint64(i)), c.Deref(src + uint64(i))) + + gdt_ptr_addr: uint64 = AP_TRAMPOLINE_ADDR + 0x0E00 + c.Set(c.Deref(uint16(gdt_ptr_addr, t.CPtr)), uint16(23)) + c.Set(c.Deref(uint64(gdt_ptr_addr + 2, t.CPtr)), uint64(AP_TRAMPOLINE_ADDR + 0x0E10)) + + gdt_addr: uint64 = AP_TRAMPOLINE_ADDR + 0x0E10 + c.Set(c.Deref(uint64(gdt_addr, t.CPtr)), uint64(0)) + c.Set(c.Deref(uint64(gdt_addr + 8, t.CPtr)), uint64(0x00AF9A000000FFFF)) + c.Set(c.Deref(uint64(gdt_addr + 16, t.CPtr)), uint64(0x00CF92000000FFFF)) + + c.Set(c.Deref(uint32(AP_TRAMPOLINE_ADDR + 0x0F00, t.CPtr)), uint32(cr3_val)) + c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F08, t.CPtr)), stack_addr) + + gp_addr: uint64 = uint64(c.Addr(gdt.gp)) + gdt_base: uint64 = c.Deref(uint64(gp_addr + 2, t.CPtr)) + gdt_limit: uint16 = c.Deref(uint16(gp_addr, t.CPtr)) + c.Set(c.Deref(uint16(AP_TRAMPOLINE_ADDR + 0x0F10, t.CPtr)), gdt_limit) + c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F12, t.CPtr)), gdt_base) + + idt_addr: uint64 = uint64(c.Addr(idt.idt)) + idt_base: uint64 = c.Deref(uint64(idt_addr + 2, t.CPtr)) + idt_limit: uint16 = c.Deref(uint16(idt_addr, t.CPtr)) + c.Set(c.Deref(uint16(AP_TRAMPOLINE_ADDR + 0x0F20, t.CPtr)), idt_limit) + c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F22, t.CPtr)), idt_base) + + # entry 槽位后移到 0x0F30:idt 伪描述符占 0x0F20..0x0F29(limit 2 + base 8), + # 原来 entry 放 0x0F28 会与其 base 尾部 2 字节重叠 → lidt 读到被覆盖的基址。 + c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F30, t.CPtr)), entry_addr) + +def start_aps(): + global _cpu_count, _ap_ready + if _cpu_count <= 1: return + + cr3_val: uint64 = 0 + c.Asm(f"""mov rax, cr3 + mov {c.AsmOut(cr3_val, t.ASM_DESCR.OUTPUT_REG)}, rax""", + [t.ASM_DESCR.CLOBBER_RAX]) + + stack_size: uint64 = 8192 + i: uint32 + for i in range(1, _cpu_count): + _ap_ready = 0 + stack: t.CPtr = mm.malloc(stack_size) + if stack is None: continue + stack_top: uint64 = uint64(stack) + stack_size + stack_top = stack_top & ~uint64(15) + + _setup_trampoline(uint64(ap_entry), stack_top, cr3_val) + + _send_ipi(i, 0, LAPIC_ICR_INIT) + timer.timer_msleep(10) + _send_ipi(i, (AP_TRAMPOLINE_ADDR >> 12) & 0xFF, LAPIC_ICR_STARTUP) + timer.timer_msleep(1) + _send_ipi(i, (AP_TRAMPOLINE_ADDR >> 12) & 0xFF, LAPIC_ICR_STARTUP) + + wait: uint32 = 0 + while _ap_ready == 0 and wait < 5000: + timer.timer_msleep(1) + wait += 1 + +def early_init(): + global _cpu_count, _bsp_lapic_id + # 直接以 IA32_APIC_BASE 的 EN 位(bit 11)判断 APIC 是否可用: + # QEMU/OVMF 必启用,且 msr_read 路径已在前置流程验证可用; + # 比依赖 cpuid 特性位更可靠(避免 cpuid 包装被误判时静默跳过 init)。 + msr_val: uint64 = cpu.msr_read(IA32_APIC_BASE) + if msr_val & APIC_BASE_MSR_ENABLE: + init() + _cpu_count = detect_cpu_count() + else: + _cpu_count = 1 + +def get_cpu_count() -> uint32: + return _cpu_count + +def get_base() -> uint64: + return _lapic_base + +def get_lapic_id() -> uint32: + return get_id() diff --git a/VKernel/Kernel/drivers/core/cpu/cpu.vp b/VKernel/Kernel/drivers/core/cpu/cpu.vp index dcec637..f3b2e1d 100644 --- a/VKernel/Kernel/drivers/core/cpu/cpu.vp +++ b/VKernel/Kernel/drivers/core/cpu/cpu.vp @@ -38,38 +38,38 @@ CPU_FEATURE_PBE: t.CDefine = (1 << 25) class cpu_info(t.CStruct): vendor_id: t.CArray[t.CChar, 13] brand_string: t.CArray[t.CChar, 48] - features: t.CUInt32T - family: t.CUInt32T - model: t.CUInt32T - stepping: t.CUInt32T - cpu_type: t.CUInt32T - ext_model: t.CUInt32T - ext_family: t.CUInt32T - cpu_freq: t.CUInt64T + features: uint32 + family: uint32 + model: uint32 + stepping: uint32 + cpu_type: uint32 + ext_model: uint32 + ext_family: uint32 + cpu_freq: uint64 @c.Attribute(t.attr.packed) class _tss: - reserved0: t.CUInt64T - rsp0: t.CUInt64T - rsp1: t.CUInt64T - rsp2: t.CUInt64T - reserved1: t.CUInt64T - ist1: t.CUInt64T - ist2: t.CUInt64T - ist3: t.CUInt64T - ist4: t.CUInt64T - ist5: t.CUInt64T - ist6: t.CUInt64T - ist7: t.CUInt64T - reserved2: t.CUInt64T - reserved3: t.CUInt16T - io_map_base: t.CUInt16T + reserved0: uint64 + rsp0: uint64 + rsp1: uint64 + rsp2: uint64 + reserved1: uint64 + ist1: uint64 + ist2: uint64 + ist3: uint64 + ist4: uint64 + ist5: uint64 + ist6: uint64 + ist7: uint64 + reserved2: uint64 + reserved3: uint16 + io_map_base: uint16 class cpuid_result(t.CStruct): - eax: t.CUInt32T - ebx: t.CUInt32T - ecx: t.CUInt32T - edx: t.CUInt32T + eax: uint32 + ebx: uint32 + ecx: uint32 + edx: uint32 @c.Attribute(t.attr.naked) def _rdmsr_naked(): @@ -91,17 +91,17 @@ def _wrmsr_naked(): ret""", op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX]) -def msr_read(msr: t.CUInt32T) -> t.CUInt64T: - result: t.CUInt64T = 0 - func: t.CVoid | t.CPtr = _rdmsr_naked +def msr_read(msr: uint32) -> uint64: + result: uint64 = 0 + func: t.CPtr = _rdmsr_naked c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)} call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)} mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX]) return result -def msr_write(msr: t.CUInt32T, value: t.CUInt64T): - func: t.CVoid | t.CPtr = _wrmsr_naked +def msr_write(msr: uint32, value: uint64): + func: t.CPtr = _wrmsr_naked c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)} mov r8, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}""", @@ -137,8 +137,8 @@ def _cpuid_sub_naked(): t.ASM_DESCR.CLOBBER_RDX]) @c.Attribute(t.attr.noinline) -def cpuid(leaf: t.CUInt32T, out: cpuid_result | t.CPtr): - func: t.CVoid | t.CPtr = _cpuid_naked +def cpuid(leaf: uint32, out: cpuid_result | t.CPtr): + func: t.CPtr = _cpuid_naked c.Asm(f"""mov ecx, {c.AsmInp(leaf, t.ASM_DESCR.REG_ANY)} mov rdx, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)} call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}""", @@ -148,8 +148,8 @@ def cpuid(leaf: t.CUInt32T, out: cpuid_result | t.CPtr): t.ASM_DESCR.CLOBBER_R11]) @c.Attribute(t.attr.noinline) -def cpuid_sub(leaf: t.CUInt32T, sub: t.CUInt32T, out: cpuid_result | t.CPtr): - func: t.CVoid | t.CPtr = _cpuid_sub_naked +def cpuid_sub(leaf: uint32, sub: uint32, out: cpuid_result | t.CPtr): + func: t.CPtr = _cpuid_sub_naked c.Asm(f"""mov ecx, {c.AsmInp(leaf, t.ASM_DESCR.REG_ANY)} mov r8d, {c.AsmInp(sub, t.ASM_DESCR.REG_ANY)} mov rdx, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)} @@ -160,8 +160,8 @@ def cpuid_sub(leaf: t.CUInt32T, sub: t.CUInt32T, out: cpuid_result | t.CPtr): t.ASM_DESCR.CLOBBER_R11]) @c.Attribute(t.attr.noinline) -def detect_features_static() -> t.CUInt32T: - features: t.CUInt32T = 0 +def detect_features_static() -> uint32: + features: uint32 = 0 res: cpuid_result cpuid(1, c.Addr(res)) if res.edx & (1 << 0): features |= CPU_FEATURE_FPU @@ -194,18 +194,18 @@ def detect_features_static() -> t.CUInt32T: @c.Attribute(t.attr.packed) class per_cpu_data: - user_rsp: t.CUInt64T - kernel_rsp0: t.CUInt64T - current_pid: t.CInt - _pad0: t.CUInt32T - _pad1: t.CUInt64T + user_rsp: uint64 + kernel_rsp0: uint64 + current_pid: int + _pad0: uint32 + _pad1: uint64 _per_cpu: per_cpu_data @t.Object class _CPUObject: tss: _tss - features: t.CUInt32T + features: uint32 def __init__(self): self.__init_tss__() @@ -214,21 +214,21 @@ class _CPUObject: string.memset(c.Addr(self.tss), 0, self.tss.__sizeof__()) self.tss.io_map_base = self.tss.__sizeof__() string.memset(c.Addr(_per_cpu), 0, per_cpu_data.__sizeof__()) - gdt.setTSS64(5, t.CUInt64T(c.Addr(self.tss)), self.tss.__sizeof__() - 1) + gdt.setTSS64(5, uint64(c.Addr(self.tss)), self.tss.__sizeof__() - 1) gdt.flush() # IA32_KERNEL_GS_BASE holds the per_cpu address for swapgs. # When entering from Ring 3, swapgs swaps IA32_GS_BASE (0) with # IA32_KERNEL_GS_BASE (_per_cpu), making gs: accessible in kernel. # When returning to Ring 3, swapgs swaps back, restoring GS base to 0. - msr_write(IA32_KERNEL_GS_BASE, t.CUInt64T(c.Addr(_per_cpu))) + msr_write(IA32_KERNEL_GS_BASE, uint64(c.Addr(_per_cpu))) def getInfo(self, info: cpu_info | t.CPtr): if not info: return res: cpuid_result cpuid(0, c.Addr(res)) - (t.CUInt32T(info.vendor_id, t.CPtr))[0] = res.ebx - (t.CUInt32T(info.vendor_id, t.CPtr))[1] = res.edx - (t.CUInt32T(info.vendor_id, t.CPtr))[2] = res.ecx + (uint32(info.vendor_id, t.CPtr))[0] = res.ebx + (uint32(info.vendor_id, t.CPtr))[1] = res.edx + (uint32(info.vendor_id, t.CPtr))[2] = res.ecx info.vendor_id[12] = '\0' info.features = self.detectFeatures() cpuid(1, c.Addr(res)) @@ -238,18 +238,23 @@ class _CPUObject: info.cpu_type = (res.eax >> 12) & 0x03 info.ext_model = (res.eax >> 16) & 0x0F info.ext_family = (res.eax >> 20) & 0xFF - for i in range(4): + # CPUID 品牌串:0x80000002..0x80000004 共 3 个叶 × 16 字节 = 48, + # 与 brand_string[48] 等长(此前 range(4) 会写 64 字节 → 越界 16 字节)。 + # 逐 u32 按字节地址显式写入,避免 uint32|t.CPtr 被降级为 i8* 后 + # 下标按字节偏移且被截断为 i8(只写低字节、偏移不乘 4)。 + brand_addr: uint64 = uint64(uint32(info.brand_string, t.CPtr)) + for i in range(3): cpuid(0x80000002 + i, c.Addr(res)) - base: t.CUInt32T | t.CPtr = t.CUInt32T(info.brand_string, t.CPtr) - base[i * 4 + 0] = res.eax - base[i * 4 + 1] = res.ebx - base[i * 4 + 2] = res.ecx - base[i * 4 + 3] = res.edx + off_b: uint64 = uint64(i) * 16 + c.Set(c.Deref(uint32(brand_addr + off_b, t.CPtr)), res.eax) + c.Set(c.Deref(uint32(brand_addr + off_b + 4, t.CPtr)), res.ebx) + c.Set(c.Deref(uint32(brand_addr + off_b + 8, t.CPtr)), res.ecx) + c.Set(c.Deref(uint32(brand_addr + off_b + 12, t.CPtr)), res.edx) info.brand_string[47] = '\0' info.cpu_freq = 2000000000 - def detectFeatures(self) -> t.CUInt32T: - features: t.CInt32T = 0 + def detectFeatures(self) -> uint32: + features: int32 = 0 res: cpuid_result cpuid(1, c.Addr(res)) if res.edx & (1 << 0): features |= CPU_FEATURE_FPU @@ -287,61 +292,61 @@ class _CPUObject: c.Asm("cli", [t.ASM_DESCR.CLOBBER_MEMORY]) def enableNmis(self): - current: t.CUInt8T = asm.inb(0x70) + current: uint8 = asm.inb(0x70) asm.outb(0x70, current & 0x7F) def disableNmis(self): - current: t.CUInt8T = asm.inb(0x70) + current: uint8 = asm.inb(0x70) asm.outb(0x70, current | 0x80) - def readCR0(self) -> t.CUInt64T: - cr0: t.CUInt64T + def readCR0(self) -> uint64: + cr0: uint64 c.Asm(f"""mov rax, cr0 mov {c.AsmOut(cr0, t.ASM_DESCR.OUTPUT_REG)}, rax""", [t.ASM_DESCR.CLOBBER_RAX]) return cr0 - def writeCR0(self, value: t.CUInt64T): + def writeCR0(self, value: uint64): c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} mov cr0, rax""", [t.ASM_DESCR.CLOBBER_RAX]) - def readCR3(self) -> t.CUInt64T: - cr3: t.CUInt64T + def readCR3(self) -> uint64: + cr3: uint64 c.Asm(f"""mov rax, cr3 mov {c.AsmOut(cr3, t.ASM_DESCR.OUTPUT_REG)}, rax""", [t.ASM_DESCR.CLOBBER_RAX]) return cr3 - def writeCR3(self, value: t.CUInt64T): + def writeCR3(self, value: uint64): c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} mov cr3, rax""", [t.ASM_DESCR.CLOBBER_RAX]) - def readCR4(self) -> t.CUInt64T: - cr4: t.CUInt64T + def readCR4(self) -> uint64: + cr4: uint64 c.Asm(f"""mov rax, cr4 mov {c.AsmOut(cr4, t.ASM_DESCR.OUTPUT_REG)}, rax""", [t.ASM_DESCR.CLOBBER_RAX]) return cr4 - def writeCR4(self, value: t.CUInt64T): + def writeCR4(self, value: uint64): c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} mov cr4, rax""", [t.ASM_DESCR.CLOBBER_RAX]) - def readMSR(self, msr: t.CUInt32T) -> t.CUInt64T: + def readMSR(self, msr: uint32) -> uint64: return msr_read(msr) - def writeMSR(self, msr: t.CUInt32T, value: t.CUInt64T): + def writeMSR(self, msr: uint32, value: uint64): msr_write(msr, value) - def setTSSRSP0(self, rsp0: t.CUInt64T): + def setTSSRSP0(self, rsp0: uint64): global _per_cpu self.tss.rsp0 = rsp0 _per_cpu.kernel_rsp0 = rsp0 -def set_kernel_rsp0(rsp0: t.CUInt64T): +def set_kernel_rsp0(rsp0: uint64): global _per_cpu _per_cpu.kernel_rsp0 = rsp0 @@ -349,20 +354,20 @@ def set_kernel_rsp0(rsp0: t.CUInt64T): # OVMF/UEFI 启动后 CR4.OSFXSR 未置位,任何 movaps 都 #GP(err=0)——变参函数 # 传 float/double 时保存 xmm 寄存器触发(serial.printf / snprintf("%.2f") 崩溃根因)。 def enable_sse(): - cr0_v: t.CUInt64T = 0 + cr0_v: uint64 = 0 c.Asm(f"""mov rax, cr0 mov {c.AsmOut(cr0_v, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_RAX]) - cr0_v = cr0_v & ~t.CUInt64T(4) # 清 EM(禁止 FPU 仿真) - cr0_v = cr0_v | t.CUInt64T(2) # 置 MP(监控协处理器) + cr0_v = cr0_v & ~uint64(4) # 清 EM(禁止 FPU 仿真) + cr0_v = cr0_v | uint64(2) # 置 MP(监控协处理器) c.Asm(f"""mov rax, {c.AsmInp(cr0_v, t.ASM_DESCR.REG_ANY)} mov cr0, rax""", op=[t.ASM_DESCR.CLOBBER_RAX]) - cr4_v: t.CUInt64T = 0 + cr4_v: uint64 = 0 c.Asm(f"""mov rax, cr4 mov {c.AsmOut(cr4_v, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_RAX]) - cr4_v = cr4_v | t.CUInt64T(0x600) # OSFXSR | OSXMMEXCPT + cr4_v = cr4_v | uint64(0x600) # OSFXSR | OSXMMEXCPT c.Asm(f"""mov rax, {c.AsmInp(cr4_v, t.ASM_DESCR.REG_ANY)} mov cr4, rax""", op=[t.ASM_DESCR.CLOBBER_RAX]) diff --git a/VKernel/Kernel/drivers/core/cpu/fpu.vp b/VKernel/Kernel/drivers/core/cpu/fpu.vp index 90013d8..b0c91fb 100644 --- a/VKernel/Kernel/drivers/core/cpu/fpu.vp +++ b/VKernel/Kernel/drivers/core/cpu/fpu.vp @@ -5,7 +5,7 @@ import t, c # FPU上下文结构体 @c.Attribute(t.attr.aligned(16)) class fpu_context: - data: t.CArray[t.CUInt8T, 512] # FXSAVE区域大小 + data: t.CArray[uint8, 512] # FXSAVE区域大小 @t.Object @@ -18,14 +18,14 @@ class _FPUObject: c.Asm("fninit", [t.ASM_DESCR.CLOBBER_MEMORY]) # 启用FPU def enable(self): - cr0: t.CUInt64T = self.CPUObject.readCR0() + cr0: uint64 = self.CPUObject.readCR0() # 清除EM位(禁用仿真),设置MP位(监控协处理器) cr0 &= ~(1 << 2); # 清除EM位 cr0 |= (1 << 1); # 设置MP位 # 写入CR0寄存器 self.CPUObject.writeCR0(cr0) # 读取CR4寄存器 - cr4: t.CUInt64T = self.CPUObject.readCR4() + cr4: uint64 = self.CPUObject.readCR4() # 设置OSFXSR位和OSXMMEXCPT位,启用SSE cr4 |= (1 << 9) | (1 << 10) # 写入CR4寄存器 @@ -34,7 +34,7 @@ class _FPUObject: c.Asm("fninit", [t.ASM_DESCR.CLOBBER_MEMORY]) # 禁用FPU def disable(self): - cr0: t.CUInt64T = self.CPUObject.readCR0() + cr0: uint64 = self.CPUObject.readCR0() # 设置EM位(启用仿真),清除MP位(禁用监控协处理器) cr0 |= (1 << 2) # 设置EM位 cr0 &= ~(1 << 1) # 清除MP位 diff --git a/VKernel/Kernel/drivers/devfs/devfs.vp b/VKernel/Kernel/drivers/devfs/devfs.vp index 8797f33..066ba57 100644 --- a/VKernel/Kernel/drivers/devfs/devfs.vp +++ b/VKernel/Kernel/drivers/devfs/devfs.vp @@ -10,15 +10,15 @@ MAX_DIRECTORIES: t.CDefine = 16 PATH_BUFFER_SIZE: t.CDefine = 256 directories: t.CArray[devfs_directory, MAX_DIRECTORIES] = [0] -directory_count: t.CStatic | t.CInt = 0 +directory_count: t.CStatic | int = 0 files: t.CArray[devfs_file, MAX_DEVICE_FILES] = [0] -file_count: t.CStatic | t.CInt = 0 +file_count: t.CStatic | int = 0 class _fd_table: file: devfs_file | t.CPtr - flags: t.CInt + flags: int fd_table: t.CArray[_fd_table, MAX_FILE_DESCRIPTORS] = [0] @@ -35,7 +35,7 @@ class devfs_directory: current_dir: devfs_directory | t.CPtr = root_directory result: t.CArray[str, PATH_BUFFER_SIZE] - token = string.split(path, "/", result) + token = string.split(path, "/", result, PATH_BUFFER_SIZE) # `for i in result` 按 NULL 终止语义遍历(i8* 元素,split 尾哨兵 NULL 停): # 编译器 _handle_array_iter 已实现"长度上限 + 解引用为空提前终止"。 @@ -63,12 +63,12 @@ class devfs_directory: @staticmethod def list_subdirs(dir_ptr: devfs_directory | t.CPtr, buffer: str, - size: t.CUInt32T, - pos: t.CInt) -> t.CInt: + size: uint32, + pos: int) -> int: for d in range(directory_count): dirp: devfs_directory = c.Addr(directories[d]) if dirp.parent == dir_ptr: - name_len: t.CInt = string.strlen(dirp.name) + name_len: int = string.strlen(dirp.name) if pos + name_len + 1 > size: break string.strcpy(buffer + pos, dirp.name) @@ -81,7 +81,7 @@ class devfs_directory: @t.CVTable class devfs_file: name: t.CArray[t.CChar, 64] - private_data: t.CVoid | t.CPtr + private_data: t.CPtr parent_dir: 'devfs_directory' | t.CPtr @staticmethod @@ -96,12 +96,12 @@ class devfs_file: @staticmethod def list_in_dir(dir_ptr: devfs_directory | t.CPtr, buffer: str, - size: t.CUInt32T, - pos: t.CInt) -> t.CInt: + size: uint32, + pos: int) -> int: for f in range(file_count): filep: devfs_file | t.CPtr = c.Addr(files[f]) if filep.parent_dir == dir_ptr: - name_len: t.CInt = string.strlen(filep.name) + name_len: int = string.strlen(filep.name) if pos + name_len + 1 > size: break string.strcpy(buffer + pos, filep.name) @@ -110,19 +110,19 @@ class devfs_file: pos += 1 return pos - def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt: + def open(self, path: t.CConst | str, flags: int) -> int: return 0 - def close(self, fd: t.CInt) -> t.CInt: + def close(self, fd: int) -> int: return 0 - def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int: return 0 - def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: return 0 - def ioctl(self, fd: t.CInt, request: t.CInt, arg: t.CVoid | t.CPtr) -> t.CInt: + def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int: return 0 @t.Object @@ -168,8 +168,8 @@ class _DevFSObject: current: devfs_directory | t.CPtr = self.root_directory buf: t.CArray[t.CChar, PATH_BUFFER_SIZE] string.memset(c.Addr(buf), 0, PATH_BUFFER_SIZE) - buf_idx: t.CInt = 0 - p: t.CInt = 0 + buf_idx: int = 0 + p: int = 0 if path[p] == '/': p += 1 serial.puts("C") @@ -199,12 +199,12 @@ class _DevFSObject: return current - def init(self) -> t.CInt: + def init(self) -> int: self.create_directory("/dev") self.create_directory("/dev/input") return 0 - def create_directory(self, path: t.CConst | str) -> t.CInt: + def create_directory(self, path: t.CConst | str) -> int: serial.puts("T1") dir_ptr: devfs_directory | t.CPtr = self.find_or_create_directory(path) serial.puts("T2") @@ -212,7 +212,7 @@ class _DevFSObject: def create_file(self, path: t.CConst | str, file_ptr: devfs_file | t.CPtr, - private_data: t.CVoid | t.CPtr) -> t.CInt: + private_data: t.CPtr) -> int: global file_count path_copy: t.CArray[t.CChar, PATH_BUFFER_SIZE] string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE) @@ -237,7 +237,7 @@ class _DevFSObject: if file_ptr: # [DIAG] 定位 register 阶段 strcpy 目标:打印 file_ptr(用后移除) _dbg3: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_dbg3), 80, "[cf] fp=%lx\n", t.CUInt64T(file_ptr)) + viperlib.snprintf(c.Addr(_dbg3), 80, "[cf] fp=%lx\n", uint64(file_ptr)) serial.puts(c.Addr(_dbg3)) string.strcpy(file_ptr.name, file_name) file_ptr.private_data = private_data @@ -252,7 +252,7 @@ class _DevFSObject: file_count += 1 return 0 - def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt: + def open(self, path: t.CConst | str, flags: int) -> int: path_copy: t.CArray[t.CChar, PATH_BUFFER_SIZE] string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE) string.strcpy(path_copy, path) @@ -273,12 +273,12 @@ class _DevFSObject: # [DIAG] 定位 vtable 悬垂:打印 file_ptr 与对象首字段(vtable 指针)(用后移除) _dbg_buf: t.CArray[t.CChar, 96] - _dbg_vt: t.CUInt64T = t.CUInt64T(file_ptr, t.CPtr)[0] + _dbg_vt: uint64 = uint64(file_ptr, t.CPtr)[0] viperlib.snprintf(c.Addr(_dbg_buf), 96, "[open] fp=%lx vt=%lx\n", - t.CUInt64T(file_ptr), _dbg_vt) + uint64(file_ptr), _dbg_vt) serial.puts(c.Addr(_dbg_buf)) - fd: t.CInt = -1 + fd: int = -1 for i in range(MAX_FILE_DESCRIPTORS): if not fd_table[i].file: fd = i @@ -286,14 +286,14 @@ class _DevFSObject: if fd == -1: return -1 - ret: t.CInt = file_ptr.open(path, flags) + ret: int = file_ptr.open(path, flags) if ret != 0: return ret fd_table[fd].file = file_ptr fd_table[fd].flags = flags return fd - def close(self, fd: t.CInt) -> t.CInt: + def close(self, fd: int) -> int: if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file: return -1 file_ptr: devfs_file | t.CPtr = fd_table[fd].file @@ -302,19 +302,19 @@ class _DevFSObject: fd_table[fd].flags = 0 return 0 - def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int: if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file: return -1 file_ptr: devfs_file | t.CPtr = fd_table[fd].file return file_ptr.read(fd, buffer, size) - def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file: return -1 file_ptr: devfs_file | t.CPtr = fd_table[fd].file return file_ptr.write(fd, buffer, size) - def ioctl(self, fd: t.CInt, cmd: t.CUInt32T, arg: t.CVoid | t.CPtr) -> t.CInt: + def ioctl(self, fd: int, cmd: uint32, arg: t.CPtr) -> int: if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file: return -1 file_ptr: devfs_file | t.CPtr = fd_table[fd].file @@ -322,11 +322,11 @@ class _DevFSObject: def list_directory(self, path: t.CConst | str, buffer: str, - size: t.CUInt32T) -> t.CInt: + size: uint32) -> int: dir_ptr: devfs_directory | t.CPtr = devfs_directory.find(path, self.root_directory) if not dir_ptr or not buffer or size == 0: return -1 - pos: t.CInt = devfs_directory.list_subdirs(dir_ptr, buffer, size, 0) + pos: int = devfs_directory.list_subdirs(dir_ptr, buffer, size, 0) pos = devfs_file.list_in_dir(dir_ptr, buffer, size, pos) return pos @@ -335,7 +335,7 @@ DevFSObject: _DevFSObject | t.CPtr _DevFSObject_instance: _DevFSObject -def devfs_init() -> t.CInt: +def devfs_init() -> int: global DevFSObject, _DevFSObject_instance DevFSObject = c.Addr(_DevFSObject_instance) _DevFSObject_instance = _DevFSObject() @@ -343,57 +343,57 @@ def devfs_init() -> t.CInt: DevFSObject.init() return 0 -def devfs_create_directory(path: t.CConst | str) -> t.CInt: +def devfs_create_directory(path: t.CConst | str) -> int: return DevFSObject.create_directory(path) def devfs_create_file(path: t.CConst | str, file_ptr: devfs_file | t.CPtr, - private_data: t.CVoid | t.CPtr) -> t.CInt: + private_data: t.CPtr) -> int: return DevFSObject.create_file(path, file_ptr, private_data) -def devfs_open(path: t.CConst | str, flags: t.CInt) -> t.CInt: +def devfs_open(path: t.CConst | str, flags: int) -> int: return DevFSObject.open(path, flags) -def devfs_close(fd: t.CInt) -> t.CInt: +def devfs_close(fd: int) -> int: return DevFSObject.close(fd) -def devfs_read(fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: +def devfs_read(fd: int, buffer: t.CPtr, size: uint32) -> int: return DevFSObject.read(fd, buffer, size) -def devfs_write(fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: +def devfs_write(fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: return DevFSObject.write(fd, buffer, size) -def devfs_ioctl(fd: t.CInt, cmd: t.CUInt32T, arg: t.CVoid | t.CPtr) -> t.CInt: +def devfs_ioctl(fd: int, cmd: uint32, arg: t.CPtr) -> int: return DevFSObject.ioctl(fd, cmd, arg) def devfs_list_directory(path: t.CConst | str, buffer: str, - size: t.CUInt32T) -> t.CInt: + size: uint32) -> int: return DevFSObject.list_directory(path, buffer, size) serial0_file: devfs_file -def serial0_open(self: t.CVoid | t.CPtr, path: t.CConst | str, flags: t.CInt) -> t.CInt: +def serial0_open(self: t.CPtr, path: t.CConst | str, flags: int) -> int: serial.puts("[serial0] open: ") serial.puts(path) serial.puts("\n") return 0 -def serial0_close(self: t.CVoid | t.CPtr, fd: t.CInt) -> t.CInt: +def serial0_close(self: t.CPtr, fd: int) -> int: serial.puts("[serial0] close\n") return 0 -def serial0_read(self: t.CVoid | t.CPtr, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: +def serial0_read(self: t.CPtr, fd: int, buffer: t.CPtr, size: uint32) -> int: serial.puts("[serial0] read\n") return 0 -def serial0_write(self: t.CVoid | t.CPtr, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: +def serial0_write(self: t.CPtr, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: serial.puts("[serial0] write\n") serial.puts(str(buffer)) serial.puts("\n") return size -def devfs_register_serial0() -> t.CInt: +def devfs_register_serial0() -> int: global serial0_file serial0_file = devfs_file() serial0_file.open = serial0_open @@ -405,21 +405,21 @@ def devfs_register_serial0() -> t.CInt: @t.Object @t.CVTable class serial1_device(devfs_file): - def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt: + def open(self, path: t.CConst | str, flags: int) -> int: serial.puts("[serial1] open: ") serial.puts(path) serial.puts("\n") return 0 - def close(self, fd: t.CInt) -> t.CInt: + def close(self, fd: int) -> int: serial.puts("[serial1] close\n") return 0 - def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int: serial.puts("[serial1] read\n") return 0 - def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: serial.puts("[serial1] write\n") serial.puts(str(buffer)) serial.puts("\n") @@ -427,7 +427,7 @@ class serial1_device(devfs_file): serial1_file: serial1_device -def devfs_register_serial1() -> t.CInt: +def devfs_register_serial1() -> int: global serial1_file serial1_file = serial1_device() return devfs_create_file("/dev/serial1", serial1_file, None) @@ -438,16 +438,16 @@ import drivers.input.mouse.mouse as mouse @t.Object @t.CVTable class keyboard_device(devfs_file): - def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt: + def open(self, path: t.CConst | str, flags: int) -> int: return 0 - def close(self, fd: t.CInt) -> t.CInt: + def close(self, fd: int) -> int: return 0 - def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: - count: t.CUInt32T = 0 + def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int: + count: uint32 = 0 while count < size and keyboard.has_data(): - sc: t.CUInt8T = keyboard.read_scancode() + sc: uint8 = keyboard.read_scancode() ch: t.CChar = keyboard.scancode_to_ascii(sc) if ch != '\0': # c.Set(t.CChar(...)[count], ch) 是 Subscript 左值,translate_c_set @@ -456,15 +456,15 @@ class keyboard_device(devfs_file): count += 1 return count - def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: return -1 - def ioctl(self, fd: t.CInt, request: t.CInt, arg: t.CVoid | t.CPtr) -> t.CInt: + def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int: return 0 kbd_file: keyboard_device -def devfs_register_keyboard() -> t.CInt: +def devfs_register_keyboard() -> int: global kbd_file kbd_file = keyboard_device() keyboard.init() @@ -473,34 +473,35 @@ def devfs_register_keyboard() -> t.CInt: @t.Object @t.CVTable class mouse_device(devfs_file): - def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt: + def open(self, path: t.CConst | str, flags: int) -> int: return 0 - def close(self, fd: t.CInt) -> t.CInt: + def close(self, fd: int) -> int: return 0 - def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int: if not mouse.has_data(): return 0 pkt: mouse.mouse_packet mouse.read_packet(c.Addr(pkt)) if size >= 1: - t.CUInt8T(buffer, t.CPtr)[0] = pkt.buttons - if size >= 5: - buf: t.CUInt32T | t.CPtr = t.CVoid(t.CUInt64T(buffer) + 1, t.CPtr) - t.CInt32T(buf, t.CPtr)[0] = mouse.get_x() - t.CInt32T(buf, t.CPtr)[1] = mouse.get_y() - return 5 + uint8(buffer, t.CPtr)[0] = pkt.buttons + # 完整包需要 1(buttons) + 4(x) + 4(y) = 9 字节,否则越界写 + if size >= 9: + buf: uint32 | t.CPtr = t.CVoid(uint64(buffer) + 1, t.CPtr) + int32(buf, t.CPtr)[0] = mouse.get_x() + int32(buf, t.CPtr)[1] = mouse.get_y() + return 9 return 1 - def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt: + def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int: return -1 - def ioctl(self, fd: t.CInt, request: t.CInt, arg: t.CVoid | t.CPtr) -> t.CInt: + def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int: return 0 mse_file: mouse_device -def devfs_register_mouse() -> t.CInt: +def devfs_register_mouse() -> int: global mse_file mse_file = mouse_device() mouse.init() diff --git a/VKernel/Kernel/drivers/fs/fat32/example_fs.vp b/VKernel/Kernel/drivers/fs/fat32/example_fs.vp index adbdded..fbeb1d5 100644 --- a/VKernel/Kernel/drivers/fs/fat32/example_fs.vp +++ b/VKernel/Kernel/drivers/fs/fat32/example_fs.vp @@ -1,238 +1,238 @@ -from stdint import * -import fat32 as fs -import fat32_types as types -import fat32_part as part -import fat32_mkfs as mkfs_mod -import string -import t, c - - -def print_fresult(res: types.FRESULT, msg: t.CConst | str) -> t.CInt: - if res == types.FRESULT.FR_OK: - print(f"[成功] {msg}") - return 0 - else: - print(f"[失败] {msg}: {res}") - return -1 - - -def print_fresult_void(res: types.FRESULT, msg: t.CConst | str): - print_fresult(res, msg) - - -def example_main() -> t.CInt: - print("=== FAT32 文件系统完整示例 ===") - print() - - # 1. 扫描可用驱动器 - print("--- 1. 扫描可用驱动器 ---") - res: types.FRESULT = fs.scan_drives() - print_fresult_void(res, "扫描驱动器") - - drive_count: t.CInt = fs.get_drive_count() - print(f"找到 {drive_count} 个驱动器") - i: t.CInt - for i in range(drive_count): - letter: t.CChar = fs.get_drive_letter(i) - part_count: t.CInt = fs.get_partition_count(letter) - print(f" 驱动器 {i}: {letter}") - for j in range(part_count): - is_fat32: t.CInt = fs.is_partition_fat32(letter, j) - print(f" 分区 {j}: FAT32={is_fat32}") - print() - - # 2. 挂载文件系统 - print("--- 2. 挂载文件系统 ---") - res = fs.mount() - if print_fresult(res, "挂载文件系统") != 0: - print("提示: 可能需要先格式化磁盘") - print() - - # 3. 文件系统信息 - print("--- 3. 文件系统信息 ---") - mounted: t.CInt = fs.is_mounted() - print(f"已挂载: {mounted}") - if mounted: - total_clusters: t.CUInt32T = fs.get_total() - free_clusters: t.CUInt32T = fs.get_free() - cluster_size: t.CUInt32T = fs.get_cluster_size() - total_bytes: t.CUInt64T = t.CUInt64T(total_clusters) * t.CUInt64T(cluster_size) - free_bytes: t.CUInt64T = t.CUInt64T(free_clusters) * t.CUInt64T(cluster_size) - print(f"总簇数: {total_clusters}") - print(f"空闲簇数: {free_clusters}") - print(f"簇大小: {cluster_size} 字节") - print(f"总大小: {total_bytes} 字节") - print(f"空闲大小: {free_bytes} 字节") - print() - - # 4. 元数据操作 - print("--- 4. 元数据操作 ---") - fs.set_metadata(0x12345678) - metadata: t.CUInt32T = fs.get_metadata() - print(f"设置的元数据: 0x{metadata:08X}") - print() - - # 5. 获取 FAT 时间 - print("--- 5. 获取 FAT 时间 ---") - fattime: t.CUInt32T = fs.get_fattime() - print(f"当前 FAT 时间: 0x{fattime:08X}") - print() - - # 6. 目录操作 - if fs.is_mounted(): - print("--- 6. 目录操作 ---") - - # 创建目录 - res = fs.mkdir("/test_dir_1") - print_fresult_void(res, "创建目录 /test_dir_1") - - res = fs.mkdir("/test_dir_1/subdir") - print_fresult_void(res, "创建子目录 /test_dir_1/subdir") - - res = fs.mkdir("/test_dir_2") - print_fresult_void(res, "创建目录 /test_dir_2") - print() - - # 7. 文件操作 - print("--- 7. 文件操作 ---") - - # 创建并写入文件 - fp1: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE) - if fp1 is not None: - test_data1: t.CConst | str = "Hello, World!" - written: t.CUInt32T = fs.write(fp1, test_data1, 13) - print(f"写入文件 /test_dir_1/file1.txt: {written} 字节") - fs.close(fp1) - - # 打开追加 - fp2: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_ALWAYS | types.FA_WRITE | types.FA_OPEN_APPEND) - if fp2 is not None: - test_data2: t.CConst | str = " Append data!" - written2: t.CUInt32T = fs.write(fp2, test_data2, 13) - print(f"追加写入: {written2} 字节") - fs.close(fp2) - - # 读取文件 - fp3: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_EXISTING | types.FA_READ) - if fp3 is not None: - buf: t.CArray[t.CUInt8T, 256] - read_bytes: t.CUInt32T = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256) - print(f"读取字节数: {read_bytes}") - print(f"文件内容: {t.CChar(c.Addr(buf[0]), t.CPtr)}") - - # seek 和 tell - fs.seek(fp3, 5) - pos: t.CUInt32T = fs.tell(fp3) - print(f"seek 到位置 5, 当前位置: {pos}") - - read_bytes2: t.CUInt32T = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256) - print(f"从位置 5 读取: {t.CChar(c.Addr(buf[0]), t.CPtr)}") - - # 获取文件大小 - fsize: t.CUInt32T = fs.size(fp3) - print(f"文件大小: {fsize} 字节") - - fs.close(fp3) - - # 创建另一个文件 - fp4: types.fileobj | t.CPtr = fs.open("/test_dir_1/large_file.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE) - if fp4 is not None: - large_data: t.CArray[t.CUInt8T, 1024] - k: t.CInt - for k in range(1024): - large_data[k] = t.CUInt8T(ord('A') + (k % 26)) - written3: t.CUInt32T = fs.write(fp4, t.CVoid(c.Addr(large_data[0]), t.CPtr), 1024) - print(f"创建大文件, 写入: {written3} 字节") - fs.close(fp4) - print() - - # 8. 文件状态和属性 - print("--- 8. 文件状态和属性 ---") - - info: types.fileinfo - res = fs.stat("/test_dir_1/file1.txt", c.Addr(info)) - print_fresult_void(res, "获取文件信息") - if res == types.FRESULT.FR_OK: - print(f" 文件名: {info.fname}") - print(f" 大小: {info.file_size} 字节") - print(f" 属性: 0x{info.attr:02X}") - print(f" 创建时间: 0x{info.ctime:04X}") - print(f" 创建日期: 0x{info.cdate:04X}") - print(f" 修改时间: 0x{info.mtime:04X}") - print(f" 修改日期: 0x{info.mdate:04X}") - print(f" 访问日期: 0x{info.adate:04X}") - - # 修改属性 - res = fs.chmod("/test_dir_1/file1.txt", types.AM_RDO, types.AM_RDO) - print_fresult_void(res, "设置文件为只读") - print() - - # 9. 重命名和移动 - print("--- 9. 重命名和移动 ---") - - res = fs.rename("/test_dir_1/file1.txt", "/test_dir_1/renamed.txt") - print_fresult_void(res, "重命名文件") - - res = fs.move("/test_dir_1/renamed.txt", "/test_dir_2/moved.txt") - print_fresult_void(res, "移动文件") - - res = fs.rename("/test_dir_2", "/test_dir_renamed") - print_fresult_void(res, "重命名目录") - print() - - # 10. 列出目录 - print("--- 10. 列出目录 ---") - - dp: types.dirobj - res = fs.opendir("/", c.Addr(dp)) - if res == types.FRESULT.FR_OK: - print("根目录内容:") - dir_info: types.fileinfo - while True: - res = fs.readdir(c.Addr(dp), c.Addr(dir_info)) - if res != types.FRESULT.FR_OK: - break - attr_str: t.CArray[t.CChar, 8] = [0] - if dir_info.attr & types.AM_DIR: - string.strcat(attr_str, "D") - else: - string.strcat(attr_str, "F") - if dir_info.attr & types.AM_RDO: - string.strcat(attr_str, "R") - if dir_info.attr & types.AM_HID: - string.strcat(attr_str, "H") - if dir_info.attr & types.AM_SYS: - string.strcat(attr_str, "S") - if dir_info.attr & types.AM_ARC: - string.strcat(attr_str, "A") - print(f" [{attr_str}] {dir_info.fname} ({dir_info.file_size} 字节)") - fs.closedir(c.Addr(dp)) - print() - - # 11. 删除文件和目录 - print("--- 11. 删除文件和目录 ---") - - res = fs.remove("/test_dir_renamed/moved.txt") - print_fresult_void(res, "删除文件") - - res = fs.remove("/test_dir_1/large_file.txt") - print_fresult_void(res, "删除大文件") - - res = fs.rmdir("/test_dir_1/subdir") - print_fresult_void(res, "删除子目录") - - res = fs.rmdir("/test_dir_1") - print_fresult_void(res, "删除目录 /test_dir_1") - - res = fs.rmdir("/test_dir_renamed") - print_fresult_void(res, "删除目录 /test_dir_renamed") - print() - - # 12. 卸载文件系统 - print("--- 12. 卸载文件系统 ---") - res = fs.unmount() - print_fresult_void(res, "卸载文件系统") - print() - - print("=== 示例完成 ===") - return 0 +from stdint import * +import fat32 as fs +import fat32_types as types +import fat32_part as part +import fat32_mkfs as mkfs_mod +import string +import t, c + + +def print_fresult(res: types.FRESULT, msg: t.CConst | str) -> int: + if res == types.FRESULT.FR_OK: + print(f"[成功] {msg}") + return 0 + else: + print(f"[失败] {msg}: {res}") + return -1 + + +def print_fresult_void(res: types.FRESULT, msg: t.CConst | str): + print_fresult(res, msg) + + +def example_main() -> int: + print("=== FAT32 文件系统完整示例 ===") + print() + + # 1. 扫描可用驱动器 + print("--- 1. 扫描可用驱动器 ---") + res: types.FRESULT = fs.scan_drives() + print_fresult_void(res, "扫描驱动器") + + drive_count: int = fs.get_drive_count() + print(f"找到 {drive_count} 个驱动器") + i: int + for i in range(drive_count): + letter: t.CChar = fs.get_drive_letter(i) + part_count: int = fs.get_partition_count(letter) + print(f" 驱动器 {i}: {letter}") + for j in range(part_count): + is_fat32: int = fs.is_partition_fat32(letter, j) + print(f" 分区 {j}: FAT32={is_fat32}") + print() + + # 2. 挂载文件系统 + print("--- 2. 挂载文件系统 ---") + res = fs.mount() + if print_fresult(res, "挂载文件系统") != 0: + print("提示: 可能需要先格式化磁盘") + print() + + # 3. 文件系统信息 + print("--- 3. 文件系统信息 ---") + mounted: int = fs.is_mounted() + print(f"已挂载: {mounted}") + if mounted: + total_clusters: uint32 = fs.get_total() + free_clusters: uint32 = fs.get_free() + cluster_size: uint32 = fs.get_cluster_size() + total_bytes: uint64 = uint64(total_clusters) * uint64(cluster_size) + free_bytes: uint64 = uint64(free_clusters) * uint64(cluster_size) + print(f"总簇数: {total_clusters}") + print(f"空闲簇数: {free_clusters}") + print(f"簇大小: {cluster_size} 字节") + print(f"总大小: {total_bytes} 字节") + print(f"空闲大小: {free_bytes} 字节") + print() + + # 4. 元数据操作 + print("--- 4. 元数据操作 ---") + fs.set_metadata(0x12345678) + metadata: uint32 = fs.get_metadata() + print(f"设置的元数据: 0x{metadata:08X}") + print() + + # 5. 获取 FAT 时间 + print("--- 5. 获取 FAT 时间 ---") + fattime: uint32 = fs.get_fattime() + print(f"当前 FAT 时间: 0x{fattime:08X}") + print() + + # 6. 目录操作 + if fs.is_mounted(): + print("--- 6. 目录操作 ---") + + # 创建目录 + res = fs.mkdir("/test_dir_1") + print_fresult_void(res, "创建目录 /test_dir_1") + + res = fs.mkdir("/test_dir_1/subdir") + print_fresult_void(res, "创建子目录 /test_dir_1/subdir") + + res = fs.mkdir("/test_dir_2") + print_fresult_void(res, "创建目录 /test_dir_2") + print() + + # 7. 文件操作 + print("--- 7. 文件操作 ---") + + # 创建并写入文件 + fp1: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE) + if fp1 is not None: + test_data1: t.CConst | str = "Hello, World!" + written: uint32 = fs.write(fp1, test_data1, 13) + print(f"写入文件 /test_dir_1/file1.txt: {written} 字节") + fs.close(fp1) + + # 打开追加 + fp2: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_ALWAYS | types.FA_WRITE | types.FA_OPEN_APPEND) + if fp2 is not None: + test_data2: t.CConst | str = " Append data!" + written2: uint32 = fs.write(fp2, test_data2, 13) + print(f"追加写入: {written2} 字节") + fs.close(fp2) + + # 读取文件 + fp3: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_EXISTING | types.FA_READ) + if fp3 is not None: + buf: t.CArray[uint8, 256] + read_bytes: uint32 = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256) + print(f"读取字节数: {read_bytes}") + print(f"文件内容: {t.CChar(c.Addr(buf[0]), t.CPtr)}") + + # seek 和 tell + fs.seek(fp3, 5) + pos: uint32 = fs.tell(fp3) + print(f"seek 到位置 5, 当前位置: {pos}") + + read_bytes2: uint32 = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256) + print(f"从位置 5 读取: {t.CChar(c.Addr(buf[0]), t.CPtr)}") + + # 获取文件大小 + fsize: uint32 = fs.size(fp3) + print(f"文件大小: {fsize} 字节") + + fs.close(fp3) + + # 创建另一个文件 + fp4: types.fileobj | t.CPtr = fs.open("/test_dir_1/large_file.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE) + if fp4 is not None: + large_data: t.CArray[uint8, 1024] + k: int + for k in range(1024): + large_data[k] = uint8(ord('A') + (k % 26)) + written3: uint32 = fs.write(fp4, t.CVoid(c.Addr(large_data[0]), t.CPtr), 1024) + print(f"创建大文件, 写入: {written3} 字节") + fs.close(fp4) + print() + + # 8. 文件状态和属性 + print("--- 8. 文件状态和属性 ---") + + info: types.fileinfo + res = fs.stat("/test_dir_1/file1.txt", c.Addr(info)) + print_fresult_void(res, "获取文件信息") + if res == types.FRESULT.FR_OK: + print(f" 文件名: {info.fname}") + print(f" 大小: {info.file_size} 字节") + print(f" 属性: 0x{info.attr:02X}") + print(f" 创建时间: 0x{info.ctime:04X}") + print(f" 创建日期: 0x{info.cdate:04X}") + print(f" 修改时间: 0x{info.mtime:04X}") + print(f" 修改日期: 0x{info.mdate:04X}") + print(f" 访问日期: 0x{info.adate:04X}") + + # 修改属性 + res = fs.chmod("/test_dir_1/file1.txt", types.AM_RDO, types.AM_RDO) + print_fresult_void(res, "设置文件为只读") + print() + + # 9. 重命名和移动 + print("--- 9. 重命名和移动 ---") + + res = fs.rename("/test_dir_1/file1.txt", "/test_dir_1/renamed.txt") + print_fresult_void(res, "重命名文件") + + res = fs.move("/test_dir_1/renamed.txt", "/test_dir_2/moved.txt") + print_fresult_void(res, "移动文件") + + res = fs.rename("/test_dir_2", "/test_dir_renamed") + print_fresult_void(res, "重命名目录") + print() + + # 10. 列出目录 + print("--- 10. 列出目录 ---") + + dp: types.dirobj + res = fs.opendir("/", c.Addr(dp)) + if res == types.FRESULT.FR_OK: + print("根目录内容:") + dir_info: types.fileinfo + while True: + res = fs.readdir(c.Addr(dp), c.Addr(dir_info)) + if res != types.FRESULT.FR_OK: + break + attr_str: t.CArray[t.CChar, 8] = [0] + if dir_info.attr & types.AM_DIR: + string.strcat(attr_str, "D") + else: + string.strcat(attr_str, "F") + if dir_info.attr & types.AM_RDO: + string.strcat(attr_str, "R") + if dir_info.attr & types.AM_HID: + string.strcat(attr_str, "H") + if dir_info.attr & types.AM_SYS: + string.strcat(attr_str, "S") + if dir_info.attr & types.AM_ARC: + string.strcat(attr_str, "A") + print(f" [{attr_str}] {dir_info.fname} ({dir_info.file_size} 字节)") + fs.closedir(c.Addr(dp)) + print() + + # 11. 删除文件和目录 + print("--- 11. 删除文件和目录 ---") + + res = fs.remove("/test_dir_renamed/moved.txt") + print_fresult_void(res, "删除文件") + + res = fs.remove("/test_dir_1/large_file.txt") + print_fresult_void(res, "删除大文件") + + res = fs.rmdir("/test_dir_1/subdir") + print_fresult_void(res, "删除子目录") + + res = fs.rmdir("/test_dir_1") + print_fresult_void(res, "删除目录 /test_dir_1") + + res = fs.rmdir("/test_dir_renamed") + print_fresult_void(res, "删除目录 /test_dir_renamed") + print() + + # 12. 卸载文件系统 + print("--- 12. 卸载文件系统 ---") + res = fs.unmount() + print_fresult_void(res, "卸载文件系统") + print() + + print("=== 示例完成 ===") + return 0 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32.vp b/VKernel/Kernel/drivers/fs/fat32/fat32.vp index 05b7832..bddcb96 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32.vp @@ -1,214 +1,214 @@ -from stdint import * -import string -import fat32_types as types -import fat32_time as ftime -import fat32_mkfs as mkfs_mod -import fat32_part as part -import fat32_diskio as diskio -import sched.sched as sched -import viperlib -import drivers.serial.uart.serial as serial -import t, c - - -default_fs: types.volinfo = types.volinfo() -_fs_lock: t.CInt = 0 - -def lock(): - global _fs_lock - while True: - c.Asm("cli") - if _fs_lock == 0: - _fs_lock = 1 - c.Asm("sti") - return - c.Asm("sti") - sched.Scheduler._yield() - -def unlock(): - global _fs_lock - _fs_lock = 0 - -def mount() -> types.FRESULT: - default_fs.pdrv = 0 - default_fs.hidden_sectors = 0 - buf: t.CArray[t.CUInt8T, 512] - dres: types.DRESULT = diskio.read(0, c.Addr(buf[0]), 0, 1) - if dres == types.DRESULT.RES_OK: - if buf[0] == 0xEB or buf[0] == 0xE9: - default_fs.hidden_sectors = 0 - else: - sig: t.CUInt16T = t.CUInt16T(buf[510]) | (t.CUInt16T(buf[511]) << 8) - if sig == 0xAA55: - ptype: t.CUInt8T = buf[450] - if ptype != 0: - slba: t.CUInt32T = t.CUInt32T(buf[454]) | (t.CUInt32T(buf[455]) << 8) | (t.CUInt32T(buf[456]) << 16) | (t.CUInt32T(buf[457]) << 24) - default_fs.hidden_sectors = slba - if default_fs.mounted: return types.FRESULT.FR_OK - dsk_res: types.DRESULT = diskio.status(default_fs.pdrv) - if dsk_res != types.DRESULT.RES_OK: - dsk_res = diskio.init(default_fs.pdrv) - if dsk_res != types.DRESULT.RES_OK: return types.FRESULT.FR_NOT_READY - default_fs.winsect = 0xFFFFFFFFFFFFFFFF - default_fs.fat_winsect = 0xFFFFFFFFFFFFFFFF - wres: types.FRESULT = default_fs.win_read(0) - if wres != types.FRESULT.FR_OK: return types.FRESULT.FR_DISK_ERR - bps: t.CUInt16T = default_fs.win[11] | (t.CUInt16T(default_fs.win[12]) << 8) - spc: t.CUInt8T = default_fs.win[13] - rsc: t.CUInt16T = default_fs.win[14] | (t.CUInt16T(default_fs.win[15]) << 8) - nf: t.CUInt8T = default_fs.win[16] - if bps != 512: return types.FRESULT.FR_NO_FILESYSTEM - if spc == 0 or (spc & (spc - 1)) != 0: return types.FRESULT.FR_NO_FILESYSTEM - if rsc == 0: return types.FRESULT.FR_NO_FILESYSTEM - if nf == 0: return types.FRESULT.FR_NO_FILESYSTEM - root_ent: t.CUInt16T = default_fs.win[17] | (t.CUInt16T(default_fs.win[18]) << 8) - fat16sz: t.CUInt16T = default_fs.win[22] | (t.CUInt16T(default_fs.win[23]) << 8) - tot32: t.CUInt32T = t.CUInt32T(default_fs.win[32]) | (t.CUInt32T(default_fs.win[33]) << 8) | (t.CUInt32T(default_fs.win[34]) << 16) | (t.CUInt32T(default_fs.win[35]) << 24) - fat32sz: t.CUInt32T = t.CUInt32T(default_fs.win[36]) | (t.CUInt32T(default_fs.win[37]) << 8) | (t.CUInt32T(default_fs.win[38]) << 16) | (t.CUInt32T(default_fs.win[39]) << 24) - root_clus: t.CUInt32T = t.CUInt32T(default_fs.win[44]) | (t.CUInt32T(default_fs.win[45]) << 8) | (t.CUInt32T(default_fs.win[46]) << 16) | (t.CUInt32T(default_fs.win[47]) << 24) - if root_ent != 0 or fat16sz != 0: return types.FRESULT.FR_NO_FILESYSTEM - if fat32sz == 0: return types.FRESULT.FR_NO_FILESYSTEM - if tot32 == 0: return types.FRESULT.FR_NO_FILESYSTEM - if default_fs.win[510] != 0x55 or default_fs.win[511] != 0xAA: return types.FRESULT.FR_NO_FILESYSTEM - fsinfo_sec: t.CUInt16T = default_fs.win[48] | (t.CUInt16T(default_fs.win[49]) << 8) - bkboot_sec: t.CUInt16T = default_fs.win[50] | (t.CUInt16T(default_fs.win[51]) << 8) - default_fs.sector_size = 512 - default_fs.cluster_sectors = spc - default_fs.cluster_size = t.CUInt32T(spc) * 512 - default_fs.num_fats = nf - default_fs.reserved_sectors = rsc - default_fs.fat_size = fat32sz - default_fs.fat_start = t.CUInt64T(rsc) - default_fs.total_sectors = t.CUInt64T(tot32) - default_fs.root_cluster = root_clus - default_fs.fsinfo_sector = fsinfo_sec - default_fs.backup_sector = bkboot_sec - default_fs.vol_id = t.CUInt32T(default_fs.win[67]) | (t.CUInt32T(default_fs.win[68]) << 8) | (t.CUInt32T(default_fs.win[69]) << 16) | (t.CUInt32T(default_fs.win[70]) << 24) - data_sectors: t.CUInt64T = default_fs.total_sectors - t.CUInt64T(rsc) - t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz)) - default_fs.total_clusters = t.CUInt32T(data_sectors / t.CUInt64T(spc)) - default_fs.data_start = default_fs.fat_start + t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz)) - default_fs.last_alloc = 2 - default_fs.free_clusters = 0xFFFFFFFF - if fsinfo_sec != 0: - default_fs.fsinfo_read() - default_fs.mounted = 1 - return types.FRESULT.FR_OK - -def unmount() -> types.FRESULT: - return default_fs.unmount() - -def format(sec_per_clus: t.CUInt8T = 0, vol_id: t.CUInt32T = 0) -> types.FRESULT: - return mkfs_mod.mkfs(default_fs.pdrv, sec_per_clus, vol_id) - -def open(path: t.CConst | str, mode: t.CUInt8T) -> types.fileobj | t.CPtr: - return default_fs.file_open(path, mode) - -def close(fp: types.fileobj | t.CPtr) -> types.FRESULT: - return fp.close() - -def read(fp: types.fileobj | t.CPtr, buff: t.CVoid | t.CPtr, btr: t.CUInt32T) -> t.CUInt32T: - br: t.CUInt32T = 0 - fp.read(buff, btr, c.Addr(br)) - # [RD2-DIAG] 确认 br 是否被 c.Set 写入(types 内 total_read=64 但外部可能收不到) - _rd2: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_rd2), 96, "[fat32.vp] read br=%lu\n", br) - serial.puts(c.Addr(_rd2)) - return br - -def write(fp: types.fileobj | t.CPtr, buff: t.CConst | t.CVoid | t.CPtr, btw: t.CUInt32T) -> t.CUInt32T: - bw: t.CUInt32T = 0 - fp.write(buff, btw, c.Addr(bw)) - return bw - -def seek(fp: types.fileobj | t.CPtr, offset: t.CUInt32T) -> types.FRESULT: - return fp.seek(offset) - -def tell(fp: types.fileobj | t.CPtr) -> t.CUInt32T: - return fp.tell() - -def size(fp: types.fileobj | t.CPtr) -> t.CUInt32T: - return fp.size() - -def truncate(fp: types.fileobj | t.CPtr) -> types.FRESULT: - return fp.truncate() - -def remove(path: t.CConst | str) -> types.FRESULT: - return default_fs.file_delete(path) - -def rename(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT: - return default_fs.file_rename(old_path, new_path) - -def move(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT: - return default_fs.file_rename(old_path, new_path) - -def stat(path: t.CConst | str, info: types.fileinfo | t.CPtr) -> types.FRESULT: - return default_fs.file_stat(path, info) - -def mkdir(path: t.CConst | str) -> types.FRESULT: - return default_fs.dir_make(path) - -def rmdir(path: t.CConst | str) -> types.FRESULT: - return default_fs.dir_remove(path) - -def opendir(path: t.CConst | str, dp: types.dirobj | t.CPtr) -> types.FRESULT: - return default_fs.dir_open_path(path, dp) - -def readdir(dp: types.dirobj | t.CPtr, info: types.fileinfo | t.CPtr) -> types.FRESULT: - return default_fs.dir_read(dp, info) - -def closedir(dp: types.dirobj | t.CPtr): - dp.is_open = 0 - -def chmod(path: t.CConst | str, attr: t.CUInt8T, mask: t.CUInt8T) -> types.FRESULT: - return default_fs.chmod(path, attr, mask) - -def utime(path: t.CConst | str, mtime: t.CUInt16T, mdate: t.CUInt16T) -> types.FRESULT: - return default_fs.utime(path, mtime, mdate) - -def get_free() -> t.CUInt32T: - if not default_fs.mounted: return 0 - if default_fs.free_clusters == 0xFFFFFFFF: - return default_fs.count_free_clusters() - return default_fs.free_clusters - -def get_total() -> t.CUInt32T: - if not default_fs.mounted: return 0 - return default_fs.total_clusters - -def get_cluster_size() -> t.CUInt32T: - if not default_fs.mounted: return 0 - return default_fs.cluster_size - -def is_mounted() -> t.CInt: - return default_fs.mounted - -def last_error() -> t.CUInt32T: - return default_fs.last_error - -def get_fattime() -> t.CUInt32T: - return ftime.get_fattime() - -def get_metadata() -> t.CUInt32T: - return default_fs.metadata - -def set_metadata(val: t.CUInt32T): - default_fs.metadata = val - -def scan_drives() -> types.FRESULT: - return part.scan_drives() - -def get_drive_count() -> t.CInt: - return part.get_drive_count() - -def get_drive_letter(idx: t.CInt) -> t.CChar: - return part.get_drive_letter(idx) - -def set_drive_letter(idx: t.CInt, letter: t.CChar) -> types.FRESULT: - return part.set_drive_letter(idx, letter) - -def get_partition_count(letter: t.CChar) -> t.CInt: - return part.get_partition_count(letter) - -def is_partition_fat32(letter: t.CChar, part_idx: t.CInt) -> t.CInt: - return part.is_partition_fat32(letter, part_idx) - +from stdint import * +import string +import fat32_types as types +import fat32_time as ftime +import fat32_mkfs as mkfs_mod +import fat32_part as part +import fat32_diskio as diskio +import sched.sched as sched +import viperlib +import drivers.serial.uart.serial as serial +import t, c + + +default_fs: types.volinfo = types.volinfo() +_fs_lock: int = 0 + +def lock(): + global _fs_lock + while True: + c.Asm("cli") + if _fs_lock == 0: + _fs_lock = 1 + c.Asm("sti") + return + c.Asm("sti") + sched.Scheduler._yield() + +def unlock(): + global _fs_lock + _fs_lock = 0 + +def mount() -> types.FRESULT: + default_fs.pdrv = 0 + default_fs.hidden_sectors = 0 + buf: t.CArray[uint8, 512] + dres: types.DRESULT = diskio.read(0, c.Addr(buf[0]), 0, 1) + if dres == types.DRESULT.RES_OK: + if buf[0] == 0xEB or buf[0] == 0xE9: + default_fs.hidden_sectors = 0 + else: + sig: uint16 = uint16(buf[510]) | (uint16(buf[511]) << 8) + if sig == 0xAA55: + ptype: uint8 = buf[450] + if ptype != 0: + slba: uint32 = uint32(buf[454]) | (uint32(buf[455]) << 8) | (uint32(buf[456]) << 16) | (uint32(buf[457]) << 24) + default_fs.hidden_sectors = slba + if default_fs.mounted: return types.FRESULT.FR_OK + dsk_res: types.DRESULT = diskio.status(default_fs.pdrv) + if dsk_res != types.DRESULT.RES_OK: + dsk_res = diskio.init(default_fs.pdrv) + if dsk_res != types.DRESULT.RES_OK: return types.FRESULT.FR_NOT_READY + default_fs.winsect = 0xFFFFFFFFFFFFFFFF + default_fs.fat_winsect = 0xFFFFFFFFFFFFFFFF + wres: types.FRESULT = default_fs.win_read(0) + if wres != types.FRESULT.FR_OK: return types.FRESULT.FR_DISK_ERR + bps: uint16 = default_fs.win[11] | (uint16(default_fs.win[12]) << 8) + spc: uint8 = default_fs.win[13] + rsc: uint16 = default_fs.win[14] | (uint16(default_fs.win[15]) << 8) + nf: uint8 = default_fs.win[16] + if bps != 512: return types.FRESULT.FR_NO_FILESYSTEM + if spc == 0 or (spc & (spc - 1)) != 0: return types.FRESULT.FR_NO_FILESYSTEM + if rsc == 0: return types.FRESULT.FR_NO_FILESYSTEM + if nf == 0: return types.FRESULT.FR_NO_FILESYSTEM + root_ent: uint16 = default_fs.win[17] | (uint16(default_fs.win[18]) << 8) + fat16sz: uint16 = default_fs.win[22] | (uint16(default_fs.win[23]) << 8) + tot32: uint32 = uint32(default_fs.win[32]) | (uint32(default_fs.win[33]) << 8) | (uint32(default_fs.win[34]) << 16) | (uint32(default_fs.win[35]) << 24) + fat32sz: uint32 = uint32(default_fs.win[36]) | (uint32(default_fs.win[37]) << 8) | (uint32(default_fs.win[38]) << 16) | (uint32(default_fs.win[39]) << 24) + root_clus: uint32 = uint32(default_fs.win[44]) | (uint32(default_fs.win[45]) << 8) | (uint32(default_fs.win[46]) << 16) | (uint32(default_fs.win[47]) << 24) + if root_ent != 0 or fat16sz != 0: return types.FRESULT.FR_NO_FILESYSTEM + if fat32sz == 0: return types.FRESULT.FR_NO_FILESYSTEM + if tot32 == 0: return types.FRESULT.FR_NO_FILESYSTEM + if default_fs.win[510] != 0x55 or default_fs.win[511] != 0xAA: return types.FRESULT.FR_NO_FILESYSTEM + fsinfo_sec: uint16 = default_fs.win[48] | (uint16(default_fs.win[49]) << 8) + bkboot_sec: uint16 = default_fs.win[50] | (uint16(default_fs.win[51]) << 8) + default_fs.sector_size = 512 + default_fs.cluster_sectors = spc + default_fs.cluster_size = uint32(spc) * 512 + default_fs.num_fats = nf + default_fs.reserved_sectors = rsc + default_fs.fat_size = fat32sz + default_fs.fat_start = uint64(rsc) + default_fs.total_sectors = uint64(tot32) + default_fs.root_cluster = root_clus + default_fs.fsinfo_sector = fsinfo_sec + default_fs.backup_sector = bkboot_sec + default_fs.vol_id = uint32(default_fs.win[67]) | (uint32(default_fs.win[68]) << 8) | (uint32(default_fs.win[69]) << 16) | (uint32(default_fs.win[70]) << 24) + data_sectors: uint64 = default_fs.total_sectors - uint64(rsc) - uint64(uint64(nf) * uint64(fat32sz)) + default_fs.total_clusters = uint32(data_sectors / uint64(spc)) + default_fs.data_start = default_fs.fat_start + uint64(uint64(nf) * uint64(fat32sz)) + default_fs.last_alloc = 2 + default_fs.free_clusters = 0xFFFFFFFF + if fsinfo_sec != 0: + default_fs.fsinfo_read() + default_fs.mounted = 1 + return types.FRESULT.FR_OK + +def unmount() -> types.FRESULT: + return default_fs.unmount() + +def format(sec_per_clus: uint8 = 0, vol_id: uint32 = 0) -> types.FRESULT: + return mkfs_mod.mkfs(default_fs.pdrv, sec_per_clus, vol_id) + +def open(path: t.CConst | str, mode: uint8) -> types.fileobj | t.CPtr: + return default_fs.file_open(path, mode) + +def close(fp: types.fileobj | t.CPtr) -> types.FRESULT: + return fp.close() + +def read(fp: types.fileobj | t.CPtr, buff: t.CPtr, btr: uint32) -> uint32: + br: uint32 = 0 + fp.read(buff, btr, c.Addr(br)) + # [RD2-DIAG] 确认 br 是否被 c.Set 写入(types 内 total_read=64 但外部可能收不到) + _rd2: t.CArray[t.CChar, 96] + viperlib.snprintf(c.Addr(_rd2), 96, "[fat32.vp] read br=%lu\n", br) + serial.puts(c.Addr(_rd2)) + return br + +def write(fp: types.fileobj | t.CPtr, buff: t.CConst | t.CPtr, btw: uint32) -> uint32: + bw: uint32 = 0 + fp.write(buff, btw, c.Addr(bw)) + return bw + +def seek(fp: types.fileobj | t.CPtr, offset: uint32) -> types.FRESULT: + return fp.seek(offset) + +def tell(fp: types.fileobj | t.CPtr) -> uint32: + return fp.tell() + +def size(fp: types.fileobj | t.CPtr) -> uint32: + return fp.size() + +def truncate(fp: types.fileobj | t.CPtr) -> types.FRESULT: + return fp.truncate() + +def remove(path: t.CConst | str) -> types.FRESULT: + return default_fs.file_delete(path) + +def rename(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT: + return default_fs.file_rename(old_path, new_path) + +def move(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT: + return default_fs.file_rename(old_path, new_path) + +def stat(path: t.CConst | str, info: types.fileinfo | t.CPtr) -> types.FRESULT: + return default_fs.file_stat(path, info) + +def mkdir(path: t.CConst | str) -> types.FRESULT: + return default_fs.dir_make(path) + +def rmdir(path: t.CConst | str) -> types.FRESULT: + return default_fs.dir_remove(path) + +def opendir(path: t.CConst | str, dp: types.dirobj | t.CPtr) -> types.FRESULT: + return default_fs.dir_open_path(path, dp) + +def readdir(dp: types.dirobj | t.CPtr, info: types.fileinfo | t.CPtr) -> types.FRESULT: + return default_fs.dir_read(dp, info) + +def closedir(dp: types.dirobj | t.CPtr): + dp.is_open = 0 + +def chmod(path: t.CConst | str, attr: uint8, mask: uint8) -> types.FRESULT: + return default_fs.chmod(path, attr, mask) + +def utime(path: t.CConst | str, mtime: uint16, mdate: uint16) -> types.FRESULT: + return default_fs.utime(path, mtime, mdate) + +def get_free() -> uint32: + if not default_fs.mounted: return 0 + if default_fs.free_clusters == 0xFFFFFFFF: + return default_fs.count_free_clusters() + return default_fs.free_clusters + +def get_total() -> uint32: + if not default_fs.mounted: return 0 + return default_fs.total_clusters + +def get_cluster_size() -> uint32: + if not default_fs.mounted: return 0 + return default_fs.cluster_size + +def is_mounted() -> int: + return default_fs.mounted + +def last_error() -> uint32: + return default_fs.last_error + +def get_fattime() -> uint32: + return ftime.get_fattime() + +def get_metadata() -> uint32: + return default_fs.metadata + +def set_metadata(val: uint32): + default_fs.metadata = val + +def scan_drives() -> types.FRESULT: + return part.scan_drives() + +def get_drive_count() -> int: + return part.get_drive_count() + +def get_drive_letter(idx: int) -> t.CChar: + return part.get_drive_letter(idx) + +def set_drive_letter(idx: int, letter: t.CChar) -> types.FRESULT: + return part.set_drive_letter(idx, letter) + +def get_partition_count(letter: t.CChar) -> int: + return part.get_partition_count(letter) + +def is_partition_fat32(letter: t.CChar, part_idx: int) -> int: + return part.is_partition_fat32(letter, part_idx) + diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp index eb59ae2..1a90c49 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp @@ -1,16 +1,16 @@ -from stdint import * -import fat32_types as types -import t, c - - -_read32 = types._read32 -_read16 = types._read16 -_write32 = types._write32 -_write16 = types._write16 - - -def is_eoc(cluster: t.CUInt32T) -> t.CInt: - return 1 if (cluster >= types.CLUSTER_EOC_MIN and cluster <= types.CLUSTER_EOC_MAX) else 0 - -def is_free(cluster: t.CUInt32T) -> t.CInt: - return 1 if cluster == types.CLUSTER_FREE else 0 +from stdint import * +import fat32_types as types +import t, c + + +_read32 = types._read32 +_read16 = types._read16 +_write32 = types._write32 +_write16 = types._write16 + + +def is_eoc(cluster: uint32) -> int: + return 1 if (cluster >= types.CLUSTER_EOC_MIN and cluster <= types.CLUSTER_EOC_MAX) else 0 + +def is_free(cluster: uint32) -> int: + return 1 if cluster == types.CLUSTER_FREE else 0 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp index 232d782..818e5f1 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp @@ -1,81 +1,81 @@ -import drivers.storage.ide.ide as ide -import fat32_types as types -import spinlock -import string -import t, c - - -MAX_DRIVES: t.CDefine = 4 - -drive_initialized: t.CArray[t.CInt, MAX_DRIVES] -drive_lock: spinlock._spinlock = spinlock._spinlock() - -def status(pdrv: t.CUInt8T) -> types.DRESULT: - global drive_initialized - if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR - if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY - return types.DRESULT.RES_OK - -def init(pdrv: t.CUInt8T) -> types.DRESULT: - global drive_lock, drive_initialized - if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR - drive_lock.lock() - err: t.CInt = ide.init() - if err != 0: - drive_lock.unlock() - return types.DRESULT.RES_NOTRDY - drive_initialized[pdrv] = 1 - drive_lock.unlock() - return types.DRESULT.RES_OK - -def read(pdrv: t.CUInt8T, buff: t.CUInt8T | t.CPtr, sector: t.CUInt32T, count: t.CUInt32T) -> types.DRESULT: - global drive_initialized, drive_lock - if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR - if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY - drive_lock.lock() - i: t.CUInt32T - for i in range(count): - rd_res: t.CInt = ide.readSector(sector + i, buff + (i * 512)) - if rd_res != 0: - drive_lock.unlock() - return types.DRESULT.RES_ERROR - drive_lock.unlock() - return types.DRESULT.RES_OK - -def write(pdrv: t.CUInt8T, buff: t.CConst | t.CUInt8T | t.CPtr, sector: t.CUInt32T, count: t.CUInt32T) -> types.DRESULT: - global drive_initialized, drive_lock - if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR - if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY - drive_lock.lock() - i: t.CUInt32T - for i in range(count): - if ide.writeSector(sector + i, buff + (i * 512)) != 0: - drive_lock.unlock() - return types.DRESULT.RES_ERROR - drive_lock.unlock() - return types.DRESULT.RES_OK - -def ioctl(pdrv: t.CUInt8T, cmd: t.CUInt8T, buff: t.CVoid | t.CPtr) -> types.DRESULT: - global drive_initialized - if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR - if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY - match cmd: - case types.GET_SECTOR_COUNT: - disk_size: t.CUInt64T = ide.getDiskSize() - if disk_size == 0: - c.Set(c.Deref(t.CUInt32T(buff, t.CPtr)), 131072) - elif disk_size > 0xFFFFFFFF: - c.Set(c.Deref(t.CUInt32T(buff, t.CPtr)), 0xFFFFFFFF) - else: - c.Set(c.Deref(t.CUInt32T(buff, t.CPtr)), t.CUInt32T(disk_size)) - return types.DRESULT.RES_OK - case types.GET_SECTOR_SIZE: - c.Set(c.Deref(t.CUInt16T(buff, t.CPtr)), 512) - return types.DRESULT.RES_OK - case types.GET_BLOCK_SIZE: - c.Set(c.Deref(t.CUInt32T(buff, t.CPtr)), 1) - return types.DRESULT.RES_OK - case types.CTRL_SYNC: - return types.DRESULT.RES_OK - case _: - return types.DRESULT.RES_PARERR +import drivers.storage.ide.ide as ide +import fat32_types as types +import spinlock +import string +import t, c + + +MAX_DRIVES: t.CDefine = 4 + +drive_initialized: t.CArray[int, MAX_DRIVES] +drive_lock: spinlock._spinlock = spinlock._spinlock() + +def status(pdrv: uint8) -> types.DRESULT: + global drive_initialized + if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR + if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY + return types.DRESULT.RES_OK + +def init(pdrv: uint8) -> types.DRESULT: + global drive_lock, drive_initialized + if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR + drive_lock.lock() + err: int = ide.init() + if err != 0: + drive_lock.unlock() + return types.DRESULT.RES_NOTRDY + drive_initialized[pdrv] = 1 + drive_lock.unlock() + return types.DRESULT.RES_OK + +def read(pdrv: uint8, buff: uint8 | t.CPtr, sector: uint32, count: uint32) -> types.DRESULT: + global drive_initialized, drive_lock + if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR + if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY + drive_lock.lock() + i: uint32 + for i in range(count): + rd_res: int = ide.readSector(sector + i, buff + (i * 512)) + if rd_res != 0: + drive_lock.unlock() + return types.DRESULT.RES_ERROR + drive_lock.unlock() + return types.DRESULT.RES_OK + +def write(pdrv: uint8, buff: t.CConst | uint8 | t.CPtr, sector: uint32, count: uint32) -> types.DRESULT: + global drive_initialized, drive_lock + if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR + if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY + drive_lock.lock() + i: uint32 + for i in range(count): + if ide.writeSector(sector + i, buff + (i * 512)) != 0: + drive_lock.unlock() + return types.DRESULT.RES_ERROR + drive_lock.unlock() + return types.DRESULT.RES_OK + +def ioctl(pdrv: uint8, cmd: uint8, buff: t.CPtr) -> types.DRESULT: + global drive_initialized + if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR + if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY + match cmd: + case types.GET_SECTOR_COUNT: + disk_size: uint64 = ide.getDiskSize() + if disk_size == 0: + c.Set(c.Deref(uint32(buff, t.CPtr)), 131072) + elif disk_size > 0xFFFFFFFF: + c.Set(c.Deref(uint32(buff, t.CPtr)), 0xFFFFFFFF) + else: + c.Set(c.Deref(uint32(buff, t.CPtr)), uint32(disk_size)) + return types.DRESULT.RES_OK + case types.GET_SECTOR_SIZE: + c.Set(c.Deref(uint16(buff, t.CPtr)), 512) + return types.DRESULT.RES_OK + case types.GET_BLOCK_SIZE: + c.Set(c.Deref(uint32(buff, t.CPtr)), 1) + return types.DRESULT.RES_OK + case types.CTRL_SYNC: + return types.DRESULT.RES_OK + case _: + return types.DRESULT.RES_PARERR diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp index e34b950..8926055 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp @@ -1,143 +1,143 @@ -from stdint import * -import fat32_types as types -import fat32_diskio as diskio -import fat32_time as ftime -import string -import t, c - - -def _div_round_up(a: t.CUInt64T, b: t.CUInt64T) -> t.CUInt64T: - return (a + b - 1) / b - -def _calc_fat_size(total_sectors: t.CUInt64T, reserved: t.CUInt32T, sec_per_clus: t.CUInt8T, num_fats: t.CUInt8T) -> t.CUInt32T: - tmp: t.CUInt64T = total_sectors - t.CUInt64T(reserved) - fat_sz: t.CUInt32T = 1 - while True: - data_sectors: t.CUInt64T = tmp - t.CUInt64T(fat_sz) * t.CUInt64T(num_fats) - total_clusters: t.CUInt32T = t.CUInt32T(data_sectors / t.CUInt64T(sec_per_clus)) - needed: t.CUInt64T = _div_round_up(t.CUInt64T(total_clusters) * 4, 512) - if needed <= t.CUInt64T(fat_sz): break - fat_sz = t.CUInt32T(needed) - return fat_sz - -def _write_boot_sector(pdrv: t.CUInt8T, total_sectors: t.CUInt64T, sec_per_clus: t.CUInt8T, vol_id: t.CUInt32T, fat_sz: t.CUInt32T) -> types.DRESULT: - buf: t.CArray[t.CUInt8T, 512] - string.memset(c.Addr(buf[0]), 0, 512) - buf[0] = 0xEB; buf[1] = 0x58; buf[2] = 0x90 - buf[3] = 'M'; buf[4] = 'S'; buf[5] = 'W'; buf[6] = 'I'; buf[7] = 'N' - buf[8] = '4'; buf[9] = '.'; buf[10] = '1' - types._write16(c.Addr(buf[0]), 11, 512) - buf[13] = sec_per_clus - types._write16(c.Addr(buf[0]), 14, 32) - buf[16] = 2 - types._write16(c.Addr(buf[0]), 17, 0) - buf[21] = 0xF8 - types._write16(c.Addr(buf[0]), 22, 0) - types._write16(c.Addr(buf[0]), 24, 63) - types._write16(c.Addr(buf[0]), 26, 255) - types._write32(c.Addr(buf[0]), 28, 0) - types._write32(c.Addr(buf[0]), 32, t.CUInt32T(total_sectors)) - types._write32(c.Addr(buf[0]), 36, fat_sz) - types._write16(c.Addr(buf[0]), 40, 0) - types._write16(c.Addr(buf[0]), 42, 0) - types._write32(c.Addr(buf[0]), 44, 2) - types._write16(c.Addr(buf[0]), 48, 1) - types._write16(c.Addr(buf[0]), 50, 6) - buf[64] = 0x80 - buf[66] = 0x29 - types._write32(c.Addr(buf[0]), 67, vol_id) - vol_label: t.CArray[t.CChar, 11] - vol_label[0] = 'N'; vol_label[1] = 'O'; vol_label[2] = ' '; vol_label[3] = ' ' - vol_label[4] = ' '; vol_label[5] = ' '; vol_label[6] = ' '; vol_label[7] = ' ' - vol_label[8] = ' '; vol_label[9] = ' '; vol_label[10] = ' ' - i: t.CInt - for i in range(11): buf[71 + i] = t.CUInt8T(vol_label[i]) - buf[82] = 'F'; buf[83] = 'A'; buf[84] = 'T'; buf[85] = '3' - buf[86] = '2'; buf[87] = ' '; buf[88] = ' '; buf[89] = ' ' - buf[510] = 0x55; buf[511] = 0xAA - return diskio.write(pdrv, c.Addr(buf[0]), 0, 1) - -def _write_fsinfo(pdrv: t.CUInt8T, free_count: t.CUInt32T, next_free: t.CUInt32T) -> types.DRESULT: - buf: t.CArray[t.CUInt8T, 512] - string.memset(c.Addr(buf[0]), 0, 512) - types._write32(c.Addr(buf[0]), 0, 0x41615252) - types._write32(c.Addr(buf[0]), 484, 0x61417272) - types._write32(c.Addr(buf[0]), 488, free_count) - types._write32(c.Addr(buf[0]), 492, next_free) - types._write32(c.Addr(buf[0]), 508, 0xAA550000) - return diskio.write(pdrv, c.Addr(buf[0]), 1, 1) - -def _init_fat(pdrv: t.CUInt8T, fat_start: t.CUInt64T, fat_sz: t.CUInt32T, root_cluster: t.CUInt32T) -> types.DRESULT: - buf: t.CArray[t.CUInt8T, 512] - string.memset(c.Addr(buf[0]), 0, 512) - types._write32(c.Addr(buf[0]), 0, 0x0FFFFFF8) - types._write32(c.Addr(buf[0]), 4, 0x0FFFFFFF) - types._write32(c.Addr(buf[0]), 8, 0x0FFFFFFF) - if root_cluster >= 2: - cluster_off: t.CUInt32T = root_cluster * 4 - sector_off: t.CUInt32T = cluster_off / 512 - byte_off: t.CUInt32T = cluster_off % 512 - if sector_off == 0: - types._write32(c.Addr(buf[0]), byte_off, 0x0FFFFFFF) - res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(fat_start), 1) - if res != types.DRESULT.RES_OK: return res - string.memset(c.Addr(buf[0]), 0, 512) - s: t.CUInt32T - for s in range(1, fat_sz): - res2: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(fat_start) + s, 1) - if res2 != types.DRESULT.RES_OK: return res2 - return types.DRESULT.RES_OK - -def _init_root_dir(pdrv: t.CUInt8T, root_sector: t.CUInt64T, sec_per_clus: t.CUInt8T) -> types.DRESULT: - buf: t.CArray[t.CUInt8T, 512] - string.memset(c.Addr(buf[0]), 0, 512) - s: t.CUInt8T - for s in range(sec_per_clus): - res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(root_sector + t.CUInt64T(s)), 1) - if res != types.DRESULT.RES_OK: return res - return types.DRESULT.RES_OK - -def _calc_sec_per_clus(total_sectors: t.CUInt64T) -> t.CUInt8T: - ts: t.CUInt64T = total_sectors - if ts < 532480: return 1 - elif ts < 16777216: return 8 - elif ts < 33554432: return 16 - elif ts < 67108864: return 32 - else: return 64 - -def mkfs(pdrv: t.CUInt8T, sec_per_clus: t.CUInt8T, vol_id: t.CUInt32T) -> types.FRESULT: - if pdrv != types.DEV_DISK: return types.FRESULT.FR_INVALID_DRIVE - total_sectors_buf: t.CUInt32T = 0 - diskio.ioctl(pdrv, types.GET_SECTOR_COUNT, c.Addr(total_sectors_buf)) - total_sectors: t.CUInt64T = t.CUInt64T(total_sectors_buf) - if total_sectors < 65536: return types.FRESULT.FR_MKFS_ABORTED - if sec_per_clus == 0: sec_per_clus = _calc_sec_per_clus(total_sectors) - if sec_per_clus != 1 and sec_per_clus != 2 and sec_per_clus != 4 and sec_per_clus != 8 and sec_per_clus != 16 and sec_per_clus != 32 and sec_per_clus != 64 and sec_per_clus != 128: - return types.FRESULT.FR_INVALID_PARAMETER - if vol_id == 0: vol_id = ftime.get_fattime() - reserved: t.CUInt32T = 32 - num_fats: t.CUInt8T = 2 - fat_sz: t.CUInt32T = _calc_fat_size(total_sectors, reserved, sec_per_clus, num_fats) - data_sectors: t.CUInt64T = total_sectors - t.CUInt64T(reserved) - t.CUInt64T(fat_sz) * t.CUInt64T(num_fats) - total_clusters: t.CUInt32T = t.CUInt32T(data_sectors / t.CUInt64T(sec_per_clus)) - free_count: t.CUInt32T = total_clusters - 1 - res: types.DRESULT = _write_boot_sector(pdrv, total_sectors, sec_per_clus, vol_id, fat_sz) - if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - res2: types.DRESULT = _write_fsinfo(pdrv, free_count, 3) - if res2 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - boot_backup: t.CArray[t.CUInt8T, 512] - diskio.read(pdrv, c.Addr(boot_backup[0]), 0, 1) - diskio.write(pdrv, c.Addr(boot_backup[0]), 6, 1) - fsinfo_backup: t.CArray[t.CUInt8T, 512] - diskio.read(pdrv, c.Addr(fsinfo_backup[0]), 1, 1) - diskio.write(pdrv, c.Addr(fsinfo_backup[0]), 7, 1) - fat_start: t.CUInt64T = t.CUInt64T(reserved) - res3: types.DRESULT = _init_fat(pdrv, fat_start, fat_sz, 2) - if res3 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - fat2_start: t.CUInt64T = fat_start + t.CUInt64T(fat_sz) - res4: types.DRESULT = _init_fat(pdrv, fat2_start, fat_sz, 2) - if res4 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - root_sector: t.CUInt64T = fat2_start + t.CUInt64T(fat_sz) - res5: types.DRESULT = _init_root_dir(pdrv, root_sector, sec_per_clus) - if res5 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - return types.FRESULT.FR_OK +from stdint import * +import fat32_types as types +import fat32_diskio as diskio +import fat32_time as ftime +import string +import t, c + + +def _div_round_up(a: uint64, b: uint64) -> uint64: + return (a + b - 1) / b + +def _calc_fat_size(total_sectors: uint64, reserved: uint32, sec_per_clus: uint8, num_fats: uint8) -> uint32: + tmp: uint64 = total_sectors - uint64(reserved) + fat_sz: uint32 = 1 + while True: + data_sectors: uint64 = tmp - uint64(fat_sz) * uint64(num_fats) + total_clusters: uint32 = uint32(data_sectors / uint64(sec_per_clus)) + needed: uint64 = _div_round_up(uint64(total_clusters) * 4, 512) + if needed <= uint64(fat_sz): break + fat_sz = uint32(needed) + return fat_sz + +def _write_boot_sector(pdrv: uint8, total_sectors: uint64, sec_per_clus: uint8, vol_id: uint32, fat_sz: uint32) -> types.DRESULT: + buf: t.CArray[uint8, 512] + string.memset(c.Addr(buf[0]), 0, 512) + buf[0] = 0xEB; buf[1] = 0x58; buf[2] = 0x90 + buf[3] = 'M'; buf[4] = 'S'; buf[5] = 'W'; buf[6] = 'I'; buf[7] = 'N' + buf[8] = '4'; buf[9] = '.'; buf[10] = '1' + types._write16(c.Addr(buf[0]), 11, 512) + buf[13] = sec_per_clus + types._write16(c.Addr(buf[0]), 14, 32) + buf[16] = 2 + types._write16(c.Addr(buf[0]), 17, 0) + buf[21] = 0xF8 + types._write16(c.Addr(buf[0]), 22, 0) + types._write16(c.Addr(buf[0]), 24, 63) + types._write16(c.Addr(buf[0]), 26, 255) + types._write32(c.Addr(buf[0]), 28, 0) + types._write32(c.Addr(buf[0]), 32, uint32(total_sectors)) + types._write32(c.Addr(buf[0]), 36, fat_sz) + types._write16(c.Addr(buf[0]), 40, 0) + types._write16(c.Addr(buf[0]), 42, 0) + types._write32(c.Addr(buf[0]), 44, 2) + types._write16(c.Addr(buf[0]), 48, 1) + types._write16(c.Addr(buf[0]), 50, 6) + buf[64] = 0x80 + buf[66] = 0x29 + types._write32(c.Addr(buf[0]), 67, vol_id) + vol_label: t.CArray[t.CChar, 11] + vol_label[0] = 'N'; vol_label[1] = 'O'; vol_label[2] = ' '; vol_label[3] = ' ' + vol_label[4] = ' '; vol_label[5] = ' '; vol_label[6] = ' '; vol_label[7] = ' ' + vol_label[8] = ' '; vol_label[9] = ' '; vol_label[10] = ' ' + i: int + for i in range(11): buf[71 + i] = uint8(vol_label[i]) + buf[82] = 'F'; buf[83] = 'A'; buf[84] = 'T'; buf[85] = '3' + buf[86] = '2'; buf[87] = ' '; buf[88] = ' '; buf[89] = ' ' + buf[510] = 0x55; buf[511] = 0xAA + return diskio.write(pdrv, c.Addr(buf[0]), 0, 1) + +def _write_fsinfo(pdrv: uint8, free_count: uint32, next_free: uint32) -> types.DRESULT: + buf: t.CArray[uint8, 512] + string.memset(c.Addr(buf[0]), 0, 512) + types._write32(c.Addr(buf[0]), 0, 0x41615252) + types._write32(c.Addr(buf[0]), 484, 0x61417272) + types._write32(c.Addr(buf[0]), 488, free_count) + types._write32(c.Addr(buf[0]), 492, next_free) + types._write32(c.Addr(buf[0]), 508, 0xAA550000) + return diskio.write(pdrv, c.Addr(buf[0]), 1, 1) + +def _init_fat(pdrv: uint8, fat_start: uint64, fat_sz: uint32, root_cluster: uint32) -> types.DRESULT: + buf: t.CArray[uint8, 512] + string.memset(c.Addr(buf[0]), 0, 512) + types._write32(c.Addr(buf[0]), 0, 0x0FFFFFF8) + types._write32(c.Addr(buf[0]), 4, 0x0FFFFFFF) + types._write32(c.Addr(buf[0]), 8, 0x0FFFFFFF) + if root_cluster >= 2: + cluster_off: uint32 = root_cluster * 4 + sector_off: uint32 = cluster_off / 512 + byte_off: uint32 = cluster_off % 512 + if sector_off == 0: + types._write32(c.Addr(buf[0]), byte_off, 0x0FFFFFFF) + res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(fat_start), 1) + if res != types.DRESULT.RES_OK: return res + string.memset(c.Addr(buf[0]), 0, 512) + s: uint32 + for s in range(1, fat_sz): + res2: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(fat_start) + s, 1) + if res2 != types.DRESULT.RES_OK: return res2 + return types.DRESULT.RES_OK + +def _init_root_dir(pdrv: uint8, root_sector: uint64, sec_per_clus: uint8) -> types.DRESULT: + buf: t.CArray[uint8, 512] + string.memset(c.Addr(buf[0]), 0, 512) + s: uint8 + for s in range(sec_per_clus): + res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(root_sector + uint64(s)), 1) + if res != types.DRESULT.RES_OK: return res + return types.DRESULT.RES_OK + +def _calc_sec_per_clus(total_sectors: uint64) -> uint8: + ts: uint64 = total_sectors + if ts < 532480: return 1 + elif ts < 16777216: return 8 + elif ts < 33554432: return 16 + elif ts < 67108864: return 32 + else: return 64 + +def mkfs(pdrv: uint8, sec_per_clus: uint8, vol_id: uint32) -> types.FRESULT: + if pdrv != types.DEV_DISK: return types.FRESULT.FR_INVALID_DRIVE + total_sectors_buf: uint32 = 0 + diskio.ioctl(pdrv, types.GET_SECTOR_COUNT, c.Addr(total_sectors_buf)) + total_sectors: uint64 = uint64(total_sectors_buf) + if total_sectors < 65536: return types.FRESULT.FR_MKFS_ABORTED + if sec_per_clus == 0: sec_per_clus = _calc_sec_per_clus(total_sectors) + if sec_per_clus != 1 and sec_per_clus != 2 and sec_per_clus != 4 and sec_per_clus != 8 and sec_per_clus != 16 and sec_per_clus != 32 and sec_per_clus != 64 and sec_per_clus != 128: + return types.FRESULT.FR_INVALID_PARAMETER + if vol_id == 0: vol_id = ftime.get_fattime() + reserved: uint32 = 32 + num_fats: uint8 = 2 + fat_sz: uint32 = _calc_fat_size(total_sectors, reserved, sec_per_clus, num_fats) + data_sectors: uint64 = total_sectors - uint64(reserved) - uint64(fat_sz) * uint64(num_fats) + total_clusters: uint32 = uint32(data_sectors / uint64(sec_per_clus)) + free_count: uint32 = total_clusters - 1 + res: types.DRESULT = _write_boot_sector(pdrv, total_sectors, sec_per_clus, vol_id, fat_sz) + if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + res2: types.DRESULT = _write_fsinfo(pdrv, free_count, 3) + if res2 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + boot_backup: t.CArray[uint8, 512] + diskio.read(pdrv, c.Addr(boot_backup[0]), 0, 1) + diskio.write(pdrv, c.Addr(boot_backup[0]), 6, 1) + fsinfo_backup: t.CArray[uint8, 512] + diskio.read(pdrv, c.Addr(fsinfo_backup[0]), 1, 1) + diskio.write(pdrv, c.Addr(fsinfo_backup[0]), 7, 1) + fat_start: uint64 = uint64(reserved) + res3: types.DRESULT = _init_fat(pdrv, fat_start, fat_sz, 2) + if res3 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + fat2_start: uint64 = fat_start + uint64(fat_sz) + res4: types.DRESULT = _init_fat(pdrv, fat2_start, fat_sz, 2) + if res4 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + root_sector: uint64 = fat2_start + uint64(fat_sz) + res5: types.DRESULT = _init_root_dir(pdrv, root_sector, sec_per_clus) + if res5 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + return types.FRESULT.FR_OK diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp index 161665e..594e49f 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp @@ -1,153 +1,153 @@ -from stdint import * -import fat32_types as types -import fat32_diskio as diskio -import string -import t, c - - -MAX_VOLUMES: t.CDefine = 4 -MAX_PARTITIONS: t.CDefine = 4 - -MBR_SIGNATURE: t.CDefine = 0xAA55 -PART_TYPE_FAT32: t.CDefine = 0x0C -PART_TYPE_FAT32_LBA: t.CDefine = 0x0B -PART_TYPE_FAT16: t.CDefine = 0x06 -PART_TYPE_FAT16_LBA: t.CDefine = 0x0E - -class partition_entry: - boot_flag: t.CUInt8T - start_chs: t.CArray[t.CUInt8T, 3] - part_type: t.CUInt8T - end_chs: t.CArray[t.CUInt8T, 3] - start_lba: t.CUInt32T - total_sectors: t.CUInt32T - -drive_pdrv: t.CArray[t.CUInt8T, MAX_VOLUMES] -drive_num_parts: t.CArray[t.CInt, MAX_VOLUMES] -drive_letter_map: t.CArray[t.CChar, MAX_VOLUMES] -volume_mounted: t.CArray[t.CInt, MAX_VOLUMES] -part_types: t.CArray[t.CUInt8T, MAX_VOLUMES * MAX_PARTITIONS] -part_start_lbas: t.CArray[t.CUInt64T, MAX_VOLUMES * MAX_PARTITIONS] -part_totals: t.CArray[t.CUInt64T, MAX_VOLUMES * MAX_PARTITIONS] -part_is_fat32: t.CArray[t.CInt, MAX_VOLUMES * MAX_PARTITIONS] - -num_drives: t.CInt = 0 - -def _init(): - global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts - global part_types, part_start_lbas, part_totals, part_is_fat32 - if num_drives > 0: return - i: t.CInt - for i in range(MAX_VOLUMES): - drive_letter_map[i] = 0 - volume_mounted[i] = 0 - drive_pdrv[i] = 0 - drive_num_parts[i] = 0 - j: t.CInt - for j in range(MAX_VOLUMES * MAX_PARTITIONS): - part_types[j] = 0 - part_start_lbas[j] = 0 - part_totals[j] = 0 - part_is_fat32[j] = 0 - -def _part_idx(drive: t.CInt, part: t.CInt) -> t.CInt: - return drive * MAX_PARTITIONS + part - -def parse_mbr(pdrv: t.CUInt8T, drive_idx: t.CInt) -> types.FRESULT: - global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts - global part_types, part_start_lbas, part_totals, part_is_fat32 - buf: t.CArray[t.CUInt8T, 512] - res: types.DRESULT = diskio.read(pdrv, c.Addr(buf[0]), 0, 1) - if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR - if buf[0] == 0xEB or buf[0] == 0xE9: - return types.FRESULT.FR_NO_FILESYSTEM - sig: t.CUInt16T = t.CUInt16T(buf[510]) | (t.CUInt16T(buf[511]) << 8) - if sig != MBR_SIGNATURE: return types.FRESULT.FR_NO_FILESYSTEM - drive_pdrv[drive_idx] = pdrv - drive_num_parts[drive_idx] = 0 - i: t.CInt - for i in range(4): - base: t.CUInt32T = 446 + t.CUInt32T(i * 16) - ptype: t.CUInt8T = buf[base + 4] - slba: t.CUInt32T = t.CUInt32T(buf[base + 8]) | (t.CUInt32T(buf[base + 9]) << 8) | (t.CUInt32T(buf[base + 10]) << 16) | (t.CUInt32T(buf[base + 11]) << 24) - tsec: t.CUInt32T = t.CUInt32T(buf[base + 12]) | (t.CUInt32T(buf[base + 13]) << 8) | (t.CUInt32T(buf[base + 14]) << 16) | (t.CUInt32T(buf[base + 15]) << 24) - if ptype != 0 and tsec > 0: - pi: t.CInt = drive_num_parts[drive_idx] - if pi < MAX_PARTITIONS: - pidx: t.CInt = _part_idx(drive_idx, pi) - part_types[pidx] = ptype - part_start_lbas[pidx] = t.CUInt64T(slba) - part_totals[pidx] = t.CUInt64T(tsec) - part_is_fat32[pidx] = 1 if (ptype == PART_TYPE_FAT32 or ptype == PART_TYPE_FAT32_LBA) else 0 - drive_num_parts[drive_idx] = pi + 1 - return types.FRESULT.FR_OK - -def scan_drives() -> types.FRESULT: - global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts - global part_types, part_start_lbas, part_totals, part_is_fat32 - _init() - global num_drives - num_drives = 0 - pdrv: t.CUInt8T - for pdrv in range(MAX_VOLUMES): - res: types.DRESULT = diskio.init(pdrv) - if res != types.DRESULT.RES_OK: continue - res2: types.FRESULT = parse_mbr(pdrv, num_drives) - if res2 == types.FRESULT.FR_OK and drive_num_parts[num_drives] > 0: - drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives) - else: - drive_pdrv[num_drives] = pdrv - drive_num_parts[num_drives] = 1 - pidx: t.CInt = _part_idx(num_drives, 0) - part_types[pidx] = PART_TYPE_FAT32_LBA - part_start_lbas[pidx] = 0 - part_totals[pidx] = 0 - part_is_fat32[pidx] = 1 - drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives) - num_drives = num_drives + 1 - if num_drives >= MAX_VOLUMES: break - return types.FRESULT.FR_OK - -def get_drive(letter: t.CChar) -> t.CInt: - _init() - i: t.CInt - for i in range(num_drives): - if drive_letter_map[i] == letter or drive_letter_map[i] == (letter - 32) or drive_letter_map[i] == (letter + 32): - return i - return -1 - -def get_pdrv(letter: t.CChar) -> t.CUInt8T: - idx: t.CInt = get_drive(letter) - if idx < 0: return 0 - return drive_pdrv[idx] - -def get_partition_start(letter: t.CChar, part_idx: t.CInt) -> t.CUInt64T: - idx: t.CInt = get_drive(letter) - if idx < 0: return 0 - if part_idx >= drive_num_parts[idx]: return 0 - pidx: t.CInt = _part_idx(idx, part_idx) - return part_start_lbas[pidx] - -def get_partition_count(letter: t.CChar) -> t.CInt: - idx: t.CInt = get_drive(letter) - if idx < 0: return 0 - return drive_num_parts[idx] - -def is_partition_fat32(letter: t.CChar, part_idx: t.CInt) -> t.CInt: - idx: t.CInt = get_drive(letter) - if idx < 0: return 0 - if part_idx >= drive_num_parts[idx]: return 0 - pidx: t.CInt = _part_idx(idx, part_idx) - return part_is_fat32[pidx] - -def get_drive_count() -> t.CInt: - return num_drives - -def get_drive_letter(idx: t.CInt) -> t.CChar: - if idx < 0 or idx >= num_drives: return 0 - return drive_letter_map[idx] - -def set_drive_letter(idx: t.CInt, letter: t.CChar) -> types.FRESULT: - if idx < 0 or idx >= num_drives: return types.FRESULT.FR_INVALID_PARAMETER - drive_letter_map[idx] = letter - return types.FRESULT.FR_OK +from stdint import * +import fat32_types as types +import fat32_diskio as diskio +import string +import t, c + + +MAX_VOLUMES: t.CDefine = 4 +MAX_PARTITIONS: t.CDefine = 4 + +MBR_SIGNATURE: t.CDefine = 0xAA55 +PART_TYPE_FAT32: t.CDefine = 0x0C +PART_TYPE_FAT32_LBA: t.CDefine = 0x0B +PART_TYPE_FAT16: t.CDefine = 0x06 +PART_TYPE_FAT16_LBA: t.CDefine = 0x0E + +class partition_entry: + boot_flag: uint8 + start_chs: t.CArray[uint8, 3] + part_type: uint8 + end_chs: t.CArray[uint8, 3] + start_lba: uint32 + total_sectors: uint32 + +drive_pdrv: t.CArray[uint8, MAX_VOLUMES] +drive_num_parts: t.CArray[int, MAX_VOLUMES] +drive_letter_map: t.CArray[t.CChar, MAX_VOLUMES] +volume_mounted: t.CArray[int, MAX_VOLUMES] +part_types: t.CArray[uint8, MAX_VOLUMES * MAX_PARTITIONS] +part_start_lbas: t.CArray[uint64, MAX_VOLUMES * MAX_PARTITIONS] +part_totals: t.CArray[uint64, MAX_VOLUMES * MAX_PARTITIONS] +part_is_fat32: t.CArray[int, MAX_VOLUMES * MAX_PARTITIONS] + +num_drives: int = 0 + +def _init(): + global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts + global part_types, part_start_lbas, part_totals, part_is_fat32 + if num_drives > 0: return + i: int + for i in range(MAX_VOLUMES): + drive_letter_map[i] = 0 + volume_mounted[i] = 0 + drive_pdrv[i] = 0 + drive_num_parts[i] = 0 + j: int + for j in range(MAX_VOLUMES * MAX_PARTITIONS): + part_types[j] = 0 + part_start_lbas[j] = 0 + part_totals[j] = 0 + part_is_fat32[j] = 0 + +def _part_idx(drive: int, part: int) -> int: + return drive * MAX_PARTITIONS + part + +def parse_mbr(pdrv: uint8, drive_idx: int) -> types.FRESULT: + global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts + global part_types, part_start_lbas, part_totals, part_is_fat32 + buf: t.CArray[uint8, 512] + res: types.DRESULT = diskio.read(pdrv, c.Addr(buf[0]), 0, 1) + if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR + if buf[0] == 0xEB or buf[0] == 0xE9: + return types.FRESULT.FR_NO_FILESYSTEM + sig: uint16 = uint16(buf[510]) | (uint16(buf[511]) << 8) + if sig != MBR_SIGNATURE: return types.FRESULT.FR_NO_FILESYSTEM + drive_pdrv[drive_idx] = pdrv + drive_num_parts[drive_idx] = 0 + i: int + for i in range(4): + base: uint32 = 446 + uint32(i * 16) + ptype: uint8 = buf[base + 4] + slba: uint32 = uint32(buf[base + 8]) | (uint32(buf[base + 9]) << 8) | (uint32(buf[base + 10]) << 16) | (uint32(buf[base + 11]) << 24) + tsec: uint32 = uint32(buf[base + 12]) | (uint32(buf[base + 13]) << 8) | (uint32(buf[base + 14]) << 16) | (uint32(buf[base + 15]) << 24) + if ptype != 0 and tsec > 0: + pi: int = drive_num_parts[drive_idx] + if pi < MAX_PARTITIONS: + pidx: int = _part_idx(drive_idx, pi) + part_types[pidx] = ptype + part_start_lbas[pidx] = uint64(slba) + part_totals[pidx] = uint64(tsec) + part_is_fat32[pidx] = 1 if (ptype == PART_TYPE_FAT32 or ptype == PART_TYPE_FAT32_LBA) else 0 + drive_num_parts[drive_idx] = pi + 1 + return types.FRESULT.FR_OK + +def scan_drives() -> types.FRESULT: + global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts + global part_types, part_start_lbas, part_totals, part_is_fat32 + _init() + global num_drives + num_drives = 0 + pdrv: uint8 + for pdrv in range(MAX_VOLUMES): + res: types.DRESULT = diskio.init(pdrv) + if res != types.DRESULT.RES_OK: continue + res2: types.FRESULT = parse_mbr(pdrv, num_drives) + if res2 == types.FRESULT.FR_OK and drive_num_parts[num_drives] > 0: + drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives) + else: + drive_pdrv[num_drives] = pdrv + drive_num_parts[num_drives] = 1 + pidx: int = _part_idx(num_drives, 0) + part_types[pidx] = PART_TYPE_FAT32_LBA + part_start_lbas[pidx] = 0 + part_totals[pidx] = 0 + part_is_fat32[pidx] = 1 + drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives) + num_drives = num_drives + 1 + if num_drives >= MAX_VOLUMES: break + return types.FRESULT.FR_OK + +def get_drive(letter: t.CChar) -> int: + _init() + i: int + for i in range(num_drives): + if drive_letter_map[i] == letter or drive_letter_map[i] == (letter - 32) or drive_letter_map[i] == (letter + 32): + return i + return -1 + +def get_pdrv(letter: t.CChar) -> uint8: + idx: int = get_drive(letter) + if idx < 0: return 0 + return drive_pdrv[idx] + +def get_partition_start(letter: t.CChar, part_idx: int) -> uint64: + idx: int = get_drive(letter) + if idx < 0: return 0 + if part_idx >= drive_num_parts[idx]: return 0 + pidx: int = _part_idx(idx, part_idx) + return part_start_lbas[pidx] + +def get_partition_count(letter: t.CChar) -> int: + idx: int = get_drive(letter) + if idx < 0: return 0 + return drive_num_parts[idx] + +def is_partition_fat32(letter: t.CChar, part_idx: int) -> int: + idx: int = get_drive(letter) + if idx < 0: return 0 + if part_idx >= drive_num_parts[idx]: return 0 + pidx: int = _part_idx(idx, part_idx) + return part_is_fat32[pidx] + +def get_drive_count() -> int: + return num_drives + +def get_drive_letter(idx: int) -> t.CChar: + if idx < 0 or idx >= num_drives: return 0 + return drive_letter_map[idx] + +def set_drive_letter(idx: int, letter: t.CChar) -> types.FRESULT: + if idx < 0 or idx >= num_drives: return types.FRESULT.FR_INVALID_PARAMETER + drive_letter_map[idx] = letter + return types.FRESULT.FR_OK diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp index 30e1e7a..494be9d 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp @@ -1,64 +1,64 @@ -from stdint import * -import t, c -import asm - - -rtc_cmos_addr: t.CUInt16T = 0x70 -rtc_cmos_data: t.CUInt16T = 0x71 - -def cmos_read(reg: t.CUInt8T) -> t.CUInt8T: - asm.outb(rtc_cmos_addr, reg) - return asm.inb(rtc_cmos_data) - -def bcd_to_bin(bcd: t.CUInt8T) -> t.CUInt8T: - return (bcd >> 4) * 10 + (bcd & 0x0F) - -def get_rtc_time() -> t.CUInt32T: - while cmos_read(0x0A) & 0x80: pass - sec: t.CUInt8T = cmos_read(0x00) - min_: t.CUInt8T = cmos_read(0x02) - hour: t.CUInt8T = cmos_read(0x04) - day: t.CUInt8T = cmos_read(0x07) - mon: t.CUInt8T = cmos_read(0x08) - year: t.CUInt8T = cmos_read(0x09) - reg_b: t.CUInt8T = cmos_read(0x0B) - if not (reg_b & 0x04): - sec = bcd_to_bin(sec) - min_ = bcd_to_bin(min_) - hour = bcd_to_bin(hour) - day = bcd_to_bin(day) - mon = bcd_to_bin(mon) - year = bcd_to_bin(year) - fat_year: t.CUInt16T = t.CUInt16T(year) + 2000 - 1980 - if fat_year > 127: fat_year = 127 - fat_date: t.CUInt16T = (fat_year << 9) | (t.CUInt16T(mon) << 5) | t.CUInt16T(day) - fat_time: t.CUInt16T = (t.CUInt16T(hour) << 11) | (t.CUInt16T(min_) << 5) | (t.CUInt16T(sec) / 2) - return (t.CUInt32T(fat_date) << 16) | t.CUInt32T(fat_time) - -def get_fattime() -> t.CUInt32T: - return get_rtc_time() - -def to_year(ft: t.CUInt32T) -> t.CUInt16T: - return t.CUInt16T((ft >> 25) & 0x7F) + 1980 - -def to_month(ft: t.CUInt32T) -> t.CUInt8T: - return t.CUInt8T((ft >> 21) & 0x0F) - -def to_day(ft: t.CUInt32T) -> t.CUInt8T: - return t.CUInt8T((ft >> 16) & 0x1F) - -def to_hour(ft: t.CUInt32T) -> t.CUInt8T: - return t.CUInt8T((ft >> 11) & 0x1F) - -def to_minute(ft: t.CUInt32T) -> t.CUInt8T: - return t.CUInt8T((ft >> 5) & 0x3F) - -def to_second(ft: t.CUInt32T) -> t.CUInt8T: - return t.CUInt8T((ft & 0x1F) * 2) - -def make(year: t.CUInt16T, month: t.CUInt8T, day: t.CUInt8T, hour: t.CUInt8T, minute: t.CUInt8T, second: t.CUInt8T) -> t.CUInt32T: - fat_year: t.CUInt16T = year - 1980 - if fat_year > 127: fat_year = 127 - fat_date: t.CUInt16T = (fat_year << 9) | (t.CUInt16T(month) << 5) | t.CUInt16T(day) - fat_time: t.CUInt16T = (t.CUInt16T(hour) << 11) | (t.CUInt16T(minute) << 5) | (t.CUInt16T(second) / 2) - return (t.CUInt32T(fat_date) << 16) | t.CUInt32T(fat_time) +from stdint import * +import t, c +import asm + + +rtc_cmos_addr: uint16 = 0x70 +rtc_cmos_data: uint16 = 0x71 + +def cmos_read(reg: uint8) -> uint8: + asm.outb(rtc_cmos_addr, reg) + return asm.inb(rtc_cmos_data) + +def bcd_to_bin(bcd: uint8) -> uint8: + return (bcd >> 4) * 10 + (bcd & 0x0F) + +def get_rtc_time() -> uint32: + while cmos_read(0x0A) & 0x80: pass + sec: uint8 = cmos_read(0x00) + min_: uint8 = cmos_read(0x02) + hour: uint8 = cmos_read(0x04) + day: uint8 = cmos_read(0x07) + mon: uint8 = cmos_read(0x08) + year: uint8 = cmos_read(0x09) + reg_b: uint8 = cmos_read(0x0B) + if not (reg_b & 0x04): + sec = bcd_to_bin(sec) + min_ = bcd_to_bin(min_) + hour = bcd_to_bin(hour) + day = bcd_to_bin(day) + mon = bcd_to_bin(mon) + year = bcd_to_bin(year) + fat_year: uint16 = uint16(year) + 2000 - 1980 + if fat_year > 127: fat_year = 127 + fat_date: uint16 = (fat_year << 9) | (uint16(mon) << 5) | uint16(day) + fat_time: uint16 = (uint16(hour) << 11) | (uint16(min_) << 5) | (uint16(sec) / 2) + return (uint32(fat_date) << 16) | uint32(fat_time) + +def get_fattime() -> uint32: + return get_rtc_time() + +def to_year(ft: uint32) -> uint16: + return uint16((ft >> 25) & 0x7F) + 1980 + +def to_month(ft: uint32) -> uint8: + return uint8((ft >> 21) & 0x0F) + +def to_day(ft: uint32) -> uint8: + return uint8((ft >> 16) & 0x1F) + +def to_hour(ft: uint32) -> uint8: + return uint8((ft >> 11) & 0x1F) + +def to_minute(ft: uint32) -> uint8: + return uint8((ft >> 5) & 0x3F) + +def to_second(ft: uint32) -> uint8: + return uint8((ft & 0x1F) * 2) + +def make(year: uint16, month: uint8, day: uint8, hour: uint8, minute: uint8, second: uint8) -> uint32: + fat_year: uint16 = year - 1980 + if fat_year > 127: fat_year = 127 + fat_date: uint16 = (fat_year << 9) | (uint16(month) << 5) | uint16(day) + fat_time: uint16 = (uint16(hour) << 11) | (uint16(minute) << 5) | (uint16(second) / 2) + return (uint32(fat_date) << 16) | uint32(fat_time) diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp index 33fce2d..59a4611 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp @@ -7,21 +7,21 @@ import fat32_time as ftime import viperlib import drivers.serial.uart.serial as serial -def _read32(buf: t.CUInt8T | t.CPtr, off: t.CUInt32T) -> t.CUInt32T: - return t.CUInt32T(buf[off]) | (t.CUInt32T(buf[off + 1]) << 8) | (t.CUInt32T(buf[off + 2]) << 16) | (t.CUInt32T(buf[off + 3]) << 24) +def _read32(buf: uint8 | t.CPtr, off: uint32) -> uint32: + return uint32(buf[off]) | (uint32(buf[off + 1]) << 8) | (uint32(buf[off + 2]) << 16) | (uint32(buf[off + 3]) << 24) -def _read16(buf: t.CUInt8T | t.CPtr, off: t.CUInt32T) -> t.CUInt16T: - return t.CUInt16T(buf[off]) | (t.CUInt16T(buf[off + 1]) << 8) +def _read16(buf: uint8 | t.CPtr, off: uint32) -> uint16: + return uint16(buf[off]) | (uint16(buf[off + 1]) << 8) -def _write32(buf: t.CUInt8T | t.CPtr, off: t.CUInt32T, val: t.CUInt32T): - buf[off + 0] = t.CUInt8T(val & 0xFF) - buf[off + 1] = t.CUInt8T((val >> 8) & 0xFF) - buf[off + 2] = t.CUInt8T((val >> 16) & 0xFF) - buf[off + 3] = t.CUInt8T((val >> 24) & 0xFF) +def _write32(buf: uint8 | t.CPtr, off: uint32, val: uint32): + buf[off + 0] = uint8(val & 0xFF) + buf[off + 1] = uint8((val >> 8) & 0xFF) + buf[off + 2] = uint8((val >> 16) & 0xFF) + buf[off + 3] = uint8((val >> 24) & 0xFF) -def _write16(buf: t.CUInt8T | t.CPtr, off: t.CUInt32T, val: t.CUInt16T): - buf[off + 0] = t.CUInt8T(val & 0xFF) - buf[off + 1] = t.CUInt8T((val >> 8) & 0xFF) +def _write16(buf: uint8 | t.CPtr, off: uint32, val: uint16): + buf[off + 0] = uint8(val & 0xFF) + buf[off + 1] = uint8((val >> 8) & 0xFF) SECTOR_SIZE: t.CDefine = 512 @@ -117,96 +117,96 @@ class DRESULT(t.CEnum): @c.Attribute(t.attr.packed) class bpb: - BS_jmpBoot: t.CArray[t.CUInt8T, 3] + BS_jmpBoot: t.CArray[uint8, 3] BS_OEMName: t.CArray[t.CChar, 8] - BPB_BytsPerSec: t.CUInt16T - BPB_SecPerClus: t.CUInt8T - BPB_RsvdSecCnt: t.CUInt16T - BPB_NumFATs: t.CUInt8T - BPB_RootEntCnt: t.CUInt16T - BPB_TotSec16: t.CUInt16T - BPB_Media: t.CUInt8T - BPB_FATSz16: t.CUInt16T - BPB_SecPerTrk: t.CUInt16T - BPB_NumHeads: t.CUInt16T - BPB_HiddSec: t.CUInt32T - BPB_TotSec32: t.CUInt32T - BPB_FATSz32: t.CUInt32T - BPB_ExtFlags: t.CUInt16T - BPB_FSVer: t.CUInt16T - BPB_RootClus: t.CUInt32T - BPB_FSInfo: t.CUInt16T - BPB_BkBootSec: t.CUInt16T - BPB_Reserved: t.CArray[t.CUInt8T, 12] - BS_DrvNum: t.CUInt8T - BS_Reserved1: t.CUInt8T - BS_BootSig: t.CUInt8T - BS_VolID: t.CUInt32T + BPB_BytsPerSec: uint16 + BPB_SecPerClus: uint8 + BPB_RsvdSecCnt: uint16 + BPB_NumFATs: uint8 + BPB_RootEntCnt: uint16 + BPB_TotSec16: uint16 + BPB_Media: uint8 + BPB_FATSz16: uint16 + BPB_SecPerTrk: uint16 + BPB_NumHeads: uint16 + BPB_HiddSec: uint32 + BPB_TotSec32: uint32 + BPB_FATSz32: uint32 + BPB_ExtFlags: uint16 + BPB_FSVer: uint16 + BPB_RootClus: uint32 + BPB_FSInfo: uint16 + BPB_BkBootSec: uint16 + BPB_Reserved: t.CArray[uint8, 12] + BS_DrvNum: uint8 + BS_Reserved1: uint8 + BS_BootSig: uint8 + BS_VolID: uint32 BS_VolLab: t.CArray[t.CChar, 11] BS_FilSysType: t.CArray[t.CChar, 8] @c.Attribute(t.attr.packed) class fsinfo: - FSI_LeadSig: t.CUInt32T - FSI_Reserved1: t.CArray[t.CUInt8T, 480] - FSI_StrucSig: t.CUInt32T - FSI_Free_Count: t.CUInt32T - FSI_Nxt_Free: t.CUInt32T - FSI_Reserved2: t.CArray[t.CUInt8T, 12] - FSI_TrailSig: t.CUInt32T + FSI_LeadSig: uint32 + FSI_Reserved1: t.CArray[uint8, 480] + FSI_StrucSig: uint32 + FSI_Free_Count: uint32 + FSI_Nxt_Free: uint32 + FSI_Reserved2: t.CArray[uint8, 12] + FSI_TrailSig: uint32 @c.Attribute(t.attr.packed) class dirent: DIR_Name: t.CArray[t.CChar, 11] - DIR_Attr: t.CUInt8T - DIR_NTRes: t.CUInt8T - DIR_CrtTimeTenth: t.CUInt8T - DIR_CrtTime: t.CUInt16T - DIR_CrtDate: t.CUInt16T - DIR_LstAccDate: t.CUInt16T - DIR_FstClusHI: t.CUInt16T - DIR_WrtTime: t.CUInt16T - DIR_WrtDate: t.CUInt16T - DIR_FstClusLO: t.CUInt16T - DIR_FileSize: t.CUInt32T + DIR_Attr: uint8 + DIR_NTRes: uint8 + DIR_CrtTimeTenth: uint8 + DIR_CrtTime: uint16 + DIR_CrtDate: uint16 + DIR_LstAccDate: uint16 + DIR_FstClusHI: uint16 + DIR_WrtTime: uint16 + DIR_WrtDate: uint16 + DIR_FstClusLO: uint16 + DIR_FileSize: uint32 @c.Attribute(t.attr.packed) class lfn_entry: - LDIR_Ord: t.CUInt8T - LDIR_Name1: t.CArray[t.CUInt16T, 5] - LDIR_Attr: t.CUInt8T - LDIR_Type: t.CUInt8T - LDIR_Chksum: t.CUInt8T - LDIR_Name2: t.CArray[t.CUInt16T, 6] - LDIR_FstClusLO: t.CUInt16T - LDIR_Name3: t.CArray[t.CUInt16T, 2] + LDIR_Ord: uint8 + LDIR_Name1: t.CArray[uint16, 5] + LDIR_Attr: uint8 + LDIR_Type: uint8 + LDIR_Chksum: uint8 + LDIR_Name2: t.CArray[uint16, 6] + LDIR_FstClusLO: uint16 + LDIR_Name3: t.CArray[uint16, 2] -def sfn_checksum(name: t.CConst | t.CChar | t.CPtr) -> t.CUInt8T: - sum: t.CUInt8T = 0 - i: t.CInt +def sfn_checksum(name: t.CConst | t.CChar | t.CPtr) -> uint8: + sum: uint8 = 0 + i: int for i in range(11): sum = ((sum & 1) << 7) + (sum >> 1) + name[i] return sum -def uni2oem_placeholder(uni: t.CUInt16T, cp: t.CUInt16T) -> t.CUInt16T: +def uni2oem_placeholder(uni: uint16, cp: uint16) -> uint16: if uni < 0x80: return uni - return t.CUInt16T(0x003F) + return uint16(0x003F) -def lfn_get_char(entry_bytes: t.CUInt8T | t.CPtr, idx: t.CInt) -> t.CUInt16T: +def lfn_get_char(entry_bytes: uint8 | t.CPtr, idx: int) -> uint16: if idx < 5: - off: t.CInt = 1 + idx * 2 + off: int = 1 + idx * 2 elif idx < 11: off = 14 + (idx - 5) * 2 else: off = 28 + (idx - 11) * 2 - lo: t.CUInt8T = c.Deref(t.CUInt8T(t.CUInt64T(entry_bytes) + off, t.CPtr)) - hi: t.CUInt8T = c.Deref(t.CUInt8T(t.CUInt64T(entry_bytes) + off + 1, t.CPtr)) - return t.CUInt16T(lo) | t.CUInt16T(t.CUInt16T(hi) << 8) + lo: uint8 = c.Deref(uint8(uint64(entry_bytes) + off, t.CPtr)) + hi: uint8 = c.Deref(uint8(uint64(entry_bytes) + off + 1, t.CPtr)) + return uint16(lo) | uint16(uint16(hi) << 8) -def lfn_set_char(entry_bytes: t.CUInt8T | t.CPtr, idx: t.CInt, ch: t.CUInt16T): +def lfn_set_char(entry_bytes: uint8 | t.CPtr, idx: int, ch: uint16): if idx < 5: - off: t.CInt = 1 + idx * 2 + off: int = 1 + idx * 2 elif idx < 11: off = 14 + (idx - 5) * 2 else: @@ -215,21 +215,27 @@ def lfn_set_char(entry_bytes: t.CUInt8T | t.CPtr, idx: t.CInt, ch: t.CUInt16T): # Call 直接 return b_val(静默不写)。必须 c.Set(c.Deref(ptr), 值) = *ptr = 值。 # 此前 lfn_set_char/lfn_extract 从未写入 entry_bytes/lfn_buf → LFN 条目 # 读写全失效 → dir_find 的 LFN 匹配(gargantua.elf 等长文件名)永远失败。 - c.Set(c.Deref(t.CUInt8T(t.CUInt64T(entry_bytes) + off, t.CPtr)), t.CUInt8T(ch & 0xFF)) - c.Set(c.Deref(t.CUInt8T(t.CUInt64T(entry_bytes) + off + 1, t.CPtr)), t.CUInt8T(ch >> 8)) + c.Set(c.Deref(uint8(uint64(entry_bytes) + off, t.CPtr)), uint8(ch & 0xFF)) + c.Set(c.Deref(uint8(uint64(entry_bytes) + off + 1, t.CPtr)), uint8(ch >> 8)) -def lfn_extract(entry_bytes: t.CUInt8T | t.CPtr, lfn: t.CUInt16T | t.CPtr, ord_val: t.CUInt8T) -> t.CInt: - seq: t.CInt = (ord_val & 0x3F) - 1 - base: t.CInt = seq * LFN_ENTRY_CHARS - i: t.CInt +def lfn_extract(entry_bytes: uint8 | t.CPtr, lfn: uint16 | t.CPtr, ord_val: uint8) -> int: + seq: int = (ord_val & 0x3F) - 1 + base: int = seq * LFN_ENTRY_CHARS + i: int for i in range(LFN_ENTRY_CHARS): - ch: t.CUInt16T = lfn_get_char(entry_bytes, i) + # 越界钳制:lfn 缓冲为 uint16[MAX_LFN+1](256 槽)。base=(ord&0x3F-1)*13, + # ord&0x3F 在畸形/损坏 LFN 目录项下可达 63 → base 最大 806,原实现直接 + # 按下标写 → 越界写。合法短名(≤255 字符 + 终止符)不受影响。 + if base + i > MAX_LFN: + return -1 + ch: uint16 = lfn_get_char(entry_bytes, i) if ch == 0x0000 or ch == 0xFFFF: - c.Set(c.Deref(t.CUInt16T(t.CUInt64T(lfn) + (base + i) * 2, t.CPtr)), 0) + c.Set(c.Deref(uint16(uint64(lfn) + (base + i) * 2, t.CPtr)), 0) return base + i - c.Set(c.Deref(t.CUInt16T(t.CUInt64T(lfn) + (base + i) * 2, t.CPtr)), ch) + c.Set(c.Deref(uint16(uint64(lfn) + (base + i) * 2, t.CPtr)), ch) if ord_val & LFN_FLAG_LAST: - c.Set(c.Deref(t.CUInt16T(t.CUInt64T(lfn) + (base + LFN_ENTRY_CHARS) * 2, t.CPtr)), 0) + if base + LFN_ENTRY_CHARS <= MAX_LFN: + c.Set(c.Deref(uint16(uint64(lfn) + (base + LFN_ENTRY_CHARS) * 2, t.CPtr)), 0) return base + LFN_ENTRY_CHARS def sfn_from_lfn(lfn: t.CConst | t.CChar | t.CPtr, sfn: t.CChar | t.CPtr): @@ -238,10 +244,10 @@ def sfn_from_lfn(lfn: t.CConst | t.CChar | t.CPtr, sfn: t.CChar | t.CPtr): sfn[0] = '.'; sfn[11] = 0; return if c.Deref(lfn) == '.' and c.Deref(lfn + 1) == '.' and c.Deref(lfn + 2) == 0: sfn[0] = '.'; sfn[1] = '.'; sfn[11] = 0; return - si: t.CInt = 0 - dot_pos: t.CInt = -1 - i: t.CInt = 0 - ext_i: t.CInt = 0 + si: int = 0 + dot_pos: int = -1 + i: int = 0 + ext_i: int = 0 for ch in lfn: if ch == '.': dot_pos = si; si += 1; ext_i = 0; continue @@ -268,8 +274,8 @@ def sfn_from_lfn(lfn: t.CConst | t.CChar | t.CPtr, sfn: t.CChar | t.CPtr): serial.puts(c.Addr(_dsf)) def sfn_to_str(sfn: t.CConst | t.CChar | t.CPtr, out: t.CChar | t.CPtr): - i: t.CInt = 0 - j: t.CInt = 0 + i: int = 0 + j: int = 0 for i in range(8): if sfn[i] == 0x20: break if sfn[i] == 0x05: out[j] = 0xE5 @@ -283,92 +289,103 @@ def sfn_to_str(sfn: t.CConst | t.CChar | t.CPtr, out: t.CChar | t.CPtr): out[j] = 0 def _split_path(path: t.CConst | t.CChar | t.CPtr, parent_out: t.CChar | t.CPtr, name_out: t.CChar | t.CPtr): - pi: t.CInt = 0; last_sep: t.CInt = -1 + # parent_out/name_out 分别按 PATH_MAX(260)/NAME_MAX(255) 截断, + # 避免超长 path 无界复制越界写调用方缓冲(pp[260]/fn[256] 等)。 + pi: int = 0; last_sep: int = -1 for ch in path: + if pi >= PATH_MAX - 1: break parent_out[pi] = ch if ch == '/' or ch == '\\': last_sep = pi pi += 1 parent_out[pi] = 0 if last_sep >= 0: - fi: t.CInt - for fi in range(last_sep + 1, pi): name_out[fi - last_sep - 1] = path[fi] - name_out[pi - last_sep - 1] = 0 + ni: int = 0 + fi: int + for fi in range(last_sep + 1, pi): + if ni >= NAME_MAX: break + name_out[ni] = path[fi] + ni += 1 + name_out[ni] = 0 parent_out[last_sep] = 0 else: - fi2: t.CInt - for fi2 in range(pi): name_out[fi2] = path[fi2] - name_out[pi] = 0 + ni2: int = 0 + fi2: int + for fi2 in range(pi): + if ni2 >= NAME_MAX: break + name_out[ni2] = path[fi2] + ni2 += 1 + name_out[ni2] = 0 parent_out[0] = '/'; parent_out[1] = 0 class fileinfo: - file_size: t.CUInt32T = 0 - attr: t.CUInt8T = 0 - ctime: t.CUInt16T = 0 - cdate: t.CUInt16T = 0 - mtime: t.CUInt16T = 0 - mdate: t.CUInt16T = 0 - adate: t.CUInt16T = 0 + file_size: uint32 = 0 + attr: uint8 = 0 + ctime: uint16 = 0 + cdate: uint16 = 0 + mtime: uint16 = 0 + mdate: uint16 = 0 + adate: uint16 = 0 fname: t.CArray[t.CChar, 256] altname: t.CArray[t.CChar, 13] class filelock: - cluster: t.CUInt32T = 0 - dir_sector: t.CUInt64T = 0 - dir_offset: t.CUInt32T = 0 - in_use: t.CInt = 0 - shared_count: t.CInt = 0 - exclusive: t.CInt = 0 + cluster: uint32 = 0 + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 + in_use: int = 0 + shared_count: int = 0 + exclusive: int = 0 @t.Object class volinfo: lock: spinlock._spinlock - mounted: t.CInt = 0 - pdrv: t.CUInt8T = 0 - sector_size: t.CUInt16T = 512 - cluster_size: t.CUInt32T = 0 - cluster_sectors: t.CUInt8T = 0 - fat_start: t.CUInt64T = 0 - fat_size: t.CUInt32T = 0 - data_start: t.CUInt64T = 0 - root_cluster: t.CUInt32T = 2 - total_sectors: t.CUInt64T = 0 - total_clusters: t.CUInt32T = 0 - free_clusters: t.CUInt32T = 4294967295 - last_alloc: t.CUInt32T = 2 - fsinfo_sector: t.CUInt16T = 0 - backup_sector: t.CUInt16T = 6 - vol_id: t.CUInt32T = 0 + mounted: int = 0 + pdrv: uint8 = 0 + sector_size: uint16 = 512 + cluster_size: uint32 = 0 + cluster_sectors: uint8 = 0 + fat_start: uint64 = 0 + fat_size: uint32 = 0 + data_start: uint64 = 0 + root_cluster: uint32 = 2 + total_sectors: uint64 = 0 + total_clusters: uint32 = 0 + free_clusters: uint32 = 4294967295 + last_alloc: uint32 = 2 + fsinfo_sector: uint16 = 0 + backup_sector: uint16 = 6 + vol_id: uint32 = 0 vol_label: t.CArray[t.CChar, 12] - num_fats: t.CUInt8T = 2 - reserved_sectors: t.CUInt16T = 0 - hidden_sectors: t.CUInt32T = 0 - winsect: t.CUInt64T = 0xFFFFFFFFFFFFFFFF - win_dirty: t.CInt = 0 - win: t.CArray[t.CUInt8T, 512] - fat_winsect: t.CUInt64T = 0xFFFFFFFFFFFFFFFF - fat_win_dirty: t.CInt = 0 - fat_win: t.CArray[t.CUInt8T, 512] - metadata: t.CUInt32T = 0 - last_error: t.CUInt32T = 0 + num_fats: uint8 = 2 + reserved_sectors: uint16 = 0 + hidden_sectors: uint32 = 0 + winsect: uint64 = 0xFFFFFFFFFFFFFFFF + win_dirty: int = 0 + win: t.CArray[uint8, 512] + fat_winsect: uint64 = 0xFFFFFFFFFFFFFFFF + fat_win_dirty: int = 0 + fat_win: t.CArray[uint8, 512] + metadata: uint32 = 0 + last_error: uint32 = 0 - def win_read(self, sector: t.CUInt64T) -> FRESULT: + def win_read(self, sector: uint64) -> FRESULT: if self.winsect == sector: return FRESULT.FR_OK if self.win_dirty: res: FRESULT = self.win_flush() if res != FRESULT.FR_OK: return res - abs_sector: t.CUInt64T = sector + t.CUInt64T(self.hidden_sectors) + abs_sector: uint64 = sector + uint64(self.hidden_sectors) self.lock.lock() win_addr: t.CPtr = c.Addr(self.win[0]) - res2: DRESULT = diskio.read(self.pdrv, win_addr, t.CUInt32T(abs_sector), 1) + res2: DRESULT = diskio.read(self.pdrv, win_addr, uint32(abs_sector), 1) self.lock.unlock() if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR # [DIAG] 定位 win[0..1] 被清零(L271 win=00 00 20...):区分读错扇区 # vs 读后被覆盖——打印 abs_sector 与读后 win 前 4 字节。 _dwr: t.CArray[t.CChar, 96] viperlib.snprintf(c.Addr(_dwr), 96, "[wr] sec=%lx abs=%lx hid=%lx w0=%02x %02x %02x %02x\n", - sector, abs_sector, t.CUInt64T(self.hidden_sectors), + sector, abs_sector, uint64(self.hidden_sectors), self.win[0], self.win[1], self.win[2], self.win[3]) serial.puts(c.Addr(_dwr)) self.winsect = sector @@ -376,22 +393,22 @@ class volinfo: def win_flush(self) -> FRESULT: if not self.win_dirty: return FRESULT.FR_OK - abs_sector: t.CUInt64T = self.winsect + t.CUInt64T(self.hidden_sectors) + abs_sector: uint64 = self.winsect + uint64(self.hidden_sectors) self.lock.lock() - res: DRESULT = diskio.write(self.pdrv, c.Addr(self.win[0]), t.CUInt32T(abs_sector), 1) + res: DRESULT = diskio.write(self.pdrv, c.Addr(self.win[0]), uint32(abs_sector), 1) self.lock.unlock() if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.win_dirty = 0 return FRESULT.FR_OK - def fat_win_read(self, sector: t.CUInt64T) -> FRESULT: + def fat_win_read(self, sector: uint64) -> FRESULT: if self.fat_winsect == sector: return FRESULT.FR_OK if self.fat_win_dirty: res: FRESULT = self.fat_win_flush() if res != FRESULT.FR_OK: return res - abs_sector: t.CUInt64T = sector + t.CUInt64T(self.hidden_sectors) + abs_sector: uint64 = sector + uint64(self.hidden_sectors) self.lock.lock() - res2: DRESULT = diskio.read(self.pdrv, c.Addr(self.fat_win[0]), t.CUInt32T(abs_sector), 1) + res2: DRESULT = diskio.read(self.pdrv, c.Addr(self.fat_win[0]), uint32(abs_sector), 1) self.lock.unlock() if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.fat_winsect = sector @@ -399,9 +416,9 @@ class volinfo: def fat_win_flush(self) -> FRESULT: if not self.fat_win_dirty: return FRESULT.FR_OK - abs_sector: t.CUInt64T = self.fat_winsect + t.CUInt64T(self.hidden_sectors) + abs_sector: uint64 = self.fat_winsect + uint64(self.hidden_sectors) self.lock.lock() - res: DRESULT = diskio.write(self.pdrv, c.Addr(self.fat_win[0]), t.CUInt32T(abs_sector), 1) + res: DRESULT = diskio.write(self.pdrv, c.Addr(self.fat_win[0]), uint32(abs_sector), 1) self.lock.unlock() if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.fat_win_dirty = 0 @@ -412,47 +429,47 @@ class volinfo: if res != FRESULT.FR_OK: return res return self.fat_win_flush() - def fat_read(self, cluster: t.CUInt32T) -> t.CUInt32T: + def fat_read(self, cluster: uint32) -> uint32: if cluster < 2 or cluster >= self.total_clusters + 2: return 0 - fat_offset: t.CUInt64T = t.CUInt64T(cluster) * 4 - fat_sector: t.CUInt64T = self.fat_start + (fat_offset / 512) - fat_offset_in_sector: t.CUInt32T = t.CUInt32T(fat_offset % 512) + fat_offset: uint64 = uint64(cluster) * 4 + fat_sector: uint64 = self.fat_start + (fat_offset / 512) + fat_offset_in_sector: uint32 = uint32(fat_offset % 512) res: FRESULT = self.fat_win_read(fat_sector) if res != FRESULT.FR_OK: return 0 return _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) & FAT_MASK - def fat_write(self, cluster: t.CUInt32T, value: t.CUInt32T) -> FRESULT: + def fat_write(self, cluster: uint32, value: uint32) -> FRESULT: if cluster < 2 or cluster >= self.total_clusters + 2: return FRESULT.FR_INVALID_PARAMETER - fat_offset: t.CUInt64T = t.CUInt64T(cluster) * 4 - fat_sector: t.CUInt64T = self.fat_start + (fat_offset / 512) - fat_offset_in_sector: t.CUInt32T = t.CUInt32T(fat_offset % 512) + fat_offset: uint64 = uint64(cluster) * 4 + fat_sector: uint64 = self.fat_start + (fat_offset / 512) + fat_offset_in_sector: uint32 = uint32(fat_offset % 512) res: FRESULT = self.fat_win_read(fat_sector) if res != FRESULT.FR_OK: return res - old: t.CUInt32T = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) - new_val: t.CUInt32T = (old & FAT_RESERVED) | (value & FAT_MASK) + old: uint32 = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) + new_val: uint32 = (old & FAT_RESERVED) | (value & FAT_MASK) _write32(c.Addr(self.fat_win[0]), fat_offset_in_sector, new_val) self.fat_win_dirty = 1 res = self.fat_win_flush() if res != FRESULT.FR_OK: return res if self.num_fats >= 2: - mirror_sector: t.CUInt64T = fat_sector + t.CUInt64T(self.fat_size) + mirror_sector: uint64 = fat_sector + uint64(self.fat_size) res2: FRESULT = self.fat_win_read(mirror_sector) if res2 != FRESULT.FR_OK: return res2 - mirror_old: t.CUInt32T = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) - mirror_new: t.CUInt32T = (mirror_old & FAT_RESERVED) | (value & FAT_MASK) + mirror_old: uint32 = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) + mirror_new: uint32 = (mirror_old & FAT_RESERVED) | (value & FAT_MASK) _write32(c.Addr(self.fat_win[0]), fat_offset_in_sector, mirror_new) self.fat_win_dirty = 1 res3: FRESULT = self.fat_win_flush() if res3 != FRESULT.FR_OK: return res3 return FRESULT.FR_OK - def cluster_alloc(self) -> t.CUInt32T: - clust: t.CUInt32T = self.last_alloc - i: t.CUInt32T + def cluster_alloc(self) -> uint32: + clust: uint32 = self.last_alloc + i: uint32 for i in range(self.total_clusters): clust += 1 if clust >= self.total_clusters + 2: clust = 2 - entry: t.CUInt32T = self.fat_read(clust) + entry: uint32 = self.fat_read(clust) if entry == CLUSTER_FREE: res: FRESULT = self.fat_write(clust, CLUSTER_EOC_MAX) if res != FRESULT.FR_OK: return 0 @@ -461,11 +478,11 @@ class volinfo: return clust return 0 - def cluster_free_chain(self, start_cluster: t.CUInt32T) -> FRESULT: + def cluster_free_chain(self, start_cluster: uint32) -> FRESULT: if start_cluster < 2: return FRESULT.FR_OK - clust: t.CUInt32T = start_cluster + clust: uint32 = start_cluster while clust >= 2 and clust < CLUSTER_EOC_MIN: - next_clust: t.CUInt32T = self.fat_read(clust) + next_clust: uint32 = self.fat_read(clust) if next_clust == 0: break res: FRESULT = self.fat_write(clust, CLUSTER_FREE) if res != FRESULT.FR_OK: return res @@ -473,8 +490,8 @@ class volinfo: clust = next_clust return FRESULT.FR_OK - def cluster_extend(self, cluster: t.CUInt32T) -> t.CUInt32T: - new_clust: t.CUInt32T = self.cluster_alloc() + def cluster_extend(self, cluster: uint32) -> uint32: + new_clust: uint32 = self.cluster_alloc() if new_clust == 0: return 0 if cluster >= 2: res: FRESULT = self.fat_write(cluster, new_clust) @@ -483,43 +500,43 @@ class volinfo: return 0 return new_clust - def cluster_get_next(self, cluster: t.CUInt32T) -> t.CUInt32T: + def cluster_get_next(self, cluster: uint32) -> uint32: if cluster < 2: return 0 - entry: t.CUInt32T = self.fat_read(cluster) + entry: uint32 = self.fat_read(cluster) if entry >= CLUSTER_EOC_MIN and entry <= CLUSTER_EOC_MAX: return 0 if entry == CLUSTER_FREE or entry == CLUSTER_BAD: return 0 return entry - def cluster_to_sector(self, cluster: t.CUInt32T) -> t.CUInt64T: + def cluster_to_sector(self, cluster: uint32) -> uint64: if cluster < 2: return 0 - return self.data_start + t.CUInt64T(cluster - 2) * t.CUInt64T(self.cluster_sectors) + return self.data_start + uint64(cluster - 2) * uint64(self.cluster_sectors) - def entries_per_cluster(self) -> t.CUInt32T: - return t.CUInt32T(self.cluster_sectors) * (512 / ENTRY_SIZE) + def entries_per_cluster(self) -> uint32: + return uint32(self.cluster_sectors) * (512 / ENTRY_SIZE) - def is_eoc(self, cluster: t.CUInt32T) -> t.CInt: + def is_eoc(self, cluster: uint32) -> int: return 1 if (cluster >= CLUSTER_EOC_MIN and cluster <= CLUSTER_EOC_MAX) else 0 def fsinfo_read(self) -> FRESULT: if self.fsinfo_sector == 0: return FRESULT.FR_OK - res: FRESULT = self.win_read(t.CUInt64T(self.fsinfo_sector)) + res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) if res != FRESULT.FR_OK: return res - lead_sig: t.CUInt32T = _read32(c.Addr(self.win[0]), 0) - struc_sig: t.CUInt32T = _read32(c.Addr(self.win[0]), 484) - trail_sig: t.CUInt32T = _read32(c.Addr(self.win[0]), 508) + lead_sig: uint32 = _read32(c.Addr(self.win[0]), 0) + struc_sig: uint32 = _read32(c.Addr(self.win[0]), 484) + trail_sig: uint32 = _read32(c.Addr(self.win[0]), 508) if lead_sig != 0x41615252 or struc_sig != 0x61417272 or trail_sig != 0xAA550000: self.free_clusters = 0xFFFFFFFF self.last_alloc = 2 return FRESULT.FR_OK - free_count: t.CUInt32T = _read32(c.Addr(self.win[0]), 488) - nxt_free: t.CUInt32T = _read32(c.Addr(self.win[0]), 492) + free_count: uint32 = _read32(c.Addr(self.win[0]), 488) + nxt_free: uint32 = _read32(c.Addr(self.win[0]), 492) if free_count <= self.total_clusters: self.free_clusters = free_count if nxt_free >= 2 and nxt_free < self.total_clusters + 2: self.last_alloc = nxt_free return FRESULT.FR_OK def fsinfo_write(self) -> FRESULT: if self.fsinfo_sector == 0: return FRESULT.FR_OK - res: FRESULT = self.win_read(t.CUInt64T(self.fsinfo_sector)) + res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) if res != FRESULT.FR_OK: return res _write32(c.Addr(self.win[0]), 0, 0x41615252) _write32(c.Addr(self.win[0]), 484, 0x61417272) @@ -529,11 +546,11 @@ class volinfo: self.win_dirty = 1 return self.win_flush() - def count_free_clusters(self) -> t.CUInt32T: - free_cnt: t.CUInt32T = 0 - clust: t.CUInt32T + def count_free_clusters(self) -> uint32: + free_cnt: uint32 = 0 + clust: uint32 for clust in range(2, self.total_clusters + 2): - entry: t.CUInt32T = self.fat_read(clust) + entry: uint32 = self.fat_read(clust) if entry == CLUSTER_FREE: free_cnt += 1 self.free_clusters = free_cnt return free_cnt @@ -546,17 +563,17 @@ class volinfo: if res != DRESULT.RES_OK: return FRESULT.FR_NOT_READY res2: FRESULT = self.win_read(0) if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - bps: t.CUInt16T = _read16(c.Addr(self.win[0]), 11) - spc: t.CUInt8T = self.win[13] - rsc: t.CUInt16T = _read16(c.Addr(self.win[0]), 14) - nf: t.CUInt8T = self.win[16] - root_ent: t.CUInt16T = _read16(c.Addr(self.win[0]), 17) - fat16sz: t.CUInt16T = _read16(c.Addr(self.win[0]), 22) - tot32: t.CUInt32T = _read32(c.Addr(self.win[0]), 32) - fat32sz: t.CUInt32T = _read32(c.Addr(self.win[0]), 36) - root_clus: t.CUInt32T = _read32(c.Addr(self.win[0]), 44) - sig0: t.CUInt8T = self.win[510] - sig1: t.CUInt8T = self.win[511] + bps: uint16 = _read16(c.Addr(self.win[0]), 11) + spc: uint8 = self.win[13] + rsc: uint16 = _read16(c.Addr(self.win[0]), 14) + nf: uint8 = self.win[16] + root_ent: uint16 = _read16(c.Addr(self.win[0]), 17) + fat16sz: uint16 = _read16(c.Addr(self.win[0]), 22) + tot32: uint32 = _read32(c.Addr(self.win[0]), 32) + fat32sz: uint32 = _read32(c.Addr(self.win[0]), 36) + root_clus: uint32 = _read32(c.Addr(self.win[0]), 44) + sig0: uint8 = self.win[510] + sig1: uint8 = self.win[511] if bps != 512: return FRESULT.FR_NO_FILESYSTEM if spc == 0 or (spc & (spc - 1)) != 0: return FRESULT.FR_NO_FILESYSTEM if rsc == 0: return FRESULT.FR_NO_FILESYSTEM @@ -565,23 +582,23 @@ class volinfo: if fat32sz == 0: return FRESULT.FR_NO_FILESYSTEM if tot32 == 0: return FRESULT.FR_NO_FILESYSTEM if sig0 != 0x55 or sig1 != 0xAA: return FRESULT.FR_NO_FILESYSTEM - fsinfo_sec: t.CUInt16T = _read16(c.Addr(self.win[0]), 48) - bkboot_sec: t.CUInt16T = _read16(c.Addr(self.win[0]), 50) + fsinfo_sec: uint16 = _read16(c.Addr(self.win[0]), 48) + bkboot_sec: uint16 = _read16(c.Addr(self.win[0]), 50) self.sector_size = 512 self.cluster_sectors = spc - self.cluster_size = t.CUInt32T(spc) * 512 + self.cluster_size = uint32(spc) * 512 self.num_fats = nf self.reserved_sectors = rsc self.fat_size = fat32sz - self.fat_start = t.CUInt64T(rsc) - self.total_sectors = t.CUInt64T(tot32) + self.fat_start = uint64(rsc) + self.total_sectors = uint64(tot32) self.root_cluster = root_clus self.fsinfo_sector = fsinfo_sec self.backup_sector = bkboot_sec self.vol_id = _read32(c.Addr(self.win[0]), 67) - data_sectors: t.CUInt64T = self.total_sectors - t.CUInt64T(rsc) - t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz)) - self.total_clusters = t.CUInt32T(data_sectors / t.CUInt64T(spc)) - self.data_start = self.fat_start + t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz)) + data_sectors: uint64 = self.total_sectors - uint64(rsc) - uint64(uint64(nf) * uint64(fat32sz)) + self.total_clusters = uint32(data_sectors / uint64(spc)) + self.data_start = self.fat_start + uint64(uint64(nf) * uint64(fat32sz)) self.last_alloc = 2 self.free_clusters = 0xFFFFFFFF self.fsinfo_read() @@ -600,11 +617,11 @@ class volinfo: self.fat_win_dirty = 0 return FRESULT.FR_OK - def _zero_cluster(self, cluster: t.CUInt32T) -> FRESULT: - sector: t.CUInt64T = self.cluster_to_sector(cluster) - s: t.CUInt32T + def _zero_cluster(self, cluster: uint32) -> FRESULT: + sector: uint64 = self.cluster_to_sector(cluster) + s: uint32 for s in range(self.cluster_sectors): - res: FRESULT = self.win_read(sector + t.CUInt64T(s)) + res: FRESULT = self.win_read(sector + uint64(s)) if res != FRESULT.FR_OK: return res string.memset(c.Addr(self.win[0]), 0, 512) self.win_dirty = 1 @@ -612,60 +629,60 @@ class volinfo: if res2 != FRESULT.FR_OK: return res2 return FRESULT.FR_OK - def file_cluster_seek(self, first_cluster: t.CUInt32T, pos: t.CUInt32T) -> t.CUInt32T: + def file_cluster_seek(self, first_cluster: uint32, pos: uint32) -> uint32: if first_cluster < 2: return 0 - cluster: t.CUInt32T = first_cluster - cluster_num: t.CUInt32T = pos / self.cluster_size - i: t.CUInt32T + cluster: uint32 = first_cluster + cluster_num: uint32 = pos / self.cluster_size + i: uint32 for i in range(cluster_num): - next_c: t.CUInt32T = self.cluster_get_next(cluster) + next_c: uint32 = self.cluster_get_next(cluster) if next_c == 0: return 0 cluster = next_c return cluster - def file_find_last_cluster(self, first_cluster: t.CUInt32T) -> t.CUInt32T: + def file_find_last_cluster(self, first_cluster: uint32) -> uint32: if first_cluster < 2: return 0 - cluster: t.CUInt32T = first_cluster + cluster: uint32 = first_cluster while True: - next_c: t.CUInt32T = self.cluster_get_next(cluster) + next_c: uint32 = self.cluster_get_next(cluster) if next_c == 0: return cluster cluster = next_c def _read_entry_from_dir(self, dp: dirobj | t.CPtr) -> FRESULT: - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) return self.win_read(entry_sector) - def _write_dirent_now(self, eo: t.CUInt32T): - now: t.CUInt32T = ftime.get_fattime() - fat_time: t.CUInt16T = t.CUInt16T(now & 0xFFFF) - fat_date: t.CUInt16T = t.CUInt16T((now >> 16) & 0xFFFF) + def _write_dirent_now(self, eo: uint32): + now: uint32 = ftime.get_fattime() + fat_time: uint16 = uint16(now & 0xFFFF) + fat_date: uint16 = uint16((now >> 16) & 0xFFFF) _write16(c.Addr(self.win[0]), eo + 14, fat_time) _write16(c.Addr(self.win[0]), eo + 16, fat_date) _write16(c.Addr(self.win[0]), eo + 18, fat_date) _write16(c.Addr(self.win[0]), eo + 22, fat_time) _write16(c.Addr(self.win[0]), eo + 24, fat_date) - def dir_offset_to_sector(self, start_cluster: t.CUInt32T, offset: t.CUInt32T) -> t.CUInt64T: - epc: t.CUInt32T = self.entries_per_cluster() - cluster: t.CUInt32T = start_cluster - cluster_idx: t.CUInt32T = offset / epc - i: t.CUInt32T + def dir_offset_to_sector(self, start_cluster: uint32, offset: uint32) -> uint64: + epc: uint32 = self.entries_per_cluster() + cluster: uint32 = start_cluster + cluster_idx: uint32 = offset / epc + i: uint32 for i in range(cluster_idx): - next_c: t.CUInt32T = self.cluster_get_next(cluster) + next_c: uint32 = self.cluster_get_next(cluster) if next_c == 0: return 0 cluster = next_c - off_in_cluster: t.CUInt32T = offset % epc - return self.cluster_to_sector(cluster) + t.CUInt64T(off_in_cluster / (512 / ENTRY_SIZE)) + off_in_cluster: uint32 = offset % epc + return self.cluster_to_sector(cluster) + uint64(off_in_cluster / (512 / ENTRY_SIZE)) def dir_next_cluster(self, dp: dirobj | t.CPtr) -> FRESULT: - next_clust: t.CUInt32T = self.cluster_get_next(dp.cluster) + next_clust: uint32 = self.cluster_get_next(dp.cluster) if next_clust == 0: return FRESULT.FR_NO_FILE dp.cluster = next_clust dp.sector = self.cluster_to_sector(next_clust) dp.offset = 0 return FRESULT.FR_OK - def dir_open(self, dp: dirobj | t.CPtr, cluster: t.CUInt32T) -> FRESULT: + def dir_open(self, dp: dirobj | t.CPtr, cluster: uint32) -> FRESULT: dp.vol = self dp.start_cluster = cluster dp.cluster = cluster @@ -677,23 +694,23 @@ class volinfo: self.winsect = 0xFFFFFFFFFFFFFFFF return FRESULT.FR_OK - def dir_read_entry(self, dp: dirobj | t.CPtr, lfn_buf: t.CUInt16T | t.CPtr) -> FRESULT: - lfn_started: t.CInt = 0 + def dir_read_entry(self, dp: dirobj | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: + lfn_started: int = 0 dp.lfn_ofs = 0xFFFFFFFF dp.lfn_cluster = 0 while True: - epc: t.CUInt32T = self.entries_per_cluster() + epc: uint32 = self.entries_per_cluster() if dp.offset >= epc: res: FRESULT = self.dir_next_cluster(dp) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res2: FRESULT = self.win_read(entry_sector) if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - first_byte: t.CUInt8T = self.win[entry_offset_in_sector] + first_byte: uint8 = self.win[entry_offset_in_sector] if first_byte == SFN_FREE: return FRESULT.FR_NO_FILE - attr: t.CUInt8T = self.win[entry_offset_in_sector + 11] + attr: uint8 = self.win[entry_offset_in_sector + 11] if first_byte == SFN_DELETED: lfn_started = 0 dp.lfn_ofs = 0xFFFFFFFF @@ -702,13 +719,13 @@ class volinfo: continue if attr == LFN_ATTR: if lfn_buf: - ord_val: t.CUInt8T = first_byte + ord_val: uint8 = first_byte if ord_val & LFN_FLAG_LAST: lfn_started = 1 dp.lfn_ofs = dp.offset dp.lfn_cluster = dp.cluster if lfn_started: - entry_bytes: t.CUInt8T | t.CPtr = t.CUInt8T(c.Addr(self.win[entry_offset_in_sector]), t.CPtr) + entry_bytes: uint8 | t.CPtr = uint8(c.Addr(self.win[entry_offset_in_sector]), t.CPtr) lfn_extract(entry_bytes, lfn_buf, ord_val) dp.offset += 1 continue @@ -720,7 +737,7 @@ class volinfo: dp.lfn_cluster = dp.cluster return FRESULT.FR_OK - def dir_find(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, lfn_buf: t.CUInt16T | t.CPtr) -> FRESULT: + def dir_find(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: sfn: t.CArray[t.CChar, 12] sfn_from_lfn(name, c.Addr(sfn[0])) # [DIAG] sfn 生成字节 hex(hello.elf 应 HELLO..ELF,异常时显示 sfn=H) @@ -730,7 +747,7 @@ class volinfo: sfn[6], sfn[7], sfn[8], sfn[9], sfn[10]) serial.puts(c.Addr(_dbhs)) _dbg_sfn: t.CArray[t.CChar, 16] - _si: t.CInt + _si: int for _si in range(11): _dbg_sfn[_si] = sfn[_si] _dbg_sfn[11] = 0 @@ -742,12 +759,12 @@ class volinfo: _db0: t.CArray[t.CChar, 120] viperlib.snprintf(c.Addr(_db0), 120, "[dir_find] dp: sect=0x%lx off=%lu clust=%lu winsect=0x%lx\n", dp.sector, dp.offset, dp.cluster, self.winsect) serial.puts(_db0) - _find_count: t.CInt = 0 + _find_count: int = 0 while True: res: FRESULT = self.dir_read_entry(dp, lfn_buf) if res != FRESULT.FR_OK: _db2: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_db2), 80, "[dir_find] dir_read_entry failed res=%d offset=%lu\n", t.CInt(res), dp.offset) + viperlib.snprintf(c.Addr(_db2), 80, "[dir_find] dir_read_entry failed res=%d offset=%lu\n", int(res), dp.offset) serial.puts(_db2) # [DIAG] win 缓冲内容 dump(磁盘数据正确但运行时 win 被污染时可见) _dbw: t.CArray[t.CChar, 96] @@ -758,12 +775,12 @@ class volinfo: self.win[12], self.win[13], self.win[14], self.win[15], self.winsect) serial.puts(c.Addr(_dbw)) return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res2: FRESULT = self.win_read(entry_sector) if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - match_found: t.CInt = 1 - i: t.CInt + match_found: int = 1 + i: int for i in range(11): a: t.CChar = self.win[entry_offset_in_sector + i] b: t.CChar = sfn[i] @@ -775,30 +792,30 @@ class volinfo: if match_found: return FRESULT.FR_OK if dp.offset < 10: _db3: t.CArray[t.CChar, 80] - _fb: t.CUInt8T = self.win[entry_offset_in_sector] - _at: t.CUInt8T = self.win[entry_offset_in_sector + 11] + _fb: uint8 = self.win[entry_offset_in_sector] + _at: uint8 = self.win[entry_offset_in_sector + 11] viperlib.snprintf(c.Addr(_db3), 80, "[dir_find] off=%lu fb=0x%02x attr=0x%02x sfn=%.11s\n", dp.offset, _fb, _at, c.Addr(self.win[entry_offset_in_sector])) serial.puts(_db3) if lfn_buf and dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset: - lfn_matched: t.CInt = 1 - li: t.CInt = 0 + lfn_matched: int = 1 + li: int = 0 for name_ch in name: - lfn_ch: t.CUInt16T = c.Deref(t.CUInt16T(t.CUInt64T(lfn_buf) + li * 2, t.CPtr)) - lfn_low: t.CUInt16T = lfn_ch + lfn_ch: uint16 = c.Deref(uint16(uint64(lfn_buf) + li * 2, t.CPtr)) + lfn_low: uint16 = lfn_ch if lfn_low >= 65 and lfn_low <= 90: lfn_low = lfn_low + 32 - n_low: t.CUInt16T = t.CUInt16T(name_ch) + n_low: uint16 = uint16(name_ch) if n_low >= 65 and n_low <= 90: n_low = n_low + 32 if lfn_low != n_low: lfn_matched = 0 break li += 1 if lfn_matched: - lfn_end: t.CUInt16T = c.Deref(t.CUInt16T(t.CUInt64T(lfn_buf) + li * 2, t.CPtr)) + lfn_end: uint16 = c.Deref(uint16(uint64(lfn_buf) + li * 2, t.CPtr)) if lfn_end == 0 or lfn_end == 0xFFFF: return FRESULT.FR_OK dp.offset += 1 - def dir_get_entry_info(self, dp: dirobj | t.CPtr, info: fileinfo | t.CPtr, lfn_buf: t.CUInt16T | t.CPtr) -> FRESULT: + def dir_get_entry_info(self, dp: dirobj | t.CPtr, info: fileinfo | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: res: FRESULT = self._read_entry_from_dir(dp) if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR # [DIAG] 定位 win 缓冲污染:磁盘根目录 off=0 应为 "APP" attr=0x10 size=0, @@ -810,9 +827,9 @@ class volinfo: self.win[4], self.win[5], self.win[6], self.win[7], self.win[8], self.win[9], self.win[10], self.win[11 + 0], _read32(c.Addr(self.win[0]), 28), self.winsect) serial.puts(c.Addr(_dge)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - off: t.CUInt32T = entry_offset_in_sector - raw_attr: t.CUInt8T = self.win[off + 11] + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + off: uint32 = entry_offset_in_sector + raw_attr: uint8 = self.win[off + 11] info.attr = raw_attr info.ctime = _read16(c.Addr(self.win[0]), off + 14) info.cdate = _read16(c.Addr(self.win[0]), off + 16) @@ -823,46 +840,46 @@ class volinfo: sfn_ptr: t.CChar | t.CPtr = t.CChar(c.Addr(self.win[0]) + off, t.CPtr) sfn_to_str(sfn_ptr, c.Addr(info.altname[0])) if dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset and lfn_buf: - lfn_ptr: t.CUInt16T | t.CPtr = lfn_buf - oi: t.CInt = 0 + lfn_ptr: uint16 | t.CPtr = lfn_buf + oi: int = 0 for i in range(MAX_LFN): - ch: t.CUInt16T = c.Deref(lfn_ptr) + ch: uint16 = c.Deref(lfn_ptr) if ch == 0: break if ch < 0x80: info.fname[oi] = t.CChar(ch) else: - oem_ch: t.CUInt16T = uni2oem_placeholder(ch, 0) + oem_ch: uint16 = uni2oem_placeholder(ch, 0) if oem_ch < 0x80: info.fname[oi] = t.CChar(oem_ch) else: info.fname[oi] = '?' oi += 1 - lfn_ptr = t.CUInt16T(t.CUInt64T(lfn_ptr) + 2, t.CPtr) + lfn_ptr = uint16(uint64(lfn_ptr) + 2, t.CPtr) info.fname[oi] = 0 else: sfn_to_str(sfn_ptr, c.Addr(info.fname[0])) return FRESULT.FR_OK - def dir_add_entry(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, attr: t.CUInt8T, first_cluster: t.CUInt32T, file_size: t.CUInt32T, dir_sector_out: t.CUInt64T | t.CPtr, dir_offset_out: t.CUInt32T | t.CPtr) -> FRESULT: + def dir_add_entry(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, attr: uint8, first_cluster: uint32, file_size: uint32, dir_sector_out: uint64 | t.CPtr, dir_offset_out: uint32 | t.CPtr) -> FRESULT: sfn: t.CArray[t.CChar, 12] sfn_from_lfn(name, c.Addr(sfn[0])) - lfn_entries: t.CInt = 0 - len_: t.CInt = 0 + lfn_entries: int = 0 + len_: int = 0 for _ in name: len_ += 1 if len_ > 12: lfn_entries = (len_ + LFN_ENTRY_CHARS - 1) / LFN_ENTRY_CHARS - total_entries: t.CInt = lfn_entries + 1 - cur_cluster: t.CUInt32T = dp.cluster - cur_sector: t.CUInt64T = dp.sector - cur_offset: t.CUInt32T = dp.offset - found: t.CInt = 0 - consecutive: t.CInt = 0 - start_offset: t.CUInt32T = 0 - start_cluster: t.CUInt32T = 0 - epc: t.CUInt32T = self.entries_per_cluster() + total_entries: int = lfn_entries + 1 + cur_cluster: uint32 = dp.cluster + cur_sector: uint64 = dp.sector + cur_offset: uint32 = dp.offset + found: int = 0 + consecutive: int = 0 + start_offset: uint32 = 0 + start_cluster: uint32 = 0 + epc: uint32 = self.entries_per_cluster() while not found: if cur_offset >= epc: - next_clust: t.CUInt32T = self.cluster_get_next(cur_cluster) + next_clust: uint32 = self.cluster_get_next(cur_cluster) if next_clust == 0: - new_clust: t.CUInt32T = self.cluster_extend(cur_cluster) + new_clust: uint32 = self.cluster_extend(cur_cluster) if new_clust == 0: return FRESULT.FR_DENIED self._zero_cluster(new_clust) cur_cluster = new_clust @@ -872,11 +889,11 @@ class volinfo: cur_cluster = next_clust cur_sector = self.cluster_to_sector(next_clust) cur_offset = 0 - es: t.CUInt64T = cur_sector + (cur_offset / (512 / ENTRY_SIZE)) - eo: t.CUInt32T = (cur_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + es: uint64 = cur_sector + (cur_offset / (512 / ENTRY_SIZE)) + eo: uint32 = (cur_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res: FRESULT = self.win_read(es) if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - first_byte: t.CUInt8T = self.win[eo] + first_byte: uint8 = self.win[eo] if first_byte == SFN_FREE or first_byte == SFN_DELETED: if consecutive == 0: start_offset = cur_offset @@ -888,23 +905,23 @@ class volinfo: else: consecutive = 0 cur_offset += 1 - write_cluster: t.CUInt32T = start_cluster - write_sector: t.CUInt64T = self.cluster_to_sector(start_cluster) - write_offset: t.CUInt32T = start_offset + write_cluster: uint32 = start_cluster + write_sector: uint64 = self.cluster_to_sector(start_cluster) + write_offset: uint32 = start_offset if lfn_entries > 0: - le: t.CInt + le: int for le in range(lfn_entries): if write_offset >= epc: - next_c: t.CUInt32T = self.cluster_get_next(write_cluster) + next_c: uint32 = self.cluster_get_next(write_cluster) if next_c == 0: return FRESULT.FR_INT_ERR write_cluster = next_c write_sector = self.cluster_to_sector(next_c) write_offset = 0 - es2: t.CUInt64T = write_sector + (write_offset / (512 / ENTRY_SIZE)) - eo2: t.CUInt32T = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + es2: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) + eo2: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res2: FRESULT = self.win_read(es2) if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - ord_val: t.CUInt8T = t.CUInt8T(lfn_entries - le) + ord_val: uint8 = uint8(lfn_entries - le) if le == 0: ord_val |= LFN_FLAG_LAST self.win[eo2 + 0] = ord_val self.win[eo2 + 11] = LFN_ATTR @@ -912,78 +929,78 @@ class volinfo: self.win[eo2 + 13] = sfn_checksum(c.Addr(sfn[0])) self.win[eo2 + 26] = 0 self.win[eo2 + 27] = 0 - base: t.CInt = (lfn_entries - 1 - le) * LFN_ENTRY_CHARS - j: t.CInt + base: int = (lfn_entries - 1 - le) * LFN_ENTRY_CHARS + j: int for j in range(LFN_ENTRY_CHARS): - idx: t.CInt = base + j - ch: t.CUInt16T - if idx < len_: ch = t.CUInt16T(name[idx]) + idx: int = base + j + ch: uint16 + if idx < len_: ch = uint16(name[idx]) elif idx == len_: ch = 0x0000 else: ch = 0xFFFF if j < 5: - self.win[eo2 + 1 + j * 2] = t.CUInt8T(ch & 0xFF) - self.win[eo2 + 2 + j * 2] = t.CUInt8T((ch >> 8) & 0xFF) + self.win[eo2 + 1 + j * 2] = uint8(ch & 0xFF) + self.win[eo2 + 2 + j * 2] = uint8((ch >> 8) & 0xFF) elif j < 11: - self.win[eo2 + 14 + (j - 5) * 2] = t.CUInt8T(ch & 0xFF) - self.win[eo2 + 15 + (j - 5) * 2] = t.CUInt8T((ch >> 8) & 0xFF) + self.win[eo2 + 14 + (j - 5) * 2] = uint8(ch & 0xFF) + self.win[eo2 + 15 + (j - 5) * 2] = uint8((ch >> 8) & 0xFF) else: - self.win[eo2 + 28 + (j - 11) * 2] = t.CUInt8T(ch & 0xFF) - self.win[eo2 + 29 + (j - 11) * 2] = t.CUInt8T((ch >> 8) & 0xFF) + self.win[eo2 + 28 + (j - 11) * 2] = uint8(ch & 0xFF) + self.win[eo2 + 29 + (j - 11) * 2] = uint8((ch >> 8) & 0xFF) self.win_dirty = 1 self.win_flush() write_offset += 1 if write_offset >= epc: - next_c2: t.CUInt32T = self.cluster_get_next(write_cluster) + next_c2: uint32 = self.cluster_get_next(write_cluster) if next_c2 == 0: return FRESULT.FR_INT_ERR write_cluster = next_c2 write_sector = self.cluster_to_sector(next_c2) write_offset = 0 - es3: t.CUInt64T = write_sector + (write_offset / (512 / ENTRY_SIZE)) - eo3: t.CUInt32T = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + es3: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) + eo3: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res3: FRESULT = self.win_read(es3) if res3 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR string.memset(c.Addr(self.win[eo3]), 0, 32) - i: t.CInt + i: int for i in range(11): self.win[eo3 + i] = sfn[i] self.win[eo3 + 11] = attr self.win[eo3 + 12] = 0 self.win[eo3 + 13] = 0 self._write_dirent_now(eo3) - _write16(c.Addr(self.win[0]), eo3 + 20, t.CUInt16T((first_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), eo3 + 26, t.CUInt16T(first_cluster & 0xFFFF)) + _write16(c.Addr(self.win[0]), eo3 + 20, uint16((first_cluster >> 16) & 0xFFFF)) + _write16(c.Addr(self.win[0]), eo3 + 26, uint16(first_cluster & 0xFFFF)) _write32(c.Addr(self.win[0]), eo3 + 28, file_size) self.win_dirty = 1 self.win_flush() - c.Set(c.Deref(t.CUInt64T(dir_sector_out, t.CPtr)), es3) - c.Set(c.Deref(t.CUInt32T(dir_offset_out, t.CPtr)), eo3) + c.Set(c.Deref(uint64(dir_sector_out, t.CPtr)), es3) + c.Set(c.Deref(uint32(dir_offset_out, t.CPtr)), eo3) return FRESULT.FR_OK - def dir_update_entry(self, dir_sector: t.CUInt64T, dir_offset: t.CUInt32T, first_cluster: t.CUInt32T, file_size: t.CUInt32T, attr: t.CUInt8T) -> FRESULT: + def dir_update_entry(self, dir_sector: uint64, dir_offset: uint32, first_cluster: uint32, file_size: uint32, attr: uint8) -> FRESULT: res: FRESULT = self.win_read(dir_sector) if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR self.win[dir_offset + 11] = attr - _write16(c.Addr(self.win[0]), dir_offset + 20, t.CUInt16T((first_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), dir_offset + 26, t.CUInt16T(first_cluster & 0xFFFF)) + _write16(c.Addr(self.win[0]), dir_offset + 20, uint16((first_cluster >> 16) & 0xFFFF)) + _write16(c.Addr(self.win[0]), dir_offset + 26, uint16(first_cluster & 0xFFFF)) _write32(c.Addr(self.win[0]), dir_offset + 28, file_size) self._write_dirent_now(dir_offset) self.win_dirty = 1 return self.win_flush() def dir_delete_entry(self, dp: dirobj | t.CPtr) -> FRESULT: - start_off: t.CUInt32T = dp.lfn_ofs if dp.lfn_ofs != 0xFFFFFFFF else dp.offset - end_off: t.CUInt32T = dp.offset - cur_off: t.CUInt32T = start_off - cur_cluster: t.CUInt32T = dp.lfn_cluster if dp.lfn_ofs != 0xFFFFFFFF else dp.cluster - epc: t.CUInt32T = self.entries_per_cluster() + start_off: uint32 = dp.lfn_ofs if dp.lfn_ofs != 0xFFFFFFFF else dp.offset + end_off: uint32 = dp.offset + cur_off: uint32 = start_off + cur_cluster: uint32 = dp.lfn_cluster if dp.lfn_ofs != 0xFFFFFFFF else dp.cluster + epc: uint32 = self.entries_per_cluster() while cur_off <= end_off: - off_in_clus: t.CUInt32T = cur_off % epc + off_in_clus: uint32 = cur_off % epc if off_in_clus == 0 and cur_off != start_off: - next_c: t.CUInt32T = self.cluster_get_next(cur_cluster) + next_c: uint32 = self.cluster_get_next(cur_cluster) if next_c == 0: return FRESULT.FR_INT_ERR cur_cluster = next_c - sector_base: t.CUInt64T = self.cluster_to_sector(cur_cluster) - es: t.CUInt64T = sector_base + t.CUInt64T(off_in_clus / (512 / ENTRY_SIZE)) - eo: t.CUInt32T = (off_in_clus % (512 / ENTRY_SIZE)) * ENTRY_SIZE + sector_base: uint64 = self.cluster_to_sector(cur_cluster) + es: uint64 = sector_base + uint64(off_in_clus / (512 / ENTRY_SIZE)) + eo: uint32 = (off_in_clus % (512 / ENTRY_SIZE)) * ENTRY_SIZE res: FRESULT = self.win_read(es) if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR self.win[eo] = SFN_DELETED @@ -993,9 +1010,9 @@ class volinfo: cur_off += 1 return FRESULT.FR_OK - def follow_path(self, dp: dirobj | t.CPtr, path: t.CConst | t.CChar | t.CPtr, lfn_buf: t.CUInt16T | t.CPtr) -> FRESULT: - cluster: t.CUInt32T = self.root_cluster - pi: t.CInt = 0 + def follow_path(self, dp: dirobj | t.CPtr, path: t.CConst | t.CChar | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: + cluster: uint32 = self.root_cluster + pi: int = 0 if path[0] >= '0' and path[0] <= '9': if path[1] == ':': pi = 2 @@ -1012,7 +1029,7 @@ class volinfo: return FRESULT.FR_OK while True: component: t.CArray[t.CChar, 256] - ci: t.CInt = 0 + ci: int = 0 while path[pi] != 0 and path[pi] != '/' and path[pi] != '\\' and ci < 255: component[ci] = path[pi] ci += 1; pi += 1 @@ -1029,11 +1046,11 @@ class volinfo: res_dd: FRESULT = self.dir_find(dp, c.Addr(dotdot_name[0]), lfn_buf) if res_dd == FRESULT.FR_OK: self._read_entry_from_dir(dp) - dd_eo: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - dd_off: t.CUInt32T = dd_eo - dd_ch: t.CUInt32T = t.CUInt32T(self.win[dd_off + 20]) | (t.CUInt32T(self.win[dd_off + 21]) << 8) - dd_cl: t.CUInt32T = t.CUInt32T(self.win[dd_off + 26]) | (t.CUInt32T(self.win[dd_off + 27]) << 8) - dd_clus: t.CUInt32T = (dd_ch << 16) | dd_cl + dd_eo: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + dd_off: uint32 = dd_eo + dd_ch: uint32 = uint32(self.win[dd_off + 20]) | (uint32(self.win[dd_off + 21]) << 8) + dd_cl: uint32 = uint32(self.win[dd_off + 26]) | (uint32(self.win[dd_off + 27]) << 8) + dd_clus: uint32 = (dd_ch << 16) | dd_cl if dd_clus == 0: dd_clus = self.root_cluster cluster = dd_clus if path[pi] == 0: @@ -1059,19 +1076,19 @@ class volinfo: res: FRESULT = self.dir_find(dp, c.Addr(component[0]), lfn_buf) if res != FRESULT.FR_OK: return res self._read_entry_from_dir(dp) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo if path[pi] == 0: return FRESULT.FR_OK if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH cluster = entry_cluster return FRESULT.FR_NO_PATH - def mkdir_create_dir_entries(self, new_cluster: t.CUInt32T, parent_cluster: t.CUInt32T) -> FRESULT: - sector: t.CUInt64T = self.cluster_to_sector(new_cluster) + def mkdir_create_dir_entries(self, new_cluster: uint32, parent_cluster: uint32) -> FRESULT: + sector: uint64 = self.cluster_to_sector(new_cluster) res: FRESULT = self.win_read(sector) if res != FRESULT.FR_OK: return res string.memset(c.Addr(self.win[0]), 0, 512) @@ -1079,28 +1096,28 @@ class volinfo: self.win[4] = ' '; self.win[5] = ' '; self.win[6] = ' '; self.win[7] = ' ' self.win[8] = ' '; self.win[9] = ' '; self.win[10] = ' ' self.win[11] = AM_DIR - _write16(c.Addr(self.win[0]), 20, t.CUInt16T((new_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), 26, t.CUInt16T(new_cluster & 0xFFFF)) + _write16(c.Addr(self.win[0]), 20, uint16((new_cluster >> 16) & 0xFFFF)) + _write16(c.Addr(self.win[0]), 26, uint16(new_cluster & 0xFFFF)) self._write_dirent_now(0) self.win[32] = '.'; self.win[33] = '.'; self.win[34] = ' '; self.win[35] = ' ' self.win[36] = ' '; self.win[37] = ' '; self.win[38] = ' '; self.win[39] = ' ' self.win[40] = ' '; self.win[41] = ' '; self.win[42] = ' ' self.win[11 + 32] = AM_DIR - _write16(c.Addr(self.win[0]), 20 + 32, t.CUInt16T((parent_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), 26 + 32, t.CUInt16T(parent_cluster & 0xFFFF)) + _write16(c.Addr(self.win[0]), 20 + 32, uint16((parent_cluster >> 16) & 0xFFFF)) + _write16(c.Addr(self.win[0]), 26 + 32, uint16(parent_cluster & 0xFFFF)) self._write_dirent_now(32) self.win_dirty = 1 return self.win_flush() - def file_open(self, path: t.CConst | t.CChar | t.CPtr, mode: t.CUInt8T) -> fileobj | t.CPtr: + def file_open(self, path: t.CConst | t.CChar | t.CPtr, mode: uint8) -> fileobj | t.CPtr: self.last_error = FRESULT.FR_OK if not self.mounted: self.last_error = FRESULT.FR_NOT_ENABLED return None dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if mode & FA_CREATE_NEW: if res == FRESULT.FR_OK: self.last_error = FRESULT.FR_EXIST @@ -1108,7 +1125,7 @@ class volinfo: if res != FRESULT.FR_NO_FILE and res != FRESULT.FR_NO_PATH: self.last_error = res return None - need_create: t.CInt = 0 + need_create: int = 0 if (mode & FA_CREATE_NEW): need_create = 1 if (mode & FA_OPEN_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 if (mode & FA_CREATE_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 @@ -1117,19 +1134,19 @@ class volinfo: fn: t.CArray[t.CChar, 256] _split_path(path, c.Addr(pp[0]), c.Addr(fn[0])) string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(pp[0]), t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(pp[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res2 != FRESULT.FR_OK: self.last_error = res2 return None - nc: t.CUInt32T = 0 + nc: uint32 = 0 if mode & FA_WRITE: nc = self.cluster_alloc() if nc == 0: self.last_error = FRESULT.FR_DENIED return None self._zero_cluster(nc) - ds: t.CUInt64T = 0 - do: t.CUInt32T = 0 + ds: uint64 = 0 + do: uint32 = 0 res3: FRESULT = self.dir_add_entry(c.Addr(dp), c.Addr(fn[0]), AM_ARC, nc, 0, c.Addr(ds), c.Addr(do)) if res3 != FRESULT.FR_OK: if nc >= 2: self.cluster_free_chain(nc) @@ -1162,14 +1179,14 @@ class volinfo: if res != FRESULT.FR_OK: self.last_error = res return None - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: self.last_error = res_wr return None - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] if entry_attr & AM_DIR: self.last_error = FRESULT.FR_DENIED return None @@ -1181,10 +1198,10 @@ class volinfo: if lres != FRESULT.FR_OK: self.last_error = lres return None - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo - entry_size: t.CUInt32T = _read32(c.Addr(self.win[0]), off + 28) + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + entry_size: uint32 = _read32(c.Addr(self.win[0]), off + 28) fp2: fileobj | t.CPtr = handle_alloc() if fp2 is None: self.last_error = FRESULT.FR_TOO_MANY_OPEN_FILES @@ -1222,23 +1239,23 @@ class volinfo: def file_delete(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] if entry_attr & AM_RDO: return FRESULT.FR_DENIED if entry_attr & AM_DIR: return FRESULT.FR_DENIED lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo res2: FRESULT = self.dir_delete_entry(c.Addr(dp)) if res2 != FRESULT.FR_OK: return res2 if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) @@ -1247,20 +1264,20 @@ class volinfo: def file_rename(self, old_path: t.CConst | t.CChar | t.CPtr, new_path: t.CConst | t.CChar | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), old_path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), old_path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo - entry_size: t.CUInt32T = _read32(c.Addr(self.win[0]), off + 28) + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + entry_size: uint32 = _read32(c.Addr(self.win[0]), off + 28) lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED new_parent: t.CArray[t.CChar, 260] @@ -1268,10 +1285,10 @@ class volinfo: _split_path(new_path, c.Addr(new_parent[0]), c.Addr(new_fname[0])) dp2: dirobj string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp2), c.Addr(new_parent[0]), t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res2: FRESULT = self.follow_path(c.Addr(dp2), c.Addr(new_parent[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH - new_dir_sector: t.CUInt64T = 0 - new_dir_offset: t.CUInt32T = 0 + new_dir_sector: uint64 = 0 + new_dir_offset: uint32 = 0 res3: FRESULT = self.dir_add_entry(c.Addr(dp2), c.Addr(new_fname[0]), entry_attr, entry_cluster, entry_size, c.Addr(new_dir_sector), c.Addr(new_dir_offset)) if res3 != FRESULT.FR_OK: return res3 res4: FRESULT = self.dir_delete_entry(c.Addr(dp)) @@ -1281,31 +1298,31 @@ class volinfo: def file_stat(self, path: t.CConst | t.CChar | t.CPtr, info: fileinfo | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - return self.dir_get_entry_info(c.Addr(dp), info, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + return self.dir_get_entry_info(c.Addr(dp), info, uint16(c.Addr(lfn_buf[0]), t.CPtr)) def dir_make(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res == FRESULT.FR_OK: return FRESULT.FR_EXIST parent_path: t.CArray[t.CChar, 260] dir_name: t.CArray[t.CChar, 256] _split_path(path, c.Addr(parent_path[0]), c.Addr(dir_name[0])) string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(parent_path[0]), t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(parent_path[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH - parent_cluster: t.CUInt32T = dp.cluster - new_cluster: t.CUInt32T = self.cluster_alloc() + parent_cluster: uint32 = dp.cluster + new_cluster: uint32 = self.cluster_alloc() if new_cluster == 0: return FRESULT.FR_DENIED self._zero_cluster(new_cluster) - dir_sector: t.CUInt64T = 0 - dir_offset: t.CUInt32T = 0 + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 res3: FRESULT = self.dir_add_entry(c.Addr(dp), c.Addr(dir_name[0]), AM_DIR, new_cluster, 0, c.Addr(dir_sector), c.Addr(dir_offset)) if res3 != FRESULT.FR_OK: self.cluster_free_chain(new_cluster) @@ -1318,7 +1335,7 @@ class volinfo: def dir_open_path(self, path: t.CConst | t.CChar | t.CPtr, dp: dirobj | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED - pi: t.CInt = 0 + pi: int = 0 if path[0] >= '0' and path[0] <= '9': if path[1] == ':' or path[1] == 0: pi = 2 @@ -1327,63 +1344,63 @@ class volinfo: return FRESULT.FR_OK if path[pi] == '/' or path[pi] == '\\': pi += 1 while path[pi] == '/' or path[pi] == '\\': pi += 1 - is_root: t.CInt = 1 if path[pi] == 0 else 0 - lfn_buf: t.CArray[t.CUInt16T, 256] + is_root: int = 1 if path[pi] == 0 else 0 + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(dp, path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(dp, path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res if is_root: return FRESULT.FR_OK - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo return self.dir_open(dp, entry_cluster) def dir_read(self, dp: dirobj | t.CPtr, info: fileinfo | t.CPtr) -> FRESULT: - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.dir_read_entry(dp, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.dir_read_entry(dp, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - res2: FRESULT = self.dir_get_entry_info(dp, info, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res2: FRESULT = self.dir_get_entry_info(dp, info, uint16(c.Addr(lfn_buf[0]), t.CPtr)) dp.offset += 1 return res2 def dir_remove(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - entry_attr: t.CUInt8T = self.win[off + 11] + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH - clus_hi: t.CUInt32T = t.CUInt32T(self.win[off + 20]) | (t.CUInt32T(self.win[off + 21]) << 8) - clus_lo: t.CUInt32T = t.CUInt32T(self.win[off + 26]) | (t.CUInt32T(self.win[off + 27]) << 8) - entry_cluster: t.CUInt32T = (clus_hi << 16) | clus_lo + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo if entry_cluster >= 2: check_dp: dirobj self.dir_open(c.Addr(check_dp), entry_cluster) - lfn_buf2: t.CArray[t.CUInt16T, 256] + lfn_buf2: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf2), 0, 256 * 2) while True: - check_res: FRESULT = self.dir_read_entry(c.Addr(check_dp), t.CUInt16T(c.Addr(lfn_buf2[0]), t.CPtr)) + check_res: FRESULT = self.dir_read_entry(c.Addr(check_dp), uint16(c.Addr(lfn_buf2[0]), t.CPtr)) if check_res != FRESULT.FR_OK: break - c_off: t.CUInt32T = (check_dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - c_sec: t.CUInt64T = check_dp.sector + (check_dp.offset / (512 / ENTRY_SIZE)) + c_off: uint32 = (check_dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + c_sec: uint64 = check_dp.sector + (check_dp.offset / (512 / ENTRY_SIZE)) self.win_read(c_sec) - c_name0: t.CUInt8T = self.win[c_off] - c_name1: t.CUInt8T = self.win[c_off + 1] + c_name0: uint8 = self.win[c_off] + c_name1: uint8 = self.win[c_off + 1] check_dp.offset += 1 if c_name0 == '.' and (c_name1 == '.' or c_name1 == 0x20): continue @@ -1395,42 +1412,42 @@ class volinfo: if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) return FRESULT.FR_OK - def chmod(self, path: t.CConst | t.CChar | t.CPtr, attr: t.CUInt8T, mask: t.CUInt8T) -> FRESULT: + def chmod(self, path: t.CConst | t.CChar | t.CPtr, attr: uint8, mask: uint8) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - old_attr: t.CUInt8T = self.win[off + 11] - new_attr: t.CUInt8T = (old_attr & ~mask) | (attr & mask) + off: uint32 = entry_offset_in_sector + old_attr: uint8 = self.win[off + 11] + new_attr: uint8 = (old_attr & ~mask) | (attr & mask) self.win[off + 11] = new_attr self.win_dirty = 1 return self.win_flush() - def utime(self, path: t.CConst | t.CChar | t.CPtr, mtime: t.CUInt16T, mdate: t.CUInt16T) -> FRESULT: + def utime(self, path: t.CConst | t.CChar | t.CPtr, mtime: uint16, mdate: uint16) -> FRESULT: if not self.mounted: return FRESULT.FR_NOT_ENABLED dp: dirobj - lfn_buf: t.CArray[t.CUInt16T, 256] + lfn_buf: t.CArray[uint16, 256] string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, t.CUInt16T(c.Addr(lfn_buf[0]), t.CPtr)) + res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) if res != FRESULT.FR_OK: return res - entry_sector: t.CUInt64T = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: t.CUInt32T = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE res_wr: FRESULT = self.win_read(entry_sector) if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: t.CUInt32T = entry_offset_in_sector - self.win[off + 22] = t.CUInt8T(mtime & 0xFF) - self.win[off + 23] = t.CUInt8T((mtime >> 8) & 0xFF) - self.win[off + 24] = t.CUInt8T(mdate & 0xFF) - self.win[off + 25] = t.CUInt8T((mdate >> 8) & 0xFF) - self.win[off + 18] = t.CUInt8T(mdate & 0xFF) - self.win[off + 19] = t.CUInt8T((mdate >> 8) & 0xFF) + off: uint32 = entry_offset_in_sector + self.win[off + 22] = uint8(mtime & 0xFF) + self.win[off + 23] = uint8((mtime >> 8) & 0xFF) + self.win[off + 24] = uint8(mdate & 0xFF) + self.win[off + 25] = uint8((mdate >> 8) & 0xFF) + self.win[off + 18] = uint8(mdate & 0xFF) + self.win[off + 19] = uint8((mdate >> 8) & 0xFF) self.win_dirty = 1 return self.win_flush() @@ -1438,45 +1455,45 @@ class volinfo: @t.Object class fileobj: vol: volinfo | t.CPtr - is_open: t.CInt = 0 - is_dir: t.CInt = 0 - first_cluster: t.CUInt32T = 0 - current_cluster: t.CUInt32T = 0 - file_size: t.CUInt32T = 0 - file_pos: t.CUInt32T = 0 - dir_sector: t.CUInt64T = 0 - dir_offset: t.CUInt32T = 0 - attr: t.CUInt8T = 0 - ctime: t.CUInt16T = 0 - cdate: t.CUInt16T = 0 - mtime: t.CUInt16T = 0 - mdate: t.CUInt16T = 0 - adate: t.CUInt16T = 0 - flags: t.CUInt8T = 0 - err: t.CUInt8T = 0 - lock_count: t.CInt = 0 - buf: t.CArray[t.CUInt8T, 512] - buf_sect: t.CUInt64T = 0 - buf_dirty: t.CInt = 0 + is_open: int = 0 + is_dir: int = 0 + first_cluster: uint32 = 0 + current_cluster: uint32 = 0 + file_size: uint32 = 0 + file_pos: uint32 = 0 + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 + attr: uint8 = 0 + ctime: uint16 = 0 + cdate: uint16 = 0 + mtime: uint16 = 0 + mdate: uint16 = 0 + adate: uint16 = 0 + flags: uint8 = 0 + err: uint8 = 0 + lock_count: int = 0 + buf: t.CArray[uint8, 512] + buf_sect: uint64 = 0 + buf_dirty: int = 0 def buf_flush(self) -> FRESULT: if not self.buf_dirty: return FRESULT.FR_OK - abs_sect: t.CUInt64T = t.CUInt64T(self.buf_sect) + t.CUInt64T(self.vol.hidden_sectors) + abs_sect: uint64 = uint64(self.buf_sect) + uint64(self.vol.hidden_sectors) self.vol.lock.lock() - res: DRESULT = diskio.write(self.vol.pdrv, c.Addr(self.buf[0]), t.CUInt32T(abs_sect), 1) + res: DRESULT = diskio.write(self.vol.pdrv, c.Addr(self.buf[0]), uint32(abs_sect), 1) self.vol.lock.unlock() if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.buf_dirty = 0 return FRESULT.FR_OK - def buf_read(self, sector: t.CUInt64T) -> FRESULT: + def buf_read(self, sector: uint64) -> FRESULT: if self.buf_sect == sector: return FRESULT.FR_OK if self.buf_dirty: res: FRESULT = self.buf_flush() if res != FRESULT.FR_OK: return res - abs_sect: t.CUInt64T = sector + t.CUInt64T(self.vol.hidden_sectors) + abs_sect: uint64 = sector + uint64(self.vol.hidden_sectors) self.vol.lock.lock() - res2: DRESULT = diskio.read(self.vol.pdrv, c.Addr(self.buf[0]), t.CUInt32T(abs_sect), 1) + res2: DRESULT = diskio.read(self.vol.pdrv, c.Addr(self.buf[0]), uint32(abs_sect), 1) self.vol.lock.unlock() if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.buf_sect = sector @@ -1493,7 +1510,7 @@ class fileobj: self.lock_count = 0 return FRESULT.FR_OK - def read(self, buff: t.CVoid | t.CPtr, btr: t.CUInt32T, br: t.CUInt32T | t.CPtr) -> FRESULT: + def read(self, buff: t.CPtr, btr: uint32, br: uint32 | t.CPtr) -> FRESULT: if not self.is_open: return FRESULT.FR_INVALID_OBJECT if not (self.flags & FA_READ): return FRESULT.FR_DENIED c.Set(c.Deref(br), 0) @@ -1503,26 +1520,26 @@ class fileobj: self.file_size, self.first_cluster, self.current_cluster, self.file_pos, btr) serial.puts(c.Addr(_rdb)) vol: volinfo | t.CPtr = self.vol - remaining: t.CUInt32T = btr - buf_ptr: t.CUInt8T | t.CPtr = t.CUInt8T(buff, t.CPtr) - total_read: t.CUInt32T = 0 + remaining: uint32 = btr + buf_ptr: uint8 | t.CPtr = uint8(buff, t.CPtr) + total_read: uint32 = 0 while remaining > 0: if self.file_pos >= self.file_size: break if self.first_cluster < 2: break if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): break - cluster_offset: t.CUInt32T = self.file_pos % vol.cluster_size - sector_in_cluster: t.CUInt32T = cluster_offset / 512 - offset_in_sector: t.CUInt32T = cluster_offset % 512 - sector: t.CUInt64T = vol.cluster_to_sector(self.current_cluster) + t.CUInt64T(sector_in_cluster) - can_read_in_sector: t.CUInt32T = 512 - offset_in_sector - can_read: t.CUInt32T = can_read_in_sector + cluster_offset: uint32 = self.file_pos % vol.cluster_size + sector_in_cluster: uint32 = cluster_offset / 512 + offset_in_sector: uint32 = cluster_offset % 512 + sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) + can_read_in_sector: uint32 = 512 - offset_in_sector + can_read: uint32 = can_read_in_sector if can_read > remaining: can_read = remaining if can_read > self.file_size - self.file_pos: can_read = self.file_size - self.file_pos if can_read == 0: break if offset_in_sector == 0 and can_read >= 512: - abs_sect: t.CUInt64T = sector + t.CUInt64T(vol.hidden_sectors) + abs_sect: uint64 = sector + uint64(vol.hidden_sectors) vol.lock.lock() - res: DRESULT = diskio.read(vol.pdrv, buf_ptr, t.CUInt32T(abs_sect), 1) + res: DRESULT = diskio.read(vol.pdrv, buf_ptr, uint32(abs_sect), 1) vol.lock.unlock() if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR else: @@ -1534,7 +1551,7 @@ class fileobj: total_read += can_read remaining -= can_read if self.file_pos % vol.cluster_size == 0: - next_c: t.CUInt32T = vol.cluster_get_next(self.current_cluster) + next_c: uint32 = vol.cluster_get_next(self.current_cluster) if next_c == 0: break self.current_cluster = next_c # [RD-DIAG] 打印实际读取字节数 @@ -1544,19 +1561,19 @@ class fileobj: c.Set(c.Deref(br), total_read) return FRESULT.FR_OK - def _extend_to(self, target_pos: t.CUInt32T) -> FRESULT: + def _extend_to(self, target_pos: uint32) -> FRESULT: if self.first_cluster < 2: - new_c: t.CUInt32T = self.vol.cluster_alloc() + new_c: uint32 = self.vol.cluster_alloc() if new_c == 0: return FRESULT.FR_DENIED self.first_cluster = new_c self.current_cluster = new_c self.vol._zero_cluster(new_c) - cur_pos: t.CUInt32T = 0 - clust: t.CUInt32T = self.first_cluster + cur_pos: uint32 = 0 + clust: uint32 = self.first_cluster while cur_pos + self.vol.cluster_size <= target_pos: - next_c: t.CUInt32T = self.vol.cluster_get_next(clust) + next_c: uint32 = self.vol.cluster_get_next(clust) if next_c == 0: - new_c2: t.CUInt32T = self.vol.cluster_extend(clust) + new_c2: uint32 = self.vol.cluster_extend(clust) if new_c2 == 0: return FRESULT.FR_DENIED self.vol._zero_cluster(new_c2) next_c = new_c2 @@ -1565,42 +1582,42 @@ class fileobj: self.current_cluster = clust return FRESULT.FR_OK - def write(self, buff: t.CConst | t.CVoid | t.CPtr, btw: t.CUInt32T, bw: t.CUInt32T | t.CPtr) -> FRESULT: + def write(self, buff: t.CConst | t.CPtr, btw: uint32, bw: uint32 | t.CPtr) -> FRESULT: if not self.is_open: return FRESULT.FR_INVALID_OBJECT if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED c.Set(c.Deref(bw), 0) vol: volinfo | t.CPtr = self.vol - remaining: t.CUInt32T = btw - buf_ptr: t.CConst | t.CUInt8T | t.CPtr = t.CUInt8T(buff, t.CPtr) - total_written: t.CUInt32T = 0 + remaining: uint32 = btw + buf_ptr: t.CConst | uint8 | t.CPtr = uint8(buff, t.CPtr) + total_written: uint32 = 0 while remaining > 0: if self.first_cluster < 2: - new_c: t.CUInt32T = vol.cluster_alloc() + new_c: uint32 = vol.cluster_alloc() if new_c == 0: return FRESULT.FR_DENIED self.first_cluster = new_c self.current_cluster = new_c vol._zero_cluster(new_c) if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): - last_c: t.CUInt32T = self.current_cluster + last_c: uint32 = self.current_cluster if self.first_cluster >= 2 and self.current_cluster < 2: last_c = vol.file_find_last_cluster(self.first_cluster) - new_c2: t.CUInt32T = vol.cluster_extend(last_c) + new_c2: uint32 = vol.cluster_extend(last_c) if new_c2 == 0: return FRESULT.FR_DENIED if self.first_cluster < 2: self.first_cluster = new_c2 self.current_cluster = new_c2 vol._zero_cluster(new_c2) - cluster_offset: t.CUInt32T = self.file_pos % vol.cluster_size - sector_in_cluster: t.CUInt32T = cluster_offset / 512 - offset_in_sector: t.CUInt32T = cluster_offset % 512 - sector: t.CUInt64T = vol.cluster_to_sector(self.current_cluster) + t.CUInt64T(sector_in_cluster) - can_write_in_sector: t.CUInt32T = 512 - offset_in_sector - can_write: t.CUInt32T = can_write_in_sector + cluster_offset: uint32 = self.file_pos % vol.cluster_size + sector_in_cluster: uint32 = cluster_offset / 512 + offset_in_sector: uint32 = cluster_offset % 512 + sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) + can_write_in_sector: uint32 = 512 - offset_in_sector + can_write: uint32 = can_write_in_sector if can_write > remaining: can_write = remaining if can_write == 0: break if offset_in_sector == 0 and can_write >= 512: - abs_sect: t.CUInt64T = sector + t.CUInt64T(vol.hidden_sectors) + abs_sect: uint64 = sector + uint64(vol.hidden_sectors) vol.lock.lock() - res: DRESULT = diskio.write(vol.pdrv, buf_ptr, t.CUInt32T(abs_sect), 1) + res: DRESULT = diskio.write(vol.pdrv, buf_ptr, uint32(abs_sect), 1) vol.lock.unlock() if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR self.buf_sect = 0xFFFFFFFFFFFFFFFF @@ -1618,26 +1635,26 @@ class fileobj: remaining -= can_write if self.file_pos > self.file_size: self.file_size = self.file_pos if self.file_pos % vol.cluster_size == 0: - next_c: t.CUInt32T = vol.cluster_get_next(self.current_cluster) + next_c: uint32 = vol.cluster_get_next(self.current_cluster) if next_c != 0: self.current_cluster = next_c c.Set(c.Deref(bw), total_written) return FRESULT.FR_OK - def seek(self, offset: t.CUInt32T) -> FRESULT: + def seek(self, offset: uint32) -> FRESULT: if not self.is_open: return FRESULT.FR_INVALID_OBJECT if offset > self.file_size: if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED - gap: t.CUInt32T = offset - self.file_size + gap: uint32 = offset - self.file_size res: FRESULT = self._extend_to(offset) if res != FRESULT.FR_OK: return res - old_size: t.CUInt32T = self.file_size - zero_buf: t.CArray[t.CUInt8T, 512] + old_size: uint32 = self.file_size + zero_buf: t.CArray[uint8, 512] string.memset(c.Addr(zero_buf[0]), 0, 512) self.file_pos = old_size while gap > 0: - chunk: t.CUInt32T = gap + chunk: uint32 = gap if chunk > 512: chunk = 512 - written: t.CUInt32T = 0 + written: uint32 = 0 res2: FRESULT = self.write(c.Addr(zero_buf[0]), chunk, c.Addr(written)) if res2 != FRESULT.FR_OK: return res2 if written == 0: return FRESULT.FR_DENIED @@ -1657,7 +1674,7 @@ class fileobj: if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED if self.file_pos >= self.file_size: return FRESULT.FR_OK vol: volinfo | t.CPtr = self.vol - new_size: t.CUInt32T = self.file_pos + new_size: uint32 = self.file_pos if new_size == 0: if self.first_cluster >= 2: vol.cluster_free_chain(self.first_cluster) self.first_cluster = 0 @@ -1666,9 +1683,9 @@ class fileobj: self.file_pos = 0 vol.dir_update_entry(self.dir_sector, self.dir_offset, 0, 0, self.attr) return FRESULT.FR_OK - cluster_at_pos: t.CUInt32T = vol.file_cluster_seek(self.first_cluster, new_size) + cluster_at_pos: uint32 = vol.file_cluster_seek(self.first_cluster, new_size) if cluster_at_pos < 2: return FRESULT.FR_INT_ERR - next_c: t.CUInt32T = vol.cluster_get_next(cluster_at_pos) + next_c: uint32 = vol.cluster_get_next(cluster_at_pos) vol.fat_write(cluster_at_pos, CLUSTER_EOC_MAX) if next_c >= 2 and next_c < CLUSTER_EOC_MIN: vol.cluster_free_chain(next_c) @@ -1677,23 +1694,23 @@ class fileobj: vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, new_size, self.attr) return FRESULT.FR_OK - def tell(self) -> t.CUInt32T: + def tell(self) -> uint32: return self.file_pos - def size(self) -> t.CUInt32T: + def size(self) -> uint32: return self.file_size @t.Object class dirobj: vol: volinfo | t.CPtr - cluster: t.CUInt32T = 0 - start_cluster: t.CUInt32T = 0 - sector: t.CUInt64T = 0 - offset: t.CUInt32T = 0 - is_open: t.CInt = 0 - lfn_ofs: t.CUInt32T = 4294967295 - lfn_cluster: t.CUInt32T = 0 + cluster: uint32 = 0 + start_cluster: uint32 = 0 + sector: uint64 = 0 + offset: uint32 = 0 + is_open: int = 0 + lfn_ofs: uint32 = 4294967295 + lfn_cluster: uint32 = 0 sfn: t.CArray[t.CChar, 12] def close(self): @@ -1702,7 +1719,7 @@ class dirobj: handle_table: t.CArray[fileobj, MAX_HANDLES] lock_table: t.CArray[filelock, MAX_LOCKS] -handles_initialized: t.CStatic | t.CInt = 0 +handles_initialized: t.CStatic | int = 0 def handles_init(): global handles_initialized, handle_table, lock_table @@ -1724,11 +1741,11 @@ def handle_alloc() -> fileobj | t.CPtr: _dha: t.CArray[t.CChar, 120] viperlib.snprintf(c.Addr(_dha), 120, "[handle] full init=%d h0=%d h1=%d h2=%d h3=%d addr=0x%lx\n", handles_initialized, handle_table[0].is_open, handle_table[1].is_open, - handle_table[2].is_open, handle_table[3].is_open, t.CUInt64T(c.Addr(handle_table[0]))) + handle_table[2].is_open, handle_table[3].is_open, uint64(c.Addr(handle_table[0]))) serial.puts(c.Addr(_dha)) return None -def lock_check(dir_sector: t.CUInt64T, dir_offset: t.CUInt32T, mode: t.CUInt8T) -> FRESULT: +def lock_check(dir_sector: uint64, dir_offset: uint32, mode: uint8) -> FRESULT: global lock_table handles_init() for i in range(MAX_LOCKS): @@ -1738,7 +1755,7 @@ def lock_check(dir_sector: t.CUInt64T, dir_offset: t.CUInt32T, mode: t.CUInt8T) if lk.exclusive: return FRESULT.FR_LOCKED return FRESULT.FR_OK -def lock_acquire(dir_sector: t.CUInt64T, dir_offset: t.CUInt32T, exclusive: t.CInt) -> FRESULT: +def lock_acquire(dir_sector: uint64, dir_offset: uint32, exclusive: int) -> FRESULT: global lock_table handles_init() for i in range(MAX_LOCKS): @@ -1752,7 +1769,7 @@ def lock_acquire(dir_sector: t.CUInt64T, dir_offset: t.CUInt32T, exclusive: t.CI return FRESULT.FR_OK return FRESULT.FR_TOO_MANY_OPEN_FILES -def lock_release(dir_sector: t.CUInt64T, dir_offset: t.CUInt32T): +def lock_release(dir_sector: uint64, dir_offset: uint32): global lock_table handles_init() for i in range(MAX_LOCKS): diff --git a/VKernel/Kernel/drivers/input/keyboard/keyboard.vp b/VKernel/Kernel/drivers/input/keyboard/keyboard.vp index d44823d..5a85029 100644 --- a/VKernel/Kernel/drivers/input/keyboard/keyboard.vp +++ b/VKernel/Kernel/drivers/input/keyboard/keyboard.vp @@ -1,148 +1,148 @@ -import asm -import intr.idt as idt -import drivers.serial.uart.serial as serial -import viperstring as string -import t, c - - -KBD_DATA: t.CDefine = 0x60 -KBD_STATUS: t.CDefine = 0x64 -KBD_COMMAND: t.CDefine = 0x64 - -KBD_BUF_SIZE: t.CDefine = 1024 - -KEY_RELEASED: t.CDefine = 0x80 - -buffer: t.CArray[t.CUInt8T, KBD_BUF_SIZE] -buf_head: t.CStatic | t.CUInt32T = 0 -buf_tail: t.CStatic | t.CUInt32T = 0 -buf_count: t.CStatic | t.CUInt32T = 0 -kbd_irq_cnt: t.CStatic | t.CUInt64T = 0 - -shift_l: t.CStatic | t.CUInt8T = 0 -shift_r: t.CStatic | t.CUInt8T = 0 -ctrl_l: t.CStatic | t.CUInt8T = 0 -alt_l: t.CStatic | t.CUInt8T = 0 -caps_lock: t.CStatic | t.CUInt8T = 0 - -scancode_set1: t.CArray[t.CChar, 128] = [ - '\0', '\x1b', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', - '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', - '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", '`', '\0', - '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0', ' ', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '-', '8', '6', '2', '\0', - '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0' -] - -scancode_set1_shift: t.CArray[t.CChar, 128] = [ - '\0', '\x1b', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', - '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', - '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '\0', - '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', ' ', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '-', '8', '6', '2', '\0', - '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0' -] - -def _wait_read(): - timeout: t.CUInt32T = 100000 - while timeout > 0: - if (asm.inb(KBD_STATUS) & 0x01) != 0: return - timeout -= 1 - -def _wait_write(): - timeout: t.CUInt32T = 100000 - while timeout > 0: - if (asm.inb(KBD_STATUS) & 0x02) == 0: return - timeout -= 1 - -def irq_handler() -> t.CInt: - global buf_head, buf_tail, buf_count, kbd_irq_cnt - kbd_irq_cnt += 1 - scancode: t.CUInt8T = asm.inb(KBD_DATA) - if buf_count < KBD_BUF_SIZE: - buffer[buf_tail] = scancode - buf_tail = buf_tail + 1 - if buf_tail >= KBD_BUF_SIZE: - buf_tail = 0 - buf_count += 1 - return 0 - -def read_scancode() -> t.CUInt8T: - global buf_head, buf_count - asm.cli() - if buf_count == 0: - asm.sti() - return 0 - code: t.CUInt8T = buffer[buf_head] - buf_head = buf_head + 1 - if buf_head >= KBD_BUF_SIZE: - buf_head = 0 - buf_count -= 1 - asm.sti() - return code - -def scancode_to_ascii(scancode: t.CUInt8T) -> t.CChar: - code: t.CUInt8T = scancode & ~t.CUInt8T(KEY_RELEASED) - if code >= 128: return '\0' - shifted: bool = (shift_l or shift_r) != 0 - if caps_lock and code >= 0x10 and code <= 0x32: - shifted = not shifted - if shifted: - return scancode_set1_shift[code] - return scancode_set1[code] - -def has_data() -> t.CInt: - return buf_count - -def init(): - drain: t.CUInt32T - drain = 0 - while (asm.inb(KBD_STATUS) & 0x01) != 0: - asm.inb(KBD_DATA) - drain += 1 - if drain > 1000: break - - _wait_write() - asm.outb(KBD_COMMAND, 0xAD) - - drain = 0 - while (asm.inb(KBD_STATUS) & 0x01) != 0: - asm.inb(KBD_DATA) - drain += 1 - if drain > 1000: break - - _wait_write() - asm.outb(KBD_COMMAND, 0x20) - _wait_read() - ccb: t.CUInt8T = asm.inb(KBD_DATA) - - ccb = ccb | 0x01 - ccb = ccb | 0x40 - ccb = ccb & 0xEF - - _wait_write() - asm.outb(KBD_COMMAND, 0x60) - _wait_write() - asm.outb(KBD_DATA, ccb) - - _wait_write() - asm.outb(KBD_COMMAND, 0xAE) - - drain = 0 - while (asm.inb(KBD_STATUS) & 0x01) != 0: - asm.inb(KBD_DATA) - drain += 1 - if drain > 1000: break - - _wait_write() - asm.outb(KBD_DATA, 0xF4) - _wait_read() - asm.inb(KBD_DATA) - - idt.irqInstallHandler(1, irq_handler, "keyboard") +import asm +import intr.idt as idt +import drivers.serial.uart.serial as serial +import viperstring as string +import t, c + + +KBD_DATA: t.CDefine = 0x60 +KBD_STATUS: t.CDefine = 0x64 +KBD_COMMAND: t.CDefine = 0x64 + +KBD_BUF_SIZE: t.CDefine = 1024 + +KEY_RELEASED: t.CDefine = 0x80 + +buffer: t.CArray[uint8, KBD_BUF_SIZE] +buf_head: t.CStatic | uint32 = 0 +buf_tail: t.CStatic | uint32 = 0 +buf_count: t.CStatic | uint32 = 0 +kbd_irq_cnt: t.CStatic | uint64 = 0 + +shift_l: t.CStatic | uint8 = 0 +shift_r: t.CStatic | uint8 = 0 +ctrl_l: t.CStatic | uint8 = 0 +alt_l: t.CStatic | uint8 = 0 +caps_lock: t.CStatic | uint8 = 0 + +scancode_set1: t.CArray[t.CChar, 128] = [ + '\0', '\x1b', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", '`', '\0', + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0', ' ', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '-', '8', '6', '2', '\0', + '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0' +] + +scancode_set1_shift: t.CArray[t.CChar, 128] = [ + '\0', '\x1b', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', + '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', + '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '\0', + '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', ' ', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '-', '8', '6', '2', '\0', + '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0' +] + +def _wait_read(): + timeout: uint32 = 100000 + while timeout > 0: + if (asm.inb(KBD_STATUS) & 0x01) != 0: return + timeout -= 1 + +def _wait_write(): + timeout: uint32 = 100000 + while timeout > 0: + if (asm.inb(KBD_STATUS) & 0x02) == 0: return + timeout -= 1 + +def irq_handler() -> int: + global buf_head, buf_tail, buf_count, kbd_irq_cnt + kbd_irq_cnt += 1 + scancode: uint8 = asm.inb(KBD_DATA) + if buf_count < KBD_BUF_SIZE: + buffer[buf_tail] = scancode + buf_tail = buf_tail + 1 + if buf_tail >= KBD_BUF_SIZE: + buf_tail = 0 + buf_count += 1 + return 0 + +def read_scancode() -> uint8: + global buf_head, buf_count + asm.cli() + if buf_count == 0: + asm.sti() + return 0 + code: uint8 = buffer[buf_head] + buf_head = buf_head + 1 + if buf_head >= KBD_BUF_SIZE: + buf_head = 0 + buf_count -= 1 + asm.sti() + return code + +def scancode_to_ascii(scancode: uint8) -> t.CChar: + code: uint8 = scancode & ~uint8(KEY_RELEASED) + if code >= 128: return '\0' + shifted: bool = (shift_l or shift_r) != 0 + if caps_lock and code >= 0x10 and code <= 0x32: + shifted = not shifted + if shifted: + return scancode_set1_shift[code] + return scancode_set1[code] + +def has_data() -> int: + return buf_count + +def init(): + drain: uint32 + drain = 0 + while (asm.inb(KBD_STATUS) & 0x01) != 0: + asm.inb(KBD_DATA) + drain += 1 + if drain > 1000: break + + _wait_write() + asm.outb(KBD_COMMAND, 0xAD) + + drain = 0 + while (asm.inb(KBD_STATUS) & 0x01) != 0: + asm.inb(KBD_DATA) + drain += 1 + if drain > 1000: break + + _wait_write() + asm.outb(KBD_COMMAND, 0x20) + _wait_read() + ccb: uint8 = asm.inb(KBD_DATA) + + ccb = ccb | 0x01 + ccb = ccb | 0x40 + ccb = ccb & 0xEF + + _wait_write() + asm.outb(KBD_COMMAND, 0x60) + _wait_write() + asm.outb(KBD_DATA, ccb) + + _wait_write() + asm.outb(KBD_COMMAND, 0xAE) + + drain = 0 + while (asm.inb(KBD_STATUS) & 0x01) != 0: + asm.inb(KBD_DATA) + drain += 1 + if drain > 1000: break + + _wait_write() + asm.outb(KBD_DATA, 0xF4) + _wait_read() + asm.inb(KBD_DATA) + + idt.irqInstallHandler(1, irq_handler, "keyboard") diff --git a/VKernel/Kernel/drivers/input/mouse/mouse.vp b/VKernel/Kernel/drivers/input/mouse/mouse.vp index 7adf140..41dd454 100644 --- a/VKernel/Kernel/drivers/input/mouse/mouse.vp +++ b/VKernel/Kernel/drivers/input/mouse/mouse.vp @@ -1,136 +1,136 @@ -import asm -import intr.idt as idt -import platform.pch.pic as pic -import drivers.serial.uart.serial as serial -import t, c - - -MOUSE_DATA: t.CDefine = 0x60 -MOUSE_STATUS: t.CDefine = 0x64 -MOUSE_COMMAND: t.CDefine = 0x64 - -MOUSE_BUF_SIZE: t.CDefine = 1024 - -MOUSE_LEFT: t.CDefine = 0x01 -MOUSE_RIGHT: t.CDefine = 0x02 -MOUSE_MIDDLE: t.CDefine = 0x04 - -class mouse_packet: - flags: t.CUInt8T - dx: t.CInt8T - dy: t.CInt8T - buttons: t.CUInt8T - -packets: t.CArray[mouse_packet, MOUSE_BUF_SIZE] -pack_head: t.CStatic | t.CUInt32T = 0 -pack_tail: t.CStatic | t.CUInt32T = 0 -pack_count: t.CStatic | t.CUInt32T = 0 -mse_irq_cnt: t.CStatic | t.CUInt64T = 0 - -cycle: t.CStatic | t.CUInt8T = 0 -byte1: t.CStatic | t.CUInt8T = 0 -byte2: t.CStatic | t.CInt8T = 0 -byte3: t.CStatic | t.CInt8T = 0 - -mouse_x: t.CStatic | t.CInt32T = 0 -mouse_y: t.CStatic | t.CInt32T = 0 -mouse_buttons: t.CStatic | t.CUInt8T = 0 - -def _wait_read(): - timeout: t.CUInt32T = 100000 - while timeout > 0: - if (asm.inb(MOUSE_STATUS) & 0x01) != 0: return - timeout -= 1 - -def _wait_write(): - timeout: t.CUInt32T = 100000 - while timeout > 0: - if (asm.inb(MOUSE_STATUS) & 0x02) == 0: return - timeout -= 1 - -def _write_cmd(cmd: t.CUInt8T): - _wait_write() - asm.outb(MOUSE_COMMAND, 0xD4) - _wait_write() - asm.outb(MOUSE_DATA, cmd) - _wait_read() - asm.inb(MOUSE_DATA) - -def irq_handler() -> t.CInt: - global cycle, byte1, byte2, byte3, pack_tail, pack_count, mse_irq_cnt - mse_irq_cnt += 1 - status: t.CUInt8T = asm.inb(MOUSE_STATUS) - if (status & 0x20) == 0: return 0 - data: t.CUInt8T = asm.inb(MOUSE_DATA) - if cycle == 0: - if (data & 0x08) != 0: - byte1 = data - cycle = 1 - return 0 - if cycle == 1: - byte2 = data - cycle = 2 - return 0 - byte3 = data - cycle = 0 - if pack_count < MOUSE_BUF_SIZE: - packets[pack_tail].flags = byte1 - packets[pack_tail].dx = byte2 - packets[pack_tail].dy = byte3 - packets[pack_tail].buttons = byte1 & t.CUInt8T(0x07) - pack_tail = pack_tail + 1 - if pack_tail >= MOUSE_BUF_SIZE: - pack_tail = 0 - pack_count += 1 - return 0 - -def read_packet(out: mouse_packet | t.CPtr) -> t.CInt: - global pack_head, pack_count - asm.cli() - if pack_count == 0: - asm.sti() - out.flags = 0 - out.dx = 0 - out.dy = 0 - out.buttons = 0 - return -1 - out.flags = packets[pack_head].flags - out.dx = packets[pack_head].dx - out.dy = packets[pack_head].dy - out.buttons = packets[pack_head].buttons - pack_head = pack_head + 1 - if pack_head >= MOUSE_BUF_SIZE: - pack_head = 0 - pack_count -= 1 - asm.sti() - return 0 - -def has_data() -> t.CInt: - return pack_count - -def get_x() -> t.CInt32T: - return mouse_x - -def get_y() -> t.CInt32T: - return mouse_y - -def get_buttons() -> t.CUInt8T: - return mouse_buttons - -def init(): - _wait_write() - asm.outb(MOUSE_COMMAND, 0xA8) - _wait_write() - asm.outb(MOUSE_COMMAND, 0x20) - _wait_read() - status: t.CUInt8T = asm.inb(MOUSE_DATA) - status = status | 0x02 - status = status & 0xDF - _wait_write() - asm.outb(MOUSE_COMMAND, 0x60) - _wait_write() - asm.outb(MOUSE_DATA, status) - _write_cmd(0xF6) - _write_cmd(0xF4) - pic.clearMask(12) - idt.irqInstallHandler(12, irq_handler, "mouse") +import asm +import intr.idt as idt +import platform.pch.pic as pic +import drivers.serial.uart.serial as serial +import t, c + + +MOUSE_DATA: t.CDefine = 0x60 +MOUSE_STATUS: t.CDefine = 0x64 +MOUSE_COMMAND: t.CDefine = 0x64 + +MOUSE_BUF_SIZE: t.CDefine = 1024 + +MOUSE_LEFT: t.CDefine = 0x01 +MOUSE_RIGHT: t.CDefine = 0x02 +MOUSE_MIDDLE: t.CDefine = 0x04 + +class mouse_packet: + flags: uint8 + dx: int8 + dy: int8 + buttons: uint8 + +packets: t.CArray[mouse_packet, MOUSE_BUF_SIZE] +pack_head: t.CStatic | uint32 = 0 +pack_tail: t.CStatic | uint32 = 0 +pack_count: t.CStatic | uint32 = 0 +mse_irq_cnt: t.CStatic | uint64 = 0 + +cycle: t.CStatic | uint8 = 0 +byte1: t.CStatic | uint8 = 0 +byte2: t.CStatic | int8 = 0 +byte3: t.CStatic | int8 = 0 + +mouse_x: t.CStatic | int32 = 0 +mouse_y: t.CStatic | int32 = 0 +mouse_buttons: t.CStatic | uint8 = 0 + +def _wait_read(): + timeout: uint32 = 100000 + while timeout > 0: + if (asm.inb(MOUSE_STATUS) & 0x01) != 0: return + timeout -= 1 + +def _wait_write(): + timeout: uint32 = 100000 + while timeout > 0: + if (asm.inb(MOUSE_STATUS) & 0x02) == 0: return + timeout -= 1 + +def _write_cmd(cmd: uint8): + _wait_write() + asm.outb(MOUSE_COMMAND, 0xD4) + _wait_write() + asm.outb(MOUSE_DATA, cmd) + _wait_read() + asm.inb(MOUSE_DATA) + +def irq_handler() -> int: + global cycle, byte1, byte2, byte3, pack_tail, pack_count, mse_irq_cnt + mse_irq_cnt += 1 + status: uint8 = asm.inb(MOUSE_STATUS) + if (status & 0x20) == 0: return 0 + data: uint8 = asm.inb(MOUSE_DATA) + if cycle == 0: + if (data & 0x08) != 0: + byte1 = data + cycle = 1 + return 0 + if cycle == 1: + byte2 = data + cycle = 2 + return 0 + byte3 = data + cycle = 0 + if pack_count < MOUSE_BUF_SIZE: + packets[pack_tail].flags = byte1 + packets[pack_tail].dx = byte2 + packets[pack_tail].dy = byte3 + packets[pack_tail].buttons = byte1 & uint8(0x07) + pack_tail = pack_tail + 1 + if pack_tail >= MOUSE_BUF_SIZE: + pack_tail = 0 + pack_count += 1 + return 0 + +def read_packet(out: mouse_packet | t.CPtr) -> int: + global pack_head, pack_count + asm.cli() + if pack_count == 0: + asm.sti() + out.flags = 0 + out.dx = 0 + out.dy = 0 + out.buttons = 0 + return -1 + out.flags = packets[pack_head].flags + out.dx = packets[pack_head].dx + out.dy = packets[pack_head].dy + out.buttons = packets[pack_head].buttons + pack_head = pack_head + 1 + if pack_head >= MOUSE_BUF_SIZE: + pack_head = 0 + pack_count -= 1 + asm.sti() + return 0 + +def has_data() -> int: + return pack_count + +def get_x() -> int32: + return mouse_x + +def get_y() -> int32: + return mouse_y + +def get_buttons() -> uint8: + return mouse_buttons + +def init(): + _wait_write() + asm.outb(MOUSE_COMMAND, 0xA8) + _wait_write() + asm.outb(MOUSE_COMMAND, 0x20) + _wait_read() + status: uint8 = asm.inb(MOUSE_DATA) + status = status | 0x02 + status = status & 0xDF + _wait_write() + asm.outb(MOUSE_COMMAND, 0x60) + _wait_write() + asm.outb(MOUSE_DATA, status) + _write_cmd(0xF6) + _write_cmd(0xF4) + pic.clearMask(12) + idt.irqInstallHandler(12, irq_handler, "mouse") diff --git a/VKernel/Kernel/drivers/serial/uart/serial.vp b/VKernel/Kernel/drivers/serial/uart/serial.vp index c553e0b..7f53cc2 100644 --- a/VKernel/Kernel/drivers/serial/uart/serial.vp +++ b/VKernel/Kernel/drivers/serial/uart/serial.vp @@ -30,15 +30,15 @@ def puts(s: str): putchar(i) # 检查COM1是否有数据可读 -def isDataAvailable() -> t.CInt: +def isDataAvailable() -> int: return su8250.isDataAvailable(su8250.COM1_PORT) # 检查COM1发送缓冲区是否为空 -def isTransmitEmpty() -> t.CInt: +def isTransmitEmpty() -> int: return su8250.isTransmitEmpty(su8250.COM1_PORT) # 发送32位十六进制值到COM1 -def put_hex32(value: t.CUInt32T): +def put_hex32(value: uint32): hex_digits: t.CArray[t.CChar, None] = ["0123456789ABCDEF"] buffer: t.CArray[t.CChar, 9] for i in range(7, -1, -1): @@ -51,24 +51,24 @@ def put_hex32(value: t.CUInt32T): # 格式化输出到串口(printf 实现,覆盖 libc printf 的裸机缺失) # 内部复用 viperlib.vsnprintf 格式化到栈缓冲,再逐字符送串口。 # print(...) 内建映射到 @printf(stdio extern),此定义提供裸机实现。 -def printf(fmt: t.CConst | str, *args) -> t.CInt | t.CExport: +def printf(fmt: t.CConst | str, *args) -> int | t.CExport: if fmt is None: return 0 buf: t.CArray[t.CChar, 1024] - n: t.CInt = viperlib.vsnprintf(c.Addr(buf), 1024, fmt, args) + n: int = viperlib.vsnprintf(c.Addr(buf), 1024, fmt, args) puts(buf) return n # 刷新输出流:串口是无缓冲直写(putchar 直接写 UART 端口),flush 即空操作。 # 覆盖 libc fflush 的裸机缺失(memhub 的诊断/终止路径 call @fflush)。 -def fflush(stream: t.CConst | t.CVoid | t.CPtr) -> t.CInt | t.CExport: +def fflush(stream: t.CConst | t.CPtr) -> int | t.CExport: return 0 # 系统退出:触发硬件关机(QEMU ACPI/Bochs 关机端口),失败则停机兜底。 # 覆盖 libc exit 的裸机缺失(memhub 等致命错误路径 call @exit)。 -def exit(status: int) -> t.CInt | t.CExport: +def exit(status: int) -> int | t.CExport: asm.outw(0x604, 0x2000) # QEMU ACPI 关机 asm.outw(0xB004, 0x2000) # Bochs/QEMU 备用端口 while True: diff --git a/VKernel/Kernel/drivers/serial/uart/su8250.vp b/VKernel/Kernel/drivers/serial/uart/su8250.vp index 568a41b..173d683 100644 --- a/VKernel/Kernel/drivers/serial/uart/su8250.vp +++ b/VKernel/Kernel/drivers/serial/uart/su8250.vp @@ -40,7 +40,7 @@ BAUD_115200: t.CDefine = 1 # 初始化UART 8250/16550 -def init(port: t.CUInt16T): +def init(port: uint16): # 1. 禁用中断 asm.outb(port + UART_IER, 0x00) delay(1000) @@ -69,18 +69,18 @@ def init(port: t.CUInt16T): delay(10000) # 延迟函数 -def delay(count: t.CInt): +def delay(count: int): for i in range(count): c.Asm("nop") # 检查发送缓冲区是否为空 -def isTransmitEmpty(port: t.CUInt16T) -> t.CInt: +def isTransmitEmpty(port: uint16) -> int: return asm.inb(port + UART_LSR) & UART_LSR_THRE -def putchar(port: t.CUInt16T, cr: t.CChar): +def putchar(port: uint16, cr: t.CChar): # 1. 处理换行符:串口终端需要\r\n才会正确换行,只发\n会错位 if cr == '\n': # 直接发送\r,避免递归调用 - timeout: t.CUInt32T = 1000000 + timeout: uint32 = 1000000 while ((asm.inb(port + UART_LSR) & UART_LSR_THRE) == 0) and timeout: c.Asm("nop") timeout -= 1 @@ -91,7 +91,7 @@ def putchar(port: t.CUInt16T, cr: t.CChar): c.Asm("nop") timeout -= 1 # 2. 等待发送缓冲区为空 - timeout: t.CUInt32T = 1000000 + timeout: uint32 = 1000000 while ((asm.inb(port + UART_LSR) & UART_LSR_THRE) == 0) and timeout: c.Asm("nop") timeout -= 1 @@ -105,11 +105,11 @@ def putchar(port: t.CUInt16T, cr: t.CChar): timeout -= 1 # 检查是否有数据可读 -def isDataAvailable(port: t.CUInt16T) -> t.CInt: +def isDataAvailable(port: uint16) -> int: return asm.inb(port + UART_LSR) & UART_LSR_DR # 读取一个字符 -def getchar(port: t.CUInt16T) -> t.CChar: +def getchar(port: uint16) -> t.CChar: # 等待数据可用 while not isDataAvailable(port): pass # 读取字符 diff --git a/VKernel/Kernel/drivers/storage/ide/ide.vp b/VKernel/Kernel/drivers/storage/ide/ide.vp index 256828d..3add315 100644 --- a/VKernel/Kernel/drivers/storage/ide/ide.vp +++ b/VKernel/Kernel/drivers/storage/ide/ide.vp @@ -29,12 +29,12 @@ IDE_STATUS_ERR: t.CDefine = 0x01 SECTOR_SIZE: t.CDefine = 512 -_ide_initialized: t.CInt = 0 +_ide_initialized: int = 0 -def waitReady(baseport: t.CUInt16T) -> t.CStatic | IDError: - timeout: t.CInt = 100000 +def waitReady(baseport: uint16) -> t.CStatic | IDError: + timeout: int = 100000 while timeout > 0: - status: t.CUInt8T = asm.inb(baseport + 7) + status: uint8 = asm.inb(baseport + 7) if status & IDE_STATUS_DF: return IDError.IDE_ERR_DEVICE_FAILURE if not status & IDE_STATUS_BSY and status & IDE_STATUS_DRDY: @@ -42,10 +42,10 @@ def waitReady(baseport: t.CUInt16T) -> t.CStatic | IDError: timeout -= 1 return IDError.IDE_ERR_TIMEOUT -def waitDataReady(baseport: t.CUInt16T) -> t.CStatic | IDError: - timeout: t.CInt = 100000 +def waitDataReady(baseport: uint16) -> t.CStatic | IDError: + timeout: int = 100000 while timeout > 0: - status: t.CUInt8T = asm.inb(baseport + 7) + status: uint8 = asm.inb(baseport + 7) if status & IDE_STATUS_ERR: return IDError.IDE_ERR_DEVICE_ERROR if status & IDE_STATUS_DF: return IDError.IDE_ERR_DEVICE_FAILURE if not status & IDE_STATUS_BSY and (status & IDE_STATUS_DRQ or status & IDE_STATUS_DRDY): @@ -53,110 +53,112 @@ def waitDataReady(baseport: t.CUInt16T) -> t.CStatic | IDError: timeout -= 1 return IDError.IDE_ERR_TIMEOUT -def init() -> t.CInt: +def init() -> int: global _ide_initialized if _ide_initialized: return IDError.IDE_ERR_NONE dbg: t.CArray[t.CChar, 120] - bus: t.CUInt8T - dev_n: t.CUInt8T - func: t.CUInt8T + bus: uint8 + dev_n: uint8 + func: uint8 for bus in range(2): for dev_n in range(32): for func in range(8): - vendor: t.CUInt16T = pci.pci_read16(bus, dev_n, func, 0x00) + vendor: uint16 = pci.pci_read16(bus, dev_n, func, 0x00) if vendor == 0xFFFF: continue - cls: t.CUInt32T = pci.pci_get_class(bus, dev_n, func) + cls: uint32 = pci.pci_get_class(bus, dev_n, func) if cls == 0x010180 or cls == 0x0101: - cmd: t.CUInt16T = pci.pci_read16(bus, dev_n, func, 0x04) - pci.pci_write32(bus, dev_n, func, 0x04, t.CUInt32T(cmd | 0x0007)) - viperlib.snprintf(c.Addr(dbg), 120, "[ide] found at %d:%d:%d cmd=0x%04x\n", t.CInt(bus), t.CInt(dev_n), t.CInt(func), t.CUInt32T(pci.pci_read16(bus, dev_n, func, 0x04))) + cmd: uint16 = pci.pci_read16(bus, dev_n, func, 0x04) + pci.pci_write32(bus, dev_n, func, 0x04, uint32(cmd | 0x0007)) + viperlib.snprintf(c.Addr(dbg), 120, "[ide] found at %d:%d:%d cmd=0x%04x\n", int(bus), int(dev_n), int(func), uint32(pci.pci_read16(bus, dev_n, func, 0x04))) serial.puts(dbg) asm.outb(0x3F6, 0x04) - i: t.CInt + i: int for i in range(10000): asm.nop() asm.outb(0x3F6, 0x00) for i in range(10000): asm.nop() - status: t.CUInt8T = asm.inb(0x1F7) - viperlib.snprintf(c.Addr(dbg), 120, "[ide] status=0x%02x\n", t.CUInt32T(status)) + status: uint8 = asm.inb(0x1F7) + viperlib.snprintf(c.Addr(dbg), 120, "[ide] status=0x%02x\n", uint32(status)) serial.puts(dbg) _ide_initialized = 1 return IDError.IDE_ERR_NONE -def readSector(lba: t.CUInt32T, buffer: t.CVoid | t.CPtr) -> t.CInt: +def readSector(lba: uint32, buffer: t.CPtr) -> int: if buffer is None: return IDError.IDE_ERR_BUFFER_NULL dbg: t.CArray[t.CChar, 120] err: IDError = waitReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: - viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitReady err=%d\n", t.CInt(err)) + viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitReady err=%d\n", int(err)) serial.puts(dbg) return err asm.outb(0x3F6, 0x00) asm.outb(0x1F2, 1) - asm.outb(0x1F3, t.CUInt8T(lba & 0xFF)) - asm.outb(0x1F4, t.CUInt8T((lba >> 8) & 0xFF)) - asm.outb(0x1F5, t.CUInt8T((lba >> 16) & 0xFF)) - asm.outb(0x1F6, t.CUInt8T(0xE0 | ((lba >> 24) & 0x0F))) + asm.outb(0x1F3, uint8(lba & 0xFF)) + asm.outb(0x1F4, uint8((lba >> 8) & 0xFF)) + asm.outb(0x1F5, uint8((lba >> 16) & 0xFF)) + asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F))) asm.outb(0x1F7, 0x20) err = waitDataReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: - st: t.CUInt8T = asm.inb(0x1F7) - viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitDataReady err=%d status=0x%02x\n", t.CInt(err), t.CUInt32T(st)) + st: uint8 = asm.inb(0x1F7) + viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitDataReady err=%d status=0x%02x\n", int(err), uint32(st)) serial.puts(dbg) return err - st2: t.CUInt8T = asm.inb(0x1F7) - buf: t.CUInt16T | t.CPtr = t.CUInt16T(buffer, t.CPtr) + st2: uint8 = asm.inb(0x1F7) + buf: uint16 | t.CPtr = uint16(buffer, t.CPtr) for j in range(256): c.Set(c.Deref(buf), asm.inw(0x1F0)) - buf += 1 - first_byte: t.CUInt8T = c.Deref(t.CUInt8T(buffer, t.CPtr)) - # viperlib.snprintf(c.Addr(dbg), 120, "[readSector] lba=%lu status=0x%02x first=%02x\n", lba, t.CUInt32T(st2), t.CUInt32T(first_byte)) + # buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节 + buf = buf + 2 + first_byte: uint8 = c.Deref(uint8(buffer, t.CPtr)) + # viperlib.snprintf(c.Addr(dbg), 120, "[readSector] lba=%lu status=0x%02x first=%02x\n", lba, uint32(st2), uint32(first_byte)) # serial.puts(dbg) return IDError.IDE_ERR_NONE -def writeSector(lba: t.CUInt32T, buffer: t.CConst | t.CVoid | t.CPtr) -> t.CInt: +def writeSector(lba: uint32, buffer: t.CConst | t.CPtr) -> int: if buffer is None: return IDError.IDE_ERR_BUFFER_NULL err: IDError = waitReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: return err asm.outb(0x3F6, 0x00) asm.outb(0x1F2, 1) - asm.outb(0x1F3, t.CUInt8T(lba & 0xFF)) - asm.outb(0x1F4, t.CUInt8T((lba >> 8) & 0xFF)) - asm.outb(0x1F5, t.CUInt8T((lba >> 16) & 0xFF)) - asm.outb(0x1F6, t.CUInt8T(0xE0 | ((lba >> 24) & 0x0F))) + asm.outb(0x1F3, uint8(lba & 0xFF)) + asm.outb(0x1F4, uint8((lba >> 8) & 0xFF)) + asm.outb(0x1F5, uint8((lba >> 16) & 0xFF)) + asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F))) asm.outb(0x1F7, 0x30) err = waitDataReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: return err - buf: t.CUInt16T | t.CPtr = t.CUInt16T(buffer, t.CPtr) + buf: uint16 | t.CPtr = uint16(buffer, t.CPtr) for j in range(256): - val: t.CUInt16T = c.Deref(buf) + val: uint16 = c.Deref(buf) asm.outw(0x1F0, val) - buf += 1 + # buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节 + buf = buf + 2 asm.outb(0x1F7, 0xE7) waitReady(IDE_baseport_PRIMARY) return IDError.IDE_ERR_NONE -def getDiskSize() -> t.CUInt64T: +def getDiskSize() -> uint64: err: IDError = waitReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: return 0 asm.outb(0x1F6, 0xE0) asm.outb(0x1F7, 0xEC) err = waitDataReady(IDE_baseport_PRIMARY) if err != IDError.IDE_ERR_NONE: return 0 - status: t.CUInt8T = asm.inb(0x1F7) + status: uint8 = asm.inb(0x1F7) if not status & IDE_STATUS_DRDY: return 0 if status & IDE_STATUS_ERR: return 0 - identify_data: t.CArray[t.CUInt16T, 256] + identify_data: t.CArray[uint16, 256] for i in range(256): identify_data[i] = asm.inw(0x1F0) - totalSectors: t.CUInt64T = identify_data[60] | t.CUInt64T(identify_data[61]) << 16 + totalSectors: uint64 = identify_data[60] | uint64(identify_data[61]) << 16 if identify_data[83] & (1 << 10): - lba48_sectors: t.CUInt64T = ( - t.CUInt64T(identify_data[100]) | - t.CUInt64T(identify_data[101]) << 16 | - t.CUInt64T(identify_data[102]) << 32 | - t.CUInt64T(identify_data[103]) << 48) + lba48_sectors: uint64 = ( + uint64(identify_data[100]) | + uint64(identify_data[101]) << 16 | + uint64(identify_data[102]) << 32 | + uint64(identify_data[103]) << 48) if lba48_sectors > totalSectors: totalSectors = lba48_sectors return totalSectors diff --git a/VKernel/Kernel/drivers/usb/hid/hid.vp b/VKernel/Kernel/drivers/usb/hid/hid.vp index a771b42..cd4806a 100644 --- a/VKernel/Kernel/drivers/usb/hid/hid.vp +++ b/VKernel/Kernel/drivers/usb/hid/hid.vp @@ -1,37 +1,37 @@ -import t, c -import drivers.usb.usb as usb - -HID_BOOT_PROTOCOL: t.CDefine = 0 -HID_REPORT_PROTOCOL: t.CDefine = 1 - -HID_KBD_REPORT_SIZE: t.CDefine = 8 -HID_MOUSE_REPORT_SIZE: t.CDefine = 4 - -class hid_kbd_report(t.CStruct): - modifier: t.CUInt8T - reserved: t.CUInt8T - keycode: t.CArray[t.CUInt8T, 6] - -class hid_mouse_report(t.CStruct): - buttons: t.CUInt8T - dx: t.CInt8T - dy: t.CInt8T - wheel: t.CInt8T - -def init_keyboard(dev: usb.usb_device | t.CPtr) -> t.CInt: - if dev.iface_class != 0x03: return -1 - if dev.iface_protocol != 0x01: return -2 - if dev.ep_in == 0: return -3 - return 0 - -def init_mouse(dev: usb.usb_device | t.CPtr) -> t.CInt: - if dev.iface_class != 0x03: return -1 - if dev.iface_protocol != 0x02: return -2 - if dev.ep_in == 0: return -3 - return 0 - -def read_keyboard(dev: usb.usb_device | t.CPtr, report: hid_kbd_report | t.CPtr) -> t.CInt: - return usb.read_interrupt(dev, c.Addr(report)) - -def read_mouse(dev: usb.usb_device | t.CPtr, report: hid_mouse_report | t.CPtr) -> t.CInt: - return usb.read_interrupt(dev, c.Addr(report)) +import t, c +import drivers.usb.usb as usb + +HID_BOOT_PROTOCOL: t.CDefine = 0 +HID_REPORT_PROTOCOL: t.CDefine = 1 + +HID_KBD_REPORT_SIZE: t.CDefine = 8 +HID_MOUSE_REPORT_SIZE: t.CDefine = 4 + +class hid_kbd_report(t.CStruct): + modifier: uint8 + reserved: uint8 + keycode: t.CArray[uint8, 6] + +class hid_mouse_report(t.CStruct): + buttons: uint8 + dx: int8 + dy: int8 + wheel: int8 + +def init_keyboard(dev: usb.usb_device | t.CPtr) -> int: + if dev.iface_class != 0x03: return -1 + if dev.iface_protocol != 0x01: return -2 + if dev.ep_in == 0: return -3 + return 0 + +def init_mouse(dev: usb.usb_device | t.CPtr) -> int: + if dev.iface_class != 0x03: return -1 + if dev.iface_protocol != 0x02: return -2 + if dev.ep_in == 0: return -3 + return 0 + +def read_keyboard(dev: usb.usb_device | t.CPtr, report: hid_kbd_report | t.CPtr) -> int: + return usb.read_interrupt(dev, c.Addr(report)) + +def read_mouse(dev: usb.usb_device | t.CPtr, report: hid_mouse_report | t.CPtr) -> int: + return usb.read_interrupt(dev, c.Addr(report)) diff --git a/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp b/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp index 10daad7..c971782 100644 --- a/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp +++ b/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp @@ -1,111 +1,116 @@ -import t, c -import drivers.usb.usb as usb -import drivers.usb.hid.hid as hid -import drivers.usb.uhci as uhci -import drivers.serial.uart.serial as serial - -KBD_BUF_SIZE: t.CDefine = 1024 -KBD_EVT_PRESS: t.CDefine = 0 -KBD_EVT_RELEASE: t.CDefine = 1 - -class usb_kbd_event(t.CStruct): - modifier: t.CUInt8T - keycode: t.CUInt8T - event_type: t.CUInt8T - -kbd_buf: t.CArray[usb_kbd_event, KBD_BUF_SIZE] -kbd_buf_head: t.CInt = 0 -kbd_buf_tail: t.CInt = 0 -kbd_buf_count: t.CInt = 0 -kbd_dev: usb.usb_device | t.CPtr = None -kbd_report: hid.hid_kbd_report -kbd_prev_keycodes: t.CArray[t.CUInt8T, 6] -kbd_initialized: t.CInt = 0 -kbd_slot_id: t.CInt = -1 - -def init() -> t.CInt: - global kbd_dev, kbd_initialized, kbd_slot_id - dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x01) - if dev is None: - serial.puts("[usb_kbd] no USB keyboard found\n") - return -1 - kbd_dev = dev - if hid.init_keyboard(dev) != 0: - serial.puts("[usb_kbd] init failed\n") - return -2 - kbd_initialized = 1 - serial.puts("[usb_kbd] initialized\n") - kbd_slot_id = uhci.register_int_callback(c.Addr(_on_int_complete)) - if kbd_slot_id < 0: - serial.puts("[usb_kbd] register callback failed\n") - kbd_initialized = 0 - return -3 - uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, t.CUInt8T(dev.ep_in_max), c.Addr(dev.ep_in_toggle), c.Addr(kbd_report)) - return 0 - -def _on_int_complete() -> t.CInt: - global kbd_buf_head, kbd_buf_tail, kbd_buf_count, kbd_prev_keycodes - if kbd_initialized == 0: return 0 - i: t.CInt - j: t.CInt - for i in range(6): - code: t.CUInt8T = kbd_report.keycode[i] - if code == 0: continue - found: t.CInt = 0 - for j in range(6): - if code == kbd_prev_keycodes[j]: - found = 1 - break - if found == 0: - if kbd_buf_count < KBD_BUF_SIZE: - kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier - kbd_buf[kbd_buf_tail].keycode = code - kbd_buf[kbd_buf_tail].event_type = KBD_EVT_PRESS - kbd_buf_tail = kbd_buf_tail + 1 - if kbd_buf_tail >= KBD_BUF_SIZE: - kbd_buf_tail = 0 - kbd_buf_count += 1 - for i in range(6): - prev: t.CUInt8T = kbd_prev_keycodes[i] - if prev == 0: continue - found2: t.CInt = 0 - for j in range(6): - if prev == kbd_report.keycode[j]: - found2 = 1 - break - if found2 == 0: - if kbd_buf_count < KBD_BUF_SIZE: - kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier - kbd_buf[kbd_buf_tail].keycode = prev - kbd_buf[kbd_buf_tail].event_type = KBD_EVT_RELEASE - kbd_buf_tail = kbd_buf_tail + 1 - if kbd_buf_tail >= KBD_BUF_SIZE: - kbd_buf_tail = 0 - kbd_buf_count += 1 - for i in range(6): - kbd_prev_keycodes[i] = kbd_report.keycode[i] - dev: usb.usb_device | t.CPtr = kbd_dev - if dev is not None and kbd_slot_id >= 0: - uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, t.CUInt8T(dev.ep_in_max), c.Addr(dev.ep_in_toggle), c.Addr(kbd_report)) - return 0 - -def has_data() -> t.CInt: - if kbd_buf_count > 0: return 1 - return 0 - -def poll() -> t.CInt: - if kbd_initialized == 0: return 0 - if kbd_buf_count > 0: return 1 - return 0 - -def read_event(out: usb_kbd_event | t.CPtr) -> t.CInt: - global kbd_buf_head, kbd_buf_count - if kbd_buf_count == 0: return -1 - out.modifier = kbd_buf[kbd_buf_head].modifier - out.keycode = kbd_buf[kbd_buf_head].keycode - out.event_type = kbd_buf[kbd_buf_head].event_type - kbd_buf_head = kbd_buf_head + 1 - if kbd_buf_head >= KBD_BUF_SIZE: - kbd_buf_head = 0 - kbd_buf_count -= 1 - return 0 +import t, c +import drivers.usb.usb as usb +import drivers.usb.hid.hid as hid +import drivers.usb.uhci as uhci +import drivers.serial.uart.serial as serial + +KBD_BUF_SIZE: t.CDefine = 1024 +KBD_EVT_PRESS: t.CDefine = 0 +KBD_EVT_RELEASE: t.CDefine = 1 + +class usb_kbd_event(t.CStruct): + modifier: uint8 + keycode: uint8 + event_type: uint8 + +kbd_buf: t.CArray[usb_kbd_event, KBD_BUF_SIZE] +kbd_buf_head: int = 0 +kbd_buf_tail: int = 0 +kbd_buf_count: int = 0 +kbd_dev: usb.usb_device | t.CPtr = None +kbd_report: hid.hid_kbd_report +kbd_prev_keycodes: t.CArray[uint8, 6] +kbd_initialized: int = 0 +kbd_slot_id: int = -1 + +def init() -> int: + global kbd_dev, kbd_initialized, kbd_slot_id + dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x01) + if dev is None: + serial.puts("[usb_kbd] no USB keyboard found\n") + return -1 + kbd_dev = dev + if hid.init_keyboard(dev) != 0: + serial.puts("[usb_kbd] init failed\n") + return -2 + kbd_initialized = 1 + serial.puts("[usb_kbd] initialized\n") + kbd_slot_id = uhci.register_int_callback(c.Addr(_on_int_complete)) + if kbd_slot_id < 0: + serial.puts("[usb_kbd] register callback failed\n") + kbd_initialized = 0 + return -3 + # 中断传输长度不得超过 kbd_report(8 字节),否则 DMA 越界写全局 + kbd_pkt_len: uint8 = 8 + if dev.ep_in_max < 8: kbd_pkt_len = uint8(dev.ep_in_max) + uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len, c.Addr(dev.ep_in_toggle), c.Addr(kbd_report)) + return 0 + +def _on_int_complete() -> int: + global kbd_buf_head, kbd_buf_tail, kbd_buf_count, kbd_prev_keycodes + if kbd_initialized == 0: return 0 + i: int + j: int + for i in range(6): + code: uint8 = kbd_report.keycode[i] + if code == 0: continue + found: int = 0 + for j in range(6): + if code == kbd_prev_keycodes[j]: + found = 1 + break + if found == 0: + if kbd_buf_count < KBD_BUF_SIZE: + kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier + kbd_buf[kbd_buf_tail].keycode = code + kbd_buf[kbd_buf_tail].event_type = KBD_EVT_PRESS + kbd_buf_tail = kbd_buf_tail + 1 + if kbd_buf_tail >= KBD_BUF_SIZE: + kbd_buf_tail = 0 + kbd_buf_count += 1 + for i in range(6): + prev: uint8 = kbd_prev_keycodes[i] + if prev == 0: continue + found2: int = 0 + for j in range(6): + if prev == kbd_report.keycode[j]: + found2 = 1 + break + if found2 == 0: + if kbd_buf_count < KBD_BUF_SIZE: + kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier + kbd_buf[kbd_buf_tail].keycode = prev + kbd_buf[kbd_buf_tail].event_type = KBD_EVT_RELEASE + kbd_buf_tail = kbd_buf_tail + 1 + if kbd_buf_tail >= KBD_BUF_SIZE: + kbd_buf_tail = 0 + kbd_buf_count += 1 + for i in range(6): + kbd_prev_keycodes[i] = kbd_report.keycode[i] + dev: usb.usb_device | t.CPtr = kbd_dev + if dev is not None and kbd_slot_id >= 0: + kbd_pkt_len2: uint8 = 8 + if dev.ep_in_max < 8: kbd_pkt_len2 = uint8(dev.ep_in_max) + uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len2, c.Addr(dev.ep_in_toggle), c.Addr(kbd_report)) + return 0 + +def has_data() -> int: + if kbd_buf_count > 0: return 1 + return 0 + +def poll() -> int: + if kbd_initialized == 0: return 0 + if kbd_buf_count > 0: return 1 + return 0 + +def read_event(out: usb_kbd_event | t.CPtr) -> int: + global kbd_buf_head, kbd_buf_count + if kbd_buf_count == 0: return -1 + out.modifier = kbd_buf[kbd_buf_head].modifier + out.keycode = kbd_buf[kbd_buf_head].keycode + out.event_type = kbd_buf[kbd_buf_head].event_type + kbd_buf_head = kbd_buf_head + 1 + if kbd_buf_head >= KBD_BUF_SIZE: + kbd_buf_head = 0 + kbd_buf_count -= 1 + return 0 diff --git a/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp b/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp index 500dfda..f6bcab7 100644 --- a/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp +++ b/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp @@ -1,77 +1,82 @@ -import t, c -import drivers.usb.usb as usb -import drivers.usb.hid.hid as hid -import drivers.usb.uhci as uhci -import drivers.serial.uart.serial as serial - -MOUSE_BUF_SIZE: t.CDefine = 1024 - -class usb_mouse_packet(t.CStruct): - buttons: t.CUInt8T - dx: t.CInt16T - dy: t.CInt16T - wheel: t.CInt8T - -mse_buf: t.CArray[usb_mouse_packet, MOUSE_BUF_SIZE] -mse_buf_head: t.CInt = 0 -mse_buf_tail: t.CInt = 0 -mse_buf_count: t.CInt = 0 -mse_dev: usb.usb_device | t.CPtr = None -mse_report: hid.hid_mouse_report -mse_initialized: t.CInt = 0 -mse_slot_id: t.CInt = -1 - -def init() -> t.CInt: - global mse_dev, mse_initialized, mse_slot_id - dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x02) - if dev is None: - serial.puts("[usb_mse] no USB mouse found\n") - return -1 - mse_dev = dev - if hid.init_mouse(dev) != 0: - serial.puts("[usb_mse] init failed\n") - return -2 - mse_initialized = 1 - serial.puts("[usb_mse] initialized\n") - mse_slot_id = uhci.register_int_callback(c.Addr(_on_int_complete)) - if mse_slot_id < 0: - serial.puts("[usb_mse] register callback failed\n") - mse_initialized = 0 - return -3 - uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, t.CUInt8T(dev.ep_in_max), c.Addr(dev.ep_in_toggle), c.Addr(mse_report)) - return 0 - -def _on_int_complete() -> t.CInt: - global mse_buf_head, mse_buf_tail, mse_buf_count - if mse_initialized == 0: return 0 - if mse_report.dx != 0 or mse_report.dy != 0 or mse_report.buttons != 0: - if mse_buf_count < MOUSE_BUF_SIZE: - mse_buf[mse_buf_tail].buttons = mse_report.buttons - mse_buf[mse_buf_tail].dx = t.CInt16T(mse_report.dx) - mse_buf[mse_buf_tail].dy = t.CInt16T(mse_report.dy) - mse_buf[mse_buf_tail].wheel = mse_report.wheel - mse_buf_tail = mse_buf_tail + 1 - if mse_buf_tail >= MOUSE_BUF_SIZE: - mse_buf_tail = 0 - mse_buf_count += 1 - dev: usb.usb_device | t.CPtr = mse_dev - if dev is not None and mse_slot_id >= 0: - uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, t.CUInt8T(dev.ep_in_max), c.Addr(dev.ep_in_toggle), c.Addr(mse_report)) - return 0 - -def has_data() -> t.CInt: - if mse_buf_count > 0: return 1 - return 0 - -def read_packet(out: usb_mouse_packet | t.CPtr) -> t.CInt: - global mse_buf_head, mse_buf_count - if mse_buf_count == 0: return -1 - out.buttons = mse_buf[mse_buf_head].buttons - out.dx = mse_buf[mse_buf_head].dx - out.dy = mse_buf[mse_buf_head].dy - out.wheel = mse_buf[mse_buf_head].wheel - mse_buf_head = mse_buf_head + 1 - if mse_buf_head >= MOUSE_BUF_SIZE: - mse_buf_head = 0 - mse_buf_count -= 1 - return 0 +import t, c +import drivers.usb.usb as usb +import drivers.usb.hid.hid as hid +import drivers.usb.uhci as uhci +import drivers.serial.uart.serial as serial + +MOUSE_BUF_SIZE: t.CDefine = 1024 + +class usb_mouse_packet(t.CStruct): + buttons: uint8 + dx: int16 + dy: int16 + wheel: int8 + +mse_buf: t.CArray[usb_mouse_packet, MOUSE_BUF_SIZE] +mse_buf_head: int = 0 +mse_buf_tail: int = 0 +mse_buf_count: int = 0 +mse_dev: usb.usb_device | t.CPtr = None +mse_report: hid.hid_mouse_report +mse_initialized: int = 0 +mse_slot_id: int = -1 + +def init() -> int: + global mse_dev, mse_initialized, mse_slot_id + dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x02) + if dev is None: + serial.puts("[usb_mse] no USB mouse found\n") + return -1 + mse_dev = dev + if hid.init_mouse(dev) != 0: + serial.puts("[usb_mse] init failed\n") + return -2 + mse_initialized = 1 + serial.puts("[usb_mse] initialized\n") + mse_slot_id = uhci.register_int_callback(c.Addr(_on_int_complete)) + if mse_slot_id < 0: + serial.puts("[usb_mse] register callback failed\n") + mse_initialized = 0 + return -3 + # 中断传输长度不得超过 mse_report(4 字节),否则 DMA 越界写全局 + mse_pkt_len: uint8 = 4 + if dev.ep_in_max < 4: mse_pkt_len = uint8(dev.ep_in_max) + uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len, c.Addr(dev.ep_in_toggle), c.Addr(mse_report)) + return 0 + +def _on_int_complete() -> int: + global mse_buf_head, mse_buf_tail, mse_buf_count + if mse_initialized == 0: return 0 + if mse_report.dx != 0 or mse_report.dy != 0 or mse_report.buttons != 0: + if mse_buf_count < MOUSE_BUF_SIZE: + mse_buf[mse_buf_tail].buttons = mse_report.buttons + mse_buf[mse_buf_tail].dx = int16(mse_report.dx) + mse_buf[mse_buf_tail].dy = int16(mse_report.dy) + mse_buf[mse_buf_tail].wheel = mse_report.wheel + mse_buf_tail = mse_buf_tail + 1 + if mse_buf_tail >= MOUSE_BUF_SIZE: + mse_buf_tail = 0 + mse_buf_count += 1 + dev: usb.usb_device | t.CPtr = mse_dev + if dev is not None and mse_slot_id >= 0: + mse_pkt_len2: uint8 = 4 + if dev.ep_in_max < 4: mse_pkt_len2 = uint8(dev.ep_in_max) + uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len2, c.Addr(dev.ep_in_toggle), c.Addr(mse_report)) + return 0 + +def has_data() -> int: + if mse_buf_count > 0: return 1 + return 0 + +def read_packet(out: usb_mouse_packet | t.CPtr) -> int: + global mse_buf_head, mse_buf_count + if mse_buf_count == 0: return -1 + out.buttons = mse_buf[mse_buf_head].buttons + out.dx = mse_buf[mse_buf_head].dx + out.dy = mse_buf[mse_buf_head].dy + out.wheel = mse_buf[mse_buf_head].wheel + mse_buf_head = mse_buf_head + 1 + if mse_buf_head >= MOUSE_BUF_SIZE: + mse_buf_head = 0 + mse_buf_count -= 1 + return 0 diff --git a/VKernel/Kernel/drivers/usb/pci.vp b/VKernel/Kernel/drivers/usb/pci.vp index 97fd0fc..72c954a 100644 --- a/VKernel/Kernel/drivers/usb/pci.vp +++ b/VKernel/Kernel/drivers/usb/pci.vp @@ -1,93 +1,93 @@ -import t, c -import asm - -PCI_CONFIG_ADDR: t.CDefine = 0xCF8 -PCI_CONFIG_DATA: t.CDefine = 0xCFC - -PCI_CLASS_SERIAL_USB: t.CDefine = 0x0C03 -PCI_CLASS_SERIAL_UHCI: t.CDefine = 0x0C0300 -PCI_CLASS_SERIAL_OHCI: t.CDefine = 0x0C0310 -PCI_CLASS_SERIAL_EHCI: t.CDefine = 0x0C0320 -PCI_CLASS_SERIAL_XHCI: t.CDefine = 0x0C0330 - -PCI_CMD_IO_SPACE: t.CDefine = 0x0001 -PCI_CMD_BUS_MASTER: t.CDefine = 0x0004 - -class pci_device(t.CStruct): - bus: t.CUInt8T - dev: t.CUInt8T - func: t.CUInt8T - vendor_id: t.CUInt16T - device_id: t.CUInt16T - class_code: t.CUInt32T - irq: t.CUInt8T - bar: t.CArray[t.CUInt32T, 6] - -def pci_read32(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T, offset: t.CUInt8T) -> t.CUInt32T: - addr: t.CUInt32T = 0x80000000 | (t.CUInt32T(bus) << 16) | (t.CUInt32T(dev) << 11) | (t.CUInt32T(func) << 8) | (t.CUInt32T(offset) & 0xFC) - asm.outl(PCI_CONFIG_ADDR, addr) - return asm.inl(PCI_CONFIG_DATA) - -def pci_write32(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T, offset: t.CUInt8T, value: t.CUInt32T): - addr: t.CUInt32T = 0x80000000 | (t.CUInt32T(bus) << 16) | (t.CUInt32T(dev) << 11) | (t.CUInt32T(func) << 8) | (t.CUInt32T(offset) & 0xFC) - asm.outl(PCI_CONFIG_ADDR, addr) - asm.outl(PCI_CONFIG_DATA, value) - -def pci_read16(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T, offset: t.CUInt8T) -> t.CUInt16T: - val: t.CUInt32T = pci_read32(bus, dev, func, offset) - shift: t.CUInt32T = (t.CUInt32T(offset) & 0x02) * 8 - return t.CUInt16T((val >> shift) & 0xFFFF) - -def pci_read8(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T, offset: t.CUInt8T) -> t.CUInt8T: - val: t.CUInt32T = pci_read32(bus, dev, func, offset) - shift: t.CUInt32T = (t.CUInt32T(offset) & 0x03) * 8 - return t.CUInt8T((val >> shift) & 0xFF) - -def pci_get_class(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T) -> t.CUInt32T: - cls: t.CUInt8T = pci_read8(bus, dev, func, 0x0B) - sub: t.CUInt8T = pci_read8(bus, dev, func, 0x0A) - proto: t.CUInt8T = pci_read8(bus, dev, func, 0x09) - return (t.CUInt32T(cls) << 16) | (t.CUInt32T(sub) << 8) | t.CUInt32T(proto) - -def pci_get_bar(bus: t.CUInt8T, dev: t.CUInt8T, func: t.CUInt8T, bar_idx: t.CUInt8T) -> t.CUInt32T: - return pci_read32(bus, dev, func, 0x10 + bar_idx * 4) - -def pci_enable_device(dev: pci_device | t.CPtr): - cmd: t.CUInt16T = pci_read16(dev.bus, dev.dev, dev.func, 0x04) - cmd = cmd | PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER - pci_write32(dev.bus, dev.dev, dev.func, 0x04, t.CUInt32T(cmd)) - -def pci_fill_device(bus: t.CUInt8T, dev_n: t.CUInt8T, func: t.CUInt8T, out: pci_device | t.CPtr): - out.bus = bus - out.dev = dev_n - out.func = func - out.vendor_id = pci_read16(bus, dev_n, func, 0x00) - out.device_id = pci_read16(bus, dev_n, func, 0x02) - out.class_code = pci_get_class(bus, dev_n, func) - out.irq = pci_read8(bus, dev_n, func, 0x3C) - i: t.CInt - for i in range(6): - out.bar[i] = pci_get_bar(bus, dev_n, func, t.CUInt8T(i)) - -_uhci_dev: pci_device -_uhci_found: t.CInt = 0 - -def find_uhci() -> t.CUInt16T: - global _uhci_dev, _uhci_found - bus: t.CUInt8T - dev_n: t.CUInt8T - func: t.CUInt8T - for bus in range(1): - for dev_n in range(32): - for func in range(8): - vendor: t.CUInt16T = pci_read16(bus, dev_n, func, 0x00) - if vendor == 0xFFFF: continue - cls: t.CUInt32T = pci_get_class(bus, dev_n, func) - if cls == PCI_CLASS_SERIAL_UHCI: - pci_fill_device(bus, dev_n, func, c.Addr(_uhci_dev)) - pci_enable_device(c.Addr(_uhci_dev)) - _uhci_found = 1 - bar: t.CUInt32T = _uhci_dev.bar[4] - io_base: t.CUInt16T = t.CUInt16T(bar & 0xFFFE) - return io_base - return 0 +import t, c +import asm + +PCI_CONFIG_ADDR: t.CDefine = 0xCF8 +PCI_CONFIG_DATA: t.CDefine = 0xCFC + +PCI_CLASS_SERIAL_USB: t.CDefine = 0x0C03 +PCI_CLASS_SERIAL_UHCI: t.CDefine = 0x0C0300 +PCI_CLASS_SERIAL_OHCI: t.CDefine = 0x0C0310 +PCI_CLASS_SERIAL_EHCI: t.CDefine = 0x0C0320 +PCI_CLASS_SERIAL_XHCI: t.CDefine = 0x0C0330 + +PCI_CMD_IO_SPACE: t.CDefine = 0x0001 +PCI_CMD_BUS_MASTER: t.CDefine = 0x0004 + +class pci_device(t.CStruct): + bus: uint8 + dev: uint8 + func: uint8 + vendor_id: uint16 + device_id: uint16 + class_code: uint32 + irq: uint8 + bar: t.CArray[uint32, 6] + +def pci_read32(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint32: + addr: uint32 = 0x80000000 | (uint32(bus) << 16) | (uint32(dev) << 11) | (uint32(func) << 8) | (uint32(offset) & 0xFC) + asm.outl(PCI_CONFIG_ADDR, addr) + return asm.inl(PCI_CONFIG_DATA) + +def pci_write32(bus: uint8, dev: uint8, func: uint8, offset: uint8, value: uint32): + addr: uint32 = 0x80000000 | (uint32(bus) << 16) | (uint32(dev) << 11) | (uint32(func) << 8) | (uint32(offset) & 0xFC) + asm.outl(PCI_CONFIG_ADDR, addr) + asm.outl(PCI_CONFIG_DATA, value) + +def pci_read16(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint16: + val: uint32 = pci_read32(bus, dev, func, offset) + shift: uint32 = (uint32(offset) & 0x02) * 8 + return uint16((val >> shift) & 0xFFFF) + +def pci_read8(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint8: + val: uint32 = pci_read32(bus, dev, func, offset) + shift: uint32 = (uint32(offset) & 0x03) * 8 + return uint8((val >> shift) & 0xFF) + +def pci_get_class(bus: uint8, dev: uint8, func: uint8) -> uint32: + cls: uint8 = pci_read8(bus, dev, func, 0x0B) + sub: uint8 = pci_read8(bus, dev, func, 0x0A) + proto: uint8 = pci_read8(bus, dev, func, 0x09) + return (uint32(cls) << 16) | (uint32(sub) << 8) | uint32(proto) + +def pci_get_bar(bus: uint8, dev: uint8, func: uint8, bar_idx: uint8) -> uint32: + return pci_read32(bus, dev, func, 0x10 + bar_idx * 4) + +def pci_enable_device(dev: pci_device | t.CPtr): + cmd: uint16 = pci_read16(dev.bus, dev.dev, dev.func, 0x04) + cmd = cmd | PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER + pci_write32(dev.bus, dev.dev, dev.func, 0x04, uint32(cmd)) + +def pci_fill_device(bus: uint8, dev_n: uint8, func: uint8, out: pci_device | t.CPtr): + out.bus = bus + out.dev = dev_n + out.func = func + out.vendor_id = pci_read16(bus, dev_n, func, 0x00) + out.device_id = pci_read16(bus, dev_n, func, 0x02) + out.class_code = pci_get_class(bus, dev_n, func) + out.irq = pci_read8(bus, dev_n, func, 0x3C) + i: int + for i in range(6): + out.bar[i] = pci_get_bar(bus, dev_n, func, uint8(i)) + +_uhci_dev: pci_device +_uhci_found: int = 0 + +def find_uhci() -> uint16: + global _uhci_dev, _uhci_found + bus: uint8 + dev_n: uint8 + func: uint8 + for bus in range(1): + for dev_n in range(32): + for func in range(8): + vendor: uint16 = pci_read16(bus, dev_n, func, 0x00) + if vendor == 0xFFFF: continue + cls: uint32 = pci_get_class(bus, dev_n, func) + if cls == PCI_CLASS_SERIAL_UHCI: + pci_fill_device(bus, dev_n, func, c.Addr(_uhci_dev)) + pci_enable_device(c.Addr(_uhci_dev)) + _uhci_found = 1 + bar: uint32 = _uhci_dev.bar[4] + io_base: uint16 = uint16(bar & 0xFFFE) + return io_base + return 0 diff --git a/VKernel/Kernel/drivers/usb/uhci.vp b/VKernel/Kernel/drivers/usb/uhci.vp index d518c3d..50c88aa 100644 --- a/VKernel/Kernel/drivers/usb/uhci.vp +++ b/VKernel/Kernel/drivers/usb/uhci.vp @@ -1,419 +1,419 @@ -import t, c -import asm -import mm.mm as mm -import viperstring as string -import drivers.serial.uart.serial as serial -import platform.pch.timer as timer -import intr.idt as idt -import platform.pch.pic as pic -import drivers.usb.pci as pci -import viperlib - -UHCI_USBCMD: t.CDefine = 0x00 -UHCI_USBSTS: t.CDefine = 0x02 -UHCI_USBINTR: t.CDefine = 0x04 -UHCI_FRNUM: t.CDefine = 0x06 -UHCI_FLBASEADD: t.CDefine = 0x08 -UHCI_SOFMOD: t.CDefine = 0x0C -UHCI_PORTSC1: t.CDefine = 0x10 -UHCI_PORTSC2: t.CDefine = 0x12 - -UHCI_CMD_RUN: t.CDefine = 0x0001 -UHCI_CMD_HCRESET: t.CDefine = 0x0002 -UHCI_CMD_GRESET: t.CDefine = 0x0004 -UHCI_CMD_MAXPKT: t.CDefine = 0x0080 -UHCI_CMD_CF: t.CDefine = 0x0040 - -UHCI_STS_HCHALTED: t.CDefine = 0x0020 -UHCI_STS_USBINT: t.CDefine = 0x0001 -UHCI_STS_USBERRINT: t.CDefine = 0x0002 -UHCI_STS_RESUME: t.CDefine = 0x0004 -UHCI_INTR_TIMEOUT: t.CDefine = 0x0001 -UHCI_INTR_RESUME: t.CDefine = 0x0002 -UHCI_INTR_IOC: t.CDefine = 0x0004 -UHCI_INTR_SHORT: t.CDefine = 0x0008 - -UHCI_PORT_CONNECT: t.CDefine = 0x0001 -UHCI_PORT_CONNECT_CHANGE: t.CDefine = 0x0002 -UHCI_PORT_ENABLE: t.CDefine = 0x0004 -UHCI_PORT_ENABLE_CHANGE: t.CDefine = 0x0008 -UHCI_PORT_RESET: t.CDefine = 0x0200 -UHCI_PORT_LOW_SPEED: t.CDefine = 0x0100 - -TD_CTRL_ACTIVE: t.CDefine = 0x00800000 -TD_CTRL_IOC: t.CDefine = 0x01000000 -TD_CTRL_LS: t.CDefine = 0x04000000 -TD_CTRL_SPD: t.CDefine = 0x20000000 -TD_CTRL_CERR_SHIFT: t.CDefine = 27 -TD_CTRL_CERR_MASK: t.CDefine = 0x18000000 - -TD_TOKEN_SETUP: t.CDefine = 0x2D -TD_TOKEN_IN: t.CDefine = 0x69 -TD_TOKEN_OUT: t.CDefine = 0xE1 - -TD_TOKEN_DATA0: t.CDefine = 0 -TD_TOKEN_DATA1: t.CDefine = 1 - -TD_LINK_TERMINATE: t.CDefine = 0x00000001 -TD_LINK_QH: t.CDefine = 0x00000002 -TD_LINK_DEPTH_FIRST: t.CDefine = 0x00000004 - -UHCI_NUM_FRAMES: t.CDefine = 1024 -UHCI_INT_SLOTS: t.CDefine = 4 - -class uhci_td(t.CStruct): - link: t.CUInt32T - ctrl_status: t.CUInt32T - token: t.CUInt32T - buffer: t.CUInt32T - -class uhci_qh(t.CStruct): - link: t.CUInt32T - element: t.CUInt32T - -class int_slot(t.CStruct): - td: uhci_td | t.CPtr - callback: t.CInt | t.CPtr - active: t.CInt - qh: uhci_qh | t.CPtr - -_io_base: t.CUInt16T = 0 -_frame_list: t.CUInt32T | t.CPtr = None -_ctrl_qh: uhci_qh | t.CPtr = None -_bulk_qh: uhci_qh | t.CPtr = None -_irq: t.CInt = -1 -_int_slots: t.CArray[int_slot, UHCI_INT_SLOTS] -_int_slot_count: t.CInt = 0 - -def _reg_read16(offset: t.CUInt16T) -> t.CUInt16T: - return asm.inw(_io_base + offset) - -def _reg_write16(offset: t.CUInt16T, value: t.CUInt16T): - asm.outw(_io_base + offset, value) - -def _reg_read32(offset: t.CUInt16T) -> t.CUInt32T: - return asm.inl(_io_base + offset) - -def _reg_write32(offset: t.CUInt16T, value: t.CUInt32T): - asm.outl(_io_base + offset, value) - -def _uhci_irq_handler() -> t.CInt: - sts: t.CUInt16T = _reg_read16(UHCI_USBSTS) - _reg_write16(UHCI_USBSTS, sts) - if (sts & (UHCI_STS_USBINT | UHCI_STS_USBERRINT)) == 0: - return 0 - for si in range(_int_slot_count): - slot: int_slot | t.CPtr = c.Addr(_int_slots[si]) - if slot.active and slot.td is not None and slot.callback is not None: - status: t.CUInt32T = slot.td.ctrl_status - if (status & TD_CTRL_ACTIVE) == 0: - slot.active = 0 - c.Asm(f"""mov rbp, rsp - and rsp, -16 - call {c.AsmInp(slot.callback, t.ASM_DESCR.REG_ANY)} - mov rsp, rbp""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, - t.ASM_DESCR.CLOBBER_RBX, - t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, - t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11, - t.ASM_DESCR.CLOBBER_RBP]) - return 0 - -def register_int_callback(cb: t.CInt | t.CPtr) -> t.CInt: - global _int_slot_count - if _int_slot_count >= UHCI_INT_SLOTS: - return -1 - si: t.CInt = _int_slot_count - qh: uhci_qh | t.CPtr = mm.malloc_direct(uhci_qh.__sizeof__()) - if qh is None: - return -2 - string.memset(c.Addr(qh), 0, uhci_qh.__sizeof__()) - _qh_set_link(qh, 0, 0, 1) - _qh_set_element(qh, 0, 1) - td: uhci_td | t.CPtr = mm.malloc_direct(uhci_td.__sizeof__()) - if td is None: - return -3 - string.memset(c.Addr(td), 0, uhci_td.__sizeof__()) - slot: int_slot | t.CPtr = c.Addr(_int_slots[si]) - slot.td = td - slot.callback = cb - slot.active = 0 - slot.qh = qh - _int_slot_count = si + 1 - _rebuild_int_chain() - return si - -def schedule_int_transfer(slot_id: t.CInt, dev_addr: t.CUInt8T, endpoint: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, toggle_ptr: t.CUInt8T | t.CPtr, buf: t.CVoid | t.CPtr): - if slot_id < 0 or slot_id >= _int_slot_count: - return - slot: int_slot | t.CPtr = c.Addr(_int_slots[slot_id]) - td: uhci_td | t.CPtr = slot.td - qh: uhci_qh | t.CPtr = slot.qh - if td is None or qh is None: - return - string.memset(c.Addr(td), 0, uhci_td.__sizeof__()) - _td_set_link(td, 0, 0, 1) - _td_set_ctrl(td, ls, max_pkt) - _td_set_token(td, TD_TOKEN_IN, dev_addr, endpoint, toggle_ptr, max_pkt) - td.ctrl_status = td.ctrl_status | TD_CTRL_IOC - td.buffer = t.CUInt32T(t.CUInt64T(buf)) - _qh_set_element(qh, t.CUInt32T(t.CUInt64T(td)), 0) - slot.active = 1 - -def _rebuild_int_chain(): - if _int_slot_count == 0: - return - first_qh: uhci_qh | t.CPtr = None - prev_qh: uhci_qh | t.CPtr = None - for si in range(_int_slot_count): - cur_qh: uhci_qh | t.CPtr = _int_slots[si].qh - if cur_qh is not None: - if first_qh is None: - first_qh = cur_qh - if prev_qh is not None: - _qh_set_link(prev_qh, t.CUInt32T(t.CUInt64T(cur_qh)) | TD_LINK_QH, 1, 0) - prev_qh = cur_qh - if prev_qh is not None: - _qh_set_link(prev_qh, t.CUInt32T(t.CUInt64T(_ctrl_qh)) | TD_LINK_QH, 1, 0) - if first_qh is not None: - qh_addr: t.CUInt32T = t.CUInt32T(t.CUInt64T(first_qh)) | TD_LINK_QH - i: t.CInt - for i in range(UHCI_NUM_FRAMES): - entry_ptr: t.CUInt32T | t.CPtr = _frame_list + t.CUInt64T(i) * 4 - c.Set(c.Deref(entry_ptr), qh_addr) - -def _td_set_link(td: uhci_td | t.CPtr, addr: t.CUInt32T, is_qh: t.CInt, terminate: t.CInt): - val: t.CUInt32T = (addr & 0xFFFFFFF0) - if is_qh: val = val | TD_LINK_QH - if terminate: val = val | TD_LINK_TERMINATE - td.link = val - -def _td_set_token(td: uhci_td | t.CPtr, pid: t.CUInt8T, dev_addr: t.CUInt8T, endpoint: t.CUInt8T, toggle: t.CUInt8T, max_len: t.CUInt16T): - len_bits: t.CUInt32T - if max_len == 0: - len_bits = 0x7FF - else: - len_bits = t.CUInt32T(max_len) - 1 - td.token = (t.CUInt32T(pid) << 0) | (t.CUInt32T(dev_addr) << 8) | (t.CUInt32T(endpoint & 0x0F) << 15) | (t.CUInt32T(toggle & 1) << 19) | (len_bits << 21) - -def _td_set_ctrl(td: uhci_td | t.CPtr, ls: t.CInt, maxlen: t.CUInt16T): - td.ctrl_status = TD_CTRL_ACTIVE | (3 << TD_CTRL_CERR_SHIFT) - if ls: td.ctrl_status = td.ctrl_status | TD_CTRL_LS - -def _qh_set_link(qh: uhci_qh | t.CPtr, addr: t.CUInt32T, is_qh: t.CInt, terminate: t.CInt): - val: t.CUInt32T = (addr & 0xFFFFFFF0) - if is_qh: val = val | TD_LINK_QH - if terminate: val = val | TD_LINK_TERMINATE - qh.link = val - -def _qh_set_element(qh: uhci_qh | t.CPtr, addr: t.CUInt32T, terminate: t.CInt): - val: t.CUInt32T = (addr & 0xFFFFFFF0) - if terminate: val = val | TD_LINK_TERMINATE - qh.element = val - -def _wait_for_complete(td: uhci_td | t.CPtr, timeout_ms: t.CInt) -> t.CInt: - start: t.CUInt64T = timer.timer_get_ticks() - deadline: t.CUInt64T = start + t.CUInt64T(timeout_ms) - poll_cnt: t.CInt = 0 - while timer.timer_get_ticks() < deadline: - status: t.CUInt32T = td.ctrl_status - if (status & TD_CTRL_ACTIVE) == 0: - if (status & 0x00600000) != 0: - return -1 - return 0 - poll_cnt += 1 - if poll_cnt >= 100: - poll_cnt = 0 - asm.sti() - asm.hlt() - return -2 - -def reset(io_base: t.CUInt16T) -> t.CInt: - global _io_base - _io_base = io_base - _reg_write16(UHCI_USBCMD, UHCI_CMD_HCRESET) - i: t.CInt - for i in range(1000): - if (_reg_read16(UHCI_USBCMD) & UHCI_CMD_HCRESET) == 0: - break - _reg_write16(UHCI_USBSTS, 0xFFFF) - _reg_write16(UHCI_USBINTR, 0x0000) - return 0 - -def init(io_base: t.CUInt16T) -> t.CInt: - global _irq, _io_base, _frame_list, _ctrl_qh, _bulk_qh, _int_slot_count - _io_base = io_base - _int_slot_count = 0 - - serial.puts("[uhci] resetting...\n") - if reset(io_base) != 0: - serial.puts("[uhci] reset failed\n") - return -1 - - serial.puts("[uhci] allocating frame list...\n") - _frame_list = mm.malloc(UHCI_NUM_FRAMES * 4) - _dbg_fl: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbg_fl), 96, "[dbg] frame_list ret=0x%lx\n", t.CUInt64T(_frame_list)) - serial.puts(c.Addr(_dbg_fl)) - if _frame_list is None: - serial.puts("[uhci] frame list alloc failed\n") - return -2 - string.memset(_frame_list, 0, UHCI_NUM_FRAMES * 4) - - _ctrl_qh = mm.malloc_direct(uhci_qh.__sizeof__()) - if _ctrl_qh is None: - serial.puts("[uhci] ctrl_qh alloc failed\n") - return -3 - string.memset(c.Addr(_ctrl_qh), 0, uhci_qh.__sizeof__()) - _qh_set_link(_ctrl_qh, 0, 0, 1) - _qh_set_element(_ctrl_qh, 0, 1) - - _bulk_qh = mm.malloc_direct(uhci_qh.__sizeof__()) - if _bulk_qh is None: - serial.puts("[uhci] bulk_qh alloc failed\n") - return -4 - string.memset(c.Addr(_bulk_qh), 0, uhci_qh.__sizeof__()) - _qh_set_link(_bulk_qh, 0, 0, 1) - _qh_set_element(_bulk_qh, 0, 1) - - serial.puts("[uhci] setting up frame list...\n") - qh_addr: t.CUInt32T = t.CUInt32T(c.Addr(_ctrl_qh)) | TD_LINK_QH - i: t.CInt - for i in range(UHCI_NUM_FRAMES): - entry_ptr: t.CUInt32T | t.CPtr = _frame_list + t.CUInt64T(i) * 4 - c.Set(c.Deref(entry_ptr), qh_addr) - - _reg_write32(UHCI_FLBASEADD, t.CUInt32T(t.CUInt64T(_frame_list))) - _reg_write16(UHCI_FRNUM, 0) - _reg_write16(UHCI_SOFMOD, 64) - - _reg_write16(UHCI_USBCMD, UHCI_CMD_CF | UHCI_CMD_MAXPKT | UHCI_CMD_RUN) - - timer.timer_msleep(10) - - _reg_write16(UHCI_USBSTS, 0xFFFF) - _reg_write16(UHCI_USBINTR, UHCI_INTR_IOC | UHCI_INTR_SHORT) - - _irq = t.CInt(pci._uhci_dev.irq) - if _irq > 0 and _irq < 16: - idt.irqInstallHandler(_irq, _uhci_irq_handler, "uhci") - pic.clearMask(t.CUInt8T(_irq)) - - serial.puts("[uhci] started\n") - return 0 - -def port_reset(port: t.CInt) -> t.CInt: - sc: t.CUInt16T - if port == 0: - sc = _reg_read16(UHCI_PORTSC1) - else: - sc = _reg_read16(UHCI_PORTSC2) - - if (sc & UHCI_PORT_CONNECT) == 0: - return -1 - - if port == 0: - _reg_write16(UHCI_PORTSC1, sc | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) - else: - _reg_write16(UHCI_PORTSC2, sc | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) - - if port == 0: - _reg_write16(UHCI_PORTSC1, UHCI_PORT_RESET) - else: - _reg_write16(UHCI_PORTSC2, UHCI_PORT_RESET) - - timer.timer_msleep(50) - - if port == 0: - _reg_write16(UHCI_PORTSC1, 0x0000) - else: - _reg_write16(UHCI_PORTSC2, 0x0000) - - timer.timer_msleep(10) - - if port == 0: - sc = _reg_read16(UHCI_PORTSC1) - _reg_write16(UHCI_PORTSC1, sc | UHCI_PORT_ENABLE | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) - else: - sc = _reg_read16(UHCI_PORTSC2) - _reg_write16(UHCI_PORTSC2, sc | UHCI_PORT_ENABLE | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) - - timer.timer_msleep(10) - - if port == 0: - sc = _reg_read16(UHCI_PORTSC1) - else: - sc = _reg_read16(UHCI_PORTSC2) - - if (sc & UHCI_PORT_ENABLE) == 0: - return -2 - - return 0 - -def port_is_connected(port: t.CInt) -> t.CInt: - sc: t.CUInt16T - if port == 0: - sc = _reg_read16(UHCI_PORTSC1) - else: - sc = _reg_read16(UHCI_PORTSC2) - if sc & UHCI_PORT_CONNECT: return 1 - return 0 - -def port_is_low_speed(port: t.CInt) -> t.CInt: - sc: t.CUInt16T - if port == 0: - sc = _reg_read16(UHCI_PORTSC1) - else: - sc = _reg_read16(UHCI_PORTSC2) - if sc & UHCI_PORT_LOW_SPEED: return 1 - return 0 - -def control_transfer(dev_addr: t.CUInt8T, endpoint: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, setup_buf: t.CVoid | t.CPtr, data_buf: t.CVoid | t.CPtr, data_len: t.CUInt16T, data_in: t.CInt) -> t.CInt: - td_count: t.CInt = 2 - if data_len > 0: - td_count = td_count + 1 - total: t.CUInt64T = t.CUInt64T(td_count) * uhci_td.__sizeof__() - tds: uhci_td | t.CPtr = mm.malloc_direct(total) - if tds is None: return -1 - string.memset(c.Addr(tds), 0, total) - - setup_td: uhci_td | t.CPtr = tds - _td_set_link(setup_td, t.CUInt32T(t.CUInt64T(tds) + uhci_td.__sizeof__()), 0, 0) - _td_set_ctrl(setup_td, ls, 8) - _td_set_token(setup_td, TD_TOKEN_SETUP, dev_addr, endpoint, TD_TOKEN_DATA0, 8) - setup_td.buffer = t.CUInt32T(t.CUInt64T(setup_buf)) - - if data_len > 0: - data_td: uhci_td | t.CPtr = t.CPtr(t.CUInt64T(tds) + uhci_td.__sizeof__()) - _td_set_link(data_td, t.CUInt32T(t.CUInt64T(data_td) + uhci_td.__sizeof__()), 0, 0) - _td_set_ctrl(data_td, ls, max_pkt) - if data_in: - _td_set_token(data_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, data_len) - else: - _td_set_token(data_td, TD_TOKEN_OUT, dev_addr, endpoint, TD_TOKEN_DATA1, data_len) - data_td.buffer = t.CUInt32T(t.CUInt64T(data_buf)) - - status_td: uhci_td | t.CPtr = t.CPtr(t.CUInt64T(data_td) + uhci_td.__sizeof__()) - _td_set_link(status_td, 0, 0, 1) - _td_set_ctrl(status_td, ls, max_pkt) - if data_in: - _td_set_token(status_td, TD_TOKEN_OUT, dev_addr, endpoint, TD_TOKEN_DATA1, 0) - else: - _td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0) - status_td.buffer = 0 - else: - status_td: uhci_td | t.CPtr = t.CPtr(t.CUInt64T(tds) + uhci_td.__sizeof__()) - _td_set_link(status_td, 0, 0, 1) - _td_set_ctrl(status_td, ls, max_pkt) - _td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0) - status_td.buffer = 0 - - _qh_set_element(_ctrl_qh, t.CUInt32T(t.CUInt64T(setup_td)), 0) - - result: t.CInt = _wait_for_complete(status_td, 500) - - _qh_set_element(_ctrl_qh, 0, 1) - mm.free(tds) - return result +import t, c +import asm +import mm.mm as mm +import viperstring as string +import drivers.serial.uart.serial as serial +import platform.pch.timer as timer +import intr.idt as idt +import platform.pch.pic as pic +import drivers.usb.pci as pci +import viperlib + +UHCI_USBCMD: t.CDefine = 0x00 +UHCI_USBSTS: t.CDefine = 0x02 +UHCI_USBINTR: t.CDefine = 0x04 +UHCI_FRNUM: t.CDefine = 0x06 +UHCI_FLBASEADD: t.CDefine = 0x08 +UHCI_SOFMOD: t.CDefine = 0x0C +UHCI_PORTSC1: t.CDefine = 0x10 +UHCI_PORTSC2: t.CDefine = 0x12 + +UHCI_CMD_RUN: t.CDefine = 0x0001 +UHCI_CMD_HCRESET: t.CDefine = 0x0002 +UHCI_CMD_GRESET: t.CDefine = 0x0004 +UHCI_CMD_MAXPKT: t.CDefine = 0x0080 +UHCI_CMD_CF: t.CDefine = 0x0040 + +UHCI_STS_HCHALTED: t.CDefine = 0x0020 +UHCI_STS_USBINT: t.CDefine = 0x0001 +UHCI_STS_USBERRINT: t.CDefine = 0x0002 +UHCI_STS_RESUME: t.CDefine = 0x0004 +UHCI_INTR_TIMEOUT: t.CDefine = 0x0001 +UHCI_INTR_RESUME: t.CDefine = 0x0002 +UHCI_INTR_IOC: t.CDefine = 0x0004 +UHCI_INTR_SHORT: t.CDefine = 0x0008 + +UHCI_PORT_CONNECT: t.CDefine = 0x0001 +UHCI_PORT_CONNECT_CHANGE: t.CDefine = 0x0002 +UHCI_PORT_ENABLE: t.CDefine = 0x0004 +UHCI_PORT_ENABLE_CHANGE: t.CDefine = 0x0008 +UHCI_PORT_RESET: t.CDefine = 0x0200 +UHCI_PORT_LOW_SPEED: t.CDefine = 0x0100 + +TD_CTRL_ACTIVE: t.CDefine = 0x00800000 +TD_CTRL_IOC: t.CDefine = 0x01000000 +TD_CTRL_LS: t.CDefine = 0x04000000 +TD_CTRL_SPD: t.CDefine = 0x20000000 +TD_CTRL_CERR_SHIFT: t.CDefine = 27 +TD_CTRL_CERR_MASK: t.CDefine = 0x18000000 + +TD_TOKEN_SETUP: t.CDefine = 0x2D +TD_TOKEN_IN: t.CDefine = 0x69 +TD_TOKEN_OUT: t.CDefine = 0xE1 + +TD_TOKEN_DATA0: t.CDefine = 0 +TD_TOKEN_DATA1: t.CDefine = 1 + +TD_LINK_TERMINATE: t.CDefine = 0x00000001 +TD_LINK_QH: t.CDefine = 0x00000002 +TD_LINK_DEPTH_FIRST: t.CDefine = 0x00000004 + +UHCI_NUM_FRAMES: t.CDefine = 1024 +UHCI_INT_SLOTS: t.CDefine = 4 + +class uhci_td(t.CStruct): + link: uint32 + ctrl_status: uint32 + token: uint32 + buffer: uint32 + +class uhci_qh(t.CStruct): + link: uint32 + element: uint32 + +class int_slot(t.CStruct): + td: uhci_td | t.CPtr + callback: int | t.CPtr + active: int + qh: uhci_qh | t.CPtr + +_io_base: uint16 = 0 +_frame_list: uint32 | t.CPtr = None +_ctrl_qh: uhci_qh | t.CPtr = None +_bulk_qh: uhci_qh | t.CPtr = None +_irq: int = -1 +_int_slots: t.CArray[int_slot, UHCI_INT_SLOTS] +_int_slot_count: int = 0 + +def _reg_read16(offset: uint16) -> uint16: + return asm.inw(_io_base + offset) + +def _reg_write16(offset: uint16, value: uint16): + asm.outw(_io_base + offset, value) + +def _reg_read32(offset: uint16) -> uint32: + return asm.inl(_io_base + offset) + +def _reg_write32(offset: uint16, value: uint32): + asm.outl(_io_base + offset, value) + +def _uhci_irq_handler() -> int: + sts: uint16 = _reg_read16(UHCI_USBSTS) + _reg_write16(UHCI_USBSTS, sts) + if (sts & (UHCI_STS_USBINT | UHCI_STS_USBERRINT)) == 0: + return 0 + for si in range(_int_slot_count): + slot: int_slot | t.CPtr = c.Addr(_int_slots[si]) + if slot.active and slot.td is not None and slot.callback is not None: + status: uint32 = slot.td.ctrl_status + if (status & TD_CTRL_ACTIVE) == 0: + slot.active = 0 + c.Asm(f"""mov rbp, rsp + and rsp, -16 + call {c.AsmInp(slot.callback, t.ASM_DESCR.REG_ANY)} + mov rsp, rbp""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, + t.ASM_DESCR.CLOBBER_RBX, + t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, + t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11, + t.ASM_DESCR.CLOBBER_RBP]) + return 0 + +def register_int_callback(cb: int | t.CPtr) -> int: + global _int_slot_count + if _int_slot_count >= UHCI_INT_SLOTS: + return -1 + si: int = _int_slot_count + qh: uhci_qh | t.CPtr = mm.malloc_direct(uhci_qh.__sizeof__()) + if qh is None: + return -2 + string.memset(c.Addr(qh), 0, uhci_qh.__sizeof__()) + _qh_set_link(qh, 0, 0, 1) + _qh_set_element(qh, 0, 1) + td: uhci_td | t.CPtr = mm.malloc_direct(uhci_td.__sizeof__()) + if td is None: + return -3 + string.memset(c.Addr(td), 0, uhci_td.__sizeof__()) + slot: int_slot | t.CPtr = c.Addr(_int_slots[si]) + slot.td = td + slot.callback = cb + slot.active = 0 + slot.qh = qh + _int_slot_count = si + 1 + _rebuild_int_chain() + return si + +def schedule_int_transfer(slot_id: int, dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, toggle_ptr: uint8 | t.CPtr, buf: t.CPtr): + if slot_id < 0 or slot_id >= _int_slot_count: + return + slot: int_slot | t.CPtr = c.Addr(_int_slots[slot_id]) + td: uhci_td | t.CPtr = slot.td + qh: uhci_qh | t.CPtr = slot.qh + if td is None or qh is None: + return + string.memset(c.Addr(td), 0, uhci_td.__sizeof__()) + _td_set_link(td, 0, 0, 1) + _td_set_ctrl(td, ls, max_pkt) + _td_set_token(td, TD_TOKEN_IN, dev_addr, endpoint, toggle_ptr, max_pkt) + td.ctrl_status = td.ctrl_status | TD_CTRL_IOC + td.buffer = uint32(uint64(buf)) + _qh_set_element(qh, uint32(uint64(td)), 0) + slot.active = 1 + +def _rebuild_int_chain(): + if _int_slot_count == 0: + return + first_qh: uhci_qh | t.CPtr = None + prev_qh: uhci_qh | t.CPtr = None + for si in range(_int_slot_count): + cur_qh: uhci_qh | t.CPtr = _int_slots[si].qh + if cur_qh is not None: + if first_qh is None: + first_qh = cur_qh + if prev_qh is not None: + _qh_set_link(prev_qh, uint32(uint64(cur_qh)) | TD_LINK_QH, 1, 0) + prev_qh = cur_qh + if prev_qh is not None: + _qh_set_link(prev_qh, uint32(uint64(_ctrl_qh)) | TD_LINK_QH, 1, 0) + if first_qh is not None: + qh_addr: uint32 = uint32(uint64(first_qh)) | TD_LINK_QH + i: int + for i in range(UHCI_NUM_FRAMES): + entry_ptr: uint32 | t.CPtr = _frame_list + uint64(i) * 4 + c.Set(c.Deref(entry_ptr), qh_addr) + +def _td_set_link(td: uhci_td | t.CPtr, addr: uint32, is_qh: int, terminate: int): + val: uint32 = (addr & 0xFFFFFFF0) + if is_qh: val = val | TD_LINK_QH + if terminate: val = val | TD_LINK_TERMINATE + td.link = val + +def _td_set_token(td: uhci_td | t.CPtr, pid: uint8, dev_addr: uint8, endpoint: uint8, toggle: uint8, max_len: uint16): + len_bits: uint32 + if max_len == 0: + len_bits = 0x7FF + else: + len_bits = uint32(max_len) - 1 + td.token = (uint32(pid) << 0) | (uint32(dev_addr) << 8) | (uint32(endpoint & 0x0F) << 15) | (uint32(toggle & 1) << 19) | (len_bits << 21) + +def _td_set_ctrl(td: uhci_td | t.CPtr, ls: int, maxlen: uint16): + td.ctrl_status = TD_CTRL_ACTIVE | (3 << TD_CTRL_CERR_SHIFT) + if ls: td.ctrl_status = td.ctrl_status | TD_CTRL_LS + +def _qh_set_link(qh: uhci_qh | t.CPtr, addr: uint32, is_qh: int, terminate: int): + val: uint32 = (addr & 0xFFFFFFF0) + if is_qh: val = val | TD_LINK_QH + if terminate: val = val | TD_LINK_TERMINATE + qh.link = val + +def _qh_set_element(qh: uhci_qh | t.CPtr, addr: uint32, terminate: int): + val: uint32 = (addr & 0xFFFFFFF0) + if terminate: val = val | TD_LINK_TERMINATE + qh.element = val + +def _wait_for_complete(td: uhci_td | t.CPtr, timeout_ms: int) -> int: + start: uint64 = timer.timer_get_ticks() + deadline: uint64 = start + uint64(timeout_ms) + poll_cnt: int = 0 + while timer.timer_get_ticks() < deadline: + status: uint32 = td.ctrl_status + if (status & TD_CTRL_ACTIVE) == 0: + if (status & 0x00600000) != 0: + return -1 + return 0 + poll_cnt += 1 + if poll_cnt >= 100: + poll_cnt = 0 + asm.sti() + asm.hlt() + return -2 + +def reset(io_base: uint16) -> int: + global _io_base + _io_base = io_base + _reg_write16(UHCI_USBCMD, UHCI_CMD_HCRESET) + i: int + for i in range(1000): + if (_reg_read16(UHCI_USBCMD) & UHCI_CMD_HCRESET) == 0: + break + _reg_write16(UHCI_USBSTS, 0xFFFF) + _reg_write16(UHCI_USBINTR, 0x0000) + return 0 + +def init(io_base: uint16) -> int: + global _irq, _io_base, _frame_list, _ctrl_qh, _bulk_qh, _int_slot_count + _io_base = io_base + _int_slot_count = 0 + + serial.puts("[uhci] resetting...\n") + if reset(io_base) != 0: + serial.puts("[uhci] reset failed\n") + return -1 + + serial.puts("[uhci] allocating frame list...\n") + _frame_list = mm.malloc(UHCI_NUM_FRAMES * 4) + _dbg_fl: t.CArray[t.CChar, 96] + viperlib.snprintf(c.Addr(_dbg_fl), 96, "[dbg] frame_list ret=0x%lx\n", uint64(_frame_list)) + serial.puts(c.Addr(_dbg_fl)) + if _frame_list is None: + serial.puts("[uhci] frame list alloc failed\n") + return -2 + string.memset(_frame_list, 0, UHCI_NUM_FRAMES * 4) + + _ctrl_qh = mm.malloc_direct(uhci_qh.__sizeof__()) + if _ctrl_qh is None: + serial.puts("[uhci] ctrl_qh alloc failed\n") + return -3 + string.memset(c.Addr(_ctrl_qh), 0, uhci_qh.__sizeof__()) + _qh_set_link(_ctrl_qh, 0, 0, 1) + _qh_set_element(_ctrl_qh, 0, 1) + + _bulk_qh = mm.malloc_direct(uhci_qh.__sizeof__()) + if _bulk_qh is None: + serial.puts("[uhci] bulk_qh alloc failed\n") + return -4 + string.memset(c.Addr(_bulk_qh), 0, uhci_qh.__sizeof__()) + _qh_set_link(_bulk_qh, 0, 0, 1) + _qh_set_element(_bulk_qh, 0, 1) + + serial.puts("[uhci] setting up frame list...\n") + qh_addr: uint32 = uint32(c.Addr(_ctrl_qh)) | TD_LINK_QH + i: int + for i in range(UHCI_NUM_FRAMES): + entry_ptr: uint32 | t.CPtr = _frame_list + uint64(i) * 4 + c.Set(c.Deref(entry_ptr), qh_addr) + + _reg_write32(UHCI_FLBASEADD, uint32(uint64(_frame_list))) + _reg_write16(UHCI_FRNUM, 0) + _reg_write16(UHCI_SOFMOD, 64) + + _reg_write16(UHCI_USBCMD, UHCI_CMD_CF | UHCI_CMD_MAXPKT | UHCI_CMD_RUN) + + timer.timer_msleep(10) + + _reg_write16(UHCI_USBSTS, 0xFFFF) + _reg_write16(UHCI_USBINTR, UHCI_INTR_IOC | UHCI_INTR_SHORT) + + _irq = int(pci._uhci_dev.irq) + if _irq > 0 and _irq < 16: + idt.irqInstallHandler(_irq, _uhci_irq_handler, "uhci") + pic.clearMask(uint8(_irq)) + + serial.puts("[uhci] started\n") + return 0 + +def port_reset(port: int) -> int: + sc: uint16 + if port == 0: + sc = _reg_read16(UHCI_PORTSC1) + else: + sc = _reg_read16(UHCI_PORTSC2) + + if (sc & UHCI_PORT_CONNECT) == 0: + return -1 + + if port == 0: + _reg_write16(UHCI_PORTSC1, sc | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) + else: + _reg_write16(UHCI_PORTSC2, sc | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) + + if port == 0: + _reg_write16(UHCI_PORTSC1, UHCI_PORT_RESET) + else: + _reg_write16(UHCI_PORTSC2, UHCI_PORT_RESET) + + timer.timer_msleep(50) + + if port == 0: + _reg_write16(UHCI_PORTSC1, 0x0000) + else: + _reg_write16(UHCI_PORTSC2, 0x0000) + + timer.timer_msleep(10) + + if port == 0: + sc = _reg_read16(UHCI_PORTSC1) + _reg_write16(UHCI_PORTSC1, sc | UHCI_PORT_ENABLE | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) + else: + sc = _reg_read16(UHCI_PORTSC2) + _reg_write16(UHCI_PORTSC2, sc | UHCI_PORT_ENABLE | UHCI_PORT_CONNECT_CHANGE | UHCI_PORT_ENABLE_CHANGE) + + timer.timer_msleep(10) + + if port == 0: + sc = _reg_read16(UHCI_PORTSC1) + else: + sc = _reg_read16(UHCI_PORTSC2) + + if (sc & UHCI_PORT_ENABLE) == 0: + return -2 + + return 0 + +def port_is_connected(port: int) -> int: + sc: uint16 + if port == 0: + sc = _reg_read16(UHCI_PORTSC1) + else: + sc = _reg_read16(UHCI_PORTSC2) + if sc & UHCI_PORT_CONNECT: return 1 + return 0 + +def port_is_low_speed(port: int) -> int: + sc: uint16 + if port == 0: + sc = _reg_read16(UHCI_PORTSC1) + else: + sc = _reg_read16(UHCI_PORTSC2) + if sc & UHCI_PORT_LOW_SPEED: return 1 + return 0 + +def control_transfer(dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, setup_buf: t.CPtr, data_buf: t.CPtr, data_len: uint16, data_in: int) -> int: + td_count: int = 2 + if data_len > 0: + td_count = td_count + 1 + total: uint64 = uint64(td_count) * uhci_td.__sizeof__() + tds: uhci_td | t.CPtr = mm.malloc_direct(total) + if tds is None: return -1 + string.memset(c.Addr(tds), 0, total) + + setup_td: uhci_td | t.CPtr = tds + _td_set_link(setup_td, uint32(uint64(tds) + uhci_td.__sizeof__()), 0, 0) + _td_set_ctrl(setup_td, ls, 8) + _td_set_token(setup_td, TD_TOKEN_SETUP, dev_addr, endpoint, TD_TOKEN_DATA0, 8) + setup_td.buffer = uint32(uint64(setup_buf)) + + if data_len > 0: + data_td: uhci_td | t.CPtr = t.CPtr(uint64(tds) + uhci_td.__sizeof__()) + _td_set_link(data_td, uint32(uint64(data_td) + uhci_td.__sizeof__()), 0, 0) + _td_set_ctrl(data_td, ls, max_pkt) + if data_in: + _td_set_token(data_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, data_len) + else: + _td_set_token(data_td, TD_TOKEN_OUT, dev_addr, endpoint, TD_TOKEN_DATA1, data_len) + data_td.buffer = uint32(uint64(data_buf)) + + status_td: uhci_td | t.CPtr = t.CPtr(uint64(data_td) + uhci_td.__sizeof__()) + _td_set_link(status_td, 0, 0, 1) + _td_set_ctrl(status_td, ls, max_pkt) + if data_in: + _td_set_token(status_td, TD_TOKEN_OUT, dev_addr, endpoint, TD_TOKEN_DATA1, 0) + else: + _td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0) + status_td.buffer = 0 + else: + status_td: uhci_td | t.CPtr = t.CPtr(uint64(tds) + uhci_td.__sizeof__()) + _td_set_link(status_td, 0, 0, 1) + _td_set_ctrl(status_td, ls, max_pkt) + _td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0) + status_td.buffer = 0 + + _qh_set_element(_ctrl_qh, uint32(uint64(setup_td)), 0) + + result: int = _wait_for_complete(status_td, 500) + + _qh_set_element(_ctrl_qh, 0, 1) + mm.free(tds) + return result diff --git a/VKernel/Kernel/drivers/usb/usb.vp b/VKernel/Kernel/drivers/usb/usb.vp index d0f8d47..668cb90 100644 --- a/VKernel/Kernel/drivers/usb/usb.vp +++ b/VKernel/Kernel/drivers/usb/usb.vp @@ -1,330 +1,333 @@ -import t, c -import mm.mm as mm -import viperstring as string -import drivers.serial.uart.serial as serial -import drivers.usb.uhci as uhci -import drivers.usb.pci as pci -import platform.pch.timer as timer -import viperlib - -USB_DESC_DEVICE: t.CDefine = 1 -USB_DESC_CONFIG: t.CDefine = 2 -USB_DESC_STRING: t.CDefine = 3 -USB_DESC_INTERFACE: t.CDefine = 4 -USB_DESC_ENDPOINT: t.CDefine = 5 - -USB_REQ_GET_STATUS: t.CDefine = 0 -USB_REQ_CLEAR_FEATURE: t.CDefine = 1 -USB_REQ_SET_FEATURE: t.CDefine = 3 -USB_REQ_SET_ADDRESS: t.CDefine = 5 -USB_REQ_GET_DESCRIPTOR: t.CDefine = 6 -USB_REQ_SET_DESCRIPTOR: t.CDefine = 7 -USB_REQ_GET_CONFIGURATION: t.CDefine = 8 -USB_REQ_SET_CONFIGURATION: t.CDefine = 9 - -USB_REQ_SET_INTERFACE: t.CDefine = 11 - -HID_CLASS: t.CDefine = 0x03 -HID_SUBCLASS_BOOT: t.CDefine = 0x01 -HID_PROTO_KEYBOARD: t.CDefine = 0x01 -HID_PROTO_MOUSE: t.CDefine = 0x02 - -HID_REQ_SET_PROTOCOL: t.CDefine = 0x0B -HID_REQ_SET_IDLE: t.CDefine = 0x0A -HID_REQ_GET_REPORT: t.CDefine = 0x01 - -USB_MAX_DEVICES: t.CDefine = 8 - -class usb_dev_desc(t.CStruct): - bLength: t.CUInt8T - bDescriptorType: t.CUInt8T - bcdUSB: t.CUInt16T - bDeviceClass: t.CUInt8T - bDeviceSubClass: t.CUInt8T - bDeviceProtocol: t.CUInt8T - bMaxPacketSize0: t.CUInt8T - idVendor: t.CUInt16T - idProduct: t.CUInt16T - bcdDevice: t.CUInt16T - iManufacturer: t.CUInt8T - iProduct: t.CUInt8T - iSerialNumber: t.CUInt8T - bNumConfigurations: t.CUInt8T - -class usb_config_desc(t.CStruct): - bLength: t.CUInt8T - bDescriptorType: t.CUInt8T - wTotalLength: t.CUInt16T - bNumInterfaces: t.CUInt8T - bConfigurationValue: t.CUInt8T - iConfiguration: t.CUInt8T - bmAttributes: t.CUInt8T - bMaxPower: t.CUInt8T - -class usb_iface_desc(t.CStruct): - bLength: t.CUInt8T - bDescriptorType: t.CUInt8T - bInterfaceNumber: t.CUInt8T - bAlternateSetting: t.CUInt8T - bNumEndpoints: t.CUInt8T - bInterfaceClass: t.CUInt8T - bInterfaceSubClass: t.CUInt8T - bInterfaceProtocol: t.CUInt8T - iInterface: t.CUInt8T - -class usb_ep_desc(t.CStruct): - bLength: t.CUInt8T - bDescriptorType: t.CUInt8T - bEndpointAddress: t.CUInt8T - bmAttributes: t.CUInt8T - wMaxPacketSize: t.CUInt16T - bInterval: t.CUInt8T - -class usb_setup_pkt(t.CStruct): - bmRequestType: t.CUInt8T - bRequest: t.CUInt8T - wValue: t.CUInt16T - wIndex: t.CUInt16T - wLength: t.CUInt16T - -class usb_device(t.CStruct): - addr: t.CUInt8T - ls: t.CInt - max_pkt0: t.CUInt8T - iface_class: t.CUInt8T - iface_subclass: t.CUInt8T - iface_protocol: t.CUInt8T - iface_num: t.CUInt8T - ep_in: t.CUInt8T - ep_in_max: t.CUInt16T - ep_in_interval: t.CUInt8T - ep_in_toggle: t.CUInt8T - configured: t.CInt - -_devices: t.CArray[usb_device, USB_MAX_DEVICES] -_device_count: t.CInt = 0 - -def _setup_packet(bmRequestType: t.CUInt8T, bRequest: t.CUInt8T, wValue: t.CUInt16T, wIndex: t.CUInt16T, wLength: t.CUInt16T, buf: usb_setup_pkt | t.CPtr): - buf.bmRequestType = bmRequestType - buf.bRequest = bRequest - buf.wValue = wValue - buf.wIndex = wIndex - buf.wLength = wLength - -def _send_control(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, setup: usb_setup_pkt | t.CPtr, data_buf: t.CVoid | t.CPtr, data_len: t.CUInt16T, data_in: t.CInt) -> t.CInt: - return uhci.control_transfer(dev_addr, 0, ls, max_pkt, c.Addr(setup), data_buf, data_len, data_in) - -def get_descriptor(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, desc_type: t.CUInt8T, desc_idx: t.CUInt8T, buf: t.CVoid | t.CPtr, length: t.CUInt16T) -> t.CInt: - setup: usb_setup_pkt - _setup_packet(0x80, USB_REQ_GET_DESCRIPTOR, (t.CUInt16T(desc_type) << 8) | desc_idx, 0, length, c.Addr(setup)) - return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), buf, length, 1) - -def set_address(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, new_addr: t.CUInt8T) -> t.CInt: - setup: usb_setup_pkt - _setup_packet(0x00, USB_REQ_SET_ADDRESS, new_addr, 0, 0, c.Addr(setup)) - return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) - -def set_configuration(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, config_val: t.CUInt8T) -> t.CInt: - setup: usb_setup_pkt - _setup_packet(0x00, USB_REQ_SET_CONFIGURATION, config_val, 0, 0, c.Addr(setup)) - return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) - -def hid_set_protocol(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, iface: t.CUInt8T, protocol: t.CUInt8T) -> t.CInt: - setup: usb_setup_pkt - _setup_packet(0x21, HID_REQ_SET_PROTOCOL, protocol, t.CUInt16T(iface), 0, c.Addr(setup)) - return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) - -def hid_set_idle(dev_addr: t.CUInt8T, ls: t.CInt, max_pkt: t.CUInt8T, iface: t.CUInt8T, duration: t.CUInt8T) -> t.CInt: - setup: usb_setup_pkt - _setup_packet(0x21, HID_REQ_SET_IDLE, t.CUInt16T(duration) << 8, t.CUInt16T(iface), 0, c.Addr(setup)) - return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) - -def _parse_config(dev: usb_device | t.CPtr, config_buf: t.CVoid | t.CPtr, total_len: t.CUInt16T): - offset: t.CInt = 0 - found_hid: t.CInt = 0 - while offset < t.CInt(total_len): - p: t.CUInt8T | t.CPtr = config_buf + t.CUInt64T(offset) - desc_len: t.CUInt8T = c.Deref(p) - p2: t.CUInt8T | t.CPtr = config_buf + t.CUInt64T(offset) + 1 - desc_type: t.CUInt8T = c.Deref(p2) - if desc_len == 0: break - if desc_type == USB_DESC_INTERFACE: - iface: usb_iface_desc | t.CPtr = config_buf + t.CUInt64T(offset) - if iface.bInterfaceClass == HID_CLASS: - found_hid = 1 - dev.iface_class = HID_CLASS - dev.iface_subclass = iface.bInterfaceSubClass - dev.iface_protocol = iface.bInterfaceProtocol - dev.iface_num = iface.bInterfaceNumber - if desc_type == USB_DESC_ENDPOINT and found_hid: - ep: usb_ep_desc | t.CPtr = config_buf + t.CUInt64T(offset) - if (ep.bEndpointAddress & 0x80) != 0: - dev.ep_in = ep.bEndpointAddress & 0x0F - dev.ep_in_max = ep.wMaxPacketSize - dev.ep_in_interval = ep.bInterval - found_hid = 0 - offset = offset + t.CInt(desc_len) - -def enumerate_port(port: t.CInt) -> t.CInt: - global _device_count - if _device_count >= USB_MAX_DEVICES: return -1 - - ls: t.CInt = uhci.port_is_low_speed(port) - - reset_ok: t.CInt = -1 - reset_retry: t.CInt - for reset_retry in range(3): - if uhci.port_reset(port) == 0: - reset_ok = 0 - break - timer.timer_msleep(50) - if reset_ok != 0: - return -2 - - timer.timer_msleep(10) - - dev_buf: t.CVoid | t.CPtr = mm.malloc(usb_dev_desc.__sizeof__()) - if dev_buf is None: return -3 - string.memset(dev_buf, 0, usb_dev_desc.__sizeof__()) - - result: t.CInt = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8) - retry: t.CInt - for retry in range(3): - if result == 0: break - timer.timer_msleep(50) - uhci.port_reset(port) - timer.timer_msleep(10) - result = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8) - if result != 0: - mm.free(dev_buf) - return -4 - - desc: usb_dev_desc | t.CPtr = dev_buf - max_pkt: t.CUInt8T = desc.bMaxPacketSize0 - if max_pkt < 8: max_pkt = 8 - - new_addr: t.CUInt8T = t.CUInt8T(_device_count + 1) - result = set_address(0, ls, max_pkt, new_addr) - for retry in range(3): - if result == 0: break - timer.timer_msleep(20) - result = set_address(0, ls, max_pkt, new_addr) - if result != 0: - mm.free(dev_buf) - return -5 - - timer.timer_msleep(10) - - dev: usb_device | t.CPtr = c.Addr(_devices[_device_count]) - dev.addr = new_addr - dev.ls = ls - dev.max_pkt0 = max_pkt - dev.configured = 0 - dev.iface_class = 0 - dev.iface_subclass = 0 - dev.iface_protocol = 0 - dev.ep_in = 0 - dev.ep_in_max = 0 - dev.ep_in_interval = 0 - dev.ep_in_toggle = 0 - - config_buf: t.CVoid | t.CPtr = mm.malloc(256) - if config_buf is None: - mm.free(dev_buf) - return -6 - string.memset(config_buf, 0, 256) - - result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9) - for retry in range(3): - if result == 0: break - timer.timer_msleep(50) - result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9) - if result != 0: - mm.free(config_buf) - mm.free(dev_buf) - return -7 - - cfg: usb_config_desc | t.CPtr = config_buf - total_len: t.CUInt16T = cfg.wTotalLength - if total_len > 256: total_len = 256 - - result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len) - for retry in range(3): - if result == 0: break - timer.timer_msleep(50) - result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len) - if result != 0: - mm.free(config_buf) - mm.free(dev_buf) - return -8 - - _parse_config(dev, config_buf, total_len) - - result = set_configuration(new_addr, ls, max_pkt, cfg.bConfigurationValue) - if result != 0: - mm.free(config_buf) - mm.free(dev_buf) - return -9 - - dev.configured = 1 - - if dev.iface_class == HID_CLASS: - hid_set_protocol(new_addr, ls, max_pkt, dev.iface_num, 0) - hid_set_idle(new_addr, ls, max_pkt, dev.iface_num, 0) - - _device_count = _device_count + 1 - mm.free(config_buf) - mm.free(dev_buf) - return t.CInt(new_addr) - -def init() -> t.CInt: - global _device_count - _device_count = 0 - - io_base: t.CUInt16T = pci.find_uhci() - if io_base == 0: - serial.puts("[usb] UHCI controller not found\n") - return -1 - - buf: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(buf), 64, "[usb] UHCI at I/O 0x%04X\n", t.CUInt32T(io_base)) - serial.puts(buf) - - if uhci.init(io_base) != 0: - serial.puts("[usb] UHCI init failed\n") - return -2 - - serial.puts("[usb] UHCI initialized\n") - - timer.timer_msleep(50) - - port: t.CInt - for port in range(2): - if uhci.port_is_connected(port): - viperlib.snprintf(c.Addr(buf), 64, "[usb] port %d connected\n", t.CUInt32T(port)) - serial.puts(buf) - dev_id: t.CInt = enumerate_port(port) - if dev_id > 0: - dev: usb_device | t.CPtr = c.Addr(_devices[dev_id - 1]) - viperlib.snprintf(c.Addr(buf), 64, "[usb] device addr=%d class=%02X proto=%02X ep=%d\n", - t.CUInt32T(dev.addr), t.CUInt32T(dev.iface_class), - t.CUInt32T(dev.iface_protocol), t.CUInt32T(dev.ep_in)) - serial.puts(buf) - else: - viperlib.snprintf(c.Addr(buf), 64, "[usb] enumerate port %d failed: %d\n", t.CUInt32T(port), t.CInt32T(dev_id)) - serial.puts(buf) - - return _device_count - -def find_hid_device(protocol: t.CUInt8T) -> usb_device | t.CPtr: - i: t.CInt - for i in range(_device_count): - dev: usb_device | t.CPtr = c.Addr(_devices[i]) - if dev.iface_class == HID_CLASS: - if dev.iface_protocol == protocol: - if dev.configured != 0: - return dev - return None - -def read_interrupt(dev: usb_device | t.CPtr, buf: t.CVoid | t.CPtr) -> t.CInt: - return 0 +import t, c +import mm.mm as mm +import viperstring as string +import drivers.serial.uart.serial as serial +import drivers.usb.uhci as uhci +import drivers.usb.pci as pci +import platform.pch.timer as timer +import viperlib + +USB_DESC_DEVICE: t.CDefine = 1 +USB_DESC_CONFIG: t.CDefine = 2 +USB_DESC_STRING: t.CDefine = 3 +USB_DESC_INTERFACE: t.CDefine = 4 +USB_DESC_ENDPOINT: t.CDefine = 5 + +USB_REQ_GET_STATUS: t.CDefine = 0 +USB_REQ_CLEAR_FEATURE: t.CDefine = 1 +USB_REQ_SET_FEATURE: t.CDefine = 3 +USB_REQ_SET_ADDRESS: t.CDefine = 5 +USB_REQ_GET_DESCRIPTOR: t.CDefine = 6 +USB_REQ_SET_DESCRIPTOR: t.CDefine = 7 +USB_REQ_GET_CONFIGURATION: t.CDefine = 8 +USB_REQ_SET_CONFIGURATION: t.CDefine = 9 + +USB_REQ_SET_INTERFACE: t.CDefine = 11 + +HID_CLASS: t.CDefine = 0x03 +HID_SUBCLASS_BOOT: t.CDefine = 0x01 +HID_PROTO_KEYBOARD: t.CDefine = 0x01 +HID_PROTO_MOUSE: t.CDefine = 0x02 + +HID_REQ_SET_PROTOCOL: t.CDefine = 0x0B +HID_REQ_SET_IDLE: t.CDefine = 0x0A +HID_REQ_GET_REPORT: t.CDefine = 0x01 + +USB_MAX_DEVICES: t.CDefine = 8 + +class usb_dev_desc(t.CStruct): + bLength: uint8 + bDescriptorType: uint8 + bcdUSB: uint16 + bDeviceClass: uint8 + bDeviceSubClass: uint8 + bDeviceProtocol: uint8 + bMaxPacketSize0: uint8 + idVendor: uint16 + idProduct: uint16 + bcdDevice: uint16 + iManufacturer: uint8 + iProduct: uint8 + iSerialNumber: uint8 + bNumConfigurations: uint8 + +class usb_config_desc(t.CStruct): + bLength: uint8 + bDescriptorType: uint8 + wTotalLength: uint16 + bNumInterfaces: uint8 + bConfigurationValue: uint8 + iConfiguration: uint8 + bmAttributes: uint8 + bMaxPower: uint8 + +class usb_iface_desc(t.CStruct): + bLength: uint8 + bDescriptorType: uint8 + bInterfaceNumber: uint8 + bAlternateSetting: uint8 + bNumEndpoints: uint8 + bInterfaceClass: uint8 + bInterfaceSubClass: uint8 + bInterfaceProtocol: uint8 + iInterface: uint8 + +class usb_ep_desc(t.CStruct): + bLength: uint8 + bDescriptorType: uint8 + bEndpointAddress: uint8 + bmAttributes: uint8 + wMaxPacketSize: uint16 + bInterval: uint8 + +class usb_setup_pkt(t.CStruct): + bmRequestType: uint8 + bRequest: uint8 + wValue: uint16 + wIndex: uint16 + wLength: uint16 + +class usb_device(t.CStruct): + addr: uint8 + ls: int + max_pkt0: uint8 + iface_class: uint8 + iface_subclass: uint8 + iface_protocol: uint8 + iface_num: uint8 + ep_in: uint8 + ep_in_max: uint16 + ep_in_interval: uint8 + ep_in_toggle: uint8 + configured: int + +_devices: t.CArray[usb_device, USB_MAX_DEVICES] +_device_count: int = 0 + +def _setup_packet(bmRequestType: uint8, bRequest: uint8, wValue: uint16, wIndex: uint16, wLength: uint16, buf: usb_setup_pkt | t.CPtr): + buf.bmRequestType = bmRequestType + buf.bRequest = bRequest + buf.wValue = wValue + buf.wIndex = wIndex + buf.wLength = wLength + +def _send_control(dev_addr: uint8, ls: int, max_pkt: uint8, setup: usb_setup_pkt | t.CPtr, data_buf: t.CPtr, data_len: uint16, data_in: int) -> int: + return uhci.control_transfer(dev_addr, 0, ls, max_pkt, c.Addr(setup), data_buf, data_len, data_in) + +def get_descriptor(dev_addr: uint8, ls: int, max_pkt: uint8, desc_type: uint8, desc_idx: uint8, buf: t.CPtr, length: uint16) -> int: + setup: usb_setup_pkt + _setup_packet(0x80, USB_REQ_GET_DESCRIPTOR, (uint16(desc_type) << 8) | desc_idx, 0, length, c.Addr(setup)) + return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), buf, length, 1) + +def set_address(dev_addr: uint8, ls: int, max_pkt: uint8, new_addr: uint8) -> int: + setup: usb_setup_pkt + _setup_packet(0x00, USB_REQ_SET_ADDRESS, new_addr, 0, 0, c.Addr(setup)) + return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) + +def set_configuration(dev_addr: uint8, ls: int, max_pkt: uint8, config_val: uint8) -> int: + setup: usb_setup_pkt + _setup_packet(0x00, USB_REQ_SET_CONFIGURATION, config_val, 0, 0, c.Addr(setup)) + return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) + +def hid_set_protocol(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, protocol: uint8) -> int: + setup: usb_setup_pkt + _setup_packet(0x21, HID_REQ_SET_PROTOCOL, protocol, uint16(iface), 0, c.Addr(setup)) + return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) + +def hid_set_idle(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, duration: uint8) -> int: + setup: usb_setup_pkt + _setup_packet(0x21, HID_REQ_SET_IDLE, uint16(duration) << 8, uint16(iface), 0, c.Addr(setup)) + return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0) + +def _parse_config(dev: usb_device | t.CPtr, config_buf: t.CPtr, total_len: uint16): + offset: int = 0 + found_hid: int = 0 + while offset < int(total_len): + p: uint8 | t.CPtr = config_buf + uint64(offset) + desc_len: uint8 = c.Deref(p) + p2: uint8 | t.CPtr = config_buf + uint64(offset) + 1 + desc_type: uint8 = c.Deref(p2) + if desc_len == 0: break + # 边界:描述符整体须落在 config_buf(total_len 字节)内,且不得短于 + # 所访问的结构体(interface=9 / endpoint=7),否则越界读。 + if offset + int(desc_len) > int(total_len): break + if desc_type == USB_DESC_INTERFACE and int(desc_len) >= 9: + iface: usb_iface_desc | t.CPtr = config_buf + uint64(offset) + if iface.bInterfaceClass == HID_CLASS: + found_hid = 1 + dev.iface_class = HID_CLASS + dev.iface_subclass = iface.bInterfaceSubClass + dev.iface_protocol = iface.bInterfaceProtocol + dev.iface_num = iface.bInterfaceNumber + if desc_type == USB_DESC_ENDPOINT and found_hid and int(desc_len) >= 7: + ep: usb_ep_desc | t.CPtr = config_buf + uint64(offset) + if (ep.bEndpointAddress & 0x80) != 0: + dev.ep_in = ep.bEndpointAddress & 0x0F + dev.ep_in_max = ep.wMaxPacketSize + dev.ep_in_interval = ep.bInterval + found_hid = 0 + offset = offset + int(desc_len) + +def enumerate_port(port: int) -> int: + global _device_count + if _device_count >= USB_MAX_DEVICES: return -1 + + ls: int = uhci.port_is_low_speed(port) + + reset_ok: int = -1 + reset_retry: int + for reset_retry in range(3): + if uhci.port_reset(port) == 0: + reset_ok = 0 + break + timer.timer_msleep(50) + if reset_ok != 0: + return -2 + + timer.timer_msleep(10) + + dev_buf: t.CPtr = mm.malloc(usb_dev_desc.__sizeof__()) + if dev_buf is None: return -3 + string.memset(dev_buf, 0, usb_dev_desc.__sizeof__()) + + result: int = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8) + retry: int + for retry in range(3): + if result == 0: break + timer.timer_msleep(50) + uhci.port_reset(port) + timer.timer_msleep(10) + result = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8) + if result != 0: + mm.free(dev_buf) + return -4 + + desc: usb_dev_desc | t.CPtr = dev_buf + max_pkt: uint8 = desc.bMaxPacketSize0 + if max_pkt < 8: max_pkt = 8 + + new_addr: uint8 = uint8(_device_count + 1) + result = set_address(0, ls, max_pkt, new_addr) + for retry in range(3): + if result == 0: break + timer.timer_msleep(20) + result = set_address(0, ls, max_pkt, new_addr) + if result != 0: + mm.free(dev_buf) + return -5 + + timer.timer_msleep(10) + + dev: usb_device | t.CPtr = c.Addr(_devices[_device_count]) + dev.addr = new_addr + dev.ls = ls + dev.max_pkt0 = max_pkt + dev.configured = 0 + dev.iface_class = 0 + dev.iface_subclass = 0 + dev.iface_protocol = 0 + dev.ep_in = 0 + dev.ep_in_max = 0 + dev.ep_in_interval = 0 + dev.ep_in_toggle = 0 + + config_buf: t.CPtr = mm.malloc(256) + if config_buf is None: + mm.free(dev_buf) + return -6 + string.memset(config_buf, 0, 256) + + result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9) + for retry in range(3): + if result == 0: break + timer.timer_msleep(50) + result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9) + if result != 0: + mm.free(config_buf) + mm.free(dev_buf) + return -7 + + cfg: usb_config_desc | t.CPtr = config_buf + total_len: uint16 = cfg.wTotalLength + if total_len > 256: total_len = 256 + + result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len) + for retry in range(3): + if result == 0: break + timer.timer_msleep(50) + result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len) + if result != 0: + mm.free(config_buf) + mm.free(dev_buf) + return -8 + + _parse_config(dev, config_buf, total_len) + + result = set_configuration(new_addr, ls, max_pkt, cfg.bConfigurationValue) + if result != 0: + mm.free(config_buf) + mm.free(dev_buf) + return -9 + + dev.configured = 1 + + if dev.iface_class == HID_CLASS: + hid_set_protocol(new_addr, ls, max_pkt, dev.iface_num, 0) + hid_set_idle(new_addr, ls, max_pkt, dev.iface_num, 0) + + _device_count = _device_count + 1 + mm.free(config_buf) + mm.free(dev_buf) + return int(new_addr) + +def init() -> int: + global _device_count + _device_count = 0 + + io_base: uint16 = pci.find_uhci() + if io_base == 0: + serial.puts("[usb] UHCI controller not found\n") + return -1 + + buf: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(buf), 64, "[usb] UHCI at I/O 0x%04X\n", uint32(io_base)) + serial.puts(buf) + + if uhci.init(io_base) != 0: + serial.puts("[usb] UHCI init failed\n") + return -2 + + serial.puts("[usb] UHCI initialized\n") + + timer.timer_msleep(50) + + port: int + for port in range(2): + if uhci.port_is_connected(port): + viperlib.snprintf(c.Addr(buf), 64, "[usb] port %d connected\n", uint32(port)) + serial.puts(buf) + dev_id: int = enumerate_port(port) + if dev_id > 0: + dev: usb_device | t.CPtr = c.Addr(_devices[dev_id - 1]) + viperlib.snprintf(c.Addr(buf), 64, "[usb] device addr=%d class=%02X proto=%02X ep=%d\n", + uint32(dev.addr), uint32(dev.iface_class), + uint32(dev.iface_protocol), uint32(dev.ep_in)) + serial.puts(buf) + else: + viperlib.snprintf(c.Addr(buf), 64, "[usb] enumerate port %d failed: %d\n", uint32(port), int32(dev_id)) + serial.puts(buf) + + return _device_count + +def find_hid_device(protocol: uint8) -> usb_device | t.CPtr: + i: int + for i in range(_device_count): + dev: usb_device | t.CPtr = c.Addr(_devices[i]) + if dev.iface_class == HID_CLASS: + if dev.iface_protocol == protocol: + if dev.configured != 0: + return dev + return None + +def read_interrupt(dev: usb_device | t.CPtr, buf: t.CPtr) -> int: + return 0 diff --git a/VKernel/Kernel/drivers/video/ui/sheet.vp b/VKernel/Kernel/drivers/video/ui/sheet.vp index 7b70613..934656a 100644 --- a/VKernel/Kernel/drivers/video/ui/sheet.vp +++ b/VKernel/Kernel/drivers/video/ui/sheet.vp @@ -5,25 +5,25 @@ import t, c MAX_SHEETS: t.CDefine = 64 MAX_UI_COMPONENTS: t.CDefine = 256 -_next_sheet_id: t.CInt = 0 -_next_component_id: t.CInt = 0 +_next_sheet_id: int = 0 +_next_component_id: int = 0 @t.Object class Sheet: - id: t.CInt - x: t.CInt - y: t.CInt - w: t.CInt - h: t.CInt - visible: t.CInt + id: int + x: int + y: int + w: int + h: int + visible: int _surf_obj: gfx.Surface _renderer_obj: gfx.Renderer surf: gfx.Surface | t.CPtr renderer: gfx.Renderer | t.CPtr parent: 'Sheet | t.CPtr' - bg_color: t.CUInt32T + bg_color: uint32 - def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, parent: 'Sheet | t.CPtr' = None): + def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, x: int, y: int, w: int, h: int, parent: 'Sheet | t.CPtr' = None): global _next_sheet_id self.id = _next_sheet_id _next_sheet_id += 1 @@ -34,16 +34,19 @@ class Sheet: self.visible = 1 self._surf_obj = gfx.Surface(fb, zb, w, h) self.surf = c.Addr(self._surf_obj) - self._renderer_obj = gfx.Renderer(self.surf) + # gfx.Renderer.__init__(fb, zb, w, h):此前只传 self.surf(Surface*)→ + # fb 被 bitcast 错位、w/h 缺省为 0 → Renderer 的 _w/_h = 0 → + # Sheet.Clear/Fill/DrawRect(走 renderer)全部空操作。按 Surface 同参构造。 + self._renderer_obj = gfx.Renderer(fb, zb, w, h) self.renderer = c.Addr(self._renderer_obj) self.parent = parent self.bg_color = gfx.COLOR_RGB(20, 20, 30) - def MoveTo(self, nx: t.CInt, ny: t.CInt): + def MoveTo(self, nx: int, ny: int): self.x = nx self.y = ny - def Resize(self, nw: t.CInt, nh: t.CInt): + def Resize(self, nw: int, nh: int): self.w = nw self.h = nh @@ -57,29 +60,29 @@ class Sheet: r: gfx.Renderer = c.Deref(self.renderer) r.Clear(self.bg_color) - def Fill(self, color: t.CUInt32T): + def Fill(self, color: uint32): r: gfx.Renderer = c.Deref(self.renderer) r.Clear(color) - def DrawRect(self, rx: t.CInt, ry: t.CInt, rw: t.CInt, rh: t.CInt, color: t.CUInt32T): + def DrawRect(self, rx: int, ry: int, rw: int, rh: int, color: uint32): r: gfx.Renderer = c.Deref(self.renderer) r.DrawLine2D(rx, ry, rx + rw - 1, ry, color) r.DrawLine2D(rx + rw - 1, ry, rx + rw - 1, ry + rh - 1, color) r.DrawLine2D(rx + rw - 1, ry + rh - 1, rx, ry + rh - 1, color) r.DrawLine2D(rx, ry + rh - 1, rx, ry, color) - def DrawFilledRect(self, rx: t.CInt, ry: t.CInt, rw: t.CInt, rh: t.CInt, color: t.CUInt32T): + def DrawFilledRect(self, rx: int, ry: int, rw: int, rh: int, color: uint32): surf: gfx.Surface = c.Deref(self.surf) fb: UINT32PTR = surf.fb - w: t.CInt = surf.w - h: t.CInt = surf.h + w: int = surf.w + h: int = surf.h for py in range(ry, ry + rh): if py < 0 or py >= h: continue for px in range(rx, rx + rw): if px < 0 or px >= w: continue fb[py * w + px] = color - def Contains(self, px: t.CInt, py: t.CInt) -> t.CInt: + def Contains(self, px: int, py: int) -> int: if px >= self.x and px < self.x + self.w and py >= self.y and py < self.y + self.h: return 1 return 0 diff --git a/VKernel/Kernel/drivers/video/ui/ui.vp b/VKernel/Kernel/drivers/video/ui/ui.vp index 42e9eca..b199897 100644 --- a/VKernel/Kernel/drivers/video/ui/ui.vp +++ b/VKernel/Kernel/drivers/video/ui/ui.vp @@ -11,21 +11,21 @@ UI_PROGRESS: t.CDefine = 3 @t.Object class UIComponent: - id: t.CInt - ctype: t.CInt - x: t.CInt - y: t.CInt - w: t.CInt - h: t.CInt - visible: t.CInt + id: int + ctype: int + x: int + y: int + w: int + h: int + visible: int sheet: sheet.Sheet | t.CPtr - fg_color: t.CUInt32T - bg_color: t.CUInt32T + fg_color: uint32 + bg_color: uint32 text: t.CArray[t.CChar, 128] - text_len: t.CInt - value: t.CInt + text_len: int + value: int - def __init__(self, ctype: t.CInt, sh: sheet.Sheet | t.CPtr, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt): + def __init__(self, ctype: int, sh: sheet.Sheet | t.CPtr, x: int, y: int, w: int, h: int): self.id = sheet._next_component_id sheet._next_component_id += 1 self.ctype = ctype @@ -42,7 +42,7 @@ class UIComponent: self.value = 0 def SetText(self, s: str): - i: t.CInt = 0 + i: int = 0 for ch in s: if i >= 127: break self.text[i] = ch @@ -50,7 +50,7 @@ class UIComponent: self.text[i] = 0 self.text_len = i - def SetValue(self, v: t.CInt): + def SetValue(self, v: int): self.value = v def Render(self): @@ -79,12 +79,12 @@ class UIComponent: def _RenderProgress(self, sh: sheet.Sheet): sh.DrawFilledRect(self.x, self.y, self.w, self.h, gfx.COLOR_RGB(30, 30, 40)) - fill_w: t.CInt = self.w * self.value / 100 + fill_w: int = self.w * self.value / 100 if fill_w > 0: sh.DrawFilledRect(self.x, self.y, fill_w, self.h, gfx.COLOR_RGB(0, 180, 255)) sh.DrawRect(self.x, self.y, self.w, self.h, gfx.COLOR_RGB(80, 80, 100)) - def Contains(self, px: t.CInt, py: t.CInt) -> t.CInt: + def Contains(self, px: int, py: int) -> int: if px >= self.x and px < self.x + self.w and py >= self.y and py < self.y + self.h: return 1 return 0 @@ -93,37 +93,37 @@ class UIComponent: @t.Object class UIManager: sheets: t.CArray[sheet.Sheet | t.CPtr, 64] - sheet_count: t.CInt + sheet_count: int components: t.CArray[UIComponent | t.CPtr, 256] - component_count: t.CInt - screen_w: t.CInt - screen_h: t.CInt + component_count: int + screen_w: int + screen_h: int - def __init__(self, w: t.CInt, h: t.CInt): + def __init__(self, w: int, h: int): self.sheet_count = 0 self.component_count = 0 self.screen_w = w self.screen_h = h - i: t.CInt + i: int for i in range(64): self.sheets[i] = None for i in range(256): self.components[i] = None - def AddSheet(self, sh: sheet.Sheet | t.CPtr) -> t.CInt: + def AddSheet(self, sh: sheet.Sheet | t.CPtr) -> int: if self.sheet_count >= 64: return -1 self.sheets[self.sheet_count] = sh self.sheet_count += 1 return 0 - def AddComponent(self, comp: UIComponent | t.CPtr) -> t.CInt: + def AddComponent(self, comp: UIComponent | t.CPtr) -> int: if self.component_count >= 256: return -1 self.components[self.component_count] = comp self.component_count += 1 return 0 - def FindComponent(self, cid: t.CInt) -> UIComponent | t.CPtr: - i: t.CInt + def FindComponent(self, cid: int) -> UIComponent | t.CPtr: + i: int for i in range(self.component_count): p: UIComponent | t.CPtr = self.components[i] if p is not None: @@ -132,15 +132,15 @@ class UIManager: return None def RenderAll(self): - i: t.CInt + i: int for i in range(self.component_count): p: UIComponent | t.CPtr = self.components[i] if p is not None: comp: UIComponent = c.Deref(p) comp.Render() - def HitTest(self, px: t.CInt, py: t.CInt) -> UIComponent | t.CPtr: - i: t.CInt = self.component_count - 1 + def HitTest(self, px: int, py: int) -> UIComponent | t.CPtr: + i: int = self.component_count - 1 while i >= 0: p: UIComponent | t.CPtr = self.components[i] if p is not None: diff --git a/VKernel/Kernel/drivers/video/vesafb/gfx.vp b/VKernel/Kernel/drivers/video/vesafb/gfx.vp index 19bcc35..522a93c 100644 --- a/VKernel/Kernel/drivers/video/vesafb/gfx.vp +++ b/VKernel/Kernel/drivers/video/vesafb/gfx.vp @@ -10,7 +10,7 @@ SPHERE_SLICES: t.CDefine = (24 * 1) SPHERE_STACKS: t.CDefine = (16 * 1) SIN_WAVE_GRID: t.CDefine = (40 * 1) -def COLOR_RGB(r: int, g: int, b: int) -> t.CInline | t.CInt: +def COLOR_RGB(r: int, g: int, b: int) -> t.CInline | int: return (255 << 24) | (r << 16) | (g << 8) | (b) @t.Object @@ -115,7 +115,7 @@ class Renderer: self._w = w self._h = h - def Clear(self, color: t.CUInt32T): + def Clear(self, color: uint32): fb: UINT32PTR = self._fb zb: float | t.CPtr = self._zb size: int = self._w * self._h @@ -123,7 +123,7 @@ class Renderer: fb[i] = color zb[i] = float(1.0) - def DrawLine2D(self, x0: int, y0: int, x1: int, y1: int, col: t.CUInt32T): + def DrawLine2D(self, x0: int, y0: int, x1: int, y1: int, col: uint32): fb: UINT32PTR = self._fb w: int = self._w; h: int = self._h dx: int = abs(x1-x0); dy: int = abs(y1-y0) @@ -136,7 +136,7 @@ class Renderer: if e2 > -dy: err -= dy; x0 += sx if e2 < dx: err += dx; y0 += sy - def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: t.CUInt32T): + def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: uint32): if v0.z < float(0.0) or v1.z < float(0.0) or v2.z < float(0.0): return if (v0.x > float(10.0) or v0.x < float(-10.0) or v0.y > float(10.0) or v0.y < float(-10.0) or v1.x > float(10.0) or v1.x < float(-10.0) or v1.y > float(10.0) or v1.y < float(-10.0) or @@ -179,7 +179,7 @@ class Renderer: fb[idx] = col dxP += float(1.0) - def DrawGlowDot(self, x: float, y: float, radius: float, core_col: t.CUInt32T, intensity: float): + def DrawGlowDot(self, x: float, y: float, radius: float, core_col: uint32, intensity: float): fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h r: int = int(radius) + 4 ix: int = int(x); iy: int = int(y) @@ -196,13 +196,13 @@ class Renderer: fade: float = 1.0 - (dist - radius) / 4.0 self.BlendPixel(px, py, core_col, intensity * fade * 0.5) - def BlendPixel(self, x: int, y: int, col: t.CUInt32T, alpha: float): + def BlendPixel(self, x: int, y: int, col: uint32, alpha: float): if alpha <= 0.0: return fb: UINT32PTR = self._fb; w: int = self._w; h: int = self._h if x < 0 or x >= w or y < 0 or y >= h: return idx: int = y * w + x - bg: t.CUInt32T = fb[idx] + bg: uint32 = fb[idx] bg_b: int = bg & 0xFF; bg_g: int = (bg >> 8) & 0xFF; bg_r: int = (bg >> 16) & 0xFF f_b: int = col & 0xFF; f_g: int = (col >> 8) & 0xFF; f_r: int = (col >> 16) & 0xFF @@ -240,7 +240,7 @@ class Scene3D: cubeMVP: Mat4 = Mat4_Mul(vp, Mat4_Translate(cubeX, 0, 0)) self._DrawCube(cubeMVP, COLOR_RGB(180, 180, 180)) - colors: t.CArray[t.CUInt32T, 4] = [COLOR_RGB(255,50,50), COLOR_RGB(50,50,255), COLOR_RGB(255,255,50), COLOR_RGB(50,255,255)] + colors: t.CArray[uint32, 4] = [COLOR_RGB(255,50,50), COLOR_RGB(50,50,255), COLOR_RGB(255,255,50), COLOR_RGB(50,255,255)] for i in range(4): a: float = time * float(1.5) + i * (PI / float(2.0)); r: float = float(3.0) pos: Vec3 = Vec3(vipermath.cosf(a) * r + cubeX, 0, vipermath.sinf(a) * r) @@ -259,7 +259,7 @@ class Scene3D: self.renderer.DrawLine2D(prev_x, prev_y, cx, cy, COLOR_RGB(0, 255, 100)) prev_x = cx; prev_y = cy - def _DrawCube(self, mvp: Mat4, col: t.CUInt32T): + def _DrawCube(self, mvp: Mat4, col: uint32): v: t.CArray[Vec3, 8] = [ Vec3(-1, -1, -1), Vec3(-1, -1, 1), Vec3(-1, 1, -1), Vec3(-1, 1, 1), Vec3( 1, -1, -1), Vec3( 1, -1, 1), Vec3( 1, 1, -1), Vec3( 1, 1, 1) @@ -271,7 +271,7 @@ class Scene3D: ] for i in range(12): self.renderer.DrawTriangle(v[faces[i][0]], v[faces[i][1]], v[faces[i][2]], col) - def _DrawSphere(self, mvp: Mat4, center: Vec3, radius: float, col: t.CUInt32T): + def _DrawSphere(self, mvp: Mat4, center: Vec3, radius: float, col: uint32): step_pi: float = PI / SPHERE_STACKS; step_2pi: float = float(2.0) * PI / SPHERE_SLICES for i in range(SPHERE_STACKS): for j in range(SPHERE_SLICES): @@ -296,9 +296,9 @@ class Scene3D: y01: float = vipermath.sinf(x0) * vipermath.cosf(z1) * scale; y11: float = vipermath.sinf(x1) * vipermath.cosf(z1) * scale t1: float = (y00 / scale + float(1.0)) * float(0.5); r1: int = int(50 + 205 * t1); g1: int = int(80 + 120 * vipermath.sinf(t1 * PI)); b1: int = int(255 - 205 * t1) - col1: t.CUInt32T = COLOR_RGB(255 if (r1 > 255) else (0 if (r1 < 0) else r1), 255 if (g1 > 255) else (0 if (g1 < 0) else g1), 255 if (b1 > 255) else (0 if (b1 < 0) else b1)) + col1: uint32 = COLOR_RGB(255 if (r1 > 255) else (0 if (r1 < 0) else r1), 255 if (g1 > 255) else (0 if (g1 < 0) else g1), 255 if (b1 > 255) else (0 if (b1 < 0) else b1)) t2: float = (y11 / scale + float(1.0)) * float(0.5); r2: int = int(50 + 205 * t2); g2: int = int(80 + 120 * vipermath.sinf(t2 * PI)); b2: int = int(255 - 205 * t2) - col2: t.CUInt32T = COLOR_RGB(255 if (r2 > 255) else (0 if (r2 < 0) else r2), 255 if (g2 > 255) else (0 if (g2 < 0) else g2), 255 if (b2 > 255) else (0 if (b2 < 0) else b2)) + col2: uint32 = COLOR_RGB(255 if (r2 > 255) else (0 if (r2 < 0) else r2), 255 if (g2 > 255) else (0 if (g2 < 0) else g2), 255 if (b2 > 255) else (0 if (b2 < 0) else b2)) v00: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y00, z0)); v10: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y10, z0)) v01: Vec3 = Mat4_MulVec(mvp, Vec3(x0, y01, z1)); v11: Vec3 = Mat4_MulVec(mvp, Vec3(x1, y11, z1)) diff --git a/VKernel/Kernel/drivers/video/vesafb/vga.vp b/VKernel/Kernel/drivers/video/vesafb/vga.vp index ef6206c..074009c 100644 --- a/VKernel/Kernel/drivers/video/vesafb/vga.vp +++ b/VKernel/Kernel/drivers/video/vesafb/vga.vp @@ -19,7 +19,7 @@ DEFAULT_CHAR: t.CDefine = 0 # 非ASCII字符的默认替换字符 SERIAL_PORT: t.CDefine = 0x3F8 # 串口调试端口地址 # 8x16字符点阵字库 (每个字符16字节,共256个字符) -font: t.CArray[t.CArray[t.CUInt8T, 16], 256] = [ +font: t.CArray[t.CArray[uint8, 16], 256] = [ # 字符编号 0x00 - 0x0F {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, # 0x00 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, # 0x01 @@ -312,7 +312,7 @@ font: t.CArray[t.CArray[t.CUInt8T, 16], 256] = [ @t.Object class _VGAScreenDriver: # 帧缓冲区信息 - fbv: t.CVoid | t.CPtr # = None + fbv: t.CPtr # = None fb: t.CUnsignedChar | t.CPtr # = None fw: int # = 800 fh: int # = 600 @@ -321,7 +321,7 @@ class _VGAScreenDriver: BgColor: t.CUnsignedInt = 0xFF000080 # RGBA: 不透明深蓝色 # 初始化VGA驱动 - def __init__(self, fb: t.CVoid | t.CPtr, width: int, height: int, pitch: int, format: int): + def __init__(self, fb: t.CPtr, width: int, height: int, pitch: int, format: int): # 先做参数合法性检查 if fb is None or width <= 0 or height <= 0 or pitch <= 0: return # 更新帧缓冲区参数 @@ -350,7 +350,7 @@ class _VGAScreenDriver: testY: int = 0 offset: int = testY * self.fp + testX * 4 # 保存测试位置原始像素值,避免污染屏幕 - OriginalPixel: t.CUInt32T = c.Deref(t.CUInt32T(fb + offset, t.CPtr)) + OriginalPixel: uint32 = c.Deref(uint32(fb + offset, t.CPtr)) # 写入测试颜色:青色 (RGBA逻辑值: 0xFF00FFFF) fb[offset + 0] = 0xFF # B fb[offset + 1] = 0xFF # G @@ -362,7 +362,7 @@ class _VGAScreenDriver: r: t.CUnsignedChar = fb[offset + 2] # t.CVoid(fb[offset + 3]) # 忽略Alpha # 恢复原始像素 - c.Set(c.Deref(t.CUInt32T(fb + offset, t.CPtr)), OriginalPixel) + c.Set(c.Deref(uint32(fb + offset, t.CPtr)), OriginalPixel) # 判定颜色格式 if r == 0x00 and g == 0xFF and b == 0xFF: self.ColorFormat = __ColorFormat.ColorFormat_BGRA elif r == 0xFF and g == 0xFF and b == 0x00: self.ColorFormat = __ColorFormat.ColorFormat_RGBA @@ -370,7 +370,7 @@ class _VGAScreenDriver: # 设置像素颜色 - 统一接口,输入为RGBA逻辑颜色 # color格式: 0xAARRGGBB (Alpha, Red, Green, Blue) - def SetPixel(self, x: int, y: int, color: t.CUInt32T): + def SetPixel(self, x: int, y: int, color: uint32): fb: t.CUnsignedChar | t.CPtr = self.fb if fb is None: return if x < 0 or x >= self.fw or y < 0 or y >= self.fh: return @@ -408,7 +408,7 @@ class _VGAScreenDriver: fb[offset + 3] = a # 清除屏幕 - 优化循环效率,减少函数调用开销 - def ClearScreen(self, color: t.CUInt32T): + def ClearScreen(self, color: uint32): fb: t.CUnsignedChar | t.CPtr = self.fb fp: int = self.fp if fb is None: return @@ -458,7 +458,7 @@ class _VGAScreenDriver: ch: t.CUnsignedChar = t.CUnsignedChar(cr) if ch >= 128: ch = DEFAULT_CHAR # 预解析背景色Alpha,避免内层循环重复计算 - bg_alpha: t.CUInt8T = (bgcolor >> 24) & 0xFF + bg_alpha: uint8 = (bgcolor >> 24) & 0xFF draw_bg: int = (bg_alpha != 0) # 背景是否需要绘制 # 渲染8x16点阵字符 for fy in range(FONT_HEIGHT): diff --git a/VKernel/Kernel/execrunner/elf.vp b/VKernel/Kernel/execrunner/elf.vp index 3275859..d46882d 100644 --- a/VKernel/Kernel/execrunner/elf.vp +++ b/VKernel/Kernel/execrunner/elf.vp @@ -1,803 +1,816 @@ -import drivers.serial.uart.serial as serial -import drivers.fs.fat32.fat32 as fat32 -import drivers.fs.fat32.fat32_types as fat32_types -import drivers.core.cpu.cpu as cpu -import mm.mm as mm -import paging.paging as paging -import sched.process as proc -import sched.sched as sched -import intr.gdt as gdt -import t, c - - -# Do NOT import KERN_STACK_SIZE/USER_STACK_SIZE from process - CDefine cross-module import is broken -# Redefine them here to ensure correct values -KERN_STACK_SIZE: t.CDefine = 8192 -USER_STACK_SIZE: t.CDefine = 65536 -import viperlib -import string -import asm -import t, c - -ELFMAG0: t.CDefine = 0x7F -ELFMAG1: t.CDefine = 0x45 -ELFMAG2: t.CDefine = 0x4C -ELFMAG3: t.CDefine = 0x46 -ELFCLASS64: t.CDefine = 2 -ELFDATA2LSB: t.CDefine = 1 -ET_EXEC: t.CDefine = 2 -ET_DYN: t.CDefine = 3 -EM_X86_64: t.CDefine = 62 -PT_LOAD: t.CDefine = 1 -PT_DYNAMIC: t.CDefine = 2 -PF_X: t.CDefine = 1 -PF_W: t.CDefine = 2 -PF_R: t.CDefine = 4 -DT_NULL: t.CDefine = 0 -DT_HASH: t.CDefine = 4 -DT_STRTAB: t.CDefine = 5 -DT_SYMTAB: t.CDefine = 6 -DT_STRSZ: t.CDefine = 10 -DT_SYMENT: t.CDefine = 11 -DT_RELA: t.CDefine = 7 -DT_RELASZ: t.CDefine = 8 -DT_RELAENT: t.CDefine = 9 -DT_PLTRELSZ: t.CDefine = 2 -DT_JMPREL: t.CDefine = 23 -R_X86_64_64: t.CDefine = 1 -R_X86_64_GLOB_DAT: t.CDefine = 6 -R_X86_64_JUMP_SLOT: t.CDefine = 7 -R_X86_64_RELATIVE: t.CDefine = 8 -STB_GLOBAL: t.CDefine = 1 -STB_WEAK: t.CDefine = 2 - -@c.Attribute(t.attr.packed) -class Elf64_Ehdr: - e_ident: t.CArray[t.CUInt8T, 16] - e_type: t.CUInt16T - e_machine: t.CUInt16T - e_version: t.CUInt32T - e_entry: t.CUInt64T - e_phoff: t.CUInt64T - e_shoff: t.CUInt64T - e_flags: t.CUInt32T - e_ehsize: t.CUInt16T - e_phentsize: t.CUInt16T - e_phnum: t.CUInt16T - e_shentsize: t.CUInt16T - e_shnum: t.CUInt16T - e_shstrndx: t.CUInt16T - -@c.Attribute(t.attr.packed) -class Elf64_Phdr: - p_type: t.CUInt32T - p_flags: t.CUInt32T - p_offset: t.CUInt64T - p_vaddr: t.CUInt64T - p_paddr: t.CUInt64T - p_filesz: t.CUInt64T - p_memsz: t.CUInt64T - p_align: t.CUInt64T - -MAX_PHDRS: t.CDefine = 16 - -@c.Attribute(t.attr.packed) -class Elf64_Shdr: - sh_name: t.CUInt32T - sh_type: t.CUInt32T - sh_flags: t.CUInt64T - sh_addr: t.CUInt64T - sh_offset: t.CUInt64T - sh_size: t.CUInt64T - sh_link: t.CUInt32T - sh_info: t.CUInt32T - sh_addralign: t.CUInt64T - sh_entsize: t.CUInt64T - -@c.Attribute(t.attr.packed) -class Elf64_Sym: - st_name: t.CUInt32T - st_info: t.CUInt8T - st_other: t.CUInt8T - st_shndx: t.CUInt16T - st_value: t.CUInt64T - st_size: t.CUInt64T - -@c.Attribute(t.attr.packed) -class Elf64_Rela: - r_offset: t.CUInt64T - r_info: t.CUInt64T - r_addend: t.CInt64T - -@c.Attribute(t.attr.packed) -class Elf64_Dyn: - d_tag: t.CInt64T - d_val: t.CUInt64T - -MAX_SHDRS: t.CDefine = 64 -MAX_DYNS: t.CDefine = 64 -MAX_RELAS: t.CDefine = 256 - -def load_elf(path: t.CConst | str, do_map: t.CInt = 1) -> t.CVoid | t.CPtr: - fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) - if fp is None: - err: t.CUInt32T = fat32.last_error() - eb: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(eb), 64, "[elf] failed to open file err=%d\n", err) - serial.puts(eb) - return None - - ehdr_buf: t.CArray[t.CUInt8T, 64] - string.memset(c.Addr(ehdr_buf), 0, 64) - read_len: t.CUInt32T = fat32.read(fp, c.Addr(ehdr_buf), 64) - # [DIAG] read_len 实际值 + call 后 RAX 快照:区分"call 返回错"(rl=0 rax=0) - # vs "store 后 RAX 被覆盖"(rl=0 rax=64) - _rax_v2: t.CUInt64T = 0 - c.Asm(f"""mov {c.AsmOut(_rax_v2, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - _dbrl: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbrl), 96, "[elf] rl=%lu rax=0x%lx\n", read_len, _rax_v2) - serial.puts(c.Addr(_dbrl)) - if read_len < 64: - serial.puts("[elf] failed to read ehdr\n") - fat32.close(fp) - return None - - ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf) - - if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3: - serial.puts("[elf] bad magic\n") - # [DIAG] 一次性定位 bad magic:dump ehdr_buf 前 16 字节 + read_len, - # 区分全 0(read 未写)/ 目录数据(sector 错)/ 垃圾(seek 或缓冲错)。 - _dbg_mg: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbg_mg), 120, - "[elf] mg=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu fp=%lu/%lu/%lu/%lu\n", - ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3], - ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7], - ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11], - ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15], - read_len, fp.first_cluster, fp.current_cluster, fp.file_pos, fp.file_size) - serial.puts(c.Addr(_dbg_mg)) - fat32.close(fp) - return None - - if ehdr.e_ident[4] != ELFCLASS64: - serial.puts("[elf] not ELF64\n") - fat32.close(fp) - return None - - if ehdr.e_ident[5] != ELFDATA2LSB: - serial.puts("[elf] not little-endian\n") - fat32.close(fp) - return None - - if ehdr.e_type != ET_EXEC and ehdr.e_type != ET_DYN: - serial.puts("[elf] not ET_EXEC or ET_DYN\n") - fat32.close(fp) - return None - - if ehdr.e_machine != EM_X86_64: - serial.puts("[elf] not x86_64\n") - # [DIAG] e_machine 错:dump ehdr 前 24 字节(read_len=64 正确但内容错) - _dbg_em: t.CArray[t.CChar, 128] - viperlib.snprintf(c.Addr(_dbg_em), 128, - "[elf] ehdr=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu\n", - ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3], - ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7], - ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11], - ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15], - ehdr_buf[16], ehdr_buf[17], ehdr_buf[18], ehdr_buf[19], read_len) - serial.puts(c.Addr(_dbg_em)) - fat32.close(fp) - return None - - entry_point: t.CUInt64T = ehdr.e_entry - phoff: t.CUInt64T = ehdr.e_phoff - phentsize: t.CUInt16T = ehdr.e_phentsize - phnum: t.CUInt16T = ehdr.e_phnum - - if phentsize == 0 or phnum == 0 or phnum > MAX_PHDRS: - serial.puts("[elf] invalid phdr count\n") - fat32.close(fp) - return None - - cr: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(cr), 80, "[elf] entry=0x%lx phoff=%lu phentsize=%u phnum=%u\n", entry_point, phoff, phentsize, phnum) - serial.puts(cr) - - phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS] - string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56) - - for pi in range(phnum): - phdr_off: t.CUInt64T = phoff + t.CUInt64T(pi) * t.CUInt64T(phentsize) - fat32.seek(fp, t.CUInt32T(phdr_off)) - fat32.read(fp, c.Addr(phdr_bufs[pi]), 56) - - found_load: t.CInt = 0 - lowest_vaddr: t.CUInt64T = 0 - highest_vaddr_end: t.CUInt64T = 0 - for pi in range(phnum): - if phdr_bufs[pi].p_type == PT_LOAD: - seg_end: t.CUInt64T = phdr_bufs[pi].p_vaddr + phdr_bufs[pi].p_memsz - if found_load == 0: - lowest_vaddr = phdr_bufs[pi].p_vaddr - highest_vaddr_end = seg_end - found_load = 1 - else: - if phdr_bufs[pi].p_vaddr < lowest_vaddr: - lowest_vaddr = phdr_bufs[pi].p_vaddr - if seg_end > highest_vaddr_end: - highest_vaddr_end = seg_end - - if found_load == 0: - serial.puts("[elf] no LOAD segments\n") - fat32.close(fp) - return None - - total_memsz: t.CUInt64T = highest_vaddr_end - lowest_vaddr - total_pages: t.CUInt64T = (total_memsz + 0xFFF) // 0x1000 - - cr2: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(cr2), 80, "[elf] vaddr 0x%lx-0x%lx pages=%lu\n", lowest_vaddr, highest_vaddr_end, total_pages) - serial.puts(cr2) - - raw_alloc: t.CVoid | t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000) - _db_ra: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_db_ra), 80, "[elf] malloc ret raw_alloc=0x%lx\n", t.CUInt64T(raw_alloc)) - serial.puts(_db_ra) - if not raw_alloc: - serial.puts("[elf] malloc failed\n") - fat32.close(fp) - return None - - phys_base_aligned: t.CUInt64T = (t.CUInt64T(raw_alloc) + t.CUInt64T(0xFFF)) & ~t.CUInt64T(0xFFF) - phys_base: t.CVoid | t.CPtr = t.CVoid(phys_base_aligned, t.CPtr) - - string.memset(phys_base, 0, total_pages * 0x1000) - - for pi in range(phnum): - if phdr_bufs[pi].p_type == PT_LOAD: - vaddr: t.CUInt64T = phdr_bufs[pi].p_vaddr - file_off: t.CUInt64T = phdr_bufs[pi].p_offset - filesz: t.CUInt64T = phdr_bufs[pi].p_filesz - memsz: t.CUInt64T = phdr_bufs[pi].p_memsz - dest_off: t.CUInt64T = vaddr - lowest_vaddr - dest: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(phys_base) + dest_off, t.CPtr) - - if filesz > 0: - fat32.seek(fp, t.CUInt32T(file_off)) - fat32.read(fp, dest, t.CUInt32T(filesz)) - - if memsz > filesz: - bss_start: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(dest) + filesz, t.CPtr) - bss_len: t.CUInt64T = memsz - filesz - string.memset(bss_start, 0, bss_len) - - fat32.close(fp) - - virt_page_start: t.CUInt64T = lowest_vaddr & ~t.CUInt64T(0xFFF) - phys_page_start: t.CUInt64T = t.CUInt64T(phys_base) & ~t.CUInt64T(0xFFF) - map_end: t.CUInt64T = (highest_vaddr_end + 0xFFF) & ~t.CUInt64T(0xFFF) - num_map_pages: t.CUInt64T = (map_end - virt_page_start) // 0x1000 - - # Store mapping info for spawn_elf (used when do_map=0) - global _last_elf_phys_page_start, _last_elf_virt_page_start, _last_elf_num_map_pages - _last_elf_phys_page_start = phys_page_start - _last_elf_virt_page_start = virt_page_start - _last_elf_num_map_pages = num_map_pages - - if do_map != 0: - for mi in range(num_map_pages): - virt_addr: t.CUInt64T = virt_page_start + mi * 0x1000 - phys_addr: t.CUInt64T = phys_page_start + mi * 0x1000 - page_flags: t.CUInt64T = paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER - paging.MapPage(virt_addr, phys_addr, page_flags) - - entry_addr: t.CVoid | t.CPtr = t.CVoid(entry_point, t.CPtr) - - return entry_addr - -def run_elf(path: t.CConst | str) -> t.CInt: - entry: t.CVoid | t.CPtr = load_elf(path) - if entry is None: - serial.puts("[elf] load failed\n") - return -1 - serial.puts("[elf] jumping to entry...\n") - c.Asm(f"""call {c.AsmInp(entry, t.ASM_DESCR.REG_ANY)}""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, - t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) - serial.puts("[elf] returned from entry\n") - return 0 - -MAX_SPAWNED: t.CDefine = 8 -_elf_entries: t.CArray[t.CVoid | t.CPtr, MAX_SPAWNED] - -# User stack virtual address: top of 48-bit user space, 64KB below -USER_STACK_VTOP: t.CDefine = 0x7FFFFFE00000 - -# Globals for ELF mapping info (set by load_elf when do_map=0, used by spawn_elf -# to map ELF pages in the cloned PML4 instead of kernel PML4). -# ROOT CAUSE: previously load_elf mapped ELF vaddr (e.g. 0x400000) into the -# kernel PML4, overwriting the identity mapping of buddy system memory_block -# headers at 0x400000. This corrupted buddy metadata -> malloc failures, -# pid=0, and #GP in split_block. Fix: load_elf does NOT map; spawn_elf maps -# in the cloned PML4 after clone_for_process. -_last_elf_phys_page_start: t.CUInt64T = 0 -_last_elf_virt_page_start: t.CUInt64T = 0 -_last_elf_num_map_pages: t.CUInt64T = 0 - -def _elf_entry_wrapper(arg: t.CVoid | t.CPtr) -> t.CInt: - pid: t.CInt = t.CInt(t.CUInt64T(arg)) - _db1: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(_db1), 64, "[elf] wrapper pid=%d\n", pid) - serial.puts(_db1) - # Disable interrupts around switch_pid + MapPage + TSS setup: @pml4 is a global - # that switch_pid modifies. A timer interrupt mid-section would make the scheduler - # call switch_pid for another thread, corrupting @pml4 for our MapPage calls. - asm.cli() - proc.switch_pid(pid) - cur_p: proc.Process | t.CPtr = proc.ProcessManager.current() - entry_fn: t.CVoid | t.CPtr = cur_p.entry - # [DIAG] 定位用户进程首个指令 PF:打印 entry 实际值(PF cr2=ELF 物理区最后一页, - # 疑似 entry 被写成 phys 地址而非虚拟 0x400000)。 - _dbw: t.CArray[t.CChar, 160] - viperlib.snprintf(c.Addr(_dbw), 160, "[wrap] pid=%d cur=0x%lx ent=0x%lx ebase=0x%lx ks=0x%lx us=0x%lx\n", - pid, t.CUInt64T(cur_p), t.CUInt64T(entry_fn), cur_p.elf_base, cur_p.kern_stack, cur_p.user_stack) - serial.puts(c.Addr(_dbw)) - if entry_fn is not None: - user_stack_vtop: t.CUInt64T = USER_STACK_VTOP - us_sz: t.CUInt64T = USER_STACK_SIZE - user_stack_vbottom: t.CUInt64T = USER_STACK_VTOP - us_sz - # Physical pages of the user stack (allocated by mm.malloc, identity-mapped) - us_size: t.CUInt64T = USER_STACK_SIZE - phys_bottom: t.CUInt64T = (cur_p.user_stack - us_size) & ~t.CUInt64T(0xFFF) - # Map each page of the user stack at the virtual address with PTE_USER - num_stack_pages: t.CUInt64T = 16 # USER_STACK_SIZE(65536) / PAGE_SIZE(4096) = 16 - si: t.CUInt64T - for si in range(num_stack_pages): - vaddr: t.CUInt64T = (user_stack_vbottom & ~t.CUInt64T(0xFFF)) + si * t.CUInt64T(0x1000) - paddr: t.CUInt64T = phys_bottom + si * t.CUInt64T(0x1000) - paging.MapPage(vaddr, paddr, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) - # Set TSS RSP0 so interrupts from Ring 3 use kernel stack - gdt.set_tss_rsp0(cur_p.kern_stack) - # Set GS kernel_rsp0 for syscall entry from Ring 3 - cpu.set_kernel_rsp0(cur_p.kern_stack) - # Keep interrupts disabled until iretq: drop_to_user_mode's iretq - # will set RFLAGS.IF from the saved frame (0x202) for user mode. - # This prevents timer interrupt preemption between TSS setup and iretq. - # Drop to Ring 3 user mode via iretq - proc.drop_to_user_mode(entry_fn, user_stack_vtop, cur_p.kern_stack) - cur: proc.Process | t.CPtr = proc.ProcessManager.current() - cur.exit() - return 0 - -def spawn_elf(path: t.CConst | str) -> t.CInt: - fat32.lock() - name_start: t.CInt = 0 - si: t.CInt = 0 - while True: - ch: t.CChar = path[si] - if ch == 0: break - if ch == 47: - name_start = si + 1 - si += 1 - - lowest_vaddr: t.CUInt64T = 0 - highest_vaddr_end: t.CUInt64T = 0 - fp_scan: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) - if fp_scan is None: - serr: t.CUInt32T = fat32.last_error() - seb: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(seb), 64, "[elf] spawn scan open failed err=%d\n", serr) - serial.puts(seb) - fat32.unlock() - return -1 - if fp_scan is not None: - ehdr_buf_s: t.CArray[t.CUInt8T, 64] - string.memset(c.Addr(ehdr_buf_s), 0, 64) - fat32.read(fp_scan, c.Addr(ehdr_buf_s), 64) - ehdr_s: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf_s) - if ehdr_s.e_type == ET_EXEC or ehdr_s.e_type == ET_DYN: - phoff_s: t.CUInt64T = ehdr_s.e_phoff - phentsize_s: t.CUInt16T = ehdr_s.e_phentsize - phnum_s: t.CUInt16T = ehdr_s.e_phnum - if phentsize_s > 0 and phnum_s > 0 and phnum_s <= MAX_PHDRS: - phdr_bufs_s: t.CArray[Elf64_Phdr, MAX_PHDRS] - string.memset(c.Addr(phdr_bufs_s), 0, MAX_PHDRS * 56) - found_load_s: t.CInt = 0 - for pi_s in range(phnum_s): - fat32.seek(fp_scan, t.CUInt32T(phoff_s + t.CUInt64T(pi_s) * t.CUInt64T(phentsize_s))) - fat32.read(fp_scan, c.Addr(phdr_bufs_s[pi_s]), 56) - if phdr_bufs_s[pi_s].p_type == PT_LOAD: - seg_end_s: t.CUInt64T = phdr_bufs_s[pi_s].p_vaddr + phdr_bufs_s[pi_s].p_memsz - if found_load_s == 0: - lowest_vaddr = phdr_bufs_s[pi_s].p_vaddr - highest_vaddr_end = seg_end_s - found_load_s = 1 - else: - if phdr_bufs_s[pi_s].p_vaddr < lowest_vaddr: - lowest_vaddr = phdr_bufs_s[pi_s].p_vaddr - if seg_end_s > highest_vaddr_end: - highest_vaddr_end = seg_end_s - fat32.close(fp_scan) - - isolate_va: t.CUInt64T = lowest_vaddr - if isolate_va == 0: - isolate_va = 0x400000 - - # Load ELF to physical memory WITHOUT mapping in kernel PML4. - # do_map=0: load_elf stores mapping info in globals for spawn_elf to use. - # ROOT CAUSE FIX: previously load_elf mapped ELF vaddr (e.g. 0x400000) into - # kernel PML4, overwriting identity mapping of buddy memory_block headers. - entry: t.CVoid | t.CPtr = load_elf(path, 0) - if entry is None: - serial.puts("[elf] spawn: load failed\n") - fat32.unlock() - return -1 - - # Clone kernel PML4 (identity mapping intact, no ELF mapping yet) - proc_pml4: t.CUInt64T = paging.clone_for_process(isolate_va) - slog1: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(slog1), 80, "[elf] spawn: clone pml4=0x%lx va=0x%lx\n", proc_pml4, isolate_va) - serial.puts(slog1) - if proc_pml4 == 0: - serial.puts("[elf] spawn: clone_for_process failed\n") - fat32.unlock() - return -1 - - # Map ELF pages in the CLONED PML4 (not kernel's). - # This prevents overwriting kernel identity mapping at 0x400000 which - # would corrupt buddy system memory_block headers. - # Must disable interrupts: @pml4 global is used by MapPage and a timer - # interrupt mid-section would call switch_pid, corrupting @pml4. - asm.cli() - _kernel_cr3: t.CUInt64T = 0 - c.Asm(f"""mov {c.AsmOut(_kernel_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - c.Asm(f"mov cr3, {c.AsmInp(proc_pml4, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - paging.set_active_pml4(proc_pml4) - mi: t.CUInt64T - for mi in range(_last_elf_num_map_pages): - _va: t.CUInt64T = _last_elf_virt_page_start + mi * 0x1000 - _pa: t.CUInt64T = _last_elf_phys_page_start + mi * 0x1000 - paging.MapPage(_va, _pa, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) - c.Asm(f"mov cr3, {c.AsmInp(_kernel_cr3, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - paging.set_active_pml4(_kernel_cr3) - asm.sti() - - # path[name_start:] 切片表达式 translate_subscript 不支持 Slice(返回 None)→ - # 作为实参丢 name、entry 错位成第一参数(TPV 已修,此处指针算术双保险) - nm_ptr: t.CConst | t.CChar | t.CPtr = t.CConst(t.CUInt64T(path) + t.CUInt64T(name_start), t.CPtr) - p: proc.Process | t.CPtr = proc.ProcessManager.create_process(nm_ptr, entry) - if p is None: - serial.puts("[elf] spawn: create_process failed\n") - fat32.unlock() - return -2 - p.elf_base = t.CUInt64T(entry) - p.pml4_root = proc_pml4 - if p.pid >= 0 and p.pid < MAX_SPAWNED: - _elf_entries[p.pid] = entry - - th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(t.CPtr(_elf_entry_wrapper), t.CPtr(t.CUInt64T(p.pid)), p.pid) - if th is None: - serial.puts("[elf] spawn: create_thread failed\n") - p.exit() - fat32.unlock() - return -3 - tid: t.CInt = th.tid - p.addThread(tid) - slog: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(slog), 80, "[elf] spawn: pid=%d tid=%d entry=0x%lx pml4=0x%lx\n", p.pid, tid, t.CUInt64T(entry), p.pml4_root) - serial.puts(slog) - # [DIAG] 确认 return p.pid 的实际值(main 收到 pid=0 而此处打印 3) - _dbw2: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(_dbw2), 64, "[elf] spawn ret pid=%d\n", p.pid) - serial.puts(c.Addr(_dbw2)) - fat32.unlock() - return p.pid - -def _resolve_symbol(name: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CPtr: - nm: t.CInt = 0 - while c.Deref(name + nm) != 0: - nm += 1 - cmp_name: t.CConst | t.CChar | t.CPtr = name - cmp_len: t.CInt = nm - if nm > 9: - sha1_len2: t.CInt = 0 - for si2 in range(nm): - ch2: t.CChar = c.Deref(name + si2) - if ch2 == 46: - if sha1_len2 >= 8: - cmp_name = str(t.CUInt64T(name) + si2 + 1) - cmp_len = nm - si2 - 1 - break - if ch2 == 0: - break - if (ch2 >= 48 and ch2 <= 57) or (ch2 >= 97 and ch2 <= 102): - sha1_len2 += 1 - else: - break - if cmp_len == 11: - match: t.CInt = 1 - for i in range(cmp_len): - if c.Deref(cmp_name + i) != c.Deref("serial_puts" + i): - match = 0 - if match: - return t.CVoid(c.Addr(serial.puts), t.CPtr) - return None - -_so_strtab: t.CVoid | t.CPtr -_so_symtab: t.CVoid | t.CPtr -_so_syment: t.CUInt64T -_so_sym_count: t.CInt - -def load_so(path: t.CConst | str) -> t.CVoid | t.CPtr: - fat32.lock() - fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) - if fp is None: - serial.puts("[so] failed to open file\n") - fat32.unlock() - return None - - ehdr_buf: t.CArray[t.CUInt8T, 64] - string.memset(c.Addr(ehdr_buf), 0, 64) - read_len: t.CUInt32T = fat32.read(fp, c.Addr(ehdr_buf), 64) - if read_len < 64: - serial.puts("[so] failed to read ehdr\n") - fat32.close(fp) - fat32.unlock() - return None - - ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf) - if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3: - serial.puts("[so] bad magic\n") - fat32.close(fp) - fat32.unlock() - return None - if ehdr.e_ident[4] != ELFCLASS64: - serial.puts("[so] not ELF64\n") - fat32.close(fp) - fat32.unlock() - return None - if ehdr.e_type == ET_DYN: - pass - elif ehdr.e_type == ET_EXEC: - pass - else: - serial.puts("[so] not ET_DYN or ET_EXEC\n") - fat32.close(fp) - fat32.unlock() - return None - - phoff: t.CUInt64T = ehdr.e_phoff - phentsize: t.CUInt16T = ehdr.e_phentsize - phnum: t.CUInt16T = ehdr.e_phnum - - phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS] - string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56) - for pi in range(phnum): - phdr_off: t.CUInt64T = phoff + t.CUInt64T(pi) * t.CUInt64T(phentsize) - fat32.seek(fp, t.CUInt32T(phdr_off)) - fat32.read(fp, c.Addr(phdr_bufs[pi]), 56) - - found_load: t.CInt = 0 - lowest_vaddr: t.CUInt64T = 0 - highest_vaddr_end: t.CUInt64T = 0 - for pi in range(phnum): - if phdr_bufs[pi].p_type == PT_LOAD: - seg_end: t.CUInt64T = phdr_bufs[pi].p_vaddr + phdr_bufs[pi].p_memsz - if found_load == 0: - lowest_vaddr = phdr_bufs[pi].p_vaddr - highest_vaddr_end = seg_end - found_load = 1 - else: - if phdr_bufs[pi].p_vaddr < lowest_vaddr: - lowest_vaddr = phdr_bufs[pi].p_vaddr - if seg_end > highest_vaddr_end: - highest_vaddr_end = seg_end - - if found_load == 0: - serial.puts("[so] no LOAD segments\n") - fat32.close(fp) - fat32.unlock() - return None - - total_memsz: t.CUInt64T = highest_vaddr_end - lowest_vaddr - total_pages: t.CUInt64T = (total_memsz + 0xFFF) // 0x1000 - - so_load_addr: t.CUInt64T = 0x600000 - raw_alloc: t.CVoid | t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000) - if not raw_alloc: - serial.puts("[so] malloc failed\n") - fat32.close(fp) - fat32.unlock() - return None - - phys_base_aligned: t.CUInt64T = (t.CUInt64T(raw_alloc) + 0xFFF) & ~t.CUInt64T(0xFFF) - phys_base: t.CVoid | t.CPtr = t.CVoid(phys_base_aligned, t.CPtr) - string.memset(phys_base, 0, total_pages * 0x1000) - - for pi in range(phnum): - if phdr_bufs[pi].p_type == PT_LOAD: - vaddr: t.CUInt64T = phdr_bufs[pi].p_vaddr - file_off: t.CUInt64T = phdr_bufs[pi].p_offset - filesz: t.CUInt64T = phdr_bufs[pi].p_filesz - memsz: t.CUInt64T = phdr_bufs[pi].p_memsz - dest_off: t.CUInt64T = vaddr - lowest_vaddr - dest: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(phys_base) + dest_off, t.CPtr) - if filesz > 0: - fat32.seek(fp, t.CUInt32T(file_off)) - fat32.read(fp, dest, t.CUInt32T(filesz)) - if memsz > filesz: - bss_start: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(dest) + filesz, t.CPtr) - bss_len: t.CUInt64T = memsz - filesz - string.memset(bss_start, 0, bss_len) - - virt_page_start: t.CUInt64T = (so_load_addr + lowest_vaddr) & ~t.CUInt64T(0xFFF) - phys_page_start: t.CUInt64T = t.CUInt64T(phys_base) & ~t.CUInt64T(0xFFF) - map_end: t.CUInt64T = (so_load_addr + highest_vaddr_end + 0xFFF) & ~t.CUInt64T(0xFFF) - num_map_pages: t.CUInt64T = (map_end - virt_page_start) // 0x1000 - - for mi in range(num_map_pages): - virt_addr: t.CUInt64T = virt_page_start + mi * 0x1000 - phys_addr: t.CUInt64T = phys_page_start + mi * 0x1000 - paging.MapPage(virt_addr, phys_addr, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) - - base_vaddr: t.CUInt64T = so_load_addr + lowest_vaddr - - dyn_buf: t.CArray[Elf64_Dyn, MAX_DYNS] - string.memset(c.Addr(dyn_buf), 0, MAX_DYNS * 16) - dyn_count: t.CInt = 0 - for pi in range(phnum): - if phdr_bufs[pi].p_type == PT_DYNAMIC: - fat32.seek(fp, t.CUInt32T(phdr_bufs[pi].p_offset)) - dyn_read: t.CUInt32T = fat32.read(fp, c.Addr(dyn_buf), t.CUInt32T(phdr_bufs[pi].p_filesz)) - dyn_count = t.CInt(dyn_read) // 16 - - strtab_vaddr: t.CUInt64T = 0 - symtab_vaddr: t.CUInt64T = 0 - hash_vaddr: t.CUInt64T = 0 - syment: t.CUInt64T = 0 - rela_vaddr: t.CUInt64T = 0 - relasz: t.CUInt64T = 0 - jmprel_vaddr: t.CUInt64T = 0 - pltrelsz: t.CUInt64T = 0 - for di in range(dyn_count): - if dyn_buf[di].d_tag == DT_NULL: break - if dyn_buf[di].d_tag == DT_STRTAB: strtab_vaddr = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_SYMTAB: symtab_vaddr = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_HASH: hash_vaddr = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_SYMENT: syment = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_RELA: rela_vaddr = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_RELASZ: relasz = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_JMPREL: jmprel_vaddr = dyn_buf[di].d_val - elif dyn_buf[di].d_tag == DT_PLTRELSZ: pltrelsz = dyn_buf[di].d_val - - strtab_ptr: t.CVoid | t.CPtr = t.CVoid(strtab_vaddr + so_load_addr, t.CPtr) - symtab_ptr: t.CVoid | t.CPtr = t.CVoid(symtab_vaddr + so_load_addr, t.CPtr) - - if rela_vaddr != 0 and relasz > 0: - rela_count: t.CUInt64T = relasz // 24 - for ri in range(rela_count): - rela: Elf64_Rela | t.CPtr = t.CVoid(t.CUInt64T(rela_vaddr) + so_load_addr + ri * 24, t.CPtr) - r_type: t.CUInt32T = t.CUInt32T(rela.r_info & 0xFFFFFFFF) - r_sym: t.CUInt32T = t.CUInt32T(rela.r_info >> 32) - target_addr: t.CVoid | t.CPtr = t.CVoid(rela.r_offset + so_load_addr, t.CPtr) - if r_type == R_X86_64_RELATIVE: - val: t.CUInt64T = t.CUInt64T(rela.r_addend) + so_load_addr - string.memcpy(target_addr, c.Addr(val), 8) - elif r_type == R_X86_64_64 or r_type == R_X86_64_GLOB_DAT or r_type == R_X86_64_JUMP_SLOT: - sym: Elf64_Sym | t.CPtr = t.CVoid(t.CUInt64T(symtab_ptr) + t.CUInt64T(r_sym) * syment, t.CPtr) - sym_name: t.CConst | t.CChar | t.CPtr = t.CConst(t.CUInt64T(strtab_ptr) + sym.st_name, t.CPtr) - resolved: t.CVoid | t.CPtr = _resolve_symbol(sym_name) - if resolved is not None: - val2: t.CUInt64T = t.CUInt64T(resolved) + t.CUInt64T(rela.r_addend) - string.memcpy(target_addr, c.Addr(val2), 8) - elif sym.st_value != 0: - val3: t.CUInt64T = sym.st_value + so_load_addr + t.CUInt64T(rela.r_addend) - string.memcpy(target_addr, c.Addr(val3), 8) - - if jmprel_vaddr != 0 and pltrelsz > 0: - jmprel_count: t.CUInt64T = pltrelsz // 24 - for ji in range(jmprel_count): - rela2: Elf64_Rela | t.CPtr = t.CVoid(jmprel_vaddr + so_load_addr + ji * 24, t.CPtr) - r_type2: t.CUInt32T = t.CUInt32T(rela2.r_info & 0xFFFFFFFF) - r_sym2: t.CUInt32T = t.CUInt32T(rela2.r_info >> 32) - target2: t.CVoid | t.CPtr = t.CVoid(rela2.r_offset + so_load_addr, t.CPtr) - if r_type2 == R_X86_64_JUMP_SLOT or r_type2 == R_X86_64_GLOB_DAT: - sym2: Elf64_Sym | t.CPtr = t.CVoid(t.CUInt64T(symtab_ptr) + t.CUInt64T(r_sym2) * syment, t.CPtr) - sym_name2: t.CConst | t.CChar | t.CPtr = t.CConst(t.CUInt64T(strtab_ptr) + sym2.st_name, t.CPtr) - resolved2: t.CVoid | t.CPtr = _resolve_symbol(sym_name2) - if resolved2 is not None: - val4: t.CUInt64T = t.CUInt64T(resolved2) + t.CUInt64T(rela2.r_addend) - string.memcpy(target2, c.Addr(val4), 8) - elif sym2.st_value != 0: - val5: t.CUInt64T = sym2.st_value + so_load_addr + t.CUInt64T(rela2.r_addend) - string.memcpy(target2, c.Addr(val5), 8) - else: - cr3: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(cr3), 80, "[so] WARN: unresolved PLT sym offset=%lu\n", sym2.st_name) - serial.puts(cr3) - - fat32.close(fp) - - global _so_strtab, _so_symtab, _so_syment, _so_sym_count - - _so_strtab = strtab_ptr - _so_symtab = symtab_ptr - _so_syment = syment - _so_sym_count = 0 - if hash_vaddr != 0: - hash_ptr: t.CVoid | t.CPtr = t.CVoid(hash_vaddr + so_load_addr, t.CPtr) - nchain: t.CUInt32T = c.Deref(t.CVoid(t.CUInt64T(hash_ptr) + 4, t.CPtr)) - _so_sym_count = t.CInt(nchain) - elif syment > 0 and strtab_vaddr > symtab_vaddr and symtab_vaddr != 0: - sym_tab_size: t.CUInt64T = strtab_vaddr - symtab_vaddr - _so_sym_count = t.CInt(sym_tab_size // syment) - - cr: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(cr), 80, "[so] loaded at 0x%lx\n", base_vaddr) - serial.puts(cr) - - fat32.unlock() - return t.CVoid(base_vaddr, t.CPtr) - -def get_so_symbol(so_base: t.CVoid | t.CPtr, name: t.CConst | t.CChar | t.CPtr, so_path: t.CConst | t.CChar | t.CPtr) -> t.CVoid | t.CPtr: - if _so_symtab is None or _so_strtab is None or _so_syment == 0: - return None - if name is None: - return None - for symi in range(_so_sym_count): - sb2: Elf64_Sym | t.CPtr = t.CVoid(t.CUInt64T(_so_symtab) + t.CUInt64T(symi) * _so_syment, t.CPtr) - if sb2.st_value != 0 and sb2.st_shndx != 0: - sym_name_off2: t.CUInt32T = sb2.st_name - cmp_off2: t.CUInt32T = sym_name_off2 - match2: t.CInt = 0 - ni2: t.CInt = 0 - while True: - sc3: t.CChar = c.Deref(t.CVoid(t.CUInt64T(_so_strtab) + cmp_off2 + ni2, t.CPtr)) - nc3: t.CChar = c.Deref(name + ni2) - if sc3 != nc3: - break - if sc3 == 0: - match2 = 1 - break - ni2 += 1 - if match2 == 0: - dot_pos3: t.CUInt32T = sym_name_off2 - is_sha1_2: t.CInt = 0 - sha1_len_2: t.CUInt32T = 0 - while True: - dc4: t.CChar = c.Deref(t.CVoid(t.CUInt64T(_so_strtab) + dot_pos3, t.CPtr)) - if dc4 == 46: - if sha1_len_2 >= 8: - is_sha1_2 = 1 - break - if dc4 == 0: - break - if (dc4 >= 48 and dc4 <= 57) or (dc4 >= 97 and dc4 <= 102): - sha1_len_2 += 1 - else: - break - dot_pos3 += 1 - if is_sha1_2: - cmp_off2 = dot_pos3 + 1 - match2 = 1 - ni2 = 0 - while True: - sc4: t.CChar = c.Deref(t.CVoid(t.CUInt64T(_so_strtab) + cmp_off2 + ni2, t.CPtr)) - nc4: t.CChar = c.Deref(name + ni2) - if sc4 != nc4: - match2 = 0 - break - if sc4 == 0: - break - ni2 += 1 - if match2: - result_addr: t.CUInt64T = t.CUInt64T(so_base) + sb2.st_value - dbg2: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(dbg2), 80, "[so] found '%s' at 0x%lx\n", t.CVoid(t.CUInt64T(_so_strtab) + sym_name_off2, t.CPtr), result_addr) - serial.puts(dbg2) - return t.CVoid(result_addr, t.CPtr) - serial.puts("[so] symbol not found\n") - return None +import drivers.serial.uart.serial as serial +import drivers.fs.fat32.fat32 as fat32 +import drivers.fs.fat32.fat32_types as fat32_types +import drivers.core.cpu.cpu as cpu +import mm.mm as mm +import paging.paging as paging +import sched.process as proc +import sched.sched as sched +import intr.gdt as gdt +import t, c + + +# Do NOT import KERN_STACK_SIZE/USER_STACK_SIZE from process - CDefine cross-module import is broken +# Redefine them here to ensure correct values +KERN_STACK_SIZE: t.CDefine = 8192 +USER_STACK_SIZE: t.CDefine = 65536 +import viperlib +import string +import asm +import t, c + +ELFMAG0: t.CDefine = 0x7F +ELFMAG1: t.CDefine = 0x45 +ELFMAG2: t.CDefine = 0x4C +ELFMAG3: t.CDefine = 0x46 +ELFCLASS64: t.CDefine = 2 +ELFDATA2LSB: t.CDefine = 1 +ET_EXEC: t.CDefine = 2 +ET_DYN: t.CDefine = 3 +EM_X86_64: t.CDefine = 62 +PT_LOAD: t.CDefine = 1 +PT_DYNAMIC: t.CDefine = 2 +PF_X: t.CDefine = 1 +PF_W: t.CDefine = 2 +PF_R: t.CDefine = 4 +DT_NULL: t.CDefine = 0 +DT_HASH: t.CDefine = 4 +DT_STRTAB: t.CDefine = 5 +DT_SYMTAB: t.CDefine = 6 +DT_STRSZ: t.CDefine = 10 +DT_SYMENT: t.CDefine = 11 +DT_RELA: t.CDefine = 7 +DT_RELASZ: t.CDefine = 8 +DT_RELAENT: t.CDefine = 9 +DT_PLTRELSZ: t.CDefine = 2 +DT_JMPREL: t.CDefine = 23 +R_X86_64_64: t.CDefine = 1 +R_X86_64_GLOB_DAT: t.CDefine = 6 +R_X86_64_JUMP_SLOT: t.CDefine = 7 +R_X86_64_RELATIVE: t.CDefine = 8 +STB_GLOBAL: t.CDefine = 1 +STB_WEAK: t.CDefine = 2 + +@c.Attribute(t.attr.packed) +class Elf64_Ehdr: + e_ident: t.CArray[uint8, 16] + e_type: uint16 + e_machine: uint16 + e_version: uint32 + e_entry: uint64 + e_phoff: uint64 + e_shoff: uint64 + e_flags: uint32 + e_ehsize: uint16 + e_phentsize: uint16 + e_phnum: uint16 + e_shentsize: uint16 + e_shnum: uint16 + e_shstrndx: uint16 + +@c.Attribute(t.attr.packed) +class Elf64_Phdr: + p_type: uint32 + p_flags: uint32 + p_offset: uint64 + p_vaddr: uint64 + p_paddr: uint64 + p_filesz: uint64 + p_memsz: uint64 + p_align: uint64 + +MAX_PHDRS: t.CDefine = 16 + +@c.Attribute(t.attr.packed) +class Elf64_Shdr: + sh_name: uint32 + sh_type: uint32 + sh_flags: uint64 + sh_addr: uint64 + sh_offset: uint64 + sh_size: uint64 + sh_link: uint32 + sh_info: uint32 + sh_addralign: uint64 + sh_entsize: uint64 + +@c.Attribute(t.attr.packed) +class Elf64_Sym: + st_name: uint32 + st_info: uint8 + st_other: uint8 + st_shndx: uint16 + st_value: uint64 + st_size: uint64 + +@c.Attribute(t.attr.packed) +class Elf64_Rela: + r_offset: uint64 + r_info: uint64 + r_addend: int64 + +@c.Attribute(t.attr.packed) +class Elf64_Dyn: + d_tag: int64 + d_val: uint64 + +MAX_SHDRS: t.CDefine = 64 +MAX_DYNS: t.CDefine = 64 +MAX_RELAS: t.CDefine = 256 + +def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr: + fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) + if fp is None: + err: uint32 = fat32.last_error() + eb: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(eb), 64, "[elf] failed to open file err=%d\n", err) + serial.puts(eb) + return None + + ehdr_buf: t.CArray[uint8, 64] + string.memset(c.Addr(ehdr_buf), 0, 64) + read_len: uint32 = fat32.read(fp, c.Addr(ehdr_buf), 64) + # [DIAG] read_len 实际值 + call 后 RAX 快照:区分"call 返回错"(rl=0 rax=0) + # vs "store 后 RAX 被覆盖"(rl=0 rax=64) + _rax_v2: uint64 = 0 + c.Asm(f"""mov {c.AsmOut(_rax_v2, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + _dbrl: t.CArray[t.CChar, 96] + viperlib.snprintf(c.Addr(_dbrl), 96, "[elf] rl=%lu rax=0x%lx\n", read_len, _rax_v2) + serial.puts(c.Addr(_dbrl)) + if read_len < 64: + serial.puts("[elf] failed to read ehdr\n") + fat32.close(fp) + return None + + ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf) + + if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3: + serial.puts("[elf] bad magic\n") + # [DIAG] 一次性定位 bad magic:dump ehdr_buf 前 16 字节 + read_len, + # 区分全 0(read 未写)/ 目录数据(sector 错)/ 垃圾(seek 或缓冲错)。 + _dbg_mg: t.CArray[t.CChar, 120] + viperlib.snprintf(c.Addr(_dbg_mg), 120, + "[elf] mg=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu fp=%lu/%lu/%lu/%lu\n", + ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3], + ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7], + ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11], + ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15], + read_len, fp.first_cluster, fp.current_cluster, fp.file_pos, fp.file_size) + serial.puts(c.Addr(_dbg_mg)) + fat32.close(fp) + return None + + if ehdr.e_ident[4] != ELFCLASS64: + serial.puts("[elf] not ELF64\n") + fat32.close(fp) + return None + + if ehdr.e_ident[5] != ELFDATA2LSB: + serial.puts("[elf] not little-endian\n") + fat32.close(fp) + return None + + if ehdr.e_type != ET_EXEC and ehdr.e_type != ET_DYN: + serial.puts("[elf] not ET_EXEC or ET_DYN\n") + fat32.close(fp) + return None + + if ehdr.e_machine != EM_X86_64: + serial.puts("[elf] not x86_64\n") + # [DIAG] e_machine 错:dump ehdr 前 24 字节(read_len=64 正确但内容错) + _dbg_em: t.CArray[t.CChar, 128] + viperlib.snprintf(c.Addr(_dbg_em), 128, + "[elf] ehdr=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu\n", + ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3], + ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7], + ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11], + ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15], + ehdr_buf[16], ehdr_buf[17], ehdr_buf[18], ehdr_buf[19], read_len) + serial.puts(c.Addr(_dbg_em)) + fat32.close(fp) + return None + + entry_point: uint64 = ehdr.e_entry + phoff: uint64 = ehdr.e_phoff + phentsize: uint16 = ehdr.e_phentsize + phnum: uint16 = ehdr.e_phnum + + if phentsize == 0 or phnum == 0 or phnum > MAX_PHDRS: + serial.puts("[elf] invalid phdr count\n") + fat32.close(fp) + return None + + cr: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(cr), 80, "[elf] entry=0x%lx phoff=%lu phentsize=%u phnum=%u\n", entry_point, phoff, phentsize, phnum) + serial.puts(cr) + + phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS] + string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56) + + for pi in range(phnum): + phdr_off: uint64 = phoff + uint64(pi) * uint64(phentsize) + fat32.seek(fp, uint32(phdr_off)) + fat32.read(fp, c.Addr(phdr_bufs[pi]), 56) + + found_load: int = 0 + lowest_vaddr: uint64 = 0 + highest_vaddr_end: uint64 = 0 + for pi in range(phnum): + if phdr_bufs[pi].p_type == PT_LOAD: + seg_end: uint64 = phdr_bufs[pi].p_vaddr + phdr_bufs[pi].p_memsz + if found_load == 0: + lowest_vaddr = phdr_bufs[pi].p_vaddr + highest_vaddr_end = seg_end + found_load = 1 + else: + if phdr_bufs[pi].p_vaddr < lowest_vaddr: + lowest_vaddr = phdr_bufs[pi].p_vaddr + if seg_end > highest_vaddr_end: + highest_vaddr_end = seg_end + + if found_load == 0: + serial.puts("[elf] no LOAD segments\n") + fat32.close(fp) + return None + + total_memsz: uint64 = highest_vaddr_end - lowest_vaddr + total_pages: uint64 = (total_memsz + 0xFFF) // 0x1000 + + cr2: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(cr2), 80, "[elf] vaddr 0x%lx-0x%lx pages=%lu\n", lowest_vaddr, highest_vaddr_end, total_pages) + serial.puts(cr2) + + raw_alloc: t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000) + _db_ra: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(_db_ra), 80, "[elf] malloc ret raw_alloc=0x%lx\n", uint64(raw_alloc)) + serial.puts(_db_ra) + if not raw_alloc: + serial.puts("[elf] malloc failed\n") + fat32.close(fp) + return None + + phys_base_aligned: uint64 = (uint64(raw_alloc) + uint64(0xFFF)) & ~uint64(0xFFF) + phys_base: t.CPtr = t.CVoid(phys_base_aligned, t.CPtr) + + string.memset(phys_base, 0, total_pages * 0x1000) + + for pi in range(phnum): + if phdr_bufs[pi].p_type == PT_LOAD: + vaddr: uint64 = phdr_bufs[pi].p_vaddr + file_off: uint64 = phdr_bufs[pi].p_offset + filesz: uint64 = phdr_bufs[pi].p_filesz + memsz: uint64 = phdr_bufs[pi].p_memsz + dest_off: uint64 = vaddr - lowest_vaddr + dest: t.CPtr = t.CVoid(uint64(phys_base) + dest_off, t.CPtr) + + if filesz > 0: + fat32.seek(fp, uint32(file_off)) + fat32.read(fp, dest, uint32(filesz)) + + if memsz > filesz: + bss_start: t.CPtr = t.CVoid(uint64(dest) + filesz, t.CPtr) + bss_len: uint64 = memsz - filesz + string.memset(bss_start, 0, bss_len) + + fat32.close(fp) + + virt_page_start: uint64 = lowest_vaddr & ~uint64(0xFFF) + phys_page_start: uint64 = uint64(phys_base) & ~uint64(0xFFF) + map_end: uint64 = (highest_vaddr_end + 0xFFF) & ~uint64(0xFFF) + num_map_pages: uint64 = (map_end - virt_page_start) // 0x1000 + + # Store mapping info for spawn_elf (used when do_map=0) + global _last_elf_phys_page_start, _last_elf_virt_page_start, _last_elf_num_map_pages + _last_elf_phys_page_start = phys_page_start + _last_elf_virt_page_start = virt_page_start + _last_elf_num_map_pages = num_map_pages + + if do_map != 0: + for mi in range(num_map_pages): + virt_addr: uint64 = virt_page_start + mi * 0x1000 + phys_addr: uint64 = phys_page_start + mi * 0x1000 + page_flags: uint64 = paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER + paging.MapPage(virt_addr, phys_addr, page_flags) + + entry_addr: t.CPtr = t.CVoid(entry_point, t.CPtr) + + return entry_addr + +def run_elf(path: t.CConst | str) -> int: + entry: t.CPtr = load_elf(path) + if entry is None: + serial.puts("[elf] load failed\n") + return -1 + serial.puts("[elf] jumping to entry...\n") + c.Asm(f"""call {c.AsmInp(entry, t.ASM_DESCR.REG_ANY)}""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, + t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, + t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + serial.puts("[elf] returned from entry\n") + return 0 + +MAX_SPAWNED: t.CDefine = 8 +_elf_entries: t.CArray[t.CPtr, MAX_SPAWNED] + +# User stack virtual address: top of 48-bit user space, 64KB below +USER_STACK_VTOP: t.CDefine = 0x7FFFFFE00000 + +# Globals for ELF mapping info (set by load_elf when do_map=0, used by spawn_elf +# to map ELF pages in the cloned PML4 instead of kernel PML4). +# ROOT CAUSE: previously load_elf mapped ELF vaddr (e.g. 0x400000) into the +# kernel PML4, overwriting the identity mapping of buddy system memory_block +# headers at 0x400000. This corrupted buddy metadata -> malloc failures, +# pid=0, and #GP in split_block. Fix: load_elf does NOT map; spawn_elf maps +# in the cloned PML4 after clone_for_process. +_last_elf_phys_page_start: uint64 = 0 +_last_elf_virt_page_start: uint64 = 0 +_last_elf_num_map_pages: uint64 = 0 + +def _elf_entry_wrapper(arg: t.CPtr) -> int: + pid: int = int(uint64(arg)) + _db1: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(_db1), 64, "[elf] wrapper pid=%d\n", pid) + serial.puts(_db1) + # Disable interrupts around switch_pid + MapPage + TSS setup: @pml4 is a global + # that switch_pid modifies. A timer interrupt mid-section would make the scheduler + # call switch_pid for another thread, corrupting @pml4 for our MapPage calls. + asm.cli() + proc.switch_pid(pid) + cur_p: proc.Process | t.CPtr = proc.ProcessManager.current() + entry_fn: t.CPtr = cur_p.entry + # [DIAG] 定位用户进程首个指令 PF:打印 entry 实际值(PF cr2=ELF 物理区最后一页, + # 疑似 entry 被写成 phys 地址而非虚拟 0x400000)。 + _dbw: t.CArray[t.CChar, 160] + viperlib.snprintf(c.Addr(_dbw), 160, "[wrap] pid=%d cur=0x%lx ent=0x%lx ebase=0x%lx ks=0x%lx us=0x%lx\n", + pid, uint64(cur_p), uint64(entry_fn), cur_p.elf_base, cur_p.kern_stack, cur_p.user_stack) + serial.puts(c.Addr(_dbw)) + if entry_fn is not None: + user_stack_vtop: uint64 = USER_STACK_VTOP + us_sz: uint64 = USER_STACK_SIZE + user_stack_vbottom: uint64 = USER_STACK_VTOP - us_sz + # Physical pages of the user stack (allocated by mm.malloc, identity-mapped) + us_size: uint64 = USER_STACK_SIZE + phys_bottom: uint64 = (cur_p.user_stack - us_size) & ~uint64(0xFFF) + # Map each page of the user stack at the virtual address with PTE_USER + num_stack_pages: uint64 = 16 # USER_STACK_SIZE(65536) / PAGE_SIZE(4096) = 16 + si: uint64 + for si in range(num_stack_pages): + vaddr: uint64 = (user_stack_vbottom & ~uint64(0xFFF)) + si * uint64(0x1000) + paddr: uint64 = phys_bottom + si * uint64(0x1000) + paging.MapPage(vaddr, paddr, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) + # Set TSS RSP0 so interrupts from Ring 3 use kernel stack + gdt.set_tss_rsp0(cur_p.kern_stack) + # Set GS kernel_rsp0 for syscall entry from Ring 3 + cpu.set_kernel_rsp0(cur_p.kern_stack) + # Keep interrupts disabled until iretq: drop_to_user_mode's iretq + # will set RFLAGS.IF from the saved frame (0x202) for user mode. + # This prevents timer interrupt preemption between TSS setup and iretq. + # Drop to Ring 3 user mode via iretq + proc.drop_to_user_mode(entry_fn, user_stack_vtop, cur_p.kern_stack) + cur: proc.Process | t.CPtr = proc.ProcessManager.current() + cur.exit() + return 0 + +def spawn_elf(path: t.CConst | str) -> int: + fat32.lock() + name_start: int = 0 + si: int = 0 + while True: + ch: t.CChar = path[si] + if ch == 0: break + if ch == 47: + name_start = si + 1 + si += 1 + + lowest_vaddr: uint64 = 0 + highest_vaddr_end: uint64 = 0 + fp_scan: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) + if fp_scan is None: + serr: uint32 = fat32.last_error() + seb: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(seb), 64, "[elf] spawn scan open failed err=%d\n", serr) + serial.puts(seb) + fat32.unlock() + return -1 + if fp_scan is not None: + ehdr_buf_s: t.CArray[uint8, 64] + string.memset(c.Addr(ehdr_buf_s), 0, 64) + fat32.read(fp_scan, c.Addr(ehdr_buf_s), 64) + ehdr_s: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf_s) + if ehdr_s.e_type == ET_EXEC or ehdr_s.e_type == ET_DYN: + phoff_s: uint64 = ehdr_s.e_phoff + phentsize_s: uint16 = ehdr_s.e_phentsize + phnum_s: uint16 = ehdr_s.e_phnum + if phentsize_s > 0 and phnum_s > 0 and phnum_s <= MAX_PHDRS: + phdr_bufs_s: t.CArray[Elf64_Phdr, MAX_PHDRS] + string.memset(c.Addr(phdr_bufs_s), 0, MAX_PHDRS * 56) + found_load_s: int = 0 + for pi_s in range(phnum_s): + fat32.seek(fp_scan, uint32(phoff_s + uint64(pi_s) * uint64(phentsize_s))) + fat32.read(fp_scan, c.Addr(phdr_bufs_s[pi_s]), 56) + if phdr_bufs_s[pi_s].p_type == PT_LOAD: + seg_end_s: uint64 = phdr_bufs_s[pi_s].p_vaddr + phdr_bufs_s[pi_s].p_memsz + if found_load_s == 0: + lowest_vaddr = phdr_bufs_s[pi_s].p_vaddr + highest_vaddr_end = seg_end_s + found_load_s = 1 + else: + if phdr_bufs_s[pi_s].p_vaddr < lowest_vaddr: + lowest_vaddr = phdr_bufs_s[pi_s].p_vaddr + if seg_end_s > highest_vaddr_end: + highest_vaddr_end = seg_end_s + fat32.close(fp_scan) + + isolate_va: uint64 = lowest_vaddr + if isolate_va == 0: + isolate_va = 0x400000 + + # Load ELF to physical memory WITHOUT mapping in kernel PML4. + # do_map=0: load_elf stores mapping info in globals for spawn_elf to use. + # ROOT CAUSE FIX: previously load_elf mapped ELF vaddr (e.g. 0x400000) into + # kernel PML4, overwriting identity mapping of buddy memory_block headers. + entry: t.CPtr = load_elf(path, 0) + if entry is None: + serial.puts("[elf] spawn: load failed\n") + fat32.unlock() + return -1 + + # Clone kernel PML4 (identity mapping intact, no ELF mapping yet) + proc_pml4: uint64 = paging.clone_for_process(isolate_va) + slog1: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(slog1), 80, "[elf] spawn: clone pml4=0x%lx va=0x%lx\n", proc_pml4, isolate_va) + serial.puts(slog1) + if proc_pml4 == 0: + serial.puts("[elf] spawn: clone_for_process failed\n") + fat32.unlock() + return -1 + + # Map ELF pages in the CLONED PML4 (not kernel's). + # This prevents overwriting kernel identity mapping at 0x400000 which + # would corrupt buddy system memory_block headers. + # Must disable interrupts: @pml4 global is used by MapPage and a timer + # interrupt mid-section would call switch_pid, corrupting @pml4. + asm.cli() + _kernel_cr3: uint64 = 0 + c.Asm(f"""mov {c.AsmOut(_kernel_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + c.Asm(f"mov cr3, {c.AsmInp(proc_pml4, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + paging.set_active_pml4(proc_pml4) + mi: uint64 + for mi in range(_last_elf_num_map_pages): + _va: uint64 = _last_elf_virt_page_start + mi * 0x1000 + _pa: uint64 = _last_elf_phys_page_start + mi * 0x1000 + paging.MapPage(_va, _pa, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) + c.Asm(f"mov cr3, {c.AsmInp(_kernel_cr3, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + paging.set_active_pml4(_kernel_cr3) + asm.sti() + + # path[name_start:] 切片表达式 translate_subscript 不支持 Slice(返回 None)→ + # 作为实参丢 name、entry 错位成第一参数(TPV 已修,此处指针算术双保险) + nm_ptr: t.CConst | t.CChar | t.CPtr = t.CConst(uint64(path) + uint64(name_start), t.CPtr) + p: proc.Process | t.CPtr = proc.ProcessManager.create_process(nm_ptr, entry) + if p is None: + serial.puts("[elf] spawn: create_process failed\n") + fat32.unlock() + return -2 + p.elf_base = uint64(entry) + p.pml4_root = proc_pml4 + if p.pid >= 0 and p.pid < MAX_SPAWNED: + _elf_entries[p.pid] = entry + + th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(t.CPtr(_elf_entry_wrapper), t.CPtr(uint64(p.pid)), p.pid) + if th is None: + serial.puts("[elf] spawn: create_thread failed\n") + p.exit() + fat32.unlock() + return -3 + tid: int = th.tid + p.addThread(tid) + slog: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(slog), 80, "[elf] spawn: pid=%d tid=%d entry=0x%lx pml4=0x%lx\n", p.pid, tid, uint64(entry), p.pml4_root) + serial.puts(slog) + # [DIAG] 确认 return p.pid 的实际值(main 收到 pid=0 而此处打印 3) + _dbw2: t.CArray[t.CChar, 64] + viperlib.snprintf(c.Addr(_dbw2), 64, "[elf] spawn ret pid=%d\n", p.pid) + serial.puts(c.Addr(_dbw2)) + fat32.unlock() + return p.pid + +def _resolve_symbol(name: t.CConst | t.CChar | t.CPtr) -> t.CPtr: + nm: int = 0 + while c.Deref(name + nm) != 0: + nm += 1 + cmp_name: t.CConst | t.CChar | t.CPtr = name + cmp_len: int = nm + if nm > 9: + sha1_len2: int = 0 + for si2 in range(nm): + ch2: t.CChar = c.Deref(name + si2) + if ch2 == 46: + if sha1_len2 >= 8: + cmp_name = str(uint64(name) + si2 + 1) + cmp_len = nm - si2 - 1 + break + if ch2 == 0: + break + if (ch2 >= 48 and ch2 <= 57) or (ch2 >= 97 and ch2 <= 102): + sha1_len2 += 1 + else: + break + if cmp_len == 11: + match: int = 1 + for i in range(cmp_len): + if c.Deref(cmp_name + i) != c.Deref("serial_puts" + i): + match = 0 + if match: + return t.CVoid(c.Addr(serial.puts), t.CPtr) + return None + +_so_strtab: t.CPtr +_so_symtab: t.CPtr +_so_syment: uint64 +_so_sym_count: int + +def load_so(path: t.CConst | str) -> t.CPtr: + fat32.lock() + fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ) + if fp is None: + serial.puts("[so] failed to open file\n") + fat32.unlock() + return None + + ehdr_buf: t.CArray[uint8, 64] + string.memset(c.Addr(ehdr_buf), 0, 64) + read_len: uint32 = fat32.read(fp, c.Addr(ehdr_buf), 64) + if read_len < 64: + serial.puts("[so] failed to read ehdr\n") + fat32.close(fp) + fat32.unlock() + return None + + ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf) + if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3: + serial.puts("[so] bad magic\n") + fat32.close(fp) + fat32.unlock() + return None + if ehdr.e_ident[4] != ELFCLASS64: + serial.puts("[so] not ELF64\n") + fat32.close(fp) + fat32.unlock() + return None + if ehdr.e_type == ET_DYN: + pass + elif ehdr.e_type == ET_EXEC: + pass + else: + serial.puts("[so] not ET_DYN or ET_EXEC\n") + fat32.close(fp) + fat32.unlock() + return None + + phoff: uint64 = ehdr.e_phoff + phentsize: uint16 = ehdr.e_phentsize + phnum: uint16 = ehdr.e_phnum + + # 程序头数量越界保护(phdr_bufs 仅 MAX_PHDRS 项):此前缺此校验, + # 异常/恶意 e_phnum > MAX_PHDRS 会越界写栈(load_elf 已有同款校验)。 + if phnum > MAX_PHDRS: + serial.puts("[so] phnum exceeds MAX_PHDRS\n") + fat32.close(fp) + fat32.unlock() + return None + + phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS] + string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56) + for pi in range(phnum): + phdr_off: uint64 = phoff + uint64(pi) * uint64(phentsize) + fat32.seek(fp, uint32(phdr_off)) + fat32.read(fp, c.Addr(phdr_bufs[pi]), 56) + + found_load: int = 0 + lowest_vaddr: uint64 = 0 + highest_vaddr_end: uint64 = 0 + for pi in range(phnum): + if phdr_bufs[pi].p_type == PT_LOAD: + seg_end: uint64 = phdr_bufs[pi].p_vaddr + phdr_bufs[pi].p_memsz + if found_load == 0: + lowest_vaddr = phdr_bufs[pi].p_vaddr + highest_vaddr_end = seg_end + found_load = 1 + else: + if phdr_bufs[pi].p_vaddr < lowest_vaddr: + lowest_vaddr = phdr_bufs[pi].p_vaddr + if seg_end > highest_vaddr_end: + highest_vaddr_end = seg_end + + if found_load == 0: + serial.puts("[so] no LOAD segments\n") + fat32.close(fp) + fat32.unlock() + return None + + total_memsz: uint64 = highest_vaddr_end - lowest_vaddr + total_pages: uint64 = (total_memsz + 0xFFF) // 0x1000 + + so_load_addr: uint64 = 0x600000 + raw_alloc: t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000) + if not raw_alloc: + serial.puts("[so] malloc failed\n") + fat32.close(fp) + fat32.unlock() + return None + + phys_base_aligned: uint64 = (uint64(raw_alloc) + 0xFFF) & ~uint64(0xFFF) + phys_base: t.CPtr = t.CVoid(phys_base_aligned, t.CPtr) + string.memset(phys_base, 0, total_pages * 0x1000) + + for pi in range(phnum): + if phdr_bufs[pi].p_type == PT_LOAD: + vaddr: uint64 = phdr_bufs[pi].p_vaddr + file_off: uint64 = phdr_bufs[pi].p_offset + filesz: uint64 = phdr_bufs[pi].p_filesz + memsz: uint64 = phdr_bufs[pi].p_memsz + dest_off: uint64 = vaddr - lowest_vaddr + dest: t.CPtr = t.CVoid(uint64(phys_base) + dest_off, t.CPtr) + if filesz > 0: + fat32.seek(fp, uint32(file_off)) + fat32.read(fp, dest, uint32(filesz)) + if memsz > filesz: + bss_start: t.CPtr = t.CVoid(uint64(dest) + filesz, t.CPtr) + bss_len: uint64 = memsz - filesz + string.memset(bss_start, 0, bss_len) + + virt_page_start: uint64 = (so_load_addr + lowest_vaddr) & ~uint64(0xFFF) + phys_page_start: uint64 = uint64(phys_base) & ~uint64(0xFFF) + map_end: uint64 = (so_load_addr + highest_vaddr_end + 0xFFF) & ~uint64(0xFFF) + num_map_pages: uint64 = (map_end - virt_page_start) // 0x1000 + + for mi in range(num_map_pages): + virt_addr: uint64 = virt_page_start + mi * 0x1000 + phys_addr: uint64 = phys_page_start + mi * 0x1000 + paging.MapPage(virt_addr, phys_addr, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) + + base_vaddr: uint64 = so_load_addr + lowest_vaddr + + dyn_buf: t.CArray[Elf64_Dyn, MAX_DYNS] + string.memset(c.Addr(dyn_buf), 0, MAX_DYNS * 16) + dyn_count: int = 0 + for pi in range(phnum): + if phdr_bufs[pi].p_type == PT_DYNAMIC: + fat32.seek(fp, uint32(phdr_bufs[pi].p_offset)) + # p_filesz 无上界,直接读会越界写 dyn_buf(MAX_DYNS*16 字节)→ 夹取 + filesz_d: uint32 = uint32(phdr_bufs[pi].p_filesz) + max_dyn_bytes: uint32 = uint32(MAX_DYNS * 16) + if filesz_d > max_dyn_bytes: + filesz_d = max_dyn_bytes + dyn_read: uint32 = fat32.read(fp, c.Addr(dyn_buf), filesz_d) + dyn_count = int(dyn_read) // 16 + + strtab_vaddr: uint64 = 0 + symtab_vaddr: uint64 = 0 + hash_vaddr: uint64 = 0 + syment: uint64 = 0 + rela_vaddr: uint64 = 0 + relasz: uint64 = 0 + jmprel_vaddr: uint64 = 0 + pltrelsz: uint64 = 0 + for di in range(dyn_count): + if dyn_buf[di].d_tag == DT_NULL: break + if dyn_buf[di].d_tag == DT_STRTAB: strtab_vaddr = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_SYMTAB: symtab_vaddr = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_HASH: hash_vaddr = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_SYMENT: syment = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_RELA: rela_vaddr = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_RELASZ: relasz = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_JMPREL: jmprel_vaddr = dyn_buf[di].d_val + elif dyn_buf[di].d_tag == DT_PLTRELSZ: pltrelsz = dyn_buf[di].d_val + + strtab_ptr: t.CPtr = t.CVoid(strtab_vaddr + so_load_addr, t.CPtr) + symtab_ptr: t.CPtr = t.CVoid(symtab_vaddr + so_load_addr, t.CPtr) + + if rela_vaddr != 0 and relasz > 0: + rela_count: uint64 = relasz // 24 + for ri in range(rela_count): + rela: Elf64_Rela | t.CPtr = t.CVoid(uint64(rela_vaddr) + so_load_addr + ri * 24, t.CPtr) + r_type: uint32 = uint32(rela.r_info & 0xFFFFFFFF) + r_sym: uint32 = uint32(rela.r_info >> 32) + target_addr: t.CPtr = t.CVoid(rela.r_offset + so_load_addr, t.CPtr) + if r_type == R_X86_64_RELATIVE: + val: uint64 = uint64(rela.r_addend) + so_load_addr + string.memcpy(target_addr, c.Addr(val), 8) + elif r_type == R_X86_64_64 or r_type == R_X86_64_GLOB_DAT or r_type == R_X86_64_JUMP_SLOT: + sym: Elf64_Sym | t.CPtr = t.CVoid(uint64(symtab_ptr) + uint64(r_sym) * syment, t.CPtr) + sym_name: t.CConst | t.CChar | t.CPtr = t.CConst(uint64(strtab_ptr) + sym.st_name, t.CPtr) + resolved: t.CPtr = _resolve_symbol(sym_name) + if resolved is not None: + val2: uint64 = uint64(resolved) + uint64(rela.r_addend) + string.memcpy(target_addr, c.Addr(val2), 8) + elif sym.st_value != 0: + val3: uint64 = sym.st_value + so_load_addr + uint64(rela.r_addend) + string.memcpy(target_addr, c.Addr(val3), 8) + + if jmprel_vaddr != 0 and pltrelsz > 0: + jmprel_count: uint64 = pltrelsz // 24 + for ji in range(jmprel_count): + rela2: Elf64_Rela | t.CPtr = t.CVoid(jmprel_vaddr + so_load_addr + ji * 24, t.CPtr) + r_type2: uint32 = uint32(rela2.r_info & 0xFFFFFFFF) + r_sym2: uint32 = uint32(rela2.r_info >> 32) + target2: t.CPtr = t.CVoid(rela2.r_offset + so_load_addr, t.CPtr) + if r_type2 == R_X86_64_JUMP_SLOT or r_type2 == R_X86_64_GLOB_DAT: + sym2: Elf64_Sym | t.CPtr = t.CVoid(uint64(symtab_ptr) + uint64(r_sym2) * syment, t.CPtr) + sym_name2: t.CConst | t.CChar | t.CPtr = t.CConst(uint64(strtab_ptr) + sym2.st_name, t.CPtr) + resolved2: t.CPtr = _resolve_symbol(sym_name2) + if resolved2 is not None: + val4: uint64 = uint64(resolved2) + uint64(rela2.r_addend) + string.memcpy(target2, c.Addr(val4), 8) + elif sym2.st_value != 0: + val5: uint64 = sym2.st_value + so_load_addr + uint64(rela2.r_addend) + string.memcpy(target2, c.Addr(val5), 8) + else: + cr3: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(cr3), 80, "[so] WARN: unresolved PLT sym offset=%lu\n", sym2.st_name) + serial.puts(cr3) + + fat32.close(fp) + + global _so_strtab, _so_symtab, _so_syment, _so_sym_count + + _so_strtab = strtab_ptr + _so_symtab = symtab_ptr + _so_syment = syment + _so_sym_count = 0 + if hash_vaddr != 0: + hash_ptr: t.CPtr = t.CVoid(hash_vaddr + so_load_addr, t.CPtr) + nchain: uint32 = c.Deref(t.CVoid(uint64(hash_ptr) + 4, t.CPtr)) + _so_sym_count = int(nchain) + elif syment > 0 and strtab_vaddr > symtab_vaddr and symtab_vaddr != 0: + sym_tab_size: uint64 = strtab_vaddr - symtab_vaddr + _so_sym_count = int(sym_tab_size // syment) + + cr: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(cr), 80, "[so] loaded at 0x%lx\n", base_vaddr) + serial.puts(cr) + + fat32.unlock() + return t.CVoid(base_vaddr, t.CPtr) + +def get_so_symbol(so_base: t.CPtr, name: t.CConst | t.CChar | t.CPtr, so_path: t.CConst | t.CChar | t.CPtr) -> t.CPtr: + if _so_symtab is None or _so_strtab is None or _so_syment == 0: + return None + if name is None: + return None + for symi in range(_so_sym_count): + sb2: Elf64_Sym | t.CPtr = t.CVoid(uint64(_so_symtab) + uint64(symi) * _so_syment, t.CPtr) + if sb2.st_value != 0 and sb2.st_shndx != 0: + sym_name_off2: uint32 = sb2.st_name + cmp_off2: uint32 = sym_name_off2 + match2: int = 0 + ni2: int = 0 + while True: + sc3: t.CChar = c.Deref(t.CVoid(uint64(_so_strtab) + cmp_off2 + ni2, t.CPtr)) + nc3: t.CChar = c.Deref(name + ni2) + if sc3 != nc3: + break + if sc3 == 0: + match2 = 1 + break + ni2 += 1 + if match2 == 0: + dot_pos3: uint32 = sym_name_off2 + is_sha1_2: int = 0 + sha1_len_2: uint32 = 0 + while True: + dc4: t.CChar = c.Deref(t.CVoid(uint64(_so_strtab) + dot_pos3, t.CPtr)) + if dc4 == 46: + if sha1_len_2 >= 8: + is_sha1_2 = 1 + break + if dc4 == 0: + break + if (dc4 >= 48 and dc4 <= 57) or (dc4 >= 97 and dc4 <= 102): + sha1_len_2 += 1 + else: + break + dot_pos3 += 1 + if is_sha1_2: + cmp_off2 = dot_pos3 + 1 + match2 = 1 + ni2 = 0 + while True: + sc4: t.CChar = c.Deref(t.CVoid(uint64(_so_strtab) + cmp_off2 + ni2, t.CPtr)) + nc4: t.CChar = c.Deref(name + ni2) + if sc4 != nc4: + match2 = 0 + break + if sc4 == 0: + break + ni2 += 1 + if match2: + result_addr: uint64 = uint64(so_base) + sb2.st_value + dbg2: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(dbg2), 80, "[so] found '%s' at 0x%lx\n", t.CVoid(uint64(_so_strtab) + sym_name_off2, t.CPtr), result_addr) + serial.puts(dbg2) + return t.CVoid(result_addr, t.CPtr) + serial.puts("[so] symbol not found\n") + return None diff --git a/VKernel/Kernel/intr/gdt.vp b/VKernel/Kernel/intr/gdt.vp index fab089e..e4036c7 100644 --- a/VKernel/Kernel/intr/gdt.vp +++ b/VKernel/Kernel/intr/gdt.vp @@ -1,142 +1,142 @@ -import t, c - - -@c.Attribute(t.attr.packed) -class gdt_entry: - limit_low: t.CUInt16T - base_low: t.CUInt16T - base_middle: t.CUInt8T - access: t.CUInt8T - granularity: t.CUInt8T - base_high: t.CUInt8T - -@c.Attribute(t.attr.packed) -class gdt_entry64: - limit_low: t.CUInt16T - base_low: t.CUInt16T - base_middle: t.CUInt8T - access: t.CUInt8T - granularity: t.CUInt8T - base_high: t.CUInt8T - base_upper: t.CUInt32T - reserved: t.CUInt32T - -@c.Attribute(t.attr.packed) -class gdt_ptr: - limit: t.CUInt16T - base: t.CUInt64T - -gdt: t.CArray[gdt_entry, 7] | t.CExport = [] -gp: t.CArray[t.CUInt8T, 10] | t.CExport -# TSS buffer: 104 bytes, raw byte array to avoid packed struct issues -# x86_64 TSS layout: reserved0(4) rsp0(8) rsp1(8) rsp2(8) reserved1(8) ist1-ist7(56) reserved2(8) reserved3(2) iomap_base(2) -tss_buf: t.CArray[t.CUInt8T, 104] - -CODE_SEG: t.CDefine | t.CUInt16T = 0x08 -DATA_SEG: t.CDefine | t.CUInt16T = 0x10 -USER_CODE_SEG: t.CDefine | t.CUInt16T = 0x18 -USER_DATA_SEG: t.CDefine | t.CUInt16T = 0x20 -TSS_SEG: t.CDefine | t.CUInt16T = 0x28 - - -def init(): - global gp, gdt, tss_buf - gdt[0].limit_low = 0 - gdt[0].base_low = 0 - gdt[0].base_middle = 0 - gdt[0].access = 0 - gdt[0].granularity = 0 - gdt[0].base_high = 0 - gdt[1].limit_low = 0 - gdt[1].base_low = 0 - gdt[1].base_middle = 0 - gdt[1].access = 0x9A - gdt[1].granularity = 0x20 - gdt[1].base_high = 0 - gdt[2].limit_low = 0 - gdt[2].base_low = 0 - gdt[2].base_middle = 0 - gdt[2].access = 0x92 - gdt[2].granularity = 0xCF - gdt[2].base_high = 0 - gdt[3].limit_low = 0 - gdt[3].base_low = 0 - gdt[3].base_middle = 0 - gdt[3].access = 0xFA - gdt[3].granularity = 0x20 - gdt[3].base_high = 0 - gdt[4].limit_low = 0 - gdt[4].base_low = 0 - gdt[4].base_middle = 0 - gdt[4].access = 0xF2 - gdt[4].granularity = 0xCF - gdt[4].base_high = 0 - # Set up TSS descriptor in GDT entries 5-6 (selector 0x28) - setTSS64(5, t.CUInt64T(c.Addr(tss_buf)), 103) - c.Asm("""lea rax, [rip + gdt] - lea rcx, [rip + gp] - mov word ptr [rcx], 0x37 - mov qword ptr [rcx+2], rax""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX]) - c.Asm("sfence; mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - flush() - # Initialize TSS: set iomap_base = 104 (0x68) at offset 102 - tss_buf[102] = 0x68 - tss_buf[103] = 0x00 - # Load Task Register with TSS selector 0x28 - c.Asm("""mov ax, 0x28 - ltr ax""", - op=[t.ASM_DESCR.CLOBBER_RAX]) - -@c.Attribute(t.attr.naked) -def flush(): - c.Asm("""lea rax, [rip + gp] - lgdt [rax] - push 0x08 - lea rax, [rip+2f] - push rax - .byte 0x48, 0xcb - 2: - mov eax, 0x10 - mov ds, eax - mov es, eax - mov fs, eax - mov gs, eax - mov ss, eax - ret""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) - -def set_tss_rsp0(rsp0: t.CUInt64T): - global tss_buf - # TSS RSP0 is at offset 4 (8 bytes) in x86_64 TSS layout - tss_buf[4] = t.CUInt8T(rsp0 & 0xFF) - tss_buf[5] = t.CUInt8T((rsp0 >> 8) & 0xFF) - tss_buf[6] = t.CUInt8T((rsp0 >> 16) & 0xFF) - tss_buf[7] = t.CUInt8T((rsp0 >> 24) & 0xFF) - tss_buf[8] = t.CUInt8T((rsp0 >> 32) & 0xFF) - tss_buf[9] = t.CUInt8T((rsp0 >> 40) & 0xFF) - tss_buf[10] = t.CUInt8T((rsp0 >> 48) & 0xFF) - tss_buf[11] = t.CUInt8T((rsp0 >> 56) & 0xFF) - -def setGate(num: int, base: t.CUInt64T, limit: t.CUInt32T, access: t.CUInt8T, gran: t.CUInt8T): - global gdt - gdt[num].limit_low = (limit & 0xFFFF) - gdt[num].base_low = (base & 0xFFFF) - gdt[num].base_middle = (base >> 16) & 0xFF - gdt[num].base_high = (base >> 24) & 0xFF - gdt[num].granularity = ((limit >> 16) & 0x0F) | (gran & 0xF0) - gdt[num].access = access - -def setTSS64(num: int, base: t.CUInt64T, limit: t.CUInt32T): - global gdt - gdt[num].limit_low = limit & 0xFFFF - gdt[num].base_low = base & 0xFFFF - gdt[num].base_middle = (base >> 16) & 0xFF - gdt[num].access = 0x89 - gdt[num].granularity = 0x00 - gdt[num].base_high = (base >> 24) & 0xFF - gdt[num + 1].limit_low = (base >> 32) & 0xFFFF - gdt[num + 1].base_low = (base >> 48) & 0xFFFF - gdt[num + 1].base_middle = 0 - gdt[num + 1].access = 0 - gdt[num + 1].granularity = 0 - gdt[num + 1].base_high = 0 +import t, c + + +@c.Attribute(t.attr.packed) +class gdt_entry: + limit_low: uint16 + base_low: uint16 + base_middle: uint8 + access: uint8 + granularity: uint8 + base_high: uint8 + +@c.Attribute(t.attr.packed) +class gdt_entry64: + limit_low: uint16 + base_low: uint16 + base_middle: uint8 + access: uint8 + granularity: uint8 + base_high: uint8 + base_upper: uint32 + reserved: uint32 + +@c.Attribute(t.attr.packed) +class gdt_ptr: + limit: uint16 + base: uint64 + +gdt: t.CArray[gdt_entry, 7] | t.CExport = [] +gp: t.CArray[uint8, 10] | t.CExport +# TSS buffer: 104 bytes, raw byte array to avoid packed struct issues +# x86_64 TSS layout: reserved0(4) rsp0(8) rsp1(8) rsp2(8) reserved1(8) ist1-ist7(56) reserved2(8) reserved3(2) iomap_base(2) +tss_buf: t.CArray[uint8, 104] + +CODE_SEG: t.CDefine | uint16 = 0x08 +DATA_SEG: t.CDefine | uint16 = 0x10 +USER_CODE_SEG: t.CDefine | uint16 = 0x18 +USER_DATA_SEG: t.CDefine | uint16 = 0x20 +TSS_SEG: t.CDefine | uint16 = 0x28 + + +def init(): + global gp, gdt, tss_buf + gdt[0].limit_low = 0 + gdt[0].base_low = 0 + gdt[0].base_middle = 0 + gdt[0].access = 0 + gdt[0].granularity = 0 + gdt[0].base_high = 0 + gdt[1].limit_low = 0 + gdt[1].base_low = 0 + gdt[1].base_middle = 0 + gdt[1].access = 0x9A + gdt[1].granularity = 0x20 + gdt[1].base_high = 0 + gdt[2].limit_low = 0 + gdt[2].base_low = 0 + gdt[2].base_middle = 0 + gdt[2].access = 0x92 + gdt[2].granularity = 0xCF + gdt[2].base_high = 0 + gdt[3].limit_low = 0 + gdt[3].base_low = 0 + gdt[3].base_middle = 0 + gdt[3].access = 0xFA + gdt[3].granularity = 0x20 + gdt[3].base_high = 0 + gdt[4].limit_low = 0 + gdt[4].base_low = 0 + gdt[4].base_middle = 0 + gdt[4].access = 0xF2 + gdt[4].granularity = 0xCF + gdt[4].base_high = 0 + # Set up TSS descriptor in GDT entries 5-6 (selector 0x28) + setTSS64(5, uint64(c.Addr(tss_buf)), 103) + c.Asm("""lea rax, [rip + gdt] + lea rcx, [rip + gp] + mov word ptr [rcx], 0x37 + mov qword ptr [rcx+2], rax""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX]) + c.Asm("sfence; mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + flush() + # Initialize TSS: set iomap_base = 104 (0x68) at offset 102 + tss_buf[102] = 0x68 + tss_buf[103] = 0x00 + # Load Task Register with TSS selector 0x28 + c.Asm("""mov ax, 0x28 + ltr ax""", + op=[t.ASM_DESCR.CLOBBER_RAX]) + +@c.Attribute(t.attr.naked) +def flush(): + c.Asm("""lea rax, [rip + gp] + lgdt [rax] + push 0x08 + lea rax, [rip+2f] + push rax + .byte 0x48, 0xcb + 2: + mov eax, 0x10 + mov ds, eax + mov es, eax + mov fs, eax + mov gs, eax + mov ss, eax + ret""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) + +def set_tss_rsp0(rsp0: uint64): + global tss_buf + # TSS RSP0 is at offset 4 (8 bytes) in x86_64 TSS layout + tss_buf[4] = uint8(rsp0 & 0xFF) + tss_buf[5] = uint8((rsp0 >> 8) & 0xFF) + tss_buf[6] = uint8((rsp0 >> 16) & 0xFF) + tss_buf[7] = uint8((rsp0 >> 24) & 0xFF) + tss_buf[8] = uint8((rsp0 >> 32) & 0xFF) + tss_buf[9] = uint8((rsp0 >> 40) & 0xFF) + tss_buf[10] = uint8((rsp0 >> 48) & 0xFF) + tss_buf[11] = uint8((rsp0 >> 56) & 0xFF) + +def setGate(num: int, base: uint64, limit: uint32, access: uint8, gran: uint8): + global gdt + gdt[num].limit_low = (limit & 0xFFFF) + gdt[num].base_low = (base & 0xFFFF) + gdt[num].base_middle = (base >> 16) & 0xFF + gdt[num].base_high = (base >> 24) & 0xFF + gdt[num].granularity = ((limit >> 16) & 0x0F) | (gran & 0xF0) + gdt[num].access = access + +def setTSS64(num: int, base: uint64, limit: uint32): + global gdt + gdt[num].limit_low = limit & 0xFFFF + gdt[num].base_low = base & 0xFFFF + gdt[num].base_middle = (base >> 16) & 0xFF + gdt[num].access = 0x89 + gdt[num].granularity = 0x00 + gdt[num].base_high = (base >> 24) & 0xFF + gdt[num + 1].limit_low = (base >> 32) & 0xFFFF + gdt[num + 1].base_low = (base >> 48) & 0xFFFF + gdt[num + 1].base_middle = 0 + gdt[num + 1].access = 0 + gdt[num + 1].granularity = 0 + gdt[num + 1].base_high = 0 diff --git a/VKernel/Kernel/intr/idt.vp b/VKernel/Kernel/intr/idt.vp index 4e0023a..9c76fc6 100644 --- a/VKernel/Kernel/intr/idt.vp +++ b/VKernel/Kernel/intr/idt.vp @@ -7,20 +7,20 @@ import viperlib import asm import t, c -CODE_SEG: t.CDefine | t.CUInt16T = 0x08 +CODE_SEG: t.CDefine | uint16 = 0x08 @c.Attribute(t.attr.packed) class idt_entry: - base_low: t.CUInt16T - selector: t.CUInt16T - ist_attr: t.CUInt8T - type_attr: t.CUInt8T - base_middle: t.CUInt16T - base_high: t.CUInt32T - reserved1: t.CUInt32T + base_low: uint16 + selector: uint16 + ist_attr: uint8 + type_attr: uint8 + base_middle: uint16 + base_high: uint32 + reserved1: uint32 idt: t.CArray[idt_entry, 256] | t.CExport = [] -irq_handler_t: t.CTypedef = t.Callable[[], t.CInt] +irq_handler_t: t.CTypedef = t.Callable[[], int] def isr0() -> t.State: pass def isr1() -> t.State: pass @@ -75,7 +75,7 @@ def isr80() -> t.State: pass def isr_default() -> t.State: pass -def setGate(num: int, base: t.CUInt64T, sel: t.CUInt16T, flags: t.CUInt8T): +def setGate(num: int, base: uint64, sel: uint16, flags: uint8): global idt idt[num].base_low = (base & 0xFFFF) idt[num].base_middle = (base >> 16) & 0xFFFF @@ -85,7 +85,7 @@ def setGate(num: int, base: t.CUInt64T, sel: t.CUInt16T, flags: t.CUInt8T): idt[num].type_attr = flags idt[num].reserved1 = 0 -def isrCommonhandler(interrupt: t.CInt): +def isrCommonhandler(interrupt: int): c.Asm(f"""mov dx, 0x3F8 mov al, 91 out dx, al @@ -112,12 +112,12 @@ def isrCommonhandler(interrupt: t.CInt): op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX]) # Print CR2 for page faults (ISR 14) if interrupt == 14: - cr2: t.CUInt64T = 0 + cr2: uint64 = 0 c.Asm(f"""mov {c.AsmOut(cr2, t.ASM_DESCR.OUTPUT_REG)}, cr2""", op=[t.ASM_DESCR.CLOBBER_RAX]) - fault_rip: t.CUInt64T = 0 - fault_err: t.CUInt64T = 0 - fault_rsp: t.CUInt64T = 0 + fault_rip: uint64 = 0 + fault_err: uint64 = 0 + fault_rsp: uint64 = 0 c.Asm(f"""mov {c.AsmOut(fault_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip] mov {c.AsmOut(fault_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err] mov {c.AsmOut(fault_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""", @@ -128,14 +128,14 @@ def isrCommonhandler(interrupt: t.CInt): # [CR3] 当前 pml4:定位栈区/对象写缺页是否因 pml4 被 switch_pid 切走 # (内核 pml4=0xf801000,用户 pml4=0x9781xxx —— 若显示用户 pml4 而 rsp # 在 bootloader 栈区 0x60000-0x80000,则是进程切换后未切回内核页表)。 - cur_cr3: t.CUInt64T = 0 + cur_cr3: uint64 = 0 c.Asm(f"mov {c.AsmOut(cur_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3", op=[t.ASM_DESCR.CLOBBER_RAX]) cr3_buf: t.CArray[t.CChar, 80] viperlib.snprintf(c.Addr(cr3_buf), 80, "[CR3] pml4=0x%lx\n", cur_cr3) serial.puts(cr3_buf) # [RAX] 崩溃时 rax(isr.s 保存):定位 cr2 与 rax 关系(rax-偏移=cr2) - f_rax: t.CUInt64T = 0 + f_rax: uint64 = 0 c.Asm(f"""mov {c.AsmOut(f_rax, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""", op=[t.ASM_DESCR.CLOBBER_RAX]) rax_buf: t.CArray[t.CChar, 80] @@ -143,7 +143,7 @@ def isrCommonhandler(interrupt: t.CInt): serial.puts(rax_buf) # [STK] rbp 链回溯(定位栈损坏源:崩溃帧 + 4 级调用链的返回地址) # 先读崩溃 rbp 判断(用户 rbp 不回溯,避免读用户地址嵌套 #PF) - fr0: t.CUInt64T = 0 + fr0: uint64 = 0 c.Asm(f"""mov rax, [_fault_rbp] mov {c.AsmOut(fr0, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_RAX]) @@ -153,10 +153,10 @@ def isrCommonhandler(interrupt: t.CInt): viperlib.snprintf(c.Addr(stk_buf), 160, "[STK] user rbp=0x%lx, chain skipped\n", fr0) serial.puts(stk_buf) else: - fr1: t.CUInt64T = 0 - fr2: t.CUInt64T = 0 - fr3: t.CUInt64T = 0 - fr4: t.CUInt64T = 0 + fr1: uint64 = 0 + fr2: uint64 = 0 + fr3: uint64 = 0 + fr4: uint64 = 0 c.Asm(f"""mov rax, [_fault_rbp] mov rax, [rax + 8] mov {c.AsmOut(fr1, t.ASM_DESCR.OUTPUT_REG)}, rax @@ -175,11 +175,11 @@ def isrCommonhandler(interrupt: t.CInt): fr0, fr1, fr2, fr3, fr4) serial.puts(stk_buf) elif interrupt == 13: - gp_rip: t.CUInt64T = 0 - gp_err: t.CUInt64T = 0 - gp_rsp: t.CUInt64T = 0 - gp_cr4: t.CUInt64T = 0 - gp_cr0: t.CUInt64T = 0 + gp_rip: uint64 = 0 + gp_err: uint64 = 0 + gp_rsp: uint64 = 0 + gp_cr4: uint64 = 0 + gp_cr0: uint64 = 0 c.Asm(f"""mov {c.AsmOut(gp_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip] mov {c.AsmOut(gp_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err] mov {c.AsmOut(gp_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp] @@ -194,8 +194,8 @@ def isrCommonhandler(interrupt: t.CInt): serial.puts(gp_buf) else: # 其他异常(#UD 等):打印 rip/rsp 定位执行位置(isr.s 已保存 _fault_rip) - ex_rip: t.CUInt64T = 0 - ex_rsp: t.CUInt64T = 0 + ex_rip: uint64 = 0 + ex_rsp: uint64 = 0 c.Asm(f"""mov {c.AsmOut(ex_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip] mov {c.AsmOut(ex_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""", op=[t.ASM_DESCR.CLOBBER_RAX]) @@ -203,18 +203,18 @@ def isrCommonhandler(interrupt: t.CInt): viperlib.snprintf(c.Addr(ex_buf), 100, "[EX] int=%d rip=0x%lx rsp=0x%lx\n", interrupt, ex_rip, ex_rsp) serial.puts(ex_buf) # [RAX] 崩溃时 rax(isr.s 保存) - f_rax: t.CUInt64T = 0 + f_rax: uint64 = 0 c.Asm(f"""mov {c.AsmOut(f_rax, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""", op=[t.ASM_DESCR.CLOBBER_RAX]) rax_buf: t.CArray[t.CChar, 80] viperlib.snprintf(c.Addr(rax_buf), 80, "[RAX] rax=0x%lx\n", f_rax) serial.puts(rax_buf) # [STK] rbp 链回溯(与 #PF 分支一致,定位栈损坏源) - fr0: t.CUInt64T = 0 - fr1: t.CUInt64T = 0 - fr2: t.CUInt64T = 0 - fr3: t.CUInt64T = 0 - fr4: t.CUInt64T = 0 + fr0: uint64 = 0 + fr1: uint64 = 0 + fr2: uint64 = 0 + fr3: uint64 = 0 + fr4: uint64 = 0 c.Asm(f"""mov rax, [_fault_rbp] mov {c.AsmOut(fr0, t.ASM_DESCR.OUTPUT_REG)}, rax mov rax, [rax + 8] @@ -246,13 +246,20 @@ def isrCommonhandler(interrupt: t.CInt): asm.sti() asm.hlt() pass - tid: t.CInt = s.current_tid + tid: int = s.current_tid if tid == 0: serial.puts(" KERNEL PANIC\n") while True: asm.sti() asm.hlt() pass + # s.threads 为 [16 x Thread](sched.MAX_THREADS),越界写会破坏调度器状态 + if tid < 0 or tid >= 16: + serial.puts(" KERNEL PANIC (bad tid)\n") + while True: + asm.sti() + asm.hlt() + pass buf2: t.CArray[t.CChar, 64] viperlib.snprintf(c.Addr(buf2), 64, " exc in tid=%d, terminating\n", tid) serial.puts(buf2) @@ -460,78 +467,78 @@ def isr47_handler() -> t.CExport | t.CVoid: apic.eoi() def init_exceptions(): - setGate(0, t.CUInt64T(isr0), CODE_SEG, 0x8E) - setGate(1, t.CUInt64T(isr1), CODE_SEG, 0x8E) - setGate(2, t.CUInt64T(isr2), CODE_SEG, 0x8E) - setGate(3, t.CUInt64T(isr3), CODE_SEG, 0x8E) - setGate(4, t.CUInt64T(isr4), CODE_SEG, 0x8E) - setGate(5, t.CUInt64T(isr5), CODE_SEG, 0x8E) - setGate(6, t.CUInt64T(isr6), CODE_SEG, 0x8E) - setGate(7, t.CUInt64T(isr7), CODE_SEG, 0x8E) - setGate(8, t.CUInt64T(isr8), CODE_SEG, 0x8E) - setGate(9, t.CUInt64T(isr9), CODE_SEG, 0x8E) - setGate(10, t.CUInt64T(isr10), CODE_SEG, 0x8E) - setGate(11, t.CUInt64T(isr11), CODE_SEG, 0x8E) - setGate(12, t.CUInt64T(isr12), CODE_SEG, 0x8E) - setGate(13, t.CUInt64T(isr13), CODE_SEG, 0x8E) - setGate(14, t.CUInt64T(isr14), CODE_SEG, 0x8E) - setGate(15, t.CUInt64T(isr15), CODE_SEG, 0x8E) - setGate(16, t.CUInt64T(isr16), CODE_SEG, 0x8E) - setGate(17, t.CUInt64T(isr17), CODE_SEG, 0x8E) - setGate(18, t.CUInt64T(isr18), CODE_SEG, 0x8E) - setGate(19, t.CUInt64T(isr19), CODE_SEG, 0x8E) - setGate(20, t.CUInt64T(isr20), CODE_SEG, 0x8E) - setGate(21, t.CUInt64T(isr21), CODE_SEG, 0x8E) - setGate(22, t.CUInt64T(isr22), CODE_SEG, 0x8E) - setGate(23, t.CUInt64T(isr23), CODE_SEG, 0x8E) - setGate(24, t.CUInt64T(isr24), CODE_SEG, 0x8E) - setGate(25, t.CUInt64T(isr25), CODE_SEG, 0x8E) - setGate(26, t.CUInt64T(isr26), CODE_SEG, 0x8E) - setGate(27, t.CUInt64T(isr27), CODE_SEG, 0x8E) - setGate(28, t.CUInt64T(isr28), CODE_SEG, 0x8E) - setGate(29, t.CUInt64T(isr29), CODE_SEG, 0x8E) - setGate(30, t.CUInt64T(isr30), CODE_SEG, 0x8E) - setGate(31, t.CUInt64T(isr31), CODE_SEG, 0x8E) + setGate(0, uint64(isr0), CODE_SEG, 0x8E) + setGate(1, uint64(isr1), CODE_SEG, 0x8E) + setGate(2, uint64(isr2), CODE_SEG, 0x8E) + setGate(3, uint64(isr3), CODE_SEG, 0x8E) + setGate(4, uint64(isr4), CODE_SEG, 0x8E) + setGate(5, uint64(isr5), CODE_SEG, 0x8E) + setGate(6, uint64(isr6), CODE_SEG, 0x8E) + setGate(7, uint64(isr7), CODE_SEG, 0x8E) + setGate(8, uint64(isr8), CODE_SEG, 0x8E) + setGate(9, uint64(isr9), CODE_SEG, 0x8E) + setGate(10, uint64(isr10), CODE_SEG, 0x8E) + setGate(11, uint64(isr11), CODE_SEG, 0x8E) + setGate(12, uint64(isr12), CODE_SEG, 0x8E) + setGate(13, uint64(isr13), CODE_SEG, 0x8E) + setGate(14, uint64(isr14), CODE_SEG, 0x8E) + setGate(15, uint64(isr15), CODE_SEG, 0x8E) + setGate(16, uint64(isr16), CODE_SEG, 0x8E) + setGate(17, uint64(isr17), CODE_SEG, 0x8E) + setGate(18, uint64(isr18), CODE_SEG, 0x8E) + setGate(19, uint64(isr19), CODE_SEG, 0x8E) + setGate(20, uint64(isr20), CODE_SEG, 0x8E) + setGate(21, uint64(isr21), CODE_SEG, 0x8E) + setGate(22, uint64(isr22), CODE_SEG, 0x8E) + setGate(23, uint64(isr23), CODE_SEG, 0x8E) + setGate(24, uint64(isr24), CODE_SEG, 0x8E) + setGate(25, uint64(isr25), CODE_SEG, 0x8E) + setGate(26, uint64(isr26), CODE_SEG, 0x8E) + setGate(27, uint64(isr27), CODE_SEG, 0x8E) + setGate(28, uint64(isr28), CODE_SEG, 0x8E) + setGate(29, uint64(isr29), CODE_SEG, 0x8E) + setGate(30, uint64(isr30), CODE_SEG, 0x8E) + setGate(31, uint64(isr31), CODE_SEG, 0x8E) def init_irqs(): - setGate(32, t.CUInt64T(isr32), CODE_SEG, 0x8E) - setGate(33, t.CUInt64T(isr33), CODE_SEG, 0x8E) - setGate(34, t.CUInt64T(isr34), CODE_SEG, 0x8E) - setGate(35, t.CUInt64T(isr35), CODE_SEG, 0x8E) - setGate(36, t.CUInt64T(isr36), CODE_SEG, 0x8E) - setGate(37, t.CUInt64T(isr37), CODE_SEG, 0x8E) - setGate(38, t.CUInt64T(isr38), CODE_SEG, 0x8E) - setGate(39, t.CUInt64T(isr39), CODE_SEG, 0x8E) - setGate(40, t.CUInt64T(isr40), CODE_SEG, 0x8E) - setGate(41, t.CUInt64T(isr41), CODE_SEG, 0x8E) - setGate(42, t.CUInt64T(isr42), CODE_SEG, 0x8E) - setGate(43, t.CUInt64T(isr43), CODE_SEG, 0x8E) - setGate(44, t.CUInt64T(isr44), CODE_SEG, 0x8E) - setGate(45, t.CUInt64T(isr45), CODE_SEG, 0x8E) - setGate(46, t.CUInt64T(isr46), CODE_SEG, 0x8E) - setGate(47, t.CUInt64T(isr47), CODE_SEG, 0x8E) + setGate(32, uint64(isr32), CODE_SEG, 0x8E) + setGate(33, uint64(isr33), CODE_SEG, 0x8E) + setGate(34, uint64(isr34), CODE_SEG, 0x8E) + setGate(35, uint64(isr35), CODE_SEG, 0x8E) + setGate(36, uint64(isr36), CODE_SEG, 0x8E) + setGate(37, uint64(isr37), CODE_SEG, 0x8E) + setGate(38, uint64(isr38), CODE_SEG, 0x8E) + setGate(39, uint64(isr39), CODE_SEG, 0x8E) + setGate(40, uint64(isr40), CODE_SEG, 0x8E) + setGate(41, uint64(isr41), CODE_SEG, 0x8E) + setGate(42, uint64(isr42), CODE_SEG, 0x8E) + setGate(43, uint64(isr43), CODE_SEG, 0x8E) + setGate(44, uint64(isr44), CODE_SEG, 0x8E) + setGate(45, uint64(isr45), CODE_SEG, 0x8E) + setGate(46, uint64(isr46), CODE_SEG, 0x8E) + setGate(47, uint64(isr47), CODE_SEG, 0x8E) irq_handlers: t.CStatic | t.CArray[irq_handler_t, 16] = [None] -def irqInstallHandler(irq: t.CInt, handler: irq_handler_t, name: str) -> t.CInt: +def irqInstallHandler(irq: int, handler: irq_handler_t, name: str) -> int: global irq_handlers if irq < 0 or irq > 15: return -1 irq_handlers[irq] = handler return 0 -def irqGetHandler(irq: t.CInt) -> irq_handler_t: +def irqGetHandler(irq: int) -> irq_handler_t: if irq < 0 or irq > 15: return None return irq_handlers[irq] def init(): global idt for i in range(256): - setGate(i, t.CUInt64T(isr_default), CODE_SEG, 0x8E) + setGate(i, uint64(isr_default), CODE_SEG, 0x8E) pic.init() init_exceptions() init_irqs() # Register ISR 0x80 for int 0x80 syscall interface (user-mode ELF apps) - setGate(0x80, t.CUInt64T(isr80), CODE_SEG, 0xEE) # DPL=3 allows Ring 3 to call int 0x80 + setGate(0x80, uint64(isr80), CODE_SEG, 0xEE) # DPL=3 allows Ring 3 to call int 0x80 # Build idt_ptr on stack and load directly in one asm block c.Asm("""lea rax, [rip + idt] sub rsp, 16 diff --git a/VKernel/Kernel/intr/syscall.vp b/VKernel/Kernel/intr/syscall.vp index 5c5fdd0..0f4d149 100644 --- a/VKernel/Kernel/intr/syscall.vp +++ b/VKernel/Kernel/intr/syscall.vp @@ -50,18 +50,18 @@ IA32_STAR: t.CDefine = 0xC0000081 IA32_LSTAR: t.CDefine = 0xC0000082 IA32_FMASK: t.CDefine = 0xC0000084 -def wrmsr(msr: t.CUInt32T, val: t.CUInt64T): - lo: t.CUInt32T = t.CUInt32T(val & 0xFFFFFFFF) - hi: t.CUInt32T = t.CUInt32T(val >> 32) +def wrmsr(msr: uint32, val: uint64): + lo: uint32 = uint32(val & 0xFFFFFFFF) + hi: uint32 = uint32(val >> 32) c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)} mov eax, {c.AsmInp(lo, t.ASM_DESCR.REG_ANY)} mov edx, {c.AsmInp(hi, t.ASM_DESCR.REG_ANY)} wrmsr""", op=[t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX]) -def rdmsr(msr: t.CUInt32T) -> t.CUInt64T: - lo: t.CUInt32T - hi: t.CUInt32T +def rdmsr(msr: uint32) -> uint64: + lo: uint32 + hi: uint32 # rdmsr 固定写 EDX:EAX;out 绑定 + CLOBBER_RAX/RDX 冲突会导致 lo/hi # 分配到非 EAX/EDX 读到垃圾。显式 mov 到输出寄存器(与 asm.inb 修复同模式)。 c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)} @@ -70,67 +70,67 @@ def rdmsr(msr: t.CUInt32T) -> t.CUInt64T: mov {c.AsmOut(hi, t.ASM_DESCR.OUTPUT_REG)}, edx""", out=[c.AsmOut(lo, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(hi, t.ASM_DESCR.OUTPUT_REG)], op=[t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX]) - return t.CUInt64T(lo) | (t.CUInt64T(hi) << 32) + return uint64(lo) | (uint64(hi) << 32) def _current_proc() -> process.Process | t.CPtr: return process.ProcessManager.current() -def _fd_alloc(p: process.Process | t.CPtr) -> t.CInt: +def _fd_alloc(p: process.Process | t.CPtr) -> int: for i in range(process.PROC_MAX_FDS): if not p.fd_used[i]: p.fd_used[i] = 1 return i return -1 -def _fd_free(p: process.Process | t.CPtr, fd: t.CInt): +def _fd_free(p: process.Process | t.CPtr, fd: int): if fd >= 0 and fd < process.PROC_MAX_FDS: p.fd_used[fd] = 0 p.fd_table[fd] = t.CVoid(0, t.CPtr) -def _dir_alloc(p: process.Process | t.CPtr) -> t.CInt: +def _dir_alloc(p: process.Process | t.CPtr) -> int: for i in range(process.PROC_MAX_DIRS): if not p.dir_used[i]: p.dir_used[i] = 1 return i return -1 -def _dir_free(p: process.Process | t.CPtr, dd: t.CInt): +def _dir_free(p: process.Process | t.CPtr, dd: int): if dd >= 0 and dd < process.PROC_MAX_DIRS: p.dir_used[dd] = 0 p.dir_table[dd] = t.CVoid(0, t.CPtr) -def CREATE_WINDOW(x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | t.CChar | t.CPtr, style: t.CInt) -> t.CInt: +def CREATE_WINDOW(x: int, y: int, w: int, h: int, title: t.CConst | t.CChar | t.CPtr, style: int) -> int: desktop.set_app_pid(process.current()) return desktop.create(x, y, w, h, title, style) -def DRAW_TEXT(win_id: t.CInt, x: t.CInt, y: t.CInt, text: t.CConst | t.CChar | t.CPtr, color: t.CUInt32T) -> t.CInt: +def DRAW_TEXT(win_id: int, x: int, y: int, text: t.CConst | t.CChar | t.CPtr, color: uint32) -> int: return desktop.draw_text(win_id, x, y, text, color) -def EXIT(code: t.CInt) -> t.CInt: +def EXIT(code: int) -> int: serial.puts("[syscall] exit called\n") desktop.destroy_by_pid(process.current()) return 0 -def WAIT_WINDOW(win_id: t.CInt) -> t.CInt: +def WAIT_WINDOW(win_id: int) -> int: while desktop.is_active(win_id): sched.Scheduler.try_reschedule() return 0 -def SERIAL_PUTS(str_ptr: t.CVoid | t.CPtr) -> t.CInt: +def SERIAL_PUTS(str_ptr: t.CPtr) -> int: s: t.CConst | t.CChar | t.CPtr = t.CVoid(str_ptr, t.CPtr) serial.puts(s) return 0 -_loaded_so_base: t.CVoid | t.CPtr = None +_loaded_so_base: t.CPtr = None _loaded_so_path: t.CArray[t.CChar, 64] -def LOAD_SO(path_ptr: t.CVoid | t.CPtr) -> t.CUInt64T: +def LOAD_SO(path_ptr: t.CPtr) -> uint64: global _loaded_so_base path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) serial.puts("[so] loading: ") serial.puts(path) serial.puts("\n") - base: t.CVoid | t.CPtr = elf.load_so(path) + base: t.CPtr = elf.load_so(path) if base is not None: _loaded_so_base = base for i in range(63): @@ -138,13 +138,13 @@ def LOAD_SO(path_ptr: t.CVoid | t.CPtr) -> t.CUInt64T: _loaded_so_path[i] = ch if ch == 0: break _loaded_so_path[63] = 0 - return t.CUInt64T(base) + return uint64(base) return 0 -def SO_CALL1(sym_name_ptr: t.CVoid | t.CPtr, arg1: t.CVoid | t.CPtr) -> t.CInt: +def SO_CALL1(sym_name_ptr: t.CPtr, arg1: t.CPtr) -> int: if _loaded_so_base is None: return -1 sym_name: t.CConst | t.CChar | t.CPtr = t.CVoid(sym_name_ptr, t.CPtr) - fn: t.CVoid | t.CPtr = elf.get_so_symbol(_loaded_so_base, sym_name, c.Addr(_loaded_so_path[0])) + fn: t.CPtr = elf.get_so_symbol(_loaded_so_base, sym_name, c.Addr(_loaded_so_path[0])) if fn is None: serial.puts("[so] symbol not found\n") return -2 @@ -158,29 +158,29 @@ def SO_CALL1(sym_name_ptr: t.CVoid | t.CPtr, arg1: t.CVoid | t.CPtr) -> t.CInt: serial.puts("[so] call returned\n") return 0 -def GET_WINBUF(win_id: t.CInt) -> t.CUInt64T: - buf: t.CVoid | t.CPtr = desktop.get_fb(win_id) +def GET_WINBUF(win_id: int) -> uint64: + buf: t.CPtr = desktop.get_fb(win_id) if buf is None: return 0 - return t.CUInt64T(buf) + return uint64(buf) -def WIN_FLUSH(win_id: t.CInt) -> t.CInt: +def WIN_FLUSH(win_id: int) -> int: desktop.flush(win_id) return 0 -def SET_CURSOR(win_id: t.CInt, cursor_t: t.CInt) -> t.CInt: +def SET_CURSOR(win_id: int, cursor_t: int) -> int: desktop.set_cursor_type(win_id, cursor_t) return 0 -def OPEN(path_ptr: t.CVoid | t.CPtr, mode: t.CUInt32T) -> t.CInt: +def OPEN(path_ptr: t.CPtr, mode: uint32) -> int: p: process.Process | t.CPtr = _current_proc() path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) fat32.lock() - fp: t.CVoid | t.CPtr = fat32.open(path, t.CUInt8T(mode)) + fp: t.CPtr = fat32.open(path, uint8(mode)) if not fp: fat32.unlock() return -1 - fd: t.CInt = _fd_alloc(p) + fd: int = _fd_alloc(p) if fd < 0: fat32.close(fp) fat32.unlock() @@ -189,146 +189,146 @@ def OPEN(path_ptr: t.CVoid | t.CPtr, mode: t.CUInt32T) -> t.CInt: fat32.unlock() return fd -def CLOSE(fd: t.CInt) -> t.CInt: +def CLOSE(fd: int) -> int: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) - fp: t.CVoid | t.CPtr = p.fd_table[fd] + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) + fp: t.CPtr = p.fd_table[fd] if not fp: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) fat32.lock() - res: t.CInt = t.CInt(fat32.close(fp)) + res: int = int(fat32.close(fp)) fat32.unlock() _fd_free(p, fd) return res -def READ(fd: t.CInt, buf_ptr: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: +def READ(fd: int, buf_ptr: t.CPtr, count: uint32) -> int: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: return -1 - fp: t.CVoid | t.CPtr = p.fd_table[fd] + fp: t.CPtr = p.fd_table[fd] if not fp: return -1 fat32.lock() - br: t.CUInt32T = fat32.read(fp, buf_ptr, count) + br: uint32 = fat32.read(fp, buf_ptr, count) fat32.unlock() - return t.CInt(br) + return int(br) -def WRITE(fd: t.CInt, buf_ptr: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: +def WRITE(fd: int, buf_ptr: t.CPtr, count: uint32) -> int: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: return -1 - fp: t.CVoid | t.CPtr = p.fd_table[fd] + fp: t.CPtr = p.fd_table[fd] if not fp: return -1 fat32.lock() - bw: t.CUInt32T = fat32.write(fp, buf_ptr, count) + bw: uint32 = fat32.write(fp, buf_ptr, count) fat32.unlock() - return t.CInt(bw) + return int(bw) -def SEEK(fd: t.CInt, offset: t.CUInt32T) -> t.CInt: +def SEEK(fd: int, offset: uint32) -> int: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) - fp: t.CVoid | t.CPtr = p.fd_table[fd] + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) + fp: t.CPtr = p.fd_table[fd] if not fp: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) fat32.lock() - r: t.CInt = t.CInt(fat32.seek(fp, offset)) + r: int = int(fat32.seek(fp, offset)) fat32.unlock() return r -def TELL(fd: t.CInt) -> t.CUInt32T: +def TELL(fd: int) -> uint32: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: return 0 - fp: t.CVoid | t.CPtr = p.fd_table[fd] + fp: t.CPtr = p.fd_table[fd] if not fp: return 0 fat32.lock() - pos: t.CUInt32T = fat32.tell(fp) + pos: uint32 = fat32.tell(fp) fat32.unlock() return pos -def fsize(fd: t.CInt) -> t.CUInt32T: +def fsize(fd: int) -> uint32: p: process.Process | t.CPtr = _current_proc() if fd < 0 or fd >= process.PROC_MAX_FDS: return 0 - fp: t.CVoid | t.CPtr = p.fd_table[fd] + fp: t.CPtr = p.fd_table[fd] if not fp: return 0 fat32.lock() - sz: t.CUInt32T = fat32.size(fp) + sz: uint32 = fat32.size(fp) fat32.unlock() return sz -def MKDIR(path_ptr: t.CVoid | t.CPtr) -> t.CInt: +def MKDIR(path_ptr: t.CPtr) -> int: path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) fat32.lock() - r: t.CInt = t.CInt(fat32.mkdir(path)) + r: int = int(fat32.mkdir(path)) fat32.unlock() return r -def REMOVE(path_ptr: t.CVoid | t.CPtr) -> t.CInt: +def REMOVE(path_ptr: t.CPtr) -> int: path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) fat32.lock() - r: t.CInt = t.CInt(fat32.remove(path)) + r: int = int(fat32.remove(path)) fat32.unlock() return r -def OPENdir(path_ptr: t.CVoid | t.CPtr) -> t.CInt: +def OPENdir(path_ptr: t.CPtr) -> int: p: process.Process | t.CPtr = _current_proc() path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) - dd: t.CInt = _dir_alloc(p) + dd: int = _dir_alloc(p) if dd < 0: return -1 dp: fat32_types.dirobj | t.CPtr = c.Addr(p.dir_pool[dd]) fat32.lock() - res: t.CInt = t.CInt(fat32.opendir(path, dp)) + res: int = int(fat32.opendir(path, dp)) fat32.unlock() if res != 0: _dir_free(p, dd) return -1 - p.dir_table[dd] = t.CVoid(t.CUInt64T(dp), t.CPtr) + p.dir_table[dd] = t.CVoid(uint64(dp), t.CPtr) return dd -def READdir(dd: t.CInt, info_ptr: t.CVoid | t.CPtr) -> t.CInt: +def READdir(dd: int, info_ptr: t.CPtr) -> int: p: process.Process | t.CPtr = _current_proc() if dd < 0 or dd >= process.PROC_MAX_DIRS: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) - dp: t.CVoid | t.CPtr = p.dir_table[dd] + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) + dp: t.CPtr = p.dir_table[dd] if not dp: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) info: fat32_types.fileinfo | t.CPtr = info_ptr fat32.lock() - r: t.CInt = t.CInt(fat32.readdir(dp, info)) + r: int = int(fat32.readdir(dp, info)) fat32.unlock() return r -def CLOSEdir(dd: t.CInt) -> t.CInt: +def CLOSEdir(dd: int) -> int: p: process.Process | t.CPtr = _current_proc() if dd < 0 or dd >= process.PROC_MAX_DIRS: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) - dp: t.CVoid | t.CPtr = p.dir_table[dd] + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) + dp: t.CPtr = p.dir_table[dd] if not dp: - return t.CInt(fat32_types.FRESULT.FR_INVALID_OBJECT) + return int(fat32_types.FRESULT.FR_INVALID_OBJECT) fat32.lock() fat32.closedir(dp) fat32.unlock() _dir_free(p, dd) return 0 -def STAT(path_ptr: t.CVoid | t.CPtr, info_ptr: t.CVoid | t.CPtr) -> t.CInt: +def STAT(path_ptr: t.CPtr, info_ptr: t.CPtr) -> int: path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) info: fat32_types.fileinfo | t.CPtr = info_ptr fat32.lock() - r: t.CInt = t.CInt(fat32.stat(path, info)) + r: int = int(fat32.stat(path, info)) fat32.unlock() return r -def SPAWN(path_ptr: t.CVoid | t.CPtr, blocking: t.CInt) -> t.CInt: +def SPAWN(path_ptr: t.CPtr, blocking: int) -> int: path: t.CConst | t.CChar | t.CPtr = t.CVoid(path_ptr, t.CPtr) - pid: t.CInt = elf.spawn_elf(path) + pid: int = elf.spawn_elf(path) if pid < 0: return pid if blocking: @@ -340,135 +340,135 @@ def SPAWN(path_ptr: t.CVoid | t.CPtr, blocking: t.CInt) -> t.CInt: USER_HEAP_BASE: t.CDefine = 0x20000000 -def MMAP(size: t.CUInt64T) -> t.CUInt64T: +def MMAP(size: uint64) -> uint64: p: process.Process | t.CPtr = _current_proc() if size == 0: return 0 - aligned_size: t.CUInt64T = (size + 4095) & ~t.CUInt64T(4095) + aligned_size: uint64 = (size + 4095) & ~uint64(4095) if p.heap_start == 0: p.heap_start = USER_HEAP_BASE - heap_end: t.CUInt64T = p.heap_start + p.heap_size - new_end: t.CUInt64T = heap_end + aligned_size + heap_end: uint64 = p.heap_start + p.heap_size + new_end: uint64 = heap_end + aligned_size for va in range(heap_end, new_end, 4096): - phys_page: t.CVoid | t.CPtr = mm.malloc(4096) + phys_page: t.CPtr = mm.malloc(4096) if phys_page is None: return 0 - paging.MapPage(va, t.CUInt64T(phys_page), paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) + paging.MapPage(va, uint64(phys_page), paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER) p.heap_size = p.heap_size + aligned_size return heap_end -def MUNMAP(ptr: t.CUInt64T, size: t.CUInt64T) -> t.CInt: +def MUNMAP(ptr: uint64, size: uint64) -> int: return 0 def syscall_entry() -> t.CExtern | t.CVoid | t.State: pass -def syscall_handler(num: t.CUInt64T, arg1: t.CUInt64T, arg2: t.CUInt64T, arg3: t.CUInt64T, arg4: t.CUInt64T, arg5: t.CUInt64T, arg6: t.CUInt64T) -> t.CExport | t.CUInt64T: - n: t.CInt = t.CInt(num) +def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4: uint64, arg5: uint64, arg6: uint64) -> t.CExport | uint64: + n: int = int(num) if n == CREATE_WINDOW: - title_ptr: t.CVoid | t.CPtr = t.CVoid(arg5, t.CPtr) - return t.CUInt64T(CREATE_WINDOW(t.CInt(arg1), t.CInt(arg2), t.CInt(arg3), t.CInt(arg4), title_ptr, t.CInt(arg6))) + title_ptr: t.CPtr = t.CVoid(arg5, t.CPtr) + return uint64(CREATE_WINDOW(int(arg1), int(arg2), int(arg3), int(arg4), title_ptr, int(arg6))) elif n == DRAW_TEXT: - text_ptr: t.CVoid | t.CPtr = t.CVoid(arg4, t.CPtr) - return t.CUInt64T(DRAW_TEXT(t.CInt(arg1), t.CInt(arg2), t.CInt(arg3), text_ptr, t.CUInt32T(arg5))) + text_ptr: t.CPtr = t.CVoid(arg4, t.CPtr) + return uint64(DRAW_TEXT(int(arg1), int(arg2), int(arg3), text_ptr, uint32(arg5))) elif n == EXIT: - return t.CUInt64T(EXIT(t.CInt(arg1))) + return uint64(EXIT(int(arg1))) elif n == OPEN: - path_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(OPEN(path_ptr, t.CUInt32T(arg2))) + path_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(OPEN(path_ptr, uint32(arg2))) elif n == CLOSE: - return t.CUInt64T(CLOSE(t.CInt(arg1))) + return uint64(CLOSE(int(arg1))) elif n == READ: - buf_ptr: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - return t.CUInt64T(READ(t.CInt(arg1), buf_ptr, t.CUInt32T(arg3))) + buf_ptr: t.CPtr = t.CVoid(arg2, t.CPtr) + return uint64(READ(int(arg1), buf_ptr, uint32(arg3))) elif n == WRITE: - buf_ptr: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - return t.CUInt64T(WRITE(t.CInt(arg1), buf_ptr, t.CUInt32T(arg3))) + buf_ptr: t.CPtr = t.CVoid(arg2, t.CPtr) + return uint64(WRITE(int(arg1), buf_ptr, uint32(arg3))) elif n == SEEK: - return t.CUInt64T(SEEK(t.CInt(arg1), t.CUInt32T(arg2))) + return uint64(SEEK(int(arg1), uint32(arg2))) elif n == TELL: - return t.CUInt64T(TELL(t.CInt(arg1))) + return uint64(TELL(int(arg1))) elif n == SIZE: - return t.CUInt64T(fsize(t.CInt(arg1))) + return uint64(fsize(int(arg1))) elif n == MKDIR: - path_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(MKDIR(path_ptr)) + path_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(MKDIR(path_ptr)) elif n == REMOVE: - path_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(REMOVE(path_ptr)) + path_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(REMOVE(path_ptr)) elif n == OPENDIR: - path_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(OPENdir(path_ptr)) + path_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(OPENdir(path_ptr)) elif n == READDIR: - info_ptr: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - return t.CUInt64T(READdir(t.CInt(arg1), info_ptr)) + info_ptr: t.CPtr = t.CVoid(arg2, t.CPtr) + return uint64(READdir(int(arg1), info_ptr)) elif n == CLOSEDIR: - return t.CUInt64T(CLOSEdir(t.CInt(arg1))) + return uint64(CLOSEdir(int(arg1))) elif n == STAT: - path_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - info_ptr: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - return t.CUInt64T(STAT(path_ptr, info_ptr)) + path_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + info_ptr: t.CPtr = t.CVoid(arg2, t.CPtr) + return uint64(STAT(path_ptr, info_ptr)) elif n == WAIT_WINDOW: - if t.CInt(arg2) == 1: - return t.CUInt64T(desktop.is_active(t.CInt(arg1))) - elif t.CInt(arg2) == 2: + if int(arg2) == 1: + return uint64(desktop.is_active(int(arg1))) + elif int(arg2) == 2: sched.Scheduler.try_reschedule() return 0 - return t.CUInt64T(WAIT_WINDOW(t.CInt(arg1))) + return uint64(WAIT_WINDOW(int(arg1))) elif n == SERIAL_PUTS: - str_ptr_sp: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(SERIAL_PUTS(str_ptr_sp)) + str_ptr_sp: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(SERIAL_PUTS(str_ptr_sp)) elif n == LOAD_SO: - path_ptr_so: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) + path_ptr_so: t.CPtr = t.CVoid(arg1, t.CPtr) return LOAD_SO(path_ptr_so) elif n == SO_CALL1: - sym_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(SO_CALL1(sym_ptr, t.CPtr(arg2))) + sym_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(SO_CALL1(sym_ptr, t.CPtr(arg2))) elif n == GET_WINBUF: - return GET_WINBUF(t.CInt(arg1)) + return GET_WINBUF(int(arg1)) elif n == WIN_FLUSH: - return t.CUInt64T(WIN_FLUSH(t.CInt(arg1))) + return uint64(WIN_FLUSH(int(arg1))) elif n == POLL_EVENT: - buf_ptr_ev: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - caller_pid_ev: t.CInt = process.current() - return t.CUInt64T(desktop.poll_event(buf_ptr_ev, caller_pid_ev)) + buf_ptr_ev: t.CPtr = t.CVoid(arg1, t.CPtr) + caller_pid_ev: int = process.current() + return uint64(desktop.poll_event(buf_ptr_ev, caller_pid_ev)) elif n == SET_CURSOR: - desktop.set_cursor_type(t.CInt(arg1), t.CInt(arg2)) + desktop.set_cursor_type(int(arg1), int(arg2)) return 0 elif n == YIELD: sched.Scheduler.try_reschedule() return 0 elif n == SET_TITLE: - title_ptr_st: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - return t.CUInt64T(desktop.set_title(t.CInt(arg1), title_ptr_st)) + title_ptr_st: t.CPtr = t.CVoid(arg2, t.CPtr) + return uint64(desktop.set_title(int(arg1), title_ptr_st)) elif n == SET_GEOMETRY: - return t.CUInt64T(desktop.set_geometry(t.CInt(arg1), t.CInt(arg2), t.CInt(arg3), t.CInt(arg4), t.CInt(arg5))) + return uint64(desktop.set_geometry(int(arg1), int(arg2), int(arg3), int(arg4), int(arg5))) elif n == SET_RESIZABLE: - return t.CUInt64T(desktop.set_resizable(t.CInt(arg1), t.CInt(arg2), t.CInt(arg3))) + return uint64(desktop.set_resizable(int(arg1), int(arg2), int(arg3))) elif n == GET_WIN_SIZE: - return t.CUInt64T(desktop.get_size(t.CInt(arg1))) + return uint64(desktop.get_size(int(arg1))) elif n == SPAWN: - path_ptr_sp: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - return t.CUInt64T(SPAWN(path_ptr_sp, t.CInt(arg2))) + path_ptr_sp: t.CPtr = t.CVoid(arg1, t.CPtr) + return uint64(SPAWN(path_ptr_sp, int(arg2))) elif n == MMAP: return MMAP(arg1) elif n == MUNMAP: - return t.CUInt64T(MUNMAP(arg1, arg2)) + return uint64(MUNMAP(arg1, arg2)) elif n == THREAD_CREATE: - func_ptr: t.CVoid | t.CPtr = t.CVoid(arg1, t.CPtr) - arg_ptr: t.CVoid | t.CPtr = t.CVoid(arg2, t.CPtr) - cur_pid: t.CInt = process.current() + func_ptr: t.CPtr = t.CVoid(arg1, t.CPtr) + arg_ptr: t.CPtr = t.CVoid(arg2, t.CPtr) + cur_pid: int = process.current() th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(func_ptr, arg_ptr, cur_pid) - if th is None: return t.CUInt64T(0xFFFFFFFFFFFFFFFF) + if th is None: return uint64(0xFFFFFFFFFFFFFFFF) p: process.Process | t.CPtr = process.ProcessManager.get_process(cur_pid) if p: p.addThread(th.tid) - return t.CUInt64T(th.tid) + return uint64(th.tid) return 0 def init(): - efer: t.CUInt64T = rdmsr(IA32_EFER) + efer: uint64 = rdmsr(IA32_EFER) efer = efer | 1 wrmsr(IA32_EFER, efer) - star_val: t.CUInt64T = (t.CUInt64T(0x08) << 32) | (t.CUInt64T(0x1B) << 48) + star_val: uint64 = (uint64(0x08) << 32) | (uint64(0x1B) << 48) wrmsr(IA32_STAR, star_val) - wrmsr(IA32_LSTAR, t.CUInt64T(syscall_entry)) + wrmsr(IA32_LSTAR, uint64(syscall_entry)) wrmsr(IA32_FMASK, 0x200) serial.puts("[syscall] MSR init done\n") diff --git a/VKernel/Kernel/main.vp b/VKernel/Kernel/main.vp index 4fb2d09..a21fd3c 100644 --- a/VKernel/Kernel/main.vp +++ b/VKernel/Kernel/main.vp @@ -32,8 +32,8 @@ import t, c import asm -kbd_tid: t.CInt = -1 -mse_tid: t.CInt = -1 +kbd_tid: int = -1 +mse_tid: int = -1 BootInfo: bootinfo.bootinfo | t.CPtr @@ -61,7 +61,7 @@ class ViperKernel: # Set IA32_KERNEL_GS_BASE = &_per_cpu so swapgs in ISR/syscall works. # _CPUObject is never instantiated, so __init_tss__ never runs; # without this, GS base stays 0 and gs:[0] writes hit null -> triple fault. - cpu.msr_write(cpu.IA32_KERNEL_GS_BASE, t.CUInt64T(c.Addr(cpu._per_cpu))) + cpu.msr_write(cpu.IA32_KERNEL_GS_BASE, uint64(c.Addr(cpu._per_cpu))) serial.puts("[main] gdt init done\n") intr.idt.init() syscall.init() @@ -84,12 +84,12 @@ class ViperKernel: serial.puts("[main] apic init done\n") # [DBG] 综合诊断:判定 LAPIC MMIO 是否真正可访问/可写(用后移除) - _dbg_base: t.CUInt64T = apic.get_base() - _dbg_ver: t.CUInt32T = apic.read(0x030) # LAPIC_VERSION:真 LAPIC 应为 0x50014 - _dbg_svr: t.CUInt32T = apic.read(0x0F0) # LAPIC_SVR:init 已写 0x1FF + _dbg_base: uint64 = apic.get_base() + _dbg_ver: uint32 = apic.read(0x030) # LAPIC_VERSION:真 LAPIC 应为 0x50014 + _dbg_svr: uint32 = apic.read(0x0F0) # LAPIC_SVR:init 已写 0x1FF apic.write(0x350, 0x700) # 再次写 LINT0,验证写粘性 - _dbg_lint0: t.CUInt32T = apic.read(0x350) - _dbg_feat: t.CUInt32T = cpu.detect_features_static() + _dbg_lint0: uint32 = apic.read(0x350) + _dbg_feat: uint32 = cpu.detect_features_static() _dbg_buf: t.CArray[t.CChar, 160] viperlib.snprintf(c.Addr(_dbg_buf), 160, "[DBG] base=0x%lx ver=0x%x svr=0x%x lint0=0x%x feat=0x%x apic=%d\n", @@ -98,9 +98,9 @@ class ViperKernel: serial.puts(c.Addr(_dbg_buf)) # [DBG] 读回 IDT 门 32,验证 isr32 分发地址是否正确安装(用后移除) - _g32: t.CUInt64T = (t.CUInt64T(intr.idt.idt[32].base_low) | - (t.CUInt64T(intr.idt.idt[32].base_middle) << 16) | - (t.CUInt64T(intr.idt.idt[32].base_high) << 32)) + _g32: uint64 = (uint64(intr.idt.idt[32].base_low) | + (uint64(intr.idt.idt[32].base_middle) << 16) | + (uint64(intr.idt.idt[32].base_high) << 32)) _g32buf: t.CArray[t.CChar, 96] viperlib.snprintf(c.Addr(_g32buf), 96, "[DBG] idt32 base=0x%lx sel=0x%x type=0x%x\n", _g32, intr.idt.idt[32].selector, intr.idt.idt[32].type_attr) @@ -118,7 +118,7 @@ class ViperKernel: # [DBG] 读 PIC1 ISR:bit0 置位说明 PIT IRQ0 已到达 PIC 并被响应(用后移除) asm.outb(0x20, 0x0B) # OCW3 读 ISR asm.io_wait() - _pic_isr: t.CUInt8T = asm.inb(0x20) + _pic_isr: uint8 = asm.inb(0x20) _isrbuf: t.CArray[t.CChar, 48] viperlib.snprintf(c.Addr(_isrbuf), 48, "[DBG] pic_isr=0x%x\n", _pic_isr) serial.puts(c.Addr(_isrbuf)) @@ -127,7 +127,7 @@ class ViperKernel: serial.puts("[main] msleep done\n") rtc.rtc_init() serial.puts("[main] rtc init done\n") - ncpu: t.CUInt32T = apic.get_cpu_count() + ncpu: uint32 = apic.get_cpu_count() ncpu_cr: t.CArray[t.CChar, 32] viperlib.snprintf(c.Addr(ncpu_cr), 32, "[main] cpu_count=%u\n", ncpu) serial.puts(ncpu_cr) @@ -135,26 +135,26 @@ class ViperKernel: apic.start_aps() serial.puts("[main] kernel init done\n") - fb: t.CVoid | t.CPtr = t.CPtr(BootInfo.framebuffer_addr) - width: t.CUInt64T = BootInfo.framebuffer_width - height: t.CUInt64T = BootInfo.framebuffer_height - pitch: t.CUInt64T = BootInfo.framebuffer_pitch - fb_format: t.CUInt64T = BootInfo.framebuffer_format - fb_size: t.CUInt64T = BootInfo.framebuffer_size + fb: t.CPtr = t.CPtr(BootInfo.framebuffer_addr) + width: uint64 = BootInfo.framebuffer_width + height: uint64 = BootInfo.framebuffer_height + pitch: uint64 = BootInfo.framebuffer_pitch + fb_format: uint64 = BootInfo.framebuffer_format + fb_size: uint64 = BootInfo.framebuffer_size # [DBG] 打印 BootInfo 指针与 memmap 原始字段,定位全 0 根因(用后移除) _dbbuf: t.CArray[t.CChar, 140] viperlib.snprintf(c.Addr(_dbbuf), 140, "[main] BootInfo=0x%lx mmap=0x%lx mmsz=%lu mmd=%lu fb=0x%lx\n", - t.CUInt64T(BootInfo), BootInfo.MemmapAddr, BootInfo.MemmapSize, + uint64(BootInfo), BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr) serial.puts(c.Addr(_dbbuf)) # [DBG] 转储 BootInfo 地址处原始 88 字节(用后移除) _dbraw: t.CArray[t.CChar, 16] - _dbi: t.CInt = 0 + _dbi: int = 0 while _dbi < 88: if (_dbi % 16) == 0: viperlib.snprintf(c.Addr(_dbraw), 16, "\n[DB] %04x:", _dbi) serial.puts(c.Addr(_dbraw)) - _dbv: t.CUInt8T = c.Deref(t.CUInt8T(t.CUInt64T(BootInfo) + t.CUInt64T(_dbi), t.CPtr)) + _dbv: uint8 = c.Deref(uint8(uint64(BootInfo) + uint64(_dbi), t.CPtr)) viperlib.snprintf(c.Addr(_dbraw), 16, " %02x", _dbv) serial.puts(c.Addr(_dbraw)) _dbi += 1 @@ -162,20 +162,20 @@ class ViperKernel: if BootInfo is not None: paging.init(BootInfo.MemmapAddr, BootInfo.MemmapSize) - fb_pages: t.CUInt64T = (fb_size + t.CUInt64T(0xFFF)) >> t.CUInt64T(12) - fpi: t.CUInt64T = 0 + fb_pages: uint64 = (fb_size + uint64(0xFFF)) >> uint64(12) + fpi: uint64 = 0 while fpi < fb_pages: - fva: t.CUInt64T = t.CUInt64T(fb) + fpi * t.CUInt64T(0x1000) + fva: uint64 = uint64(fb) + fpi * uint64(0x1000) paging.MapPage(fva, fva, paging.PTE_WRITABLE | paging.PTE_PCD) fpi += 1 mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size) - pt_pool_buf: t.CVoid | t.CPtr = mm.malloc(t.CUInt64T(513) * t.CUInt64T(4096)) - paging.init_pool(pt_pool_buf, t.CUInt64T(513) * t.CUInt64T(4096)) + pt_pool_buf: t.CPtr = mm.malloc(uint64(513) * uint64(4096)) + paging.init_pool(pt_pool_buf, uint64(513) * uint64(4096)) else: paging.init(0, 0) mm.init(0, 0, 0, 0, 0) - pt_pool_buf2: t.CVoid | t.CPtr = mm.malloc(t.CUInt64T(513) * t.CUInt64T(4096)) - paging.init_pool(pt_pool_buf2, t.CUInt64T(513) * t.CUInt64T(4096)) + pt_pool_buf2: t.CPtr = mm.malloc(uint64(513) * uint64(4096)) + paging.init_pool(pt_pool_buf2, uint64(513) * uint64(4096)) serial.puts("[main] paging and mm init done\n") # 把 .rodata(字符串常量/vtable)映射只读 + CR0.WP=1: # 越界写立即 #PF 暴露 cr2/rip(此前静默破坏格式串/路径/符号名 → P2/P3/P4/P5 连锁) @@ -192,26 +192,26 @@ class ViperKernel: serial.puts("[main] ide init done\n") serial.puts("[main] initializing FAT32 filesystem\n") - scan_res: t.CInt = fat32.scan_drives() - ndrives: t.CInt = fat32.get_drive_count() + scan_res: int = fat32.scan_drives() + ndrives: int = fat32.get_drive_count() ndrives_cr: t.CArray[t.CChar, 64] viperlib.snprintf(c.Addr(ndrives_cr), 64, "[fat32] scan_res=%d found %d drives\n", scan_res, ndrives) serial.puts(ndrives_cr) if ndrives > 0: - mount_res: t.CInt = fat32.mount() + mount_res: int = fat32.mount() if mount_res == 0: dp: fat32_types.dirobj - res: t.CInt = fat32.opendir("/", c.Addr(dp)) + res: int = fat32.opendir("/", c.Addr(dp)) if res == 0: serial.puts("[fat32] listing 0:/\n") - count: t.CInt = 0 + count: int = 0 while count < 20: info: fat32_types.fileinfo - res2: t.CInt = fat32.readdir(c.Addr(dp), c.Addr(info)) + res2: int = fat32.readdir(c.Addr(dp), c.Addr(info)) if res2 != 0: break if info.fname[0] == 0: break - is_dir: t.CInt = 1 if (info.attr & fat32_types.AM_DIR) else 0 + is_dir: int = 1 if (info.attr & fat32_types.AM_DIR) else 0 entry_cr: t.CArray[t.CChar, 300] viperlib.snprintf(c.Addr(entry_cr), 300, " %s size=%lu dir=%d\n", c.Addr(info.fname[0]), info.file_size, is_dir) serial.puts(entry_cr) @@ -224,13 +224,13 @@ class ViperKernel: # Load ELF apps BEFORE running destructive FAT32 tests serial.puts("[main] loading ELF apps...\n") dp_apps: fat32_types.dirobj - apps_res: t.CInt = fat32.opendir("/APPS", c.Addr(dp_apps)) + apps_res: int = fat32.opendir("/APPS", c.Addr(dp_apps)) if apps_res == 0: serial.puts("[main] APPS dir listing:\n") - ac: t.CInt = 0 + ac: int = 0 while ac < 20: ai: fat32_types.fileinfo - ar: t.CInt = fat32.readdir(c.Addr(dp_apps), c.Addr(ai)) + ar: int = fat32.readdir(c.Addr(dp_apps), c.Addr(ai)) if ar != 0: break if ai.fname[0] == 0: break ae: t.CArray[t.CChar, 300] @@ -265,7 +265,7 @@ class ViperKernel: serial.puts("[main] sched started\n") - fd: t.CInt = devfs.devfs_open("/dev/serial0", 0) + fd: int = devfs.devfs_open("/dev/serial0", 0) buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) devfs.devfs_write(fd, "hello from devfs!", 17) @@ -327,10 +327,10 @@ class ViperKernel: serial.puts("[main] entering main loop\n") # sched.sched_dump() - last_sec: t.CUInt32T = 0 - loop_cnt: t.CUInt32T = 0 + last_sec: uint32 = 0 + loop_cnt: uint32 = 0 while True: - cur_sec: t.CUInt32T = timer.timer_get_seconds() + cur_sec: uint32 = timer.timer_get_seconds() if cur_sec != last_sec: last_sec = cur_sec #if cur_sec % 5 == 0: @@ -360,7 +360,7 @@ VKP: ViperKernel | t.CPtr # stackrealign:_start 由 bootloader jmp 进入(rsp≡0 mod 16),llc 按 call 约定 # 假设入口 rsp≡8 → 帧偏 8 → 变参函数 movaps #GP。动态重对齐栈修复。 @c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16), t.attr.stackrealign) -def _start() -> t.CInt: +def _start() -> int: global VKP, BootInfo saved_rdi: t.CUnsignedLong c.Asm(f"mov {c.AsmOut(saved_rdi, t.ASM_DESCR.OUTPUT_REG)}, rdi", diff --git a/VKernel/Kernel/mm/mm.vp b/VKernel/Kernel/mm/mm.vp index 0c63819..20a9b1f 100644 --- a/VKernel/Kernel/mm/mm.vp +++ b/VKernel/Kernel/mm/mm.vp @@ -15,24 +15,24 @@ BLOCK_FREE: t.CDefine = 0 # 空闲 BLOCK_USED: t.CDefine = 1 # 已使用 # 内存类型定义 -MEMORY_TYPE_AVAILABLE: t.CUInt64T = 7 -MEMORY_TYPE_RESERVED: t.CUInt64T = 0 -MEMORY_TYPE_LOADER_CODE: t.CUInt64T = 1 -MEMORY_TYPE_LOADER_DATA: t.CUInt64T = 2 -MEMORY_TYPE_BOOT_SERVICES_CODE: t.CUInt64T = 3 -MEMORY_TYPE_BOOT_SERVICES_DATA: t.CUInt64T = 4 -MEMORY_TYPE_RUNTIME_SERVICES_CODE: t.CUInt64T = 5 -MEMORY_TYPE_RUNTIME_SERVICES_DATA: t.CUInt64T = 6 -MEMORY_TYPE_ACPI_RECLAIMABLE: t.CUInt64T = 9 -MEMORY_TYPE_ACPI_NVS: t.CUInt64T = 10 -MEMORY_TYPE_BAD_MEMORY: t.CUInt64T = 8 +MEMORY_TYPE_AVAILABLE: uint64 = 7 +MEMORY_TYPE_RESERVED: uint64 = 0 +MEMORY_TYPE_LOADER_CODE: uint64 = 1 +MEMORY_TYPE_LOADER_DATA: uint64 = 2 +MEMORY_TYPE_BOOT_SERVICES_CODE: uint64 = 3 +MEMORY_TYPE_BOOT_SERVICES_DATA: uint64 = 4 +MEMORY_TYPE_RUNTIME_SERVICES_CODE: uint64 = 5 +MEMORY_TYPE_RUNTIME_SERVICES_DATA: uint64 = 6 +MEMORY_TYPE_ACPI_RECLAIMABLE: uint64 = 9 +MEMORY_TYPE_ACPI_NVS: uint64 = 10 +MEMORY_TYPE_BAD_MEMORY: uint64 = 8 # 内存区域结构 class memory_region(t.CStruct): - start: t.CUInt64T - end: t.CUInt64T - size: t.CUInt64T - type: t.CUInt32T + start: uint64 + end: uint64 + size: uint64 + type: uint32 next: 'memory_region' | t.CPtr # 全局内存区域链表 @@ -40,20 +40,20 @@ memory_regions: t.CStatic | memory_region | t.CPtr = None # 内存块结构 class memory_block(t.CStruct): - size: t.CUInt64T # 块大小 - state: t.CUInt8T # 块状态 - order: t.CUInt8T # 块阶数 + size: uint64 # 块大小 + state: uint8 # 块状态 + order: uint8 # 块阶数 next: 'memory_block' | t.CPtr # 下一个块 prev: 'memory_block' | t.CPtr # 上一个块 # 伙伴系统结构 class __buddy_system(t.CStruct): free_lists: t.CArray[memory_block | t.CPtr, MAX_ORDER + 1] - total_memory: t.CUInt64T # 总内存大小 - used_memory: t.CUInt64T # 已使用内存大小 - free_memory: t.CUInt64T # 空闲内存大小 - start_addr: t.CVoid | t.CPtr # 内存起始地址 - end_addr: t.CVoid | t.CPtr # 内存结束地址 + total_memory: uint64 # 总内存大小 + used_memory: uint64 # 已使用内存大小 + free_memory: uint64 # 空闲内存大小 + start_addr: t.CPtr # 内存起始地址 + end_addr: t.CPtr # 内存结束地址 SLAB_MAGIC: t.CDefine = 0x534C4142 @@ -61,34 +61,34 @@ SLAB_NUM_SIZES: t.CDefine = 6 SLAB_THRESHOLD: t.CDefine = 1024 class slab_page(t.CStruct): - magic: t.CUInt32T - obj_size: t.CUInt16T - free_count: t.CUInt16T - data_offset: t.CUInt16T - total_objs: t.CUInt16T - free_head: t.CVoid | t.CPtr + magic: uint32 + obj_size: uint16 + free_count: uint16 + data_offset: uint16 + total_objs: uint16 + free_head: t.CPtr block_ptr: memory_block | t.CPtr next: 'slab_page' | t.CPtr prev: 'slab_page' | t.CPtr # 4K对齐函数 -def align_4k(addr: t.CUInt64T) -> t.CUInt64T: +def align_4k(addr: uint64) -> uint64: return (addr + 0xFFF) & ~0xFFF # 计算阶数 -def get_order(size: t.CUInt64T) -> t.CStatic | t.CInt: - order: t.CInt = 0 +def get_order(size: uint64) -> t.CStatic | int: + order: int = 0 while size > MIN_BLOCK_SIZE: size >>= 1 order += 1 return order # 计算块大小 -def get_block_size(order: t.CInt) -> t.CStatic | t.CUInt64T: +def get_block_size(order: int) -> t.CStatic | uint64: # 4096 << 20 = 4GB 超出 i32 范围 → 0x0 → 伙伴初始化无限循环(bs=0x0)。 # 必须用 64 位移位(4096<<20 = 4294967296)。 - return t.CUInt64T(MIN_BLOCK_SIZE) << t.CUInt64T(order) + return uint64(MIN_BLOCK_SIZE) << uint64(order) @t.Object @@ -96,27 +96,27 @@ class _BuddySystemObject: # 全局伙伴系统实例 buddy: __buddy_system # 初始化伙伴系统 - def __init__(self, start_addr: t.CVoid | t.CPtr, size: t.CUInt64T): + def __init__(self, start_addr: t.CPtr, size: uint64): for i in range(MAX_ORDER + 1): self.buddy.free_lists[i] = None self.buddy.total_memory = size self.buddy.used_memory = 0 self.buddy.free_memory = size self.buddy.start_addr = start_addr - self.buddy.end_addr = t.CVoid(t.CUInt64T(start_addr) + size, t.CPtr) - remaining: t.CUInt64T = size - cur_addr: t.CUInt64T = t.CUInt64T(start_addr) + self.buddy.end_addr = t.CVoid(uint64(start_addr) + size, t.CPtr) + remaining: uint64 = size + cur_addr: uint64 = uint64(start_addr) # [DBG] buddy 初始化循环进度(用后移除) import drivers.serial.uart.serial as _sdbg _dbp: t.CArray[t.CChar, 80] - _itc: t.CInt = 0 + _itc: int = 0 while remaining >= MIN_BLOCK_SIZE: - order: t.CInt = 0 - tmp: t.CUInt64T = remaining + order: int = 0 + tmp: uint64 = remaining while tmp > MIN_BLOCK_SIZE: tmp >>= 1 order += 1 - block_size: t.CUInt64T = get_block_size(order) + block_size: uint64 = get_block_size(order) while block_size > remaining and order > 0: order -= 1 block_size = get_block_size(order) @@ -144,23 +144,23 @@ class _BuddySystemObject: import drivers.serial.uart.serial as serial _dmsg: t.CArray[t.CChar, 40] serial.puts("[mm] buddy init:") - _di: t.CInt = 0 + _di: int = 0 while _di <= MAX_ORDER: if self.buddy.free_lists[_di]: - viperlib.snprintf(c.Addr(_dmsg), 40, " [%d]=0x%lx", _di, t.CUInt64T(self.buddy.free_lists[_di])) + viperlib.snprintf(c.Addr(_dmsg), 40, " [%d]=0x%lx", _di, uint64(self.buddy.free_lists[_di])) serial.puts(_dmsg) _di += 1 serial.puts("\n") # 分割内存块 - def split_block(self, block: memory_block | t.CPtr, target_order: t.CInt) -> memory_block | t.CPtr: - current_order: t.CInt = block.order + def split_block(self, block: memory_block | t.CPtr, target_order: int) -> memory_block | t.CPtr: + current_order: int = block.order # 从当前阶数向下分割,直到达到目标阶数 while current_order > target_order: current_order -= 1 - new_block_size: t.CUInt64T = get_block_size(current_order) + new_block_size: uint64 = get_block_size(current_order) # 创建新块 - new_block: memory_block | t.CPtr = t.CPtr(t.CUInt64T(block) + new_block_size) + new_block: memory_block | t.CPtr = t.CPtr(uint64(block) + new_block_size) new_block.size = new_block_size new_block.state = BLOCK_FREE new_block.order = current_order @@ -179,13 +179,13 @@ class _BuddySystemObject: # 合并内存块 def merge_blocks(self, block: memory_block | t.CPtr) -> t.CStatic | memory_block | t.CPtr: - order: t.CInt = block.order + order: int = block.order while order < MAX_ORDER: - block_size: t.CUInt64T = get_block_size(order) - block_addr: t.CUInt64T = t.CUInt64T(block) - t.CUInt64T(self.buddy.start_addr) - buddy_addr: t.CUInt64T = block_addr ^ block_size + block_size: uint64 = get_block_size(order) + block_addr: uint64 = uint64(block) - uint64(self.buddy.start_addr) + buddy_addr: uint64 = block_addr ^ block_size # 计算伙伴块地址 - buddy: memory_block | t.CPtr = t.CPtr(t.CUInt64T(self.buddy.start_addr) + buddy_addr) + buddy: memory_block | t.CPtr = t.CPtr(uint64(self.buddy.start_addr) + buddy_addr) # 检查伙伴块是否存在且空闲 if buddy >= t.CType(self.buddy.end_addr, memory_block, t.CPtr): break # 伙伴块超出内存范围 @@ -205,12 +205,12 @@ class _BuddySystemObject: return block # 分配内存块 - def allocate_block(self, size: t.CUInt64T) -> t.CStatic | memory_block | t.CPtr: + def allocate_block(self, size: uint64) -> t.CStatic | memory_block | t.CPtr: # 计算所需阶数 - order: t.CInt = get_order(size) + order: int = get_order(size) if order > MAX_ORDER: return None # 所需块大小超过最大限制 # 查找合适的空闲块 - found_order: t.CInt = -1 + found_order: int = -1 for i in range(order, MAX_ORDER + 1): if self.buddy.free_lists[i]: found_order = i @@ -222,11 +222,11 @@ class _BuddySystemObject: viperlib.snprintf(c.Addr(_dba), 120, "[mm] alloc FAIL size=%lu order=%d\n", size, order) serial.puts(_dba) _dbf: t.CArray[t.CChar, 200] - _fi: t.CInt = 0 - _fo: t.CInt = 0 + _fi: int = 0 + _fo: int = 0 while _fi <= MAX_ORDER: if self.buddy.free_lists[_fi]: - _fs: t.CInt = viperlib.snprintf(c.Addr(_dbf) + _fo, 200 - _fo, "[%d]=0x%lx ", _fi, t.CUInt64T(self.buddy.free_lists[_fi])) + _fs: int = viperlib.snprintf(c.Addr(_dbf) + _fo, 200 - _fo, "[%d]=0x%lx ", _fi, uint64(self.buddy.free_lists[_fi])) _fo = _fo + _fs _fi += 1 if _fo == 0: @@ -249,7 +249,7 @@ class _BuddySystemObject: # 更新内存统计 self.buddy.used_memory += block.size self.buddy.free_memory -= block.size - viperlib.snprintf(c.Addr(_dba), 120, "[mm] alloc OK size=%lu order=%d found=%d block=0x%lx\n", size, order, found_order, t.CUInt64T(block)) + viperlib.snprintf(c.Addr(_dba), 120, "[mm] alloc OK size=%lu order=%d found=%d block=0x%lx\n", size, order, found_order, uint64(block)) serial.puts(_dba) return block @@ -263,7 +263,7 @@ class _BuddySystemObject: # 尝试合并块 block = self.merge_blocks(block) # 将块添加到对应阶数的空闲链表 - order: t.CInt = block.order + order: int = block.order if order <= MAX_ORDER: block.next = self.buddy.free_lists[order] block.prev = None @@ -273,7 +273,7 @@ class _BuddySystemObject: BuddySystemObject: _BuddySystemObject -def _slab_obj_size(size_class: t.CInt) -> t.CUInt16T: +def _slab_obj_size(size_class: int) -> uint16: if size_class == 0: return 32 if size_class == 1: return 64 if size_class == 2: return 128 @@ -281,7 +281,7 @@ def _slab_obj_size(size_class: t.CInt) -> t.CUInt16T: if size_class == 4: return 512 return 1024 -def _slab_size_class(size: t.CUInt64T) -> t.CInt: +def _slab_size_class(size: uint64) -> int: if size <= 32: return 0 if size <= 64: return 1 if size <= 128: return 2 @@ -290,31 +290,31 @@ def _slab_size_class(size: t.CUInt64T) -> t.CInt: if size <= 1024: return 5 return -1 -def _slab_read_ptr(addr: t.CVoid | t.CPtr) -> t.CVoid | t.CPtr: - result: t.CVoid | t.CPtr +def _slab_read_ptr(addr: t.CPtr) -> t.CPtr: + result: t.CPtr c.Asm(f"""mov rax, [{c.AsmInp(addr, t.ASM_DESCR.REG_ANY)}] mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) return result -def _slab_write_ptr(addr: t.CVoid | t.CPtr, val: t.CVoid | t.CPtr): +def _slab_write_ptr(addr: t.CPtr, val: t.CPtr): c.Asm(f"""mov rax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)} mov [{c.AsmInp(addr, t.ASM_DESCR.REG_ANY)}], rax""", op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_MEMORY]) -def _slab_find_page(ptr: t.CVoid | t.CPtr) -> slab_page | t.CPtr: +def _slab_find_page(ptr: t.CPtr) -> slab_page | t.CPtr: if ptr is None: return None - hdr_off: t.CUInt64T = memory_block.__sizeof__() - page_addr: t.CUInt64T = t.CUInt64T(ptr) & ~t.CUInt64T(0xFFF) + hdr_off: uint64 = memory_block.__sizeof__() + page_addr: uint64 = uint64(ptr) & ~uint64(0xFFF) page: slab_page | t.CPtr = t.CPtr(page_addr + hdr_off) if page.magic == SLAB_MAGIC: - os: t.CUInt16T = page.obj_size + os: uint16 = page.obj_size if os == 32 or os == 64 or os == 128 or os == 256 or os == 512 or os == 1024: return page - page_addr2: t.CUInt64T = page_addr - 4096 + page_addr2: uint64 = page_addr - 4096 page2: slab_page | t.CPtr = t.CPtr(page_addr2 + hdr_off) if page2.magic == SLAB_MAGIC: - os2: t.CUInt16T = page2.obj_size + os2: uint16 = page2.obj_size if os2 == 32 or os2 == 64 or os2 == 128 or os2 == 256 or os2 == 512 or os2 == 1024: return page2 return None @@ -327,34 +327,34 @@ class _SlabAllocator: for i in range(SLAB_NUM_SIZES): self.caches[i] = None - def _create_page(self, size_class: t.CInt) -> slab_page | t.CPtr: - obj_size: t.CUInt16T = _slab_obj_size(size_class) - aligned_size: t.CUInt16T = t.CUInt16T((obj_size + 15) & ~15) + def _create_page(self, size_class: int) -> slab_page | t.CPtr: + obj_size: uint16 = _slab_obj_size(size_class) + aligned_size: uint16 = uint16((obj_size + 15) & ~15) block: memory_block | t.CPtr = BuddySystemObject.allocate_block(4096 + memory_block.__sizeof__()) if not block: return None - hdr_off: t.CUInt64T = memory_block.__sizeof__() - page: slab_page | t.CPtr = t.CPtr(t.CUInt64T(block) + hdr_off) + hdr_off: uint64 = memory_block.__sizeof__() + page: slab_page | t.CPtr = t.CPtr(uint64(block) + hdr_off) page.magic = SLAB_MAGIC page.obj_size = aligned_size - d_off: t.CUInt16T = t.CUInt16T((hdr_off + slab_page.__sizeof__() + 15) & ~15) + d_off: uint16 = uint16((hdr_off + slab_page.__sizeof__() + 15) & ~15) page.data_offset = d_off - total: t.CUInt16T = t.CUInt16T((block.size - d_off) / aligned_size) + total: uint16 = uint16((block.size - d_off) / aligned_size) page.total_objs = total page.free_count = total page.block_ptr = block page.next = None page.prev = None - data_start: t.CUInt64T = t.CUInt64T(block) + d_off + data_start: uint64 = uint64(block) + d_off page.free_head = t.CVoid(data_start, t.CPtr) for i in range(1, total): - cur: t.CVoid | t.CPtr = t.CVoid(data_start + t.CUInt64T(i - 1) * aligned_size, t.CPtr) - nxt: t.CVoid | t.CPtr = t.CVoid(data_start + t.CUInt64T(i) * aligned_size, t.CPtr) + cur: t.CPtr = t.CVoid(data_start + uint64(i - 1) * aligned_size, t.CPtr) + nxt: t.CPtr = t.CVoid(data_start + uint64(i) * aligned_size, t.CPtr) _slab_write_ptr(cur, nxt) - last: t.CVoid | t.CPtr = t.CVoid(data_start + t.CUInt64T(total - 1) * aligned_size, t.CPtr) + last: t.CPtr = t.CVoid(data_start + uint64(total - 1) * aligned_size, t.CPtr) _slab_write_ptr(last, t.CVoid(0, t.CPtr)) return page - def alloc(self, size_class: t.CInt) -> t.CVoid | t.CPtr: + def alloc(self, size_class: int) -> t.CPtr: page: slab_page | t.CPtr = self.caches[size_class] while page: if page.free_count > 0: break @@ -366,12 +366,12 @@ class _SlabAllocator: if self.caches[size_class]: self.caches[size_class].prev = page self.caches[size_class] = page - obj: t.CVoid | t.CPtr = page.free_head + obj: t.CPtr = page.free_head page.free_head = _slab_read_ptr(obj) page.free_count -= 1 return obj - def free_obj(self, ptr: t.CVoid | t.CPtr, page: slab_page | t.CPtr): + def free_obj(self, ptr: t.CPtr, page: slab_page | t.CPtr): _slab_write_ptr(ptr, page.free_head) page.free_head = ptr page.free_count += 1 @@ -379,7 +379,7 @@ class _SlabAllocator: if page.prev: page.prev.next = page.next else: - sc: t.CInt = _slab_size_class(page.obj_size) + sc: int = _slab_size_class(page.obj_size) if sc >= 0: self.caches[sc] = page.next if page.next: @@ -391,99 +391,99 @@ SlabAllocator: _SlabAllocator # 内存分配函数 -def malloc(size: t.CUInt64T) -> t.CVoid | t.CPtr | t.CExport: +def malloc(size: uint64) -> t.CPtr | t.CExport: if size == 0: return None if size <= SLAB_THRESHOLD: - sc: t.CInt = _slab_size_class(size) + sc: int = _slab_size_class(size) if sc >= 0: - result: t.CVoid | t.CPtr = SlabAllocator.alloc(sc) + result: t.CPtr = SlabAllocator.alloc(sc) return result - hdr: t.CUInt64T = memory_block.__sizeof__() + hdr: uint64 = memory_block.__sizeof__() if size >= 4096: - total: t.CUInt64T = size + 4096 + total: uint64 = size + 4096 total = align_4k(total) - order: t.CInt = get_order(total) + order: int = get_order(total) if order > MAX_ORDER: return None block: memory_block | t.CPtr = BuddySystemObject.allocate_block(total) import drivers.serial.uart.serial as serial _dbm: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbm), 120, "[mm] malloc buddy size=%lu block=0x%lx\n", size, t.CUInt64T(block)) + viperlib.snprintf(c.Addr(_dbm), 120, "[mm] malloc buddy size=%lu block=0x%lx\n", size, uint64(block)) serial.puts(_dbm) if not block: return None - user_ptr: t.CUInt64T = (t.CUInt64T(block) + hdr + 4095) & ~t.CUInt64T(4095) - real_hdr: t.CUInt64T = user_ptr - 8 + user_ptr: uint64 = (uint64(block) + hdr + 4095) & ~uint64(4095) + real_hdr: uint64 = user_ptr - 8 c.Asm(f"""mov rax, {c.AsmInp(block, t.ASM_DESCR.REG_ANY)} mov [{c.AsmInp(t.CVoid(real_hdr, t.CPtr), t.ASM_DESCR.REG_ANY)}], rax""", op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_MEMORY]) viperlib.snprintf(c.Addr(_dbm), 120, "[mm] malloc ret user_ptr=0x%lx\n", user_ptr) serial.puts(_dbm) return t.CVoid(user_ptr, t.CPtr) - total2: t.CUInt64T = size + hdr + total2: uint64 = size + hdr total2 = align_4k(total2) - order2: t.CInt = get_order(total2) + order2: int = get_order(total2) if order2 > MAX_ORDER: return None block2: memory_block | t.CPtr = BuddySystemObject.allocate_block(total2) if not block2: return None - return t.CVoid(t.CUInt64T(block2) + hdr, t.CPtr) + return t.CVoid(uint64(block2) + hdr, t.CPtr) -def malloc_direct(size: t.CUInt64T) -> t.CVoid | t.CPtr | t.CExport: +def malloc_direct(size: uint64) -> t.CPtr | t.CExport: if size == 0: return None - hdr: t.CUInt64T = memory_block.__sizeof__() - total: t.CUInt64T = size + hdr + hdr: uint64 = memory_block.__sizeof__() + total: uint64 = size + hdr total = align_4k(total) - order: t.CInt = get_order(total) + order: int = get_order(total) if order > MAX_ORDER: return None block: memory_block | t.CPtr = BuddySystemObject.allocate_block(total) if not block: return None - return t.CVoid(t.CUInt64T(block) + hdr, t.CPtr) + return t.CVoid(uint64(block) + hdr, t.CPtr) -def free(ptr: t.CVoid | t.CPtr) -> t.CExport: +def free(ptr: t.CPtr) -> t.CExport: if ptr is None: return sp: slab_page | t.CPtr = _slab_find_page(ptr) if sp: SlabAllocator.free_obj(ptr, sp) return - if (t.CUInt64T(ptr) & 0xFFF) == 0: - real_hdr: t.CUInt64T = t.CUInt64T(ptr) - 8 + if (uint64(ptr) & 0xFFF) == 0: + real_hdr: uint64 = uint64(ptr) - 8 block: memory_block | t.CPtr c.Asm(f"""mov rax, [{c.AsmInp(t.CVoid(real_hdr, t.CPtr), t.ASM_DESCR.REG_ANY)}] mov {c.AsmOut(block, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) BuddySystemObject.free_block(block) return - block2: memory_block | t.CPtr = t.CPtr(t.CUInt64T(ptr) - memory_block.__sizeof__()) + block2: memory_block | t.CPtr = t.CPtr(uint64(ptr) - memory_block.__sizeof__()) BuddySystemObject.free_block(block2) -def calloc(nmemb: t.CUInt64T, size: t.CUInt64T) -> t.CVoid | t.CPtr | t.CExport: - total_size: t.CUInt64T = nmemb * size - ptr: t.CVoid | t.CPtr = malloc(total_size) +def calloc(nmemb: uint64, size: uint64) -> t.CPtr | t.CExport: + total_size: uint64 = nmemb * size + ptr: t.CPtr = malloc(total_size) if ptr: string.memset(ptr, 0, total_size) return ptr -def realloc(ptr: t.CVoid | t.CPtr, size: t.CUInt64T) -> t.CVoid | t.CPtr | t.CExport: +def realloc(ptr: t.CPtr, size: uint64) -> t.CPtr | t.CExport: if ptr is None: return malloc(size) if size == 0: free(ptr) return None - new_ptr: t.CVoid | t.CPtr = malloc(size) + new_ptr: t.CPtr = malloc(size) if not new_ptr: return None sp: slab_page | t.CPtr = _slab_find_page(ptr) if sp: - old_size: t.CUInt64T = sp.obj_size - elif (t.CUInt64T(ptr) & 0xFFF) == 0: - real_hdr_r: t.CUInt64T = t.CUInt64T(ptr) - 8 + old_size: uint64 = sp.obj_size + elif (uint64(ptr) & 0xFFF) == 0: + real_hdr_r: uint64 = uint64(ptr) - 8 block_r: memory_block | t.CPtr c.Asm(f"""mov rax, [{c.AsmInp(t.CVoid(real_hdr_r, t.CPtr), t.ASM_DESCR.REG_ANY)}] mov {c.AsmOut(block_r, t.ASM_DESCR.OUTPUT_REG)}, rax""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) old_size = block_r.size - 4096 else: - block2: memory_block | t.CPtr = t.CPtr(t.CUInt64T(ptr) - memory_block.__sizeof__()) + block2: memory_block | t.CPtr = t.CPtr(uint64(ptr) - memory_block.__sizeof__()) old_size = block2.size - memory_block.__sizeof__() - copy_size: t.CUInt64T = old_size if old_size < size else size + copy_size: uint64 = old_size if old_size < size else size string.memcpy(new_ptr, ptr, copy_size) free(ptr) return new_ptr @@ -500,7 +500,7 @@ def free_memory_regions() -> t.CStatic | t.CVoid: memory_regions = None # 初始化内存管理系统 -def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt64T, FbAddr: t.CUInt64T = 0, FbSize: t.CUInt64T = 0): +def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0): global BuddySystemObject import drivers.serial.uart.serial as serial # [DBG] 无条件打印 memmap 三参数,判定分支未走的根因(用后移除) @@ -508,43 +508,43 @@ def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt viperlib.snprintf(c.Addr(_dk0), 100, "[mm] raw addr=0x%lx size=%lu desc=%lu\n", MemmapAddr, MemmapSize, MemmapDescSize) serial.puts(c.Addr(_dk0)) - start_addr: t.CVoid | t.CPtr = None - size: t.CUInt64T = 0 + start_addr: t.CPtr = None + size: uint64 = 0 if MemmapAddr != 0: if MemmapSize > 0: if MemmapDescSize > 0: - num_entries: t.CUInt64T = MemmapSize / MemmapDescSize + num_entries: uint64 = MemmapSize / MemmapDescSize # [DBG] 关键数值:memmap 缓冲/步长/条目数(用后移除) _dk1: t.CArray[t.CChar, 100] viperlib.snprintf(c.Addr(_dk1), 100, "[mm] addr=0x%lx size=%lu desc=%lu entries=%lu\n", MemmapAddr, MemmapSize, MemmapDescSize, num_entries) serial.puts(c.Addr(_dk1)) - max_memory: t.CUInt64T = 0 - best_start: t.CUInt64T = 0 - best_avail_size: t.CUInt64T = 0 - best_avail_start: t.CUInt64T = 0 - best_bs_size: t.CUInt64T = 0 - best_bs_start: t.CUInt64T = 0 - best_ld_size: t.CUInt64T = 0 - best_ld_start: t.CUInt64T = 0 - i: t.CUInt64T + max_memory: uint64 = 0 + best_start: uint64 = 0 + best_avail_size: uint64 = 0 + best_avail_start: uint64 = 0 + best_bs_size: uint64 = 0 + best_bs_start: uint64 = 0 + best_ld_size: uint64 = 0 + best_ld_start: uint64 = 0 + i: uint64 # [DBG] 转储全部 memmap 描述符,定位 4GB 伪可用区的来源(用后移除) for i in range(num_entries): entry: bootinfo.memory_map_entry | t.CPtr = t.CVoid(MemmapAddr + i * MemmapDescSize, t.CPtr) _dbgd: t.CArray[t.CChar, 100] viperlib.snprintf(c.Addr(_dbgd), 100, "[mm] d[%lu] t=%lu start=0x%lx np=%lu\n", - i, t.CUInt64T(entry.type), entry.physical_start, entry.num_pages) + i, uint64(entry.type), entry.physical_start, entry.num_pages) serial.puts(c.Addr(_dbgd)) for i in range(num_entries): entry: bootinfo.memory_map_entry | t.CPtr = t.CVoid(MemmapAddr + i * MemmapDescSize, t.CPtr) - etype: t.CUInt64T = entry.type - start: t.CUInt64T = align_4k(entry.physical_start) - np: t.CUInt64T = entry.num_pages - end: t.CUInt64T = entry.physical_start + np * 4096 + etype: uint64 = entry.type + start: uint64 = align_4k(entry.physical_start) + np: uint64 = entry.num_pages + end: uint64 = entry.physical_start + np * 4096 end = align_4k(end - 1) - region_size: t.CUInt64T = end - start + region_size: uint64 = end - start if FbAddr != 0 and FbSize != 0: - fb_end: t.CUInt64T = FbAddr + FbSize + fb_end: uint64 = FbAddr + FbSize if start < fb_end and end > FbAddr: continue if etype == MEMORY_TYPE_AVAILABLE: @@ -559,7 +559,7 @@ def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt if region_size > best_ld_size: best_ld_size = region_size best_ld_start = start - min_blk: t.CUInt64T = MIN_BLOCK_SIZE + min_blk: uint64 = MIN_BLOCK_SIZE if best_avail_size >= min_blk: best_start = best_avail_start max_memory = best_avail_size @@ -584,7 +584,7 @@ def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt viperlib.snprintf(c.Addr(_dc0), 100, "[mm] fallback cmos 0x%02x 0x%02x 0x%02x 0x%02x\n", cmos_read(0x15), cmos_read(0x16), cmos_read(0x17), cmos_read(0x18)) serial.puts(c.Addr(_dc0)) - _dsz: t.CUInt64T = detect_memory_size() + _dsz: uint64 = detect_memory_size() viperlib.snprintf(c.Addr(_dc0), 100, "[mm] fallback detect=%lu\n", _dsz) serial.puts(c.Addr(_dc0)) size = detect_memory_size() @@ -595,13 +595,13 @@ def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt if size > 0x400000: size = size - 0x400000 size = align_4k(size) - min_blk2: t.CUInt64T = MIN_BLOCK_SIZE + min_blk2: uint64 = MIN_BLOCK_SIZE if size < min_blk2: size = 33554432 cr2: t.CArray[t.CChar, 128] string.memset(c.Addr(cr2), 0, 128) viperlib.snprintf(c.Addr(cr2), 128, "mm.init: start=0x%lx size=%lu bytes\n", - t.CUInt64T(start_addr), size) + uint64(start_addr), size) serial.puts(cr2) BuddySystemObject.__init__(start_addr, size) SlabAllocator.__init__() @@ -609,10 +609,10 @@ def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T, MemmapDescSize: t.CUInt # 虚拟内存映射结构 class vm_area(t.CStruct): - VirtAddr: t.CUInt64T - PhysAddr: t.CUInt64T - size: t.CUInt64T - flags: t.CUInt32T + VirtAddr: uint64 + PhysAddr: uint64 + size: uint64 + flags: uint32 next: 'vm_area' | t.CPtr # 全局虚拟内存区域链表 @@ -623,15 +623,15 @@ ALLOCATION_RETRIES: t.CDefine = 5 # 分配重试次数 FRAGMENTATION_THRESHOLD: t.CDefine = 0.7 # 碎片率阈值 # 获取内存使用统计 -@c.CReturn(t.CUInt64T, t.CUInt64T, t.CUInt64T) +@c.CReturn(uint64, uint64, uint64) def GetMemoryStats(): return (BuddySystemObject.buddy.total_memory, BuddySystemObject.buddy.used_memory, BuddySystemObject.buddy.free_memory) # 计算内存碎片率 def calculate_fragmentation() -> t.CDouble: # 计算空闲块的数量和总大小 - free_blocks: t.CInt = 0 - free_size: t.CUInt64T = 0 + free_blocks: int = 0 + free_size: uint64 = 0 for i in range(MAX_ORDER + 1): block: memory_block | t.CPtr = BuddySystemObject.buddy.free_lists[i] @@ -646,7 +646,7 @@ def calculate_fragmentation() -> t.CDouble: # 计算碎片率 # 碎片率 = 1 - (最大空闲块大小 / 总空闲内存大小) - max_free_block: t.CUInt64T = 0 + max_free_block: uint64 = 0 for i in range(MAX_ORDER, -1, -1): if BuddySystemObject.buddy.free_lists[i]: max_free_block = get_block_size(i) @@ -658,8 +658,8 @@ def calculate_fragmentation() -> t.CDouble: return 1.0 - (t.CDouble(max_free_block) / t.CDouble(free_size)) # 内存整理函数 -def compact_memory() -> t.CStatic | t.CInt: - freed_pages: t.CInt = 0 +def compact_memory() -> t.CStatic | int: + freed_pages: int = 0 for sc in range(SLAB_NUM_SIZES): page: slab_page | t.CPtr = SlabAllocator.caches[sc] while page: @@ -678,14 +678,14 @@ def compact_memory() -> t.CStatic | t.CInt: return freed_pages # 虚拟内存分配函数 -def vm_alloc(size: t.CUInt64T, flags: t.CUInt32T) -> t.CUInt64T: +def vm_alloc(size: uint64, flags: uint32) -> uint64: global vm_areas # 4K对齐 size = align_4k(size) # 尝试分配物理内存,使用博弈机制 - PhysAddr: t.CVoid | t.CPtr = None - retries: t.CInt = 0 + PhysAddr: t.CPtr = None + retries: int = 0 while retries < ALLOCATION_RETRIES: PhysAddr = malloc(size) @@ -703,7 +703,7 @@ def vm_alloc(size: t.CUInt64T, flags: t.CUInt32T) -> t.CUInt64T: # 分配虚拟地址 # 简单的虚拟地址分配策略:从0x100000000开始 - VirtAddr: t.CUInt64T = 0x100000000 + VirtAddr: uint64 = 0x100000000 current: vm_area | t.CPtr = vm_areas # 寻找合适的虚拟地址空间 @@ -717,7 +717,7 @@ def vm_alloc(size: t.CUInt64T, flags: t.CUInt32T) -> t.CUInt64T: area: vm_area | t.CPtr = malloc(vm_area.__sizeof__()) if area: area.VirtAddr = VirtAddr - area.PhysAddr = t.CUInt64T(PhysAddr) + area.PhysAddr = uint64(PhysAddr) area.size = size area.flags = flags area.next = vm_areas @@ -725,18 +725,18 @@ def vm_alloc(size: t.CUInt64T, flags: t.CUInt32T) -> t.CUInt64T: # 映射虚拟地址到物理地址 # 计算需要映射的页数 - pages: t.CUInt64T = size / 4096 - i: t.CUInt64T + pages: uint64 = size / 4096 + i: uint64 for i in range(pages): - page_virt: t.CUInt64T = VirtAddr + (i * 4096) - page_phys: t.CUInt64T = t.CUInt64T(PhysAddr) + (i * 4096) + page_virt: uint64 = VirtAddr + (i * 4096) + page_phys: uint64 = uint64(PhysAddr) + (i * 4096) # 调用paging模块的映射函数 paging.MapPage(page_virt, page_phys, flags) return VirtAddr # 虚拟内存释放函数 -def vm_free(VirtAddr: t.CUInt64T): +def vm_free(VirtAddr: uint64): global vm_areas # 查找虚拟内存区域 current: vm_area | t.CPtr = vm_areas @@ -745,10 +745,10 @@ def vm_free(VirtAddr: t.CUInt64T): while current: if current.VirtAddr == VirtAddr: # 取消虚拟地址映射 - pages: t.CUInt64T = current.size / 4096 - i: t.CUInt64T + pages: uint64 = current.size / 4096 + i: uint64 for i in range(pages): - page_virt: t.CUInt64T = current.VirtAddr + (i * 4096) + page_virt: uint64 = current.VirtAddr + (i * 4096) paging.UnMapPage(page_virt) # 释放物理内存 @@ -763,42 +763,42 @@ def vm_free(VirtAddr: t.CUInt64T): current = current.next # CMOS读取函数 -def cmos_read(reg: t.CUInt8T) -> t.CUInt8T: +def cmos_read(reg: uint8) -> uint8: # in/out al 会改 EAX,必须 CLOBBER_RAX;显式 mov 到输出寄存器 #(与 asm.inb/inw 修复同模式,避免调用方 EAX 被静默破坏)。 - c.Asm(f"""mov eax, {c.AsmInp(t.CUInt32T(reg), t.ASM_DESCR.REG_ANY)} + c.Asm(f"""mov eax, {c.AsmInp(uint32(reg), t.ASM_DESCR.REG_ANY)} out 0x70, al""", op=[t.ASM_DESCR.CLOBBER_RAX]) - val32: t.CUInt32T + val32: uint32 c.Asm(f"""in al, 0x71 movzx eax, al mov {c.AsmOut(val32, t.ASM_DESCR.OUTPUT_REG)}, eax""", out=[c.AsmOut(val32, t.ASM_DESCR.OUTPUT_REG)], op=[t.ASM_DESCR.CLOBBER_RAX]) - return t.CUInt8T(val32) + return uint8(val32) # 内存大小测试函数 -def detect_memory_size() -> t.CUInt64T: +def detect_memory_size() -> uint64: # 读取 1MB-16MB 扩展内存(KB 单位) - low: t.CUInt8T = cmos_read(0x15) - high: t.CUInt8T = cmos_read(0x16) - mem_kb: t.CUInt32T = (t.CUInt32T(high) << 8) | low + low: uint8 = cmos_read(0x15) + high: uint8 = cmos_read(0x16) + mem_kb: uint32 = (uint32(high) << 8) | low # 读取 16MB 以上扩展内存(64KB 块为单位) - low2: t.CUInt8T = cmos_read(0x17) - high2: t.CUInt8T = cmos_read(0x18) - mem_above_16mb: t.CUInt32T = (t.CUInt32T(high2) << 8) | low2 + low2: uint8 = cmos_read(0x17) + high2: uint8 = cmos_read(0x18) + mem_above_16mb: uint32 = (uint32(high2) << 8) | low2 # 两个寄存器都为 0 时使用默认值 if mem_kb == 0 and mem_above_16mb == 0: return 0x10000000 # 256MB # 计算总内存:1MB 基础 + 1MB-16MB + 16MB 以上 - total_size: t.CUInt64T = 1048576 # 前 1MB + total_size: uint64 = 1048576 # 前 1MB if mem_kb > 0: - total_size = total_size + t.CUInt64T(mem_kb) * 1024 + total_size = total_size + uint64(mem_kb) * 1024 if mem_above_16mb > 0: - total_size = total_size + t.CUInt64T(mem_above_16mb) * 65536 + total_size = total_size + uint64(mem_above_16mb) * 65536 total_size = align_4k(total_size) diff --git a/VKernel/Kernel/paging/paging.vp b/VKernel/Kernel/paging/paging.vp index 9c4cbd5..a95b3c7 100644 --- a/VKernel/Kernel/paging/paging.vp +++ b/VKernel/Kernel/paging/paging.vp @@ -1,479 +1,479 @@ -import drivers.serial.uart.serial as serial -import viperlib -import t, c - - -PTE_PRESENT: t.CDefine = (1 << 0) -PTE_WRITABLE: t.CDefine = (1 << 1) -PTE_USER: t.CDefine = (1 << 2) -PTE_PWT: t.CDefine = (1 << 3) -PTE_PCD: t.CDefine = (1 << 4) -PTE_ACCESSED: t.CDefine = (1 << 5) -PTE_DIRTY: t.CDefine = (1 << 6) -PTE_PS: t.CDefine = (1 << 7) -PTE_GLOBAL: t.CDefine = (1 << 8) - -class _p: - entries: t.CArray[t.CUInt64T, 512] - -PT_POOL_PAGES: t.CDefine = 512 -pt_pool_raw: t.CVoid | t.CPtr = None -pt_pool_start: t.CUInt64T = 0 -pt_pool_used: t.CUInt64T = 0 - -AllocatedPages: t.CUInt64T = 0 -pml4: _p | t.CPtr = None -pdp: _p | t.CPtr -pd: _p | t.CPtr -pt: _p | t.CPtr - -def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T): - global pml4 - pml4 = GetCurrentPml4() - # bootloader/UEFI 的 CR0.WP 通常已是 1(原代码清 WP 正因此)。页表页 - # (pml4/pdp/pd/pt,0xf8xxxx)默认只读,而内核运行时 MapPage/clone 需 - # 修改页表。顺序:先清 WP(允许写只读页表页)→ MakePTWritable 放开 - # 全部页表页 → 再置 WP=1(此后写只读页即 #PF 暴露越界写源)。 - c.Asm(f""" - mov rax, cr0 - and rax, ~0x10000 - mov cr0, rax - """) - MakePTWritable() - c.Asm(f""" - mov rax, cr0 - or rax, 0x10000 - mov cr0, rax - """) - -def init_pool(buf: t.CVoid | t.CPtr, buf_size: t.CUInt64T): - global pt_pool_raw, pt_pool_start, pt_pool_used - pt_pool_raw = buf - if buf is None: return - raw_addr: t.CUInt64T = t.CUInt64T(buf) - aligned_addr: t.CUInt64T = (raw_addr + t.CUInt64T(0xFFF)) & ~t.CUInt64T(0xFFF) - pt_pool_start = aligned_addr - pt_pool_used = 0 - # [DIAG] 定位 clone 时 pt_pool_raw=0x0(init 后被覆盖?还是 init 收到 0) - _dip: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_dip), 80, "[paging] init_pool raw=0x%lx start=0x%lx\n", t.CUInt64T(pt_pool_raw), pt_pool_start) - serial.puts(c.Addr(_dip)) - -def AllocPage() -> t.CVoid | t.CPtr: - global AllocatedPages, pt_pool_used, pml4, pdp, pd, pt - if pt_pool_raw is None: return None - if pt_pool_used >= t.CUInt64T(PT_POOL_PAGES): return None - page: t.CVoid | t.CPtr = t.CVoid(pt_pool_start + pt_pool_used * t.CUInt64T(4096), t.CPtr) - pt_pool_used = pt_pool_used + t.CUInt64T(1) - c.Asm(f"""mov al, 0 - mov ecx, 4096 - mov rdi, {c.AsmInp(page, t.ASM_DESCR.REG_ANY)} - rep stosb""", - op = [t.ASM_DESCR.CLOBBER_AL, t.ASM_DESCR.CLOBBER_ECX, t.ASM_DESCR.CLOBBER_RDI]) - AllocatedPages = AllocatedPages + t.CUInt64T(1) - return page - -def FreePage(page: t.CVoid | t.CPtr): - global AllocatedPages, pml4, pdp, pd, pt - if page is None: return - if AllocatedPages > 0: AllocatedPages = AllocatedPages - t.CUInt64T(1) - -def MapPage(VirtAddr: t.CUInt64T, PhysAddr: t.CUInt64T, flags: t.CUInt64T): - global pml4, pdp, pd, pt - if VirtAddr == 0 or PhysAddr == 0: return - VirtAddr = VirtAddr & ~t.CUInt64T(0xFFF) - PhysAddr = PhysAddr & ~t.CUInt64T(0xFFF) - Pml4Index: t.CUInt64T = (VirtAddr >> 39) & 0x1FF - PdpIndex: t.CUInt64T = (VirtAddr >> 30) & 0x1FF - PdIndex: t.CUInt64T = (VirtAddr >> 21) & 0x1FF - PtIndex: t.CUInt64T = (VirtAddr >> 12) & 0x1FF - - if not pml4: - pml4 = AllocPage() - if not pml4: return - - if not (pml4.entries[Pml4Index] & PTE_PRESENT): - pdp: _p | t.CPtr = AllocPage() - if not pdp: return - pml4.entries[Pml4Index] = (t.CUInt64T(pdp) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) - else: - if (flags & PTE_USER) and not (pml4.entries[Pml4Index] & PTE_USER): - pml4.entries[Pml4Index] = pml4.entries[Pml4Index] | PTE_USER - pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - if not (pdp.entries[PdpIndex] & PTE_PRESENT): - pd: _p | t.CPtr = AllocPage() - if not pd: return - pdp.entries[PdpIndex] = (t.CUInt64T(pd) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) - else: - if (flags & PTE_USER) and not (pdp.entries[PdpIndex] & PTE_USER): - pdp.entries[PdpIndex] = pdp.entries[PdpIndex] | PTE_USER - pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - if pd.entries[PdIndex] & 1: - if pd.entries[PdIndex] & 0x80: - big_phys: t.CUInt64T = pd.entries[PdIndex] & ~t.CUInt64T(0x1FFFFF) - inherit_flags: t.CUInt64T = pd.entries[PdIndex] & (PTE_PCD | PTE_PWT) - pt: _p | t.CPtr = AllocPage() - if not pt: return - split_i: t.CInt = 0 - while split_i < 512: - pt.entries[split_i] = (big_phys + t.CUInt64T(split_i) * 0x1000) | PTE_PRESENT | PTE_WRITABLE | inherit_flags - split_i += 1 - pd.entries[PdIndex] = (t.CUInt64T(pt) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) - else: - # PD entry exists as a regular PT (e.g. cloned identity mapping). - # Must propagate PTE_USER to the PD entry so user-mode access is - # allowed at all paging levels, otherwise #PF err=0x5. - if (flags & PTE_USER) and not (pd.entries[PdIndex] & PTE_USER): - pd.entries[PdIndex] = pd.entries[PdIndex] | PTE_USER - else: - pt: _p | t.CPtr = AllocPage() - if not pt: return - pd.entries[PdIndex] = (t.CUInt64T(pt) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) - pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - pt.entries[PtIndex] = PhysAddr | flags | PTE_PRESENT - c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") - -def MapLargePage(VirtAddr: t.CUInt64T, PhysAddr: t.CUInt64T, flags: t.CUInt64T) -> t.CVoid: - global pml4, pdp, pd, pt - VirtAddr = VirtAddr & ~t.CUInt64T(0x1FFFFF) - PhysAddr = PhysAddr & ~t.CUInt64T(0x1FFFFF) - Pml4Index: t.CUInt64T = (VirtAddr >> 39) & 0x1FF - PdpIndex: t.CUInt64T = (VirtAddr >> 30) & 0x1FF - PdIndex: t.CUInt64T = (VirtAddr >> 21) & 0x1FF - - if not pml4: - pml4 = AllocPage() - if not pml4: return - - if not pml4.entries[Pml4Index] & PTE_PRESENT: - pdp: _p | t.CPtr = AllocPage() - if not pdp: return - pml4.entries[Pml4Index] = (t.CUInt64T(pdp) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE - pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - if not (pdp.entries[PdpIndex] & PTE_PRESENT): - pd: _p | t.CPtr = AllocPage() - if not pd: return - pdp.entries[PdpIndex] = (t.CUInt64T(pd) & ~t.CUInt64T(0xFFF)) | PTE_PRESENT | PTE_WRITABLE - pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - pd.entries[PdIndex] = PhysAddr | flags | PTE_PRESENT | PTE_PS - c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") - -def UnMapPage(VirtAddr: t.CUInt64T): - global pml4, pdp, pd, pt - if VirtAddr == 0: return - if not pml4: return - Pml4Index: t.CUInt64T = (VirtAddr >> 39) & 0x1FF - PdpIndex: t.CUInt64T = (VirtAddr >> 30) & 0x1FF - PdIndex: t.CUInt64T = (VirtAddr >> 21) & 0x1FF - PtIndex: t.CUInt64T = (VirtAddr >> 12) & 0x1FF - - if not pml4.entries[Pml4Index] & PTE_PRESENT: return - - pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - if not pdp.entries[PdpIndex] & PTE_PRESENT: return - - pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - - if not pd.entries[PdIndex] & PTE_PRESENT: return - - if pd.entries[PdIndex] & PTE_PS: - pd.entries[PdIndex] = 0 - else: - pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt.entries[PtIndex] = 0 - - c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") - -def EnablePaging(): - global pml4, pdp, pd, pt - c.Asm(f"mov cr3, {c.AsmInp(t.CUInt64T(pml4), t.ASM_DESCR.REG_ANY)}") - -def _set_page_writable(phys_addr: t.CUInt64T): - """把物理页 phys_addr(identity 映射,虚拟=物理)的 PTE 置 W 位 - - 页表页(bootloader 建立的 pml4/pdp/pd/pt 位于 0xf8xxxx)默认只读, - 而内核运行时 MapPage/clone 需修改页表 → 必须先把这些页表页自身设为可写, - 否则 CR0.WP=1 下写页表触发 #PF(slog.so 映射 0x600000 新建页表项时 - cr2=0xf801000 err=0x3 根因)。 - """ - global pml4 - if not pml4: return - va: t.CUInt64T = phys_addr & ~t.CUInt64T(0xFFF) - pml4_idx: t.CUInt64T = (va >> 39) & 0x1FF - if not (pml4.entries[pml4_idx] & PTE_PRESENT): return - pdp_s: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pdp_idx: t.CUInt64T = (va >> 30) & 0x1FF - if not (pdp_s.entries[pdp_idx] & PTE_PRESENT): return - pd_s: _p | t.CPtr = t.CType(pdp_s.entries[pdp_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pd_idx: t.CUInt64T = (va >> 21) & 0x1FF - if not (pd_s.entries[pd_idx] & PTE_PRESENT): return - if pd_s.entries[pd_idx] & PTE_PS: - # 2MB 大页:W 位在 PD 条目自身(无下层 PT),直接置位 - pd_s.entries[pd_idx] = pd_s.entries[pd_idx] | t.CUInt64T(PTE_WRITABLE) - c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") - return - pt_s: _p | t.CPtr = t.CType(pd_s.entries[pd_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt_idx: t.CUInt64T = (va >> 12) & 0x1FF - pt_s.entries[pt_idx] = pt_s.entries[pt_idx] | t.CUInt64T(PTE_WRITABLE) - c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") - -def MakePTWritable(): - """把当前页表层次所有页表页(pml4 自身 + pdp/pd/pt)设为可写 - - 内核运行时需修改页表(MapPage/clone_for_process),而 bootloader 建立的 - 页表页映射为只读——CR0.WP=1 下必须先放开页表页自身,否则写页表即 #PF。 - """ - global pml4 - if not pml4: return - _set_page_writable(t.CUInt64T(pml4)) - pi: t.CUInt64T - for pi in range(512): - if not (pml4.entries[pi] & PTE_PRESENT): continue - pdp_m: _p | t.CPtr = t.CType(pml4.entries[pi] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - _set_page_writable(t.CUInt64T(pdp_m)) - pj: t.CUInt64T - for pj in range(512): - if not (pdp_m.entries[pj] & PTE_PRESENT): continue - pd_m: _p | t.CPtr = t.CType(pdp_m.entries[pj] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - _set_page_writable(t.CUInt64T(pd_m)) - pk: t.CUInt64T - for pk in range(512): - if not (pd_m.entries[pk] & PTE_PRESENT): continue - if pd_m.entries[pk] & PTE_PS: continue - pt_m: _p | t.CPtr = t.CType(pd_m.entries[pk] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - _set_page_writable(t.CUInt64T(pt_m)) - -def MakeRangeRO(vaddr_start: t.CUInt64T, vaddr_end: t.CUInt64T): - """把 [vaddr_start, vaddr_end) 范围内所有页的 PTE 清 W 位(只读) - - 定位越界写源:内核态写只读页在 CR0.WP=1 下触发 #PF(int=14), - isrCommonhandler 打印 cr2/rip → 写源立即暴露,不再静默破坏 .rodata。 - """ - global pml4 - if not pml4: return - va: t.CUInt64T = vaddr_start & ~t.CUInt64T(0xFFF) - # ro_end 下取整到页:不保护含 ro_end 的未对齐尾页。链接脚本输出段未页对齐, - # .data 紧跟 .rodata(__rodata_end 未对齐时 .data 起始落在 rodata 尾页内), - # 整页置只读会把 .data 全局(如 devfs @DevFSObject=0x141630)误保护 → - # devfs_init 写全局 #PF(cr2=0x141630 rip=0x101aaa mov [r15],rax 根因)。 - # 尾页含少量 rodata 尾部(对齐填充),保持可写可容忍。 - ro_end_align: t.CUInt64T = vaddr_end & ~t.CUInt64T(0xFFF) - while va < ro_end_align: - pml4_idx: t.CUInt64T = (va >> 39) & 0x1FF - if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue - pdp_r: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pdp_idx: t.CUInt64T = (va >> 30) & 0x1FF - if not (pdp_r.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue - pd_r: _p | t.CPtr = t.CType(pdp_r.entries[pdp_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pd_idx: t.CUInt64T = (va >> 21) & 0x1FF - if not (pd_r.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue - if pd_r.entries[pd_idx] & PTE_PS: - # 2MB 大页:直接跳过会让 .rodata 保持可写——越界写被静默吞掉 - # (perf 格式串 win=%lu/work=%lu 被逐步破坏的根因)。拆分为 512 - # 个 4KB 页(复用 MapPage 的分裂逻辑),再走下方常规路径清 W 位。 - # WP=1 后内核态写只读页即 #PF → isrCommonhandler 打印 cr2/rip 暴露写源。 - big_phys: t.CUInt64T = pd_r.entries[pd_idx] & ~t.CUInt64T(0x1FFFFF) - inherit_flags: t.CUInt64T = pd_r.entries[pd_idx] & (PTE_PCD | PTE_PWT | PTE_USER | t.CUInt64T(0x8000000000000000)) - pt_split: _p | t.CPtr = AllocPage() - if not pt_split: - va += 0x1000 - continue - split_i: t.CInt = 0 - while split_i < 512: - pt_split.entries[split_i] = (big_phys + t.CUInt64T(split_i) * t.CUInt64T(0x1000)) \ - | PTE_PRESENT | PTE_WRITABLE | inherit_flags - split_i += 1 - pd_r.entries[pd_idx] = (t.CUInt64T(pt_split) & ~t.CUInt64T(0xFFF)) \ - | PTE_PRESENT | PTE_WRITABLE | (pd_r.entries[pd_idx] & PTE_USER) - c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") - # 分裂后落入下方 4KB 常规路径,继续清当前页 W 位 - pt_r: _p | t.CPtr = t.CType(pd_r.entries[pd_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt_idx: t.CUInt64T = (va >> 12) & 0x1FF - pt_r.entries[pt_idx] = pt_r.entries[pt_idx] & ~t.CUInt64T(PTE_WRITABLE) - c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") - va += 0x1000 - -def ProtectKernelRO(): - """把内核镜像 .rodata 段(字符串常量/vtable 等)映射为只读 - - 地址经 c.Asm 内联引用链接器符号 __rodata_start/__rodata_end - (linker.ld 定义,TPV 不声明 extern——避免生成定义与链接器符号冲突)。 - """ - global pml4 - if not pml4: return - # 页表页可写已在 paging.init(WP=0 阶段)由 MakePTWritable 完成, - # 此处只保护 .rodata 内容页(WP=1 后写只读页即 #PF 暴露写源)。 - ro_start: t.CUInt64T = 0 - ro_end: t.CUInt64T = 0 - c.Asm(f"""lea rax, [rip + __rodata_start] - mov {c.AsmOut(ro_start, t.ASM_DESCR.OUTPUT_REG)}, rax - lea rax, [rip + __rodata_end] - mov {c.AsmOut(ro_end, t.ASM_DESCR.OUTPUT_REG)}, rax""", - op=[t.ASM_DESCR.CLOBBER_RAX]) - MakeRangeRO(ro_start, ro_end) - # [PG] 打印 .rodata 起始页映射:确认只读真正生效。 - # ps=1 说明仍在 2MB 大页(分裂失败)→ .rodata 保持可写 → 越界写继续被静默吞掉。 - DumpMapping(ro_start, "ro_s") - -def DumpMapping(va: t.CUInt64T, tag: t.CConst | str): - """[PG] 打印指定 VA 的 pml4/pdp/pd/pt 条目,定位大页(PS)与权限位 - - 内核区域若为 UEFI 2MB 大页,MakeRangeRO 无法只读 .rodata(越界写静默破坏 - 格式串);1GB 页同理(PS 位在 pdpe)。W=1 且 PS=1 → 该页可写且是大页。 - """ - global pml4 - if not pml4: return - pml4_i: t.CUInt64T = (va >> 39) & 0x1FF - pdp_i: t.CUInt64T = (va >> 30) & 0x1FF - pd_i: t.CUInt64T = (va >> 21) & 0x1FF - pt_i: t.CUInt64T = (va >> 12) & 0x1FF - pml4_e: t.CUInt64T = pml4.entries[pml4_i] - pdp_e: t.CUInt64T = 0 - pd_e: t.CUInt64T = 0 - pt_e: t.CUInt64T = 0 - if pml4_e & PTE_PRESENT: - pdp_r: _p | t.CPtr = t.CType(pml4_e & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pdp_e = pdp_r.entries[pdp_i] - if pdp_e & PTE_PRESENT: - if pdp_e & PTE_PS: - pd_e = pdp_e - else: - pd_r: _p | t.CPtr = t.CType(pdp_e & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pd_e = pd_r.entries[pd_i] - if (pd_e & PTE_PRESENT) and not (pd_e & PTE_PS): - pt_r: _p | t.CPtr = t.CType(pd_e & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt_e = pt_r.entries[pt_i] - buf_d: t.CArray[t.CChar, 200] - viperlib.snprintf(c.Addr(buf_d), 200, "[PG] %s va=0x%lx pdpe=0x%lx pde=0x%lx pte=0x%lx (ps=%d W=%d)\n", - tag, va, pdp_e, pd_e, pt_e, - 1 if (pd_e & PTE_PS) else 0, - 1 if (pt_e & PTE_WRITABLE) or (pd_e & PTE_WRITABLE) or (pdp_e & PTE_WRITABLE) else 0) - serial.puts(c.Addr(buf_d)) - -def GetCurrentPml4() -> _p | t.CPtr: - global pml4, pdp, pd, pt - cr3: t.CUInt64T - c.Asm(f"mov {c.AsmOut(cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3") - return (_p | t.CPtr)(cr3 & ~t.CUInt64T(0xFFF)) - -def create_process_page_table() -> t.CUInt64T: - global pml4 - if not pml4: return 0 - new_pml4: _p | t.CPtr = AllocPage() - if not new_pml4: return 0 - i: t.CUInt64T - for i in range(512): - entry: t.CUInt64T = pml4.entries[i] - if entry & PTE_PRESENT: - new_pml4.entries[i] = entry - return t.CUInt64T(new_pml4) - -def clone_for_process(isolate_vaddr: t.CUInt64T) -> t.CUInt64T: - global pml4 - _dbg: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbg), 120, "[clone] pml4=0x%lx pool_used=%lu iso_va=0x%lx\n", t.CUInt64T(pml4), pt_pool_used, isolate_vaddr) - serial.puts(_dbg) - if not pml4: return 0 - new_pml4_page: _p | t.CPtr = AllocPage() - if not new_pml4_page: - # [DIAG] 定位 AllocPage 失败:pool_used 打印 0 但分配失败 → BSS 全局 - # (pt_pool_raw/pt_pool_used)疑似被内存越界写覆盖。 - _dbgf: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbgf), 120, "[clone] AllocPage FAIL raw=0x%lx used=%lu PP=%d\n", - t.CUInt64T(pt_pool_raw), pt_pool_used, PT_POOL_PAGES) - serial.puts(c.Addr(_dbgf)) - serial.puts("[clone] AllocPage pml4 failed\n") - return 0 - _dbg2: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbg2), 120, "[clone] new_pml4=0x%lx\n", t.CUInt64T(new_pml4_page)) - serial.puts(_dbg2) - i: t.CUInt64T - for i in range(512): - new_pml4_page.entries[i] = pml4.entries[i] - pml4_idx: t.CUInt64T = (isolate_vaddr >> 39) & 0x1FF - _dbg3: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dbg3), 120, "[clone] pml4_idx=%lu entry0=0x%lx\n", pml4_idx, pml4.entries[pml4_idx]) - serial.puts(_dbg3) - if not (pml4.entries[pml4_idx] & PTE_PRESENT): return t.CUInt64T(new_pml4_page) - kernel_pdp: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - new_pdp_page: _p | t.CPtr = AllocPage() - if not new_pdp_page: return t.CUInt64T(new_pml4_page) - for i in range(512): - new_pdp_page.entries[i] = kernel_pdp.entries[i] - new_pml4_page.entries[pml4_idx] = (t.CUInt64T(new_pdp_page) & ~t.CUInt64T(0xFFF)) | (pml4.entries[pml4_idx] & t.CUInt64T(0xFFF)) - pdp_idx: t.CUInt64T = (isolate_vaddr >> 30) & 0x1FF - if not (kernel_pdp.entries[pdp_idx] & PTE_PRESENT): return t.CUInt64T(new_pml4_page) - kernel_pd: _p | t.CPtr = t.CType(kernel_pdp.entries[pdp_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - new_pd_page: _p | t.CPtr = AllocPage() - if not new_pd_page: return t.CUInt64T(new_pml4_page) - for i in range(512): - new_pd_page.entries[i] = kernel_pd.entries[i] - new_pdp_page.entries[pdp_idx] = (t.CUInt64T(new_pd_page) & ~t.CUInt64T(0xFFF)) | (kernel_pdp.entries[pdp_idx] & t.CUInt64T(0xFFF)) - pd_idx: t.CUInt64T = (isolate_vaddr >> 21) & 0x1FF - if not (kernel_pd.entries[pd_idx] & PTE_PRESENT): return t.CUInt64T(new_pml4_page) - if kernel_pd.entries[pd_idx] & PTE_PS: return t.CUInt64T(new_pml4_page) - kernel_pt: _p | t.CPtr = t.CType(kernel_pd.entries[pd_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - new_pt_page: _p | t.CPtr = AllocPage() - if not new_pt_page: return t.CUInt64T(new_pml4_page) - for i in range(512): - new_pt_page.entries[i] = kernel_pt.entries[i] - new_pd_page.entries[pd_idx] = (t.CUInt64T(new_pt_page) & ~t.CUInt64T(0xFFF)) | (kernel_pd.entries[pd_idx] & t.CUInt64T(0xFFF)) - return t.CUInt64T(new_pml4_page) - -def save_pt_range(vaddr_start: t.CUInt64T, vaddr_end: t.CUInt64T, save_buf: t.CUInt64T | t.CPtr, save_count: t.CUInt32T | t.CPtr) -> t.CInt: - global pml4 - if not pml4: return -1 - # c.Set(a,b)=a=b(改指针变量本身);写所指地址必须 c.Set(c.Deref(a),b) - c.Set(c.Deref(save_count), t.CUInt32T(0)) - va: t.CUInt64T = vaddr_start & ~t.CUInt64T(0xFFF) - while va < vaddr_end: - pml4_idx: t.CUInt64T = (va >> 39) & 0x1FF - if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue - pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pdp_idx: t.CUInt64T = (va >> 30) & 0x1FF - if not (pdp_.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue - pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pd_idx: t.CUInt64T = (va >> 21) & 0x1FF - if not (pd_.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue - if pd_.entries[pd_idx] & PTE_PS: va += 0x200000; continue - pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt_idx: t.CUInt64T = (va >> 12) & 0x1FF - saved: t.CUInt32T = c.DerefAs(save_count) - entry_ptr: t.CUInt64T | t.CPtr = save_buf + t.CUInt64T(saved) * 16 - c.DerefAs(entry_ptr, va) - c.DerefAs(entry_ptr + 8, pt_.entries[pt_idx]) - c.Set(c.Deref(save_count), t.CUInt32T(saved + 1)) - va += 0x1000 - return 0 - -def restore_pt_range(save_buf: t.CUInt64T | t.CPtr, save_count: t.CUInt32T): - global pml4 - if not pml4: return - i: t.CUInt32T = 0 - while i < save_count: - entry_ptr: t.CUInt64T | t.CPtr = save_buf + t.CUInt64T(i) * 16 - va: t.CUInt64T = c.DerefAs(entry_ptr) - orig_pte: t.CUInt64T = c.DerefAs(entry_ptr + 8) - pml4_idx: t.CUInt64T = (va >> 39) & 0x1FF - if not (pml4.entries[pml4_idx] & PTE_PRESENT): i += 1; continue - pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pdp_idx: t.CUInt64T = (va >> 30) & 0x1FF - if not (pdp_.entries[pdp_idx] & PTE_PRESENT): i += 1; continue - pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pd_idx: t.CUInt64T = (va >> 21) & 0x1FF - if not (pd_.entries[pd_idx] & PTE_PRESENT): i += 1; continue - if pd_.entries[pd_idx] & PTE_PS: i += 1; continue - pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~t.CUInt64T(0xFFF), _p, t.CPtr) - pt_idx: t.CUInt64T = (va >> 12) & 0x1FF - pt_.entries[pt_idx] = orig_pte - c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - i += 1 - -def set_active_pml4(cr3_val: t.CUInt64T): - global pml4 - pml4 = (_p | t.CPtr)(cr3_val & ~t.CUInt64T(0xFFF)) +import drivers.serial.uart.serial as serial +import viperlib +import t, c + + +PTE_PRESENT: t.CDefine = (1 << 0) +PTE_WRITABLE: t.CDefine = (1 << 1) +PTE_USER: t.CDefine = (1 << 2) +PTE_PWT: t.CDefine = (1 << 3) +PTE_PCD: t.CDefine = (1 << 4) +PTE_ACCESSED: t.CDefine = (1 << 5) +PTE_DIRTY: t.CDefine = (1 << 6) +PTE_PS: t.CDefine = (1 << 7) +PTE_GLOBAL: t.CDefine = (1 << 8) + +class _p: + entries: t.CArray[uint64, 512] + +PT_POOL_PAGES: t.CDefine = 512 +pt_pool_raw: t.CPtr = None +pt_pool_start: uint64 = 0 +pt_pool_used: uint64 = 0 + +AllocatedPages: uint64 = 0 +pml4: _p | t.CPtr = None +pdp: _p | t.CPtr +pd: _p | t.CPtr +pt: _p | t.CPtr + +def init(MemmapAddr: uint64, MemmapSize: uint64): + global pml4 + pml4 = GetCurrentPml4() + # bootloader/UEFI 的 CR0.WP 通常已是 1(原代码清 WP 正因此)。页表页 + # (pml4/pdp/pd/pt,0xf8xxxx)默认只读,而内核运行时 MapPage/clone 需 + # 修改页表。顺序:先清 WP(允许写只读页表页)→ MakePTWritable 放开 + # 全部页表页 → 再置 WP=1(此后写只读页即 #PF 暴露越界写源)。 + c.Asm(f""" + mov rax, cr0 + and rax, ~0x10000 + mov cr0, rax + """) + MakePTWritable() + c.Asm(f""" + mov rax, cr0 + or rax, 0x10000 + mov cr0, rax + """) + +def init_pool(buf: t.CPtr, buf_size: uint64): + global pt_pool_raw, pt_pool_start, pt_pool_used + pt_pool_raw = buf + if buf is None: return + raw_addr: uint64 = uint64(buf) + aligned_addr: uint64 = (raw_addr + uint64(0xFFF)) & ~uint64(0xFFF) + pt_pool_start = aligned_addr + pt_pool_used = 0 + # [DIAG] 定位 clone 时 pt_pool_raw=0x0(init 后被覆盖?还是 init 收到 0) + _dip: t.CArray[t.CChar, 80] + viperlib.snprintf(c.Addr(_dip), 80, "[paging] init_pool raw=0x%lx start=0x%lx\n", uint64(pt_pool_raw), pt_pool_start) + serial.puts(c.Addr(_dip)) + +def AllocPage() -> t.CPtr: + global AllocatedPages, pt_pool_used, pml4, pdp, pd, pt + if pt_pool_raw is None: return None + if pt_pool_used >= uint64(PT_POOL_PAGES): return None + page: t.CPtr = t.CVoid(pt_pool_start + pt_pool_used * uint64(4096), t.CPtr) + pt_pool_used = pt_pool_used + uint64(1) + c.Asm(f"""mov al, 0 + mov ecx, 4096 + mov rdi, {c.AsmInp(page, t.ASM_DESCR.REG_ANY)} + rep stosb""", + op = [t.ASM_DESCR.CLOBBER_AL, t.ASM_DESCR.CLOBBER_ECX, t.ASM_DESCR.CLOBBER_RDI]) + AllocatedPages = AllocatedPages + uint64(1) + return page + +def FreePage(page: t.CPtr): + global AllocatedPages, pml4, pdp, pd, pt + if page is None: return + if AllocatedPages > 0: AllocatedPages = AllocatedPages - uint64(1) + +def MapPage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64): + global pml4, pdp, pd, pt + if VirtAddr == 0 or PhysAddr == 0: return + VirtAddr = VirtAddr & ~uint64(0xFFF) + PhysAddr = PhysAddr & ~uint64(0xFFF) + Pml4Index: uint64 = (VirtAddr >> 39) & 0x1FF + PdpIndex: uint64 = (VirtAddr >> 30) & 0x1FF + PdIndex: uint64 = (VirtAddr >> 21) & 0x1FF + PtIndex: uint64 = (VirtAddr >> 12) & 0x1FF + + if not pml4: + pml4 = AllocPage() + if not pml4: return + + if not (pml4.entries[Pml4Index] & PTE_PRESENT): + pdp: _p | t.CPtr = AllocPage() + if not pdp: return + pml4.entries[Pml4Index] = (uint64(pdp) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) + else: + if (flags & PTE_USER) and not (pml4.entries[Pml4Index] & PTE_USER): + pml4.entries[Pml4Index] = pml4.entries[Pml4Index] | PTE_USER + pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr) + + if not (pdp.entries[PdpIndex] & PTE_PRESENT): + pd: _p | t.CPtr = AllocPage() + if not pd: return + pdp.entries[PdpIndex] = (uint64(pd) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) + else: + if (flags & PTE_USER) and not (pdp.entries[PdpIndex] & PTE_USER): + pdp.entries[PdpIndex] = pdp.entries[PdpIndex] | PTE_USER + pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr) + + if pd.entries[PdIndex] & 1: + if pd.entries[PdIndex] & 0x80: + big_phys: uint64 = pd.entries[PdIndex] & ~uint64(0x1FFFFF) + inherit_flags: uint64 = pd.entries[PdIndex] & (PTE_PCD | PTE_PWT) + pt: _p | t.CPtr = AllocPage() + if not pt: return + split_i: int = 0 + while split_i < 512: + pt.entries[split_i] = (big_phys + uint64(split_i) * 0x1000) | PTE_PRESENT | PTE_WRITABLE | inherit_flags + split_i += 1 + pd.entries[PdIndex] = (uint64(pt) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) + else: + # PD entry exists as a regular PT (e.g. cloned identity mapping). + # Must propagate PTE_USER to the PD entry so user-mode access is + # allowed at all paging levels, otherwise #PF err=0x5. + if (flags & PTE_USER) and not (pd.entries[PdIndex] & PTE_USER): + pd.entries[PdIndex] = pd.entries[PdIndex] | PTE_USER + else: + pt: _p | t.CPtr = AllocPage() + if not pt: return + pd.entries[PdIndex] = (uint64(pt) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER) + pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~uint64(0xFFF), _p, t.CPtr) + + pt.entries[PtIndex] = PhysAddr | flags | PTE_PRESENT + c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") + +def MapLargePage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64) -> t.CVoid: + global pml4, pdp, pd, pt + VirtAddr = VirtAddr & ~uint64(0x1FFFFF) + PhysAddr = PhysAddr & ~uint64(0x1FFFFF) + Pml4Index: uint64 = (VirtAddr >> 39) & 0x1FF + PdpIndex: uint64 = (VirtAddr >> 30) & 0x1FF + PdIndex: uint64 = (VirtAddr >> 21) & 0x1FF + + if not pml4: + pml4 = AllocPage() + if not pml4: return + + if not pml4.entries[Pml4Index] & PTE_PRESENT: + pdp: _p | t.CPtr = AllocPage() + if not pdp: return + pml4.entries[Pml4Index] = (uint64(pdp) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE + pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr) + + if not (pdp.entries[PdpIndex] & PTE_PRESENT): + pd: _p | t.CPtr = AllocPage() + if not pd: return + pdp.entries[PdpIndex] = (uint64(pd) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE + pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr) + + pd.entries[PdIndex] = PhysAddr | flags | PTE_PRESENT | PTE_PS + c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") + +def UnMapPage(VirtAddr: uint64): + global pml4, pdp, pd, pt + if VirtAddr == 0: return + if not pml4: return + Pml4Index: uint64 = (VirtAddr >> 39) & 0x1FF + PdpIndex: uint64 = (VirtAddr >> 30) & 0x1FF + PdIndex: uint64 = (VirtAddr >> 21) & 0x1FF + PtIndex: uint64 = (VirtAddr >> 12) & 0x1FF + + if not pml4.entries[Pml4Index] & PTE_PRESENT: return + + pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr) + if not pdp.entries[PdpIndex] & PTE_PRESENT: return + + pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr) + + if not pd.entries[PdIndex] & PTE_PRESENT: return + + if pd.entries[PdIndex] & PTE_PS: + pd.entries[PdIndex] = 0 + else: + pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~uint64(0xFFF), _p, t.CPtr) + pt.entries[PtIndex] = 0 + + c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]") + +def EnablePaging(): + global pml4, pdp, pd, pt + c.Asm(f"mov cr3, {c.AsmInp(uint64(pml4), t.ASM_DESCR.REG_ANY)}") + +def _set_page_writable(phys_addr: uint64): + """把物理页 phys_addr(identity 映射,虚拟=物理)的 PTE 置 W 位 + + 页表页(bootloader 建立的 pml4/pdp/pd/pt 位于 0xf8xxxx)默认只读, + 而内核运行时 MapPage/clone 需修改页表 → 必须先把这些页表页自身设为可写, + 否则 CR0.WP=1 下写页表触发 #PF(slog.so 映射 0x600000 新建页表项时 + cr2=0xf801000 err=0x3 根因)。 + """ + global pml4 + if not pml4: return + va: uint64 = phys_addr & ~uint64(0xFFF) + pml4_idx: uint64 = (va >> 39) & 0x1FF + if not (pml4.entries[pml4_idx] & PTE_PRESENT): return + pdp_s: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr) + pdp_idx: uint64 = (va >> 30) & 0x1FF + if not (pdp_s.entries[pdp_idx] & PTE_PRESENT): return + pd_s: _p | t.CPtr = t.CType(pdp_s.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr) + pd_idx: uint64 = (va >> 21) & 0x1FF + if not (pd_s.entries[pd_idx] & PTE_PRESENT): return + if pd_s.entries[pd_idx] & PTE_PS: + # 2MB 大页:W 位在 PD 条目自身(无下层 PT),直接置位 + pd_s.entries[pd_idx] = pd_s.entries[pd_idx] | uint64(PTE_WRITABLE) + c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") + return + pt_s: _p | t.CPtr = t.CType(pd_s.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr) + pt_idx: uint64 = (va >> 12) & 0x1FF + pt_s.entries[pt_idx] = pt_s.entries[pt_idx] | uint64(PTE_WRITABLE) + c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") + +def MakePTWritable(): + """把当前页表层次所有页表页(pml4 自身 + pdp/pd/pt)设为可写 + + 内核运行时需修改页表(MapPage/clone_for_process),而 bootloader 建立的 + 页表页映射为只读——CR0.WP=1 下必须先放开页表页自身,否则写页表即 #PF。 + """ + global pml4 + if not pml4: return + _set_page_writable(uint64(pml4)) + pi: uint64 + for pi in range(512): + if not (pml4.entries[pi] & PTE_PRESENT): continue + pdp_m: _p | t.CPtr = t.CType(pml4.entries[pi] & ~uint64(0xFFF), _p, t.CPtr) + _set_page_writable(uint64(pdp_m)) + pj: uint64 + for pj in range(512): + if not (pdp_m.entries[pj] & PTE_PRESENT): continue + pd_m: _p | t.CPtr = t.CType(pdp_m.entries[pj] & ~uint64(0xFFF), _p, t.CPtr) + _set_page_writable(uint64(pd_m)) + pk: uint64 + for pk in range(512): + if not (pd_m.entries[pk] & PTE_PRESENT): continue + if pd_m.entries[pk] & PTE_PS: continue + pt_m: _p | t.CPtr = t.CType(pd_m.entries[pk] & ~uint64(0xFFF), _p, t.CPtr) + _set_page_writable(uint64(pt_m)) + +def MakeRangeRO(vaddr_start: uint64, vaddr_end: uint64): + """把 [vaddr_start, vaddr_end) 范围内所有页的 PTE 清 W 位(只读) + + 定位越界写源:内核态写只读页在 CR0.WP=1 下触发 #PF(int=14), + isrCommonhandler 打印 cr2/rip → 写源立即暴露,不再静默破坏 .rodata。 + """ + global pml4 + if not pml4: return + va: uint64 = vaddr_start & ~uint64(0xFFF) + # ro_end 下取整到页:不保护含 ro_end 的未对齐尾页。链接脚本输出段未页对齐, + # .data 紧跟 .rodata(__rodata_end 未对齐时 .data 起始落在 rodata 尾页内), + # 整页置只读会把 .data 全局(如 devfs @DevFSObject=0x141630)误保护 → + # devfs_init 写全局 #PF(cr2=0x141630 rip=0x101aaa mov [r15],rax 根因)。 + # 尾页含少量 rodata 尾部(对齐填充),保持可写可容忍。 + ro_end_align: uint64 = vaddr_end & ~uint64(0xFFF) + while va < ro_end_align: + pml4_idx: uint64 = (va >> 39) & 0x1FF + if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue + pdp_r: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr) + pdp_idx: uint64 = (va >> 30) & 0x1FF + if not (pdp_r.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue + pd_r: _p | t.CPtr = t.CType(pdp_r.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr) + pd_idx: uint64 = (va >> 21) & 0x1FF + if not (pd_r.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue + if pd_r.entries[pd_idx] & PTE_PS: + # 2MB 大页:直接跳过会让 .rodata 保持可写——越界写被静默吞掉 + # (perf 格式串 win=%lu/work=%lu 被逐步破坏的根因)。拆分为 512 + # 个 4KB 页(复用 MapPage 的分裂逻辑),再走下方常规路径清 W 位。 + # WP=1 后内核态写只读页即 #PF → isrCommonhandler 打印 cr2/rip 暴露写源。 + big_phys: uint64 = pd_r.entries[pd_idx] & ~uint64(0x1FFFFF) + inherit_flags: uint64 = pd_r.entries[pd_idx] & (PTE_PCD | PTE_PWT | PTE_USER | uint64(0x8000000000000000)) + pt_split: _p | t.CPtr = AllocPage() + if not pt_split: + va += 0x1000 + continue + split_i: int = 0 + while split_i < 512: + pt_split.entries[split_i] = (big_phys + uint64(split_i) * uint64(0x1000)) \ + | PTE_PRESENT | PTE_WRITABLE | inherit_flags + split_i += 1 + pd_r.entries[pd_idx] = (uint64(pt_split) & ~uint64(0xFFF)) \ + | PTE_PRESENT | PTE_WRITABLE | (pd_r.entries[pd_idx] & PTE_USER) + c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") + # 分裂后落入下方 4KB 常规路径,继续清当前页 W 位 + pt_r: _p | t.CPtr = t.CType(pd_r.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr) + pt_idx: uint64 = (va >> 12) & 0x1FF + pt_r.entries[pt_idx] = pt_r.entries[pt_idx] & ~uint64(PTE_WRITABLE) + c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]") + va += 0x1000 + +def ProtectKernelRO(): + """把内核镜像 .rodata 段(字符串常量/vtable 等)映射为只读 + + 地址经 c.Asm 内联引用链接器符号 __rodata_start/__rodata_end + (linker.ld 定义,TPV 不声明 extern——避免生成定义与链接器符号冲突)。 + """ + global pml4 + if not pml4: return + # 页表页可写已在 paging.init(WP=0 阶段)由 MakePTWritable 完成, + # 此处只保护 .rodata 内容页(WP=1 后写只读页即 #PF 暴露写源)。 + ro_start: uint64 = 0 + ro_end: uint64 = 0 + c.Asm(f"""lea rax, [rip + __rodata_start] + mov {c.AsmOut(ro_start, t.ASM_DESCR.OUTPUT_REG)}, rax + lea rax, [rip + __rodata_end] + mov {c.AsmOut(ro_end, t.ASM_DESCR.OUTPUT_REG)}, rax""", + op=[t.ASM_DESCR.CLOBBER_RAX]) + MakeRangeRO(ro_start, ro_end) + # [PG] 打印 .rodata 起始页映射:确认只读真正生效。 + # ps=1 说明仍在 2MB 大页(分裂失败)→ .rodata 保持可写 → 越界写继续被静默吞掉。 + DumpMapping(ro_start, "ro_s") + +def DumpMapping(va: uint64, tag: t.CConst | str): + """[PG] 打印指定 VA 的 pml4/pdp/pd/pt 条目,定位大页(PS)与权限位 + + 内核区域若为 UEFI 2MB 大页,MakeRangeRO 无法只读 .rodata(越界写静默破坏 + 格式串);1GB 页同理(PS 位在 pdpe)。W=1 且 PS=1 → 该页可写且是大页。 + """ + global pml4 + if not pml4: return + pml4_i: uint64 = (va >> 39) & 0x1FF + pdp_i: uint64 = (va >> 30) & 0x1FF + pd_i: uint64 = (va >> 21) & 0x1FF + pt_i: uint64 = (va >> 12) & 0x1FF + pml4_e: uint64 = pml4.entries[pml4_i] + pdp_e: uint64 = 0 + pd_e: uint64 = 0 + pt_e: uint64 = 0 + if pml4_e & PTE_PRESENT: + pdp_r: _p | t.CPtr = t.CType(pml4_e & ~uint64(0xFFF), _p, t.CPtr) + pdp_e = pdp_r.entries[pdp_i] + if pdp_e & PTE_PRESENT: + if pdp_e & PTE_PS: + pd_e = pdp_e + else: + pd_r: _p | t.CPtr = t.CType(pdp_e & ~uint64(0xFFF), _p, t.CPtr) + pd_e = pd_r.entries[pd_i] + if (pd_e & PTE_PRESENT) and not (pd_e & PTE_PS): + pt_r: _p | t.CPtr = t.CType(pd_e & ~uint64(0xFFF), _p, t.CPtr) + pt_e = pt_r.entries[pt_i] + buf_d: t.CArray[t.CChar, 200] + viperlib.snprintf(c.Addr(buf_d), 200, "[PG] %s va=0x%lx pdpe=0x%lx pde=0x%lx pte=0x%lx (ps=%d W=%d)\n", + tag, va, pdp_e, pd_e, pt_e, + 1 if (pd_e & PTE_PS) else 0, + 1 if (pt_e & PTE_WRITABLE) or (pd_e & PTE_WRITABLE) or (pdp_e & PTE_WRITABLE) else 0) + serial.puts(c.Addr(buf_d)) + +def GetCurrentPml4() -> _p | t.CPtr: + global pml4, pdp, pd, pt + cr3: uint64 + c.Asm(f"mov {c.AsmOut(cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3") + return (_p | t.CPtr)(cr3 & ~uint64(0xFFF)) + +def create_process_page_table() -> uint64: + global pml4 + if not pml4: return 0 + new_pml4: _p | t.CPtr = AllocPage() + if not new_pml4: return 0 + i: uint64 + for i in range(512): + entry: uint64 = pml4.entries[i] + if entry & PTE_PRESENT: + new_pml4.entries[i] = entry + return uint64(new_pml4) + +def clone_for_process(isolate_vaddr: uint64) -> uint64: + global pml4 + _dbg: t.CArray[t.CChar, 120] + viperlib.snprintf(c.Addr(_dbg), 120, "[clone] pml4=0x%lx pool_used=%lu iso_va=0x%lx\n", uint64(pml4), pt_pool_used, isolate_vaddr) + serial.puts(_dbg) + if not pml4: return 0 + new_pml4_page: _p | t.CPtr = AllocPage() + if not new_pml4_page: + # [DIAG] 定位 AllocPage 失败:pool_used 打印 0 但分配失败 → BSS 全局 + # (pt_pool_raw/pt_pool_used)疑似被内存越界写覆盖。 + _dbgf: t.CArray[t.CChar, 120] + viperlib.snprintf(c.Addr(_dbgf), 120, "[clone] AllocPage FAIL raw=0x%lx used=%lu PP=%d\n", + uint64(pt_pool_raw), pt_pool_used, PT_POOL_PAGES) + serial.puts(c.Addr(_dbgf)) + serial.puts("[clone] AllocPage pml4 failed\n") + return 0 + _dbg2: t.CArray[t.CChar, 120] + viperlib.snprintf(c.Addr(_dbg2), 120, "[clone] new_pml4=0x%lx\n", uint64(new_pml4_page)) + serial.puts(_dbg2) + i: uint64 + for i in range(512): + new_pml4_page.entries[i] = pml4.entries[i] + pml4_idx: uint64 = (isolate_vaddr >> 39) & 0x1FF + _dbg3: t.CArray[t.CChar, 120] + viperlib.snprintf(c.Addr(_dbg3), 120, "[clone] pml4_idx=%lu entry0=0x%lx\n", pml4_idx, pml4.entries[pml4_idx]) + serial.puts(_dbg3) + if not (pml4.entries[pml4_idx] & PTE_PRESENT): return uint64(new_pml4_page) + kernel_pdp: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr) + new_pdp_page: _p | t.CPtr = AllocPage() + if not new_pdp_page: return uint64(new_pml4_page) + for i in range(512): + new_pdp_page.entries[i] = kernel_pdp.entries[i] + new_pml4_page.entries[pml4_idx] = (uint64(new_pdp_page) & ~uint64(0xFFF)) | (pml4.entries[pml4_idx] & uint64(0xFFF)) + pdp_idx: uint64 = (isolate_vaddr >> 30) & 0x1FF + if not (kernel_pdp.entries[pdp_idx] & PTE_PRESENT): return uint64(new_pml4_page) + kernel_pd: _p | t.CPtr = t.CType(kernel_pdp.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr) + new_pd_page: _p | t.CPtr = AllocPage() + if not new_pd_page: return uint64(new_pml4_page) + for i in range(512): + new_pd_page.entries[i] = kernel_pd.entries[i] + new_pdp_page.entries[pdp_idx] = (uint64(new_pd_page) & ~uint64(0xFFF)) | (kernel_pdp.entries[pdp_idx] & uint64(0xFFF)) + pd_idx: uint64 = (isolate_vaddr >> 21) & 0x1FF + if not (kernel_pd.entries[pd_idx] & PTE_PRESENT): return uint64(new_pml4_page) + if kernel_pd.entries[pd_idx] & PTE_PS: return uint64(new_pml4_page) + kernel_pt: _p | t.CPtr = t.CType(kernel_pd.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr) + new_pt_page: _p | t.CPtr = AllocPage() + if not new_pt_page: return uint64(new_pml4_page) + for i in range(512): + new_pt_page.entries[i] = kernel_pt.entries[i] + new_pd_page.entries[pd_idx] = (uint64(new_pt_page) & ~uint64(0xFFF)) | (kernel_pd.entries[pd_idx] & uint64(0xFFF)) + return uint64(new_pml4_page) + +def save_pt_range(vaddr_start: uint64, vaddr_end: uint64, save_buf: uint64 | t.CPtr, save_count: uint32 | t.CPtr) -> int: + global pml4 + if not pml4: return -1 + # c.Set(a,b)=a=b(改指针变量本身);写所指地址必须 c.Set(c.Deref(a),b) + c.Set(c.Deref(save_count), uint32(0)) + va: uint64 = vaddr_start & ~uint64(0xFFF) + while va < vaddr_end: + pml4_idx: uint64 = (va >> 39) & 0x1FF + if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue + pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr) + pdp_idx: uint64 = (va >> 30) & 0x1FF + if not (pdp_.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue + pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr) + pd_idx: uint64 = (va >> 21) & 0x1FF + if not (pd_.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue + if pd_.entries[pd_idx] & PTE_PS: va += 0x200000; continue + pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr) + pt_idx: uint64 = (va >> 12) & 0x1FF + saved: uint32 = c.DerefAs(save_count) + entry_ptr: uint64 | t.CPtr = save_buf + uint64(saved) * 16 + c.DerefAs(entry_ptr, va) + c.DerefAs(entry_ptr + 8, pt_.entries[pt_idx]) + c.Set(c.Deref(save_count), uint32(saved + 1)) + va += 0x1000 + return 0 + +def restore_pt_range(save_buf: uint64 | t.CPtr, save_count: uint32): + global pml4 + if not pml4: return + i: uint32 = 0 + while i < save_count: + entry_ptr: uint64 | t.CPtr = save_buf + uint64(i) * 16 + va: uint64 = c.DerefAs(entry_ptr) + orig_pte: uint64 = c.DerefAs(entry_ptr + 8) + pml4_idx: uint64 = (va >> 39) & 0x1FF + if not (pml4.entries[pml4_idx] & PTE_PRESENT): i += 1; continue + pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr) + pdp_idx: uint64 = (va >> 30) & 0x1FF + if not (pdp_.entries[pdp_idx] & PTE_PRESENT): i += 1; continue + pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr) + pd_idx: uint64 = (va >> 21) & 0x1FF + if not (pd_.entries[pd_idx] & PTE_PRESENT): i += 1; continue + if pd_.entries[pd_idx] & PTE_PS: i += 1; continue + pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr) + pt_idx: uint64 = (va >> 12) & 0x1FF + pt_.entries[pt_idx] = orig_pte + c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + i += 1 + +def set_active_pml4(cr3_val: uint64): + global pml4 + pml4 = (_p | t.CPtr)(cr3_val & ~uint64(0xFFF)) diff --git a/VKernel/Kernel/platform/pch/pic.vp b/VKernel/Kernel/platform/pch/pic.vp index 239fd69..ae4a882 100644 --- a/VKernel/Kernel/platform/pch/pic.vp +++ b/VKernel/Kernel/platform/pch/pic.vp @@ -1,120 +1,120 @@ -import asm -import t, c - - -# PIC端口定义 -PIC1_COMMAND: t.CDefine = 0x20 -PIC1_DATA: t.CDefine = 0x21 -PIC2_COMMAND: t.CDefine = 0xA0 -PIC2_DATA: t.CDefine = 0xA1 - -# ICW1 - 初始化命令字1 -ICW1_ICW4: t.CDefine = 0x01 # 需要ICW4 -ICW1_SINGLE: t.CDefine = 0x02 # 单级模式 -ICW1_INTERVAL4: t.CDefine = 0x04 # 间隔4字节 -ICW1_LEVEL: t.CDefine = 0x08 # 电平触发模式 -ICW1_INIT: t.CDefine = 0x10 # 初始化 - -# ICW4 - 初始化命令字4 -ICW4_8086: t.CDefine = 0x01 # 8086/88模式 -ICW4_AUTO: t.CDefine = 0x02 # 自动EOI -ICW4_BUF_SLAVE: t.CDefine = 0x08 # 缓冲模式(从片) -ICW4_BUF_MASTER: t.CDefine = 0x0C # 缓冲模式(主片) -ICW4_SFNM: t.CDefine = 0x10 # 特殊全嵌套模式 - -# OCW2 - 操作命令字2 -OCW2_EOI: t.CDefine = 0x20 # 结束中断 - -# OCW3 - 操作命令字3 -OCW3_READ_ISR: t.CDefine = 0x0B # 读取中断服务寄存器(ISR) - -# 初始化PIC -def init(): - # 发送ICW1:开始初始化,需要ICW4 - asm.outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4) - asm.io_wait() - asm.outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4) - asm.io_wait() - - # 发送ICW2:中断向量偏移 - asm.outb(PIC1_DATA, 0x20) # IRQ0-7映射到0x20-0x27 - asm.io_wait() - asm.outb(PIC2_DATA, 0x28) # IRQ8-15映射到0x28-0x2F - asm.io_wait() - - # 发送ICW3:级联信息 - asm.outb(PIC1_DATA, 0x04) # 主PIC的IRQ2连接从PIC - asm.io_wait() - asm.outb(PIC2_DATA, 0x02) # 从PIC连接到主PIC的IRQ2 - asm.io_wait() - - # 发送ICW4:8086模式 - asm.outb(PIC1_DATA, ICW4_8086) - asm.io_wait() - asm.outb(PIC2_DATA, ICW4_8086) - asm.io_wait() - - # 设置初始屏蔽字:只启用IRQ0(定时器)、IRQ1(键盘)、IRQ2(级联) - # 主PIC: 屏蔽所有除了IRQ0, IRQ1, IRQ2 (0xF8 = 11111000) - # 从PIC: 屏蔽所有 (0xFF = 11111111),鼠标中断由驱动程序自己启用 - asm.outb(PIC1_DATA, 0xF8) # 启用IRQ0, IRQ1, IRQ2 - asm.io_wait() - asm.outb(PIC2_DATA, 0xFF) # 屏蔽所有从PIC中断 - asm.io_wait() - -# 发送EOI信号 -def eoi(irq: t.CUInt8T): - if irq >= 8: asm.outb(PIC2_COMMAND, OCW2_EOI) - asm.outb(PIC1_COMMAND, OCW2_EOI) - - -# 检查是否是虚假中断(spurious interrupt) -# 返回 1 表示是虚假中断,0 表示是真实中断 -def isSpurious(irq: t.CInt) -> t.CInt: - # 边界检查 - if irq < 0 or irq > 15: return 0 - isr: t.CUInt8T - if irq < 8: - # 发送OCW3,读取ISR(Interrupt Service Register) - asm.outb(PIC1_COMMAND, OCW3_READ_ISR) - asm.io_wait() - isr = asm.inb(PIC1_COMMAND) - # 如果ISR中对应位为0,说明是虚假中断 - return not (isr & (1 << irq)) - else: - # 发送OCW3,读取从PIC的ISR - asm.outb(PIC2_COMMAND, OCW3_READ_ISR) - asm.io_wait() - isr = asm.inb(PIC2_COMMAND) - # 如果ISR中对应位为0,说明是虚假中断 - return not (isr & (1 << (irq - 8))) - -# 设置IRQ屏蔽 -def setMask(irq: t.CUInt8T): - # 边界检查 - if irq > 15: return - port: t.CUInt16T - value: t.CUInt8T - if irq < 8: - port = PIC1_DATA - else: - port = PIC2_DATA - irq -= 8 - value = asm.inb(port) | (1 << irq) - asm.outb(port, value) - asm.io_wait() # 确保命令生效 - -# 清除IRQ屏蔽 -def clearMask(irq: t.CUInt8T): - # 边界检查 - if irq > 15: return - port: t.CUInt16T - value: t.CUInt8T - if irq < 8: - port = PIC1_DATA - else: - port = PIC2_DATA - irq -= 8 - value = asm.inb(port) & ~(1 << irq) - asm.outb(port, value) - asm.io_wait() # 确保命令生效 +import asm +import t, c + + +# PIC端口定义 +PIC1_COMMAND: t.CDefine = 0x20 +PIC1_DATA: t.CDefine = 0x21 +PIC2_COMMAND: t.CDefine = 0xA0 +PIC2_DATA: t.CDefine = 0xA1 + +# ICW1 - 初始化命令字1 +ICW1_ICW4: t.CDefine = 0x01 # 需要ICW4 +ICW1_SINGLE: t.CDefine = 0x02 # 单级模式 +ICW1_INTERVAL4: t.CDefine = 0x04 # 间隔4字节 +ICW1_LEVEL: t.CDefine = 0x08 # 电平触发模式 +ICW1_INIT: t.CDefine = 0x10 # 初始化 + +# ICW4 - 初始化命令字4 +ICW4_8086: t.CDefine = 0x01 # 8086/88模式 +ICW4_AUTO: t.CDefine = 0x02 # 自动EOI +ICW4_BUF_SLAVE: t.CDefine = 0x08 # 缓冲模式(从片) +ICW4_BUF_MASTER: t.CDefine = 0x0C # 缓冲模式(主片) +ICW4_SFNM: t.CDefine = 0x10 # 特殊全嵌套模式 + +# OCW2 - 操作命令字2 +OCW2_EOI: t.CDefine = 0x20 # 结束中断 + +# OCW3 - 操作命令字3 +OCW3_READ_ISR: t.CDefine = 0x0B # 读取中断服务寄存器(ISR) + +# 初始化PIC +def init(): + # 发送ICW1:开始初始化,需要ICW4 + asm.outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4) + asm.io_wait() + asm.outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4) + asm.io_wait() + + # 发送ICW2:中断向量偏移 + asm.outb(PIC1_DATA, 0x20) # IRQ0-7映射到0x20-0x27 + asm.io_wait() + asm.outb(PIC2_DATA, 0x28) # IRQ8-15映射到0x28-0x2F + asm.io_wait() + + # 发送ICW3:级联信息 + asm.outb(PIC1_DATA, 0x04) # 主PIC的IRQ2连接从PIC + asm.io_wait() + asm.outb(PIC2_DATA, 0x02) # 从PIC连接到主PIC的IRQ2 + asm.io_wait() + + # 发送ICW4:8086模式 + asm.outb(PIC1_DATA, ICW4_8086) + asm.io_wait() + asm.outb(PIC2_DATA, ICW4_8086) + asm.io_wait() + + # 设置初始屏蔽字:只启用IRQ0(定时器)、IRQ1(键盘)、IRQ2(级联) + # 主PIC: 屏蔽所有除了IRQ0, IRQ1, IRQ2 (0xF8 = 11111000) + # 从PIC: 屏蔽所有 (0xFF = 11111111),鼠标中断由驱动程序自己启用 + asm.outb(PIC1_DATA, 0xF8) # 启用IRQ0, IRQ1, IRQ2 + asm.io_wait() + asm.outb(PIC2_DATA, 0xFF) # 屏蔽所有从PIC中断 + asm.io_wait() + +# 发送EOI信号 +def eoi(irq: uint8): + if irq >= 8: asm.outb(PIC2_COMMAND, OCW2_EOI) + asm.outb(PIC1_COMMAND, OCW2_EOI) + + +# 检查是否是虚假中断(spurious interrupt) +# 返回 1 表示是虚假中断,0 表示是真实中断 +def isSpurious(irq: int) -> int: + # 边界检查 + if irq < 0 or irq > 15: return 0 + isr: uint8 + if irq < 8: + # 发送OCW3,读取ISR(Interrupt Service Register) + asm.outb(PIC1_COMMAND, OCW3_READ_ISR) + asm.io_wait() + isr = asm.inb(PIC1_COMMAND) + # 如果ISR中对应位为0,说明是虚假中断 + return not (isr & (1 << irq)) + else: + # 发送OCW3,读取从PIC的ISR + asm.outb(PIC2_COMMAND, OCW3_READ_ISR) + asm.io_wait() + isr = asm.inb(PIC2_COMMAND) + # 如果ISR中对应位为0,说明是虚假中断 + return not (isr & (1 << (irq - 8))) + +# 设置IRQ屏蔽 +def setMask(irq: uint8): + # 边界检查 + if irq > 15: return + port: uint16 + value: uint8 + if irq < 8: + port = PIC1_DATA + else: + port = PIC2_DATA + irq -= 8 + value = asm.inb(port) | (1 << irq) + asm.outb(port, value) + asm.io_wait() # 确保命令生效 + +# 清除IRQ屏蔽 +def clearMask(irq: uint8): + # 边界检查 + if irq > 15: return + port: uint16 + value: uint8 + if irq < 8: + port = PIC1_DATA + else: + port = PIC2_DATA + irq -= 8 + value = asm.inb(port) & ~(1 << irq) + asm.outb(port, value) + asm.io_wait() # 确保命令生效 diff --git a/VKernel/Kernel/platform/pch/pit.vp b/VKernel/Kernel/platform/pch/pit.vp index f4a76a3..de6ccea 100644 --- a/VKernel/Kernel/platform/pch/pit.vp +++ b/VKernel/Kernel/platform/pch/pit.vp @@ -1,26 +1,26 @@ -import asm -import t, c - -PIT_CHANNEL0: t.CDefine = 0x40 -PIT_CHANNEL1: t.CDefine = 0x41 -PIT_CHANNEL2: t.CDefine = 0x42 -PIT_COMMAND: t.CDefine = 0x43 - -def pit_init(frequency: t.CInt): - # 参数验证:确保频率为正数 - if frequency <= 0: return - - # 计算除数,使用16位无符号整数 - divisor: t.CUInt32T = 1193180 / frequency - - # 发送命令字:通道0,先低后高,模式3(方波),二进制计数 - asm.outb(PIT_COMMAND, 0x36) - asm.io_wait() - - # 写入低字节 - asm.outb(PIT_CHANNEL0, divisor & 0xFF) - asm.io_wait() - - # 写入高字节 - asm.outb(PIT_CHANNEL0, (divisor >> 8) & 0xFF) - asm.io_wait() +import asm +import t, c + +PIT_CHANNEL0: t.CDefine = 0x40 +PIT_CHANNEL1: t.CDefine = 0x41 +PIT_CHANNEL2: t.CDefine = 0x42 +PIT_COMMAND: t.CDefine = 0x43 + +def pit_init(frequency: int): + # 参数验证:确保频率为正数 + if frequency <= 0: return + + # 计算除数,使用16位无符号整数 + divisor: uint32 = 1193180 / frequency + + # 发送命令字:通道0,先低后高,模式3(方波),二进制计数 + asm.outb(PIT_COMMAND, 0x36) + asm.io_wait() + + # 写入低字节 + asm.outb(PIT_CHANNEL0, divisor & 0xFF) + asm.io_wait() + + # 写入高字节 + asm.outb(PIT_CHANNEL0, (divisor >> 8) & 0xFF) + asm.io_wait() diff --git a/VKernel/Kernel/platform/pch/rtc.vp b/VKernel/Kernel/platform/pch/rtc.vp index 52d9850..9d74f37 100644 --- a/VKernel/Kernel/platform/pch/rtc.vp +++ b/VKernel/Kernel/platform/pch/rtc.vp @@ -1,97 +1,97 @@ -from stdint import * -import t, c -import asm - - -RTC_CMOS_ADDR: t.CUInt16T = 0x70 -RTC_CMOS_DATA: t.CUInt16T = 0x71 - -RTC_REG_SECONDS: t.CDefine = 0x00 -RTC_REG_MINUTES: t.CDefine = 0x02 -RTC_REG_HOURS: t.CDefine = 0x04 -RTC_REG_DAY: t.CDefine = 0x07 -RTC_REG_MONTH: t.CDefine = 0x08 -RTC_REG_YEAR: t.CDefine = 0x09 -RTC_REG_STATUS_A: t.CDefine = 0x0A -RTC_REG_STATUS_B: t.CDefine = 0x0B - -RTC_TZ_OFFSET: t.CDefine = 8 - -rtc_seconds: t.CStatic | t.CVolatile | t.CUInt8T = 0 -rtc_minutes: t.CStatic | t.CVolatile | t.CUInt8T = 0 -rtc_hours: t.CStatic | t.CVolatile | t.CUInt8T = 0 -rtc_day: t.CStatic | t.CVolatile | t.CUInt8T = 0 -rtc_month: t.CStatic | t.CVolatile | t.CUInt8T = 0 -rtc_year: t.CStatic | t.CVolatile | t.CUInt16T = 0 - -def cmos_read(reg: t.CUInt8T) -> t.CUInt8T: - asm.outb(RTC_CMOS_ADDR, reg) - return asm.inb(RTC_CMOS_DATA) - -def bcd_to_bin(bcd: t.CUInt8T) -> t.CUInt8T: - return (bcd >> 4) * 10 + (bcd & 0x0F) - -def rtc_read_time(): - while cmos_read(RTC_REG_STATUS_A) & 0x80: pass - sec: t.CUInt8T = cmos_read(RTC_REG_SECONDS) - min_: t.CUInt8T = cmos_read(RTC_REG_MINUTES) - hour: t.CUInt8T = cmos_read(RTC_REG_HOURS) - day: t.CUInt8T = cmos_read(RTC_REG_DAY) - mon: t.CUInt8T = cmos_read(RTC_REG_MONTH) - year: t.CUInt8T = cmos_read(RTC_REG_YEAR) - reg_b: t.CUInt8T = cmos_read(RTC_REG_STATUS_B) - if not (reg_b & 0x04): - sec = bcd_to_bin(sec) - min_ = bcd_to_bin(min_) - hour = bcd_to_bin(hour) - day = bcd_to_bin(day) - mon = bcd_to_bin(mon) - year = bcd_to_bin(year) - if not (reg_b & 0x02) and (hour & 0x80): - hour = ((hour & 0x7F) + 12) % 24 - hour = hour + RTC_TZ_OFFSET - if hour >= 24: - hour = hour - 24 - day = day + 1 - max_day: t.CUInt8T = 31 - if mon == 4 or mon == 6 or mon == 9 or mon == 11: - max_day = 30 - elif mon == 2: - max_day = 28 - y4: t.CUInt16T = t.CUInt16T(year) + 2000 - if (y4 % 4 == 0 and y4 % 100 != 0) or (y4 % 400 == 0): - max_day = 29 - if day > max_day: - day = 1 - mon = mon + 1 - if mon > 12: - mon = 1 - year = year + 1 - global rtc_seconds, rtc_minutes, rtc_hours, rtc_day, rtc_month, rtc_year - rtc_seconds = sec - rtc_minutes = min_ - rtc_hours = hour - rtc_day = day - rtc_month = mon - rtc_year = t.CUInt16T(year) + 2000 - -def rtc_init(): - rtc_read_time() - -def rtc_get_hours() -> t.CUInt8T: - return rtc_hours - -def rtc_get_minutes() -> t.CUInt8T: - return rtc_minutes - -def rtc_get_seconds() -> t.CUInt8T: - return rtc_seconds - -def rtc_get_day() -> t.CUInt8T: - return rtc_day - -def rtc_get_month() -> t.CUInt8T: - return rtc_month - -def rtc_get_year() -> t.CUInt16T: - return rtc_year +from stdint import * +import t, c +import asm + + +RTC_CMOS_ADDR: uint16 = 0x70 +RTC_CMOS_DATA: uint16 = 0x71 + +RTC_REG_SECONDS: t.CDefine = 0x00 +RTC_REG_MINUTES: t.CDefine = 0x02 +RTC_REG_HOURS: t.CDefine = 0x04 +RTC_REG_DAY: t.CDefine = 0x07 +RTC_REG_MONTH: t.CDefine = 0x08 +RTC_REG_YEAR: t.CDefine = 0x09 +RTC_REG_STATUS_A: t.CDefine = 0x0A +RTC_REG_STATUS_B: t.CDefine = 0x0B + +RTC_TZ_OFFSET: t.CDefine = 8 + +rtc_seconds: t.CStatic | t.CVolatile | uint8 = 0 +rtc_minutes: t.CStatic | t.CVolatile | uint8 = 0 +rtc_hours: t.CStatic | t.CVolatile | uint8 = 0 +rtc_day: t.CStatic | t.CVolatile | uint8 = 0 +rtc_month: t.CStatic | t.CVolatile | uint8 = 0 +rtc_year: t.CStatic | t.CVolatile | uint16 = 0 + +def cmos_read(reg: uint8) -> uint8: + asm.outb(RTC_CMOS_ADDR, reg) + return asm.inb(RTC_CMOS_DATA) + +def bcd_to_bin(bcd: uint8) -> uint8: + return (bcd >> 4) * 10 + (bcd & 0x0F) + +def rtc_read_time(): + while cmos_read(RTC_REG_STATUS_A) & 0x80: pass + sec: uint8 = cmos_read(RTC_REG_SECONDS) + min_: uint8 = cmos_read(RTC_REG_MINUTES) + hour: uint8 = cmos_read(RTC_REG_HOURS) + day: uint8 = cmos_read(RTC_REG_DAY) + mon: uint8 = cmos_read(RTC_REG_MONTH) + year: uint8 = cmos_read(RTC_REG_YEAR) + reg_b: uint8 = cmos_read(RTC_REG_STATUS_B) + if not (reg_b & 0x04): + sec = bcd_to_bin(sec) + min_ = bcd_to_bin(min_) + hour = bcd_to_bin(hour) + day = bcd_to_bin(day) + mon = bcd_to_bin(mon) + year = bcd_to_bin(year) + if not (reg_b & 0x02) and (hour & 0x80): + hour = ((hour & 0x7F) + 12) % 24 + hour = hour + RTC_TZ_OFFSET + if hour >= 24: + hour = hour - 24 + day = day + 1 + max_day: uint8 = 31 + if mon == 4 or mon == 6 or mon == 9 or mon == 11: + max_day = 30 + elif mon == 2: + max_day = 28 + y4: uint16 = uint16(year) + 2000 + if (y4 % 4 == 0 and y4 % 100 != 0) or (y4 % 400 == 0): + max_day = 29 + if day > max_day: + day = 1 + mon = mon + 1 + if mon > 12: + mon = 1 + year = year + 1 + global rtc_seconds, rtc_minutes, rtc_hours, rtc_day, rtc_month, rtc_year + rtc_seconds = sec + rtc_minutes = min_ + rtc_hours = hour + rtc_day = day + rtc_month = mon + rtc_year = uint16(year) + 2000 + +def rtc_init(): + rtc_read_time() + +def rtc_get_hours() -> uint8: + return rtc_hours + +def rtc_get_minutes() -> uint8: + return rtc_minutes + +def rtc_get_seconds() -> uint8: + return rtc_seconds + +def rtc_get_day() -> uint8: + return rtc_day + +def rtc_get_month() -> uint8: + return rtc_month + +def rtc_get_year() -> uint16: + return rtc_year diff --git a/VKernel/Kernel/platform/pch/timer.vp b/VKernel/Kernel/platform/pch/timer.vp index 5fb19b4..9e0ae76 100644 --- a/VKernel/Kernel/platform/pch/timer.vp +++ b/VKernel/Kernel/platform/pch/timer.vp @@ -1,129 +1,129 @@ -import platform.pch.pic as pic -import platform.pch.pit as pit -import sched.sched as sched -import drivers.core.cpu.apic as apic -import drivers.serial.uart.serial as serial -import viperlib -import asm -import t, c - -TIMER_FREQUENCY: t.CDefine = 1000 -TICKS_PER_SECOND: t.CDefine = TIMER_FREQUENCY -MILLISECONDS_PER_TICK: t.CDefine = (1000 / TIMER_FREQUENCY) - -ticks: t.CStatic | t.CVolatile | t.CUInt64T = 0 -seconds: t.CStatic | t.CVolatile | t.CUInt32T = 0 -milliseconds: t.CStatic | t.CVolatile | t.CUInt32T = 0 -timer_running: t.CStatic | t.CVolatile | bool = False -_dbg_once: t.CInt = 0 - -def timer_init(): - global ticks, seconds, milliseconds, timer_running - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - ticks = 0 - seconds = 0 - milliseconds = 0 - timer_running = True - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - pit.pit_init(TIMER_FREQUENCY) - # [DBG] 读 PIT 计数器验证是否在走(用后移除) - asm.outb(0x43, 0x00) # latch channel 0 - _lo: t.CUInt8T = asm.inb(0x40) - _hi: t.CUInt8T = asm.inb(0x40) - _cnt: t.CInt = t.CInt(_lo) | (t.CInt(_hi) << 8) - _cb: t.CArray[t.CChar, 40] - viperlib.snprintf(c.Addr(_cb), 40, "[PIT] cnt=%d\n", _cnt) - serial.puts(c.Addr(_cb)) - -def timer_handler(): - global ticks, seconds, milliseconds, timer_running, _dbg_once - # [DBG] 一次性打印:'H' 出现说明定时 ISR 被调用(用后移除) - if _dbg_once == 0: - _dbg_once = 1 - serial.puts("H") - if not timer_running: - pic.eoi(0) - apic.eoi() - return - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - ticks = ticks + 1 - milliseconds = milliseconds + MILLISECONDS_PER_TICK - if milliseconds >= 1000: - seconds = seconds + 1 - milliseconds = milliseconds - 1000 - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - sched.Scheduler.sched_tick() - pic.eoi(0) - # LAPIC EOI:APIC 启用后中断经 LINT0(EXTINT) 送达会置 LAPIC ISR, - # 只发 PIC EOI 不清 LAPIC ISR → 首个定时中断后后续中断被屏蔽 → - # ticks 不推进 → msleep 永久挂起(QEMU/OVMF 下 APIC 必启用)。 - apic.eoi() - -def timer_start(): - global timer_running - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - timer_running = True - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - -def timer_stop(): - global timer_running - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - timer_running = False - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - -def timer_reset(): - global ticks, seconds, milliseconds - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - ticks = 0 - seconds = 0 - milliseconds = 0 - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - -def timer_get_ticks() -> t.CUInt64T: - current_ticks: t.CUInt64T - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - current_ticks = ticks - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - return current_ticks - -def timer_get_seconds() -> t.CUInt32T: - current_seconds: t.CUInt32T - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - current_seconds = seconds - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - return current_seconds - -def timer_get_milliseconds() -> t.CUInt32T: - current_milliseconds: t.CUInt32T - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - current_milliseconds = milliseconds - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - return current_milliseconds - -def timer_get_time(out_seconds: t.CUInt32T | t.CPtr, out_milliseconds: t.CUInt32T | t.CPtr): - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - if out_seconds: - c.Set(c.Deref(out_seconds), seconds) - if out_milliseconds: - c.Set(c.Deref(out_milliseconds), milliseconds) - c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - -def timer_msleep(ms: t.CUInt32T): - target: t.CUInt64T = ticks + (ms + MILLISECONDS_PER_TICK - 1) / MILLISECONDS_PER_TICK - _spin: t.CUInt64T = 0 - while ticks < target: - # [DBG] 自旋计数:每 1M 次迭代打印 s——hlt 能唤醒说明中断触发 - # (用后移除) - _spin += 1 - if (_spin & 0xFFFFF) == 0: - serial.puts("s") - asm.sti() - asm.hlt() - sched.Scheduler._yield() - -def timer_sleep(sec: t.CUInt32T): - target: t.CUInt64T = ticks + sec * TICKS_PER_SECOND - while ticks < target: - asm.sti() - asm.hlt() - sched.Scheduler._yield() +import platform.pch.pic as pic +import platform.pch.pit as pit +import sched.sched as sched +import drivers.core.cpu.apic as apic +import drivers.serial.uart.serial as serial +import viperlib +import asm +import t, c + +TIMER_FREQUENCY: t.CDefine = 1000 +TICKS_PER_SECOND: t.CDefine = TIMER_FREQUENCY +MILLISECONDS_PER_TICK: t.CDefine = (1000 / TIMER_FREQUENCY) + +ticks: t.CStatic | t.CVolatile | uint64 = 0 +seconds: t.CStatic | t.CVolatile | uint32 = 0 +milliseconds: t.CStatic | t.CVolatile | uint32 = 0 +timer_running: t.CStatic | t.CVolatile | bool = False +_dbg_once: int = 0 + +def timer_init(): + global ticks, seconds, milliseconds, timer_running + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + ticks = 0 + seconds = 0 + milliseconds = 0 + timer_running = True + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + pit.pit_init(TIMER_FREQUENCY) + # [DBG] 读 PIT 计数器验证是否在走(用后移除) + asm.outb(0x43, 0x00) # latch channel 0 + _lo: uint8 = asm.inb(0x40) + _hi: uint8 = asm.inb(0x40) + _cnt: int = int(_lo) | (int(_hi) << 8) + _cb: t.CArray[t.CChar, 40] + viperlib.snprintf(c.Addr(_cb), 40, "[PIT] cnt=%d\n", _cnt) + serial.puts(c.Addr(_cb)) + +def timer_handler(): + global ticks, seconds, milliseconds, timer_running, _dbg_once + # [DBG] 一次性打印:'H' 出现说明定时 ISR 被调用(用后移除) + if _dbg_once == 0: + _dbg_once = 1 + serial.puts("H") + if not timer_running: + pic.eoi(0) + apic.eoi() + return + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + ticks = ticks + 1 + milliseconds = milliseconds + MILLISECONDS_PER_TICK + if milliseconds >= 1000: + seconds = seconds + 1 + milliseconds = milliseconds - 1000 + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + sched.Scheduler.sched_tick() + pic.eoi(0) + # LAPIC EOI:APIC 启用后中断经 LINT0(EXTINT) 送达会置 LAPIC ISR, + # 只发 PIC EOI 不清 LAPIC ISR → 首个定时中断后后续中断被屏蔽 → + # ticks 不推进 → msleep 永久挂起(QEMU/OVMF 下 APIC 必启用)。 + apic.eoi() + +def timer_start(): + global timer_running + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + timer_running = True + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + +def timer_stop(): + global timer_running + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + timer_running = False + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + +def timer_reset(): + global ticks, seconds, milliseconds + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + ticks = 0 + seconds = 0 + milliseconds = 0 + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + +def timer_get_ticks() -> uint64: + current_ticks: uint64 + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + current_ticks = ticks + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + return current_ticks + +def timer_get_seconds() -> uint32: + current_seconds: uint32 + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + current_seconds = seconds + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + return current_seconds + +def timer_get_milliseconds() -> uint32: + current_milliseconds: uint32 + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + current_milliseconds = milliseconds + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + return current_milliseconds + +def timer_get_time(out_seconds: uint32 | t.CPtr, out_milliseconds: uint32 | t.CPtr): + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + if out_seconds: + c.Set(c.Deref(out_seconds), seconds) + if out_milliseconds: + c.Set(c.Deref(out_milliseconds), milliseconds) + c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + +def timer_msleep(ms: uint32): + target: uint64 = ticks + (ms + MILLISECONDS_PER_TICK - 1) / MILLISECONDS_PER_TICK + _spin: uint64 = 0 + while ticks < target: + # [DBG] 自旋计数:每 1M 次迭代打印 s——hlt 能唤醒说明中断触发 + # (用后移除) + _spin += 1 + if (_spin & 0xFFFFF) == 0: + serial.puts("s") + asm.sti() + asm.hlt() + sched.Scheduler._yield() + +def timer_sleep(sec: uint32): + target: uint64 = ticks + sec * TICKS_PER_SECOND + while ticks < target: + asm.sti() + asm.hlt() + sched.Scheduler._yield() diff --git a/VKernel/Kernel/sched/coroutine.vp b/VKernel/Kernel/sched/coroutine.vp index 95a854c..f671013 100644 --- a/VKernel/Kernel/sched/coroutine.vp +++ b/VKernel/Kernel/sched/coroutine.vp @@ -13,27 +13,27 @@ CORO_STACK_SIZE: t.CDefine = 8192 @t.Object class Coroutine: - rsp: t.CUInt64T - stack: t.CVoid | t.CPtr - stack_size: t.CUInt64T - func: t.CVoid | t.CPtr - arg: t.CVoid | t.CPtr - state: t.CInt - cid: t.CInt - caller_rsp: t.CUInt64T - ret_val: t.CInt + rsp: uint64 + stack: t.CPtr + stack_size: uint64 + func: t.CPtr + arg: t.CPtr + state: int + cid: int + caller_rsp: uint64 + ret_val: int - def resume(self) -> t.CInt: + def resume(self) -> int: global _coro_old_rsp, _coro_new_rsp m: CoroutineManager | t.CPtr = _coro_mgr_ptr if self.state == CORO_DONE: return self.ret_val if self.state != CORO_READY and self.state != CORO_YIELDED: return -1 - prev_cid: t.CInt = m.current_cid + prev_cid: int = m.current_cid m.current_cid = self.cid self.state = CORO_RUNNING _coro_old_rsp = c.Addr(m.coroutines[prev_cid].rsp) _coro_new_rsp = c.Addr(self.rsp) - self.caller_rsp = t.CUInt64T(_coro_old_rsp) + self.caller_rsp = uint64(_coro_old_rsp) _coro_switch() if self.state == CORO_DONE: return self.ret_val @@ -43,11 +43,11 @@ class Coroutine: def _yield(): global _coro_old_rsp, _coro_new_rsp m: CoroutineManager | t.CPtr = _coro_mgr_ptr - cid: t.CInt = m.current_cid + cid: int = m.current_cid if cid < 0: return m.coroutines[cid].state = CORO_YIELDED - prev_cid: t.CInt = -1 - i: t.CInt + prev_cid: int = -1 + i: int for i in range(m.count): if m.coroutines[i].state == CORO_RUNNING and m.coroutines[i].caller_rsp != 0: prev_cid = i @@ -59,27 +59,27 @@ class Coroutine: _coro_switch() @property - def is_done(self) -> t.CInt: + def is_done(self) -> int: if self.state == CORO_DONE: return 1 return 0 @property - def is_yielded(self) -> t.CInt: + def is_yielded(self) -> int: if self.state == CORO_YIELDED: return 1 return 0 @property - def retval(self) -> t.CInt: + def retval(self) -> int: return self.ret_val @t.Object class CoroutineManager: coroutines: t.CArray[Coroutine, MAX_COROUTINES] - current_cid: t.CInt - count: t.CInt + current_cid: int + count: int def __init__(self): global _coro_mgr_ptr @@ -96,7 +96,7 @@ class CoroutineManager: m.coroutines[0].stack_size = 0 m.coroutines[0].func = None m.coroutines[0].arg = None - main_rsp_ptr: t.CVoid | t.CPtr = c.Addr(m.coroutines[0].rsp) + main_rsp_ptr: t.CPtr = c.Addr(m.coroutines[0].rsp) c.Asm(f"""mov qword ptr [{c.AsmInp(main_rsp_ptr, t.ASM_DESCR.REG_ANY)}], rsp""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) @@ -106,16 +106,16 @@ class CoroutineManager: return c.Addr(m.coroutines[m.current_cid]) @staticmethod - def get_coroutine(cid: t.CInt) -> Coroutine | t.CPtr: + def get_coroutine(cid: int) -> Coroutine | t.CPtr: m: CoroutineManager | t.CPtr = _coro_mgr_ptr if cid < 0 or cid >= m.count: return None return c.Addr(m.coroutines[cid]) @staticmethod - def create(func: t.CVoid | t.CPtr, arg: t.CVoid | t.CPtr) -> Coroutine | t.CPtr: + def create(func: t.CPtr, arg: t.CPtr) -> Coroutine | t.CPtr: m: CoroutineManager | t.CPtr = _coro_mgr_ptr if m.count >= MAX_COROUTINES: return None - cid: t.CInt = m.count + cid: int = m.count m.count += 1 co: Coroutine | t.CPtr = c.Addr(m.coroutines[cid]) co.state = CORO_READY @@ -124,13 +124,13 @@ class CoroutineManager: co.arg = arg co.caller_rsp = 0 co.ret_val = 0 - stack_ptr: t.CVoid | t.CPtr = mm.malloc(CORO_STACK_SIZE) + stack_ptr: t.CPtr = mm.malloc(CORO_STACK_SIZE) if not stack_ptr: return None co.stack = stack_ptr co.stack_size = CORO_STACK_SIZE - stack_top: t.CUInt64T = t.CUInt64T(stack_ptr) + CORO_STACK_SIZE - 16 - stack_top = stack_top & ~t.CUInt64T(0xF) - entry_addr: t.CUInt64T = t.CUInt64T(c.Addr(_coro_entry)) + stack_top: uint64 = uint64(stack_ptr) + CORO_STACK_SIZE - 16 + stack_top = stack_top & ~uint64(0xF) + entry_addr: uint64 = uint64(c.Addr(_coro_entry)) sp: t.CPtr = t.CPtr(stack_top) c.Asm(f"""mov rax, {c.AsmInp(sp, t.ASM_DESCR.REG_ANY)} mov qword ptr [rax - 56], 0 @@ -149,8 +149,8 @@ class CoroutineManager: _coro_mgr: CoroutineManager = CoroutineManager() _coro_mgr_ptr: CoroutineManager | t.CPtr | t.CExport = c.Addr(_coro_mgr) -_coro_old_rsp: t.CVoid | t.CPtr | t.CExport -_coro_new_rsp: t.CVoid | t.CPtr | t.CExport +_coro_old_rsp: t.CPtr | t.CExport +_coro_new_rsp: t.CPtr | t.CExport @c.Attribute(t.attr.naked) def _coro_switch(): @@ -177,20 +177,25 @@ def _coro_switch(): @c.Attribute(t.attr.naked) def _coro_entry(): + # 结构体布局(以 stub.ll 为权威): + # Coroutine = {rsp@0, stack@8, stack_size@16, func@24, arg@32, + # state@40, cid@44, caller_rsp@48, ret_val@56}, sizeof=64 + # CoroutineManager= {coroutines[32]@0 (32*64=2048), current_cid@2048, count@2052} + # 取 func/arg 入口,写 state=CORO_DONE(3)、ret_val。 c.Asm(f"""sub rsp, 8 mov rax, qword ptr [rip + _coro_mgr_ptr] - mov ecx, dword ptr [rax + 1056] + mov ecx, dword ptr [rax + 2048] movsxd rcx, ecx - shl rcx, 5 - mov rdi, qword ptr [rax + rcx + 24] - mov rax, qword ptr [rax + rcx + 16] + shl rcx, 6 + mov rdi, qword ptr [rax + rcx + 32] + mov rax, qword ptr [rax + rcx + 24] call rax mov rax, qword ptr [rip + _coro_mgr_ptr] - mov ecx, dword ptr [rax + 1056] + mov ecx, dword ptr [rax + 2048] movsxd rcx, ecx - shl rcx, 5 - mov dword ptr [rax + rcx + 32], 3 - mov dword ptr [rax + rcx + 48], eax + shl rcx, 6 + mov dword ptr [rax + rcx + 40], 3 + mov dword ptr [rax + rcx + 56], eax add rsp, 8""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, diff --git a/VKernel/Kernel/sched/process.vp b/VKernel/Kernel/sched/process.vp index ae2eae0..669241a 100644 --- a/VKernel/Kernel/sched/process.vp +++ b/VKernel/Kernel/sched/process.vp @@ -23,25 +23,25 @@ USER_STACK_SIZE: t.CDefine = 65536 @t.Object class Process: - pid: t.CInt - pml4_root: t.CUInt64T - threads: t.CArray[t.CInt, 8] - thread_count: t.CInt - state: t.CInt - entry: t.CVoid | t.CPtr - elf_base: t.CUInt64T - heap_start: t.CUInt64T - heap_size: t.CUInt64T + pid: int + pml4_root: uint64 + threads: t.CArray[int, 8] + thread_count: int + state: int + entry: t.CPtr + elf_base: uint64 + heap_start: uint64 + heap_size: uint64 name: t.CArray[t.CChar, 32] - fd_table: t.CArray[t.CVoid | t.CPtr, PROC_MAX_FDS] - fd_used: t.CArray[t.CUInt8T, PROC_MAX_FDS] - dir_table: t.CArray[t.CVoid | t.CPtr, PROC_MAX_DIRS] - dir_used: t.CArray[t.CUInt8T, PROC_MAX_DIRS] + fd_table: t.CArray[t.CPtr, PROC_MAX_FDS] + fd_used: t.CArray[uint8, PROC_MAX_FDS] + dir_table: t.CArray[t.CPtr, PROC_MAX_DIRS] + dir_used: t.CArray[uint8, PROC_MAX_DIRS] dir_pool: t.CArray[fat32_types.dirobj, PROC_MAX_DIRS] - kern_stack: t.CUInt64T - user_stack: t.CUInt64T + kern_stack: uint64 + user_stack: uint64 - def addThread(self, tid: t.CInt) -> t.CInt: + def addThread(self, tid: int) -> int: if self.thread_count >= MAX_PROC_THREADS: return -1 self.threads[self.thread_count] = tid self.thread_count += 1 @@ -51,14 +51,14 @@ class Process: self.state = PROC_DONE for i in range(PROC_MAX_FDS): if self.fd_used[i]: - fp: t.CVoid | t.CPtr = self.fd_table[i] + fp: t.CPtr = self.fd_table[i] if fp: fat32.close(fp) self.fd_used[i] = 0 self.fd_table[i] = t.CVoid(0, t.CPtr) for i in range(PROC_MAX_DIRS): if self.dir_used[i]: - dp: t.CVoid | t.CPtr = self.dir_table[i] + dp: t.CPtr = self.dir_table[i] if dp: fat32.closedir(dp) self.dir_used[i] = 0 @@ -68,20 +68,20 @@ class Process: m.current_pid = 0 m.processes[0].state = PROC_RUNNING if self.pml4_root != 0: - kernel_cr3: t.CUInt64T = m.processes[0].pml4_root + kernel_cr3: uint64 = m.processes[0].pml4_root if kernel_cr3 != 0: c.Asm(f"mov cr3, {c.AsmInp(kernel_cr3, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) paging.set_active_pml4(kernel_cr3) @property - def is_running(self) -> t.CInt: + def is_running(self) -> int: if self.state == PROC_RUNNING: return 1 return 0 @property - def is_done(self) -> t.CInt: + def is_done(self) -> int: if self.state == PROC_DONE: return 1 return 0 @@ -90,8 +90,8 @@ class Process: @t.Object class ProcessManager: processes: t.CArray[Process, MAX_PROCESSES] - current_pid: t.CInt - count: t.CInt + current_pid: int + count: int def __init__(self): global _proc_mgr_ptr @@ -109,13 +109,13 @@ class ProcessManager: p.heap_start = 0 p.heap_size = 0 name_str: str = "kernel" - i: t.CInt = 0 + i: int = 0 for ch in name_str: if i >= 31: break p.name[i] = ch i += 1 p.name[i] = 0 - j: t.CInt + j: int for j in range(MAX_PROC_THREADS): p.threads[j] = -1 for j in range(PROC_MAX_FDS): @@ -128,13 +128,13 @@ class ProcessManager: op=[t.ASM_DESCR.CLOBBER_MEMORY]) @staticmethod - def _switch(pid: t.CInt) -> t.CInt: + def _switch(pid: int) -> int: global _saved_cr3 m: ProcessManager | t.CPtr = _proc_mgr_ptr if pid < 0 or pid >= m.count: return -1 p: Process | t.CPtr = c.Addr(m.processes[pid]) if p.state == PROC_DONE: return -1 - old_pid: t.CInt = m.current_pid + old_pid: int = m.current_pid if old_pid == pid: return 0 if old_pid >= 0 and old_pid < m.count: m.processes[old_pid].state = PROC_READY @@ -152,19 +152,19 @@ class ProcessManager: return c.Addr(m.processes[m.current_pid]) @staticmethod - def get_process(pid: t.CInt) -> Process | t.CPtr: + def get_process(pid: int) -> Process | t.CPtr: m: ProcessManager | t.CPtr = _proc_mgr_ptr if pid < 0 or pid >= m.count: return None return c.Addr(m.processes[pid]) @staticmethod - def create_process(name: str, entry: t.CVoid | t.CPtr) -> Process | t.CPtr: + def create_process(name: str, entry: t.CPtr) -> Process | t.CPtr: m: ProcessManager | t.CPtr = _proc_mgr_ptr _dbp: t.CArray[t.CChar, 80] viperlib.snprintf(c.Addr(_dbp), 80, "[process] create_process count=%d MAX=%d\n", m.count, MAX_PROCESSES) serial.puts(_dbp) if m.count >= MAX_PROCESSES: return None - pid: t.CInt = m.count + pid: int = m.count m.count += 1 p: Process | t.CPtr = c.Addr(m.processes[pid]) p.pid = pid @@ -175,13 +175,13 @@ class ProcessManager: p.heap_start = 0 p.heap_size = 0 string.memset(c.Addr(p.name), 0, 32) - i: t.CInt = 0 + i: int = 0 for ch in name: if i >= 31: break p.name[i] = ch i += 1 p.name[i] = 0 - j: t.CInt + j: int for j in range(MAX_PROC_THREADS): p.threads[j] = -1 for j in range(PROC_MAX_FDS): @@ -190,29 +190,29 @@ class ProcessManager: for j in range(PROC_MAX_DIRS): p.dir_used[j] = 0 p.dir_table[j] = t.CVoid(0, t.CPtr) - ks: t.CVoid | t.CPtr = mm_mm.malloc(KERN_STACK_SIZE) + ks: t.CPtr = mm_mm.malloc(KERN_STACK_SIZE) # [DIAG] 定位跨模块 malloc 返回值(mm 成功但调用方收到 None) _dbg_ks: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(_dbg_ks), 64, "[proc] ks=0x%lx\n", t.CUInt64T(ks)) + viperlib.snprintf(c.Addr(_dbg_ks), 64, "[proc] ks=0x%lx\n", uint64(ks)) serial.puts(c.Addr(_dbg_ks)) if ks is None: serial.puts("[process] kernel stack alloc failed\n") m.count = m.count - 1 return None - ks_size: t.CUInt64T = KERN_STACK_SIZE - p.kern_stack = t.CUInt64T(ks) + ks_size - us: t.CVoid | t.CPtr = mm_mm.malloc(USER_STACK_SIZE) + ks_size: uint64 = KERN_STACK_SIZE + p.kern_stack = uint64(ks) + ks_size + us: t.CPtr = mm_mm.malloc(USER_STACK_SIZE) # [DIAG] 定位 user_stack 收到 None(mm 内部打印成功但此处收 0x0) _dbg_us: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(_dbg_us), 64, "[proc] us=0x%lx\n", t.CUInt64T(us)) + viperlib.snprintf(c.Addr(_dbg_us), 64, "[proc] us=0x%lx\n", uint64(us)) serial.puts(c.Addr(_dbg_us)) if us is None: serial.puts("[process] user stack alloc failed\n") mm_mm.free(ks) m.count = m.count - 1 return None - us_size: t.CUInt64T = USER_STACK_SIZE - p.user_stack = t.CUInt64T(us) + us_size + us_size: uint64 = USER_STACK_SIZE + p.user_stack = uint64(us) + us_size c.Asm(f"""mov {c.AsmOut(p.pml4_root, t.ASM_DESCR.OUTPUT_REG)}, cr3""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX]) return p @@ -220,13 +220,13 @@ class ProcessManager: _proc_mgr: ProcessManager = ProcessManager() _proc_mgr_ptr: ProcessManager | t.CPtr = c.Addr(_proc_mgr) -_saved_cr3: t.CUInt64T | t.CExport +_saved_cr3: uint64 | t.CExport -def current() -> t.CInt: +def current() -> int: m: ProcessManager | t.CPtr = _proc_mgr_ptr return m.current_pid -def switch_pid(new_pid: t.CInt): +def switch_pid(new_pid: int): m: ProcessManager | t.CPtr = _proc_mgr_ptr if m.current_pid == new_pid: return if m.current_pid >= 0 and m.current_pid < m.count: @@ -236,7 +236,7 @@ def switch_pid(new_pid: t.CInt): if new_pid >= 0 and new_pid < m.count: new_p: Process | t.CPtr = c.Addr(m.processes[new_pid]) new_p.state = PROC_RUNNING - new_cr3: t.CUInt64T = new_p.pml4_root + new_cr3: uint64 = new_p.pml4_root if new_cr3 != 0: c.Asm(f"mov cr3, {c.AsmInp(new_cr3, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY]) @@ -248,18 +248,18 @@ def switch_pid(new_pid: t.CInt): cpu.set_kernel_rsp0(new_p.kern_stack) m.current_pid = new_pid -def get_pid(tid: t.CInt) -> t.CInt: +def get_pid(tid: int) -> int: m: ProcessManager | t.CPtr = _proc_mgr_ptr - i: t.CInt + i: int for i in range(m.count): p: Process | t.CPtr = c.Addr(m.processes[i]) - j: t.CInt + j: int for j in range(p.thread_count): if p.threads[j] == tid: return p.pid return -1 -def drop_to_user_mode(entry: t.CVoid | t.CPtr, user_rsp: t.CUInt64T, kern_rsp: t.CUInt64T): +def drop_to_user_mode(entry: t.CPtr, user_rsp: uint64, kern_rsp: uint64): # NOTE: Do NOT swapgs here. This OS uses reverse GS convention: # GS_BASE = 0 (kernel & user), KERNEL_GS_BASE = &_per_cpu # syscall/ISR entry does swapgs to get GS_BASE = &_per_cpu diff --git a/VKernel/Kernel/sched/sched.vp b/VKernel/Kernel/sched/sched.vp index 7821307..12f34de 100644 --- a/VKernel/Kernel/sched/sched.vp +++ b/VKernel/Kernel/sched/sched.vp @@ -14,20 +14,20 @@ MAX_THREADS: t.CDefine = 16 THREAD_STACK_SIZE: t.CDefine = 65536 SCHED_QUANTUM: t.CDefine = 10 -_yield_cnt: t.CUInt32T = 0 -_yield_lock: t.CInt = 0 +_yield_cnt: uint32 = 0 +_yield_lock: int = 0 @t.Object class Thread: - rsp: t.CUInt64T - stack: t.CVoid | t.CPtr - stack_size: t.CUInt64T - func: t.CVoid | t.CPtr - arg: t.CVoid | t.CPtr - state: t.CInt + rsp: uint64 + stack: t.CPtr + stack_size: uint64 + func: t.CPtr + arg: t.CPtr + state: int tid: int - pid: t.CInt + pid: int def block(self): self.state = THREAD_BLOCKED @@ -38,19 +38,19 @@ class Thread: self.state = THREAD_READY @property - def is_running(self) -> t.CInt: + def is_running(self) -> int: if self.state == THREAD_RUNNING: return 1 return 0 @property - def is_blocked(self) -> t.CInt: + def is_blocked(self) -> int: if self.state == THREAD_BLOCKED: return 1 return 0 @property - def is_done(self) -> t.CInt: + def is_done(self) -> int: if self.state == THREAD_DONE: return 1 return 0 @@ -59,11 +59,11 @@ class Thread: @t.Object class Scheduler: threads: t.CArray[Thread, MAX_THREADS] - current_tid: t.CInt - thread_count: t.CInt - enabled: t.CInt - needs_reschedule: t.CInt - tick_count: t.CInt + current_tid: int + thread_count: int + enabled: int + needs_reschedule: int + tick_count: int def __init__(self): global _sched_ptr @@ -87,14 +87,14 @@ class Scheduler: s.enabled = 1 s.threads[0].state = THREAD_RUNNING s.threads[0].tid = 0 - main_rsp_ptr: t.CVoid | t.CPtr = c.Addr(s.threads[0].rsp) + main_rsp_ptr: t.CPtr = c.Addr(s.threads[0].rsp) c.Asm(f"""mov qword ptr [{c.AsmInp(main_rsp_ptr, t.ASM_DESCR.REG_ANY)}], rsp""", op=[t.ASM_DESCR.CLOBBER_MEMORY]) @staticmethod def _yield(): global _switch_old_rsp, _switch_new_rsp, _yield_cnt, _yield_lock - _if_saved: t.CInt = 0 + _if_saved: int = 0 c.Asm(f"""pushfq pop rax shr rax, 9 @@ -110,14 +110,14 @@ class Scheduler: s: Scheduler | t.CPtr = _sched_ptr s.needs_reschedule = 0 s.tick_count = 0 - old_tid: t.CInt = s.current_tid - next_tid: t.CInt = old_tid + 1 + old_tid: int = s.current_tid + next_tid: int = old_tid + 1 if next_tid >= s.thread_count: next_tid = 0 - found: t.CInt = 0 - count: t.CInt = 0 + found: int = 0 + count: int = 0 while count < s.thread_count: - st: t.CInt = s.threads[next_tid].state + st: int = s.threads[next_tid].state if st == THREAD_READY or st == THREAD_RUNNING: found = 1 break @@ -141,7 +141,7 @@ class Scheduler: _switch_old_rsp = c.Addr(s.threads[old_tid].rsp) _switch_new_rsp = c.Addr(s.threads[next_tid].rsp) s.current_tid = next_tid - next_pid: t.CInt = s.threads[next_tid].pid + next_pid: int = s.threads[next_tid].pid _yield_cnt += 1 proc.switch_pid(next_pid) _yield_lock = 0 @@ -182,13 +182,13 @@ class Scheduler: return c.Addr(s.threads[s.current_tid]) @staticmethod - def get_thread(tid: t.CInt) -> Thread | t.CPtr: + def get_thread(tid: int) -> Thread | t.CPtr: s: Scheduler | t.CPtr = _sched_ptr if tid < 0 or tid >= s.thread_count: return None return c.Addr(s.threads[tid]) @staticmethod - def create_thread(func: t.CVoid | t.CPtr, arg: t.CVoid | t.CPtr, thread_pid: t.CInt = 0) -> Thread | t.CPtr: + def create_thread(func: t.CPtr, arg: t.CPtr, thread_pid: int = 0) -> Thread | t.CPtr: s: Scheduler | t.CPtr = _sched_ptr if s.thread_count >= MAX_THREADS: return None tid: int = s.thread_count @@ -199,11 +199,11 @@ class Scheduler: th.pid = thread_pid th.func = func th.arg = arg - stack_size: t.CUInt64T = THREAD_STACK_SIZE - stack_ptr: t.CVoid | t.CPtr = mm.malloc(stack_size) + stack_size: uint64 = THREAD_STACK_SIZE + stack_ptr: t.CPtr = mm.malloc(stack_size) _dbg_ct: t.CArray[t.CChar, 96] viperlib.snprintf(c.Addr(_dbg_ct), 96, "[sched] ct t%d func=0x%lx stack=0x%lx\n", - tid, t.CUInt64T(th.func), t.CUInt64T(stack_ptr)) + tid, uint64(th.func), uint64(stack_ptr)) serial.puts(c.Addr(_dbg_ct)) if not stack_ptr: # B4:栈分配失败回退槽位计数(对齐 process.vp create_process 失败路径), @@ -212,9 +212,9 @@ class Scheduler: return None th.stack = stack_ptr th.stack_size = stack_size - stack_top: t.CUInt64T = t.CUInt64T(stack_ptr) + stack_size - 16 - stack_top = stack_top & ~t.CUInt64T(0xF) - entry_addr: t.CUInt64T = t.CUInt64T(c.Addr(_thread_entry)) + stack_top: uint64 = uint64(stack_ptr) + stack_size - 16 + stack_top = stack_top & ~uint64(0xF) + entry_addr: uint64 = uint64(c.Addr(_thread_entry)) sp: t.CPtr = t.CPtr(stack_top) c.Asm(f"""mov rax, {c.AsmInp(sp, t.ASM_DESCR.REG_ANY)} mov qword ptr [rax - 64], 0x202 @@ -234,8 +234,8 @@ class Scheduler: _sched_storage: Scheduler = Scheduler() _sched_ptr: Scheduler | t.CPtr | t.CExport = c.Addr(_sched_storage) -_switch_old_rsp: t.CVoid | t.CPtr | t.CExport -_switch_new_rsp: t.CVoid | t.CPtr | t.CExport +_switch_old_rsp: t.CPtr | t.CExport +_switch_new_rsp: t.CPtr | t.CExport @c.Attribute(t.attr.naked) def _do_switch(): @@ -288,11 +288,11 @@ def _thread_entry(): asm.hlt() Scheduler._yield() -def thread_current() -> t.CInt: +def thread_current() -> int: s: Scheduler | t.CPtr = _sched_ptr return s.current_tid -def needs_reschedule() -> t.CInt: +def needs_reschedule() -> int: s: Scheduler | t.CPtr = _sched_ptr return s.needs_reschedule diff --git a/VKernel/Kernel/services/desktop.vp b/VKernel/Kernel/services/desktop.vp index 66a1df0..093b949 100644 --- a/VKernel/Kernel/services/desktop.vp +++ b/VKernel/Kernel/services/desktop.vp @@ -54,70 +54,70 @@ STYLE_WIN7: t.CDefine = 3 STYLE_WINXP: t.CDefine = 4 _fb: UINT32PTR -_screen_w: t.CInt = 0 -_screen_h: t.CInt = 0 -_fb_pitch: t.CInt = 0 -_cursor_x: t.CInt = 512 -_cursor_y: t.CInt = 300 -_cursor_buttons: t.CUInt8T = 0 +_screen_w: int = 0 +_screen_h: int = 0 +_fb_pitch: int = 0 +_cursor_x: int = 512 +_cursor_y: int = 300 +_cursor_buttons: uint8 = 0 _back_fb: UINT32PTR -_last_time_sec: t.CUInt32T = 0 +_last_time_sec: uint32 = 0 _row_buf: UINT32PTR _bg_row_buf: UINT32PTR @t.Object class AppWindow: - active: t.CInt - x: t.CInt - y: t.CInt - w: t.CInt - h: t.CInt + active: int + x: int + y: int + w: int + h: int title: t.CArray[t.CChar, 32] orig_title: t.CArray[t.CChar, 32] - content_h: t.CInt + content_h: int fb: UINT32PTR - fb_w: t.CInt - fb_h: t.CInt - z_order: t.CInt - style: t.CInt - close_hover: t.CInt - min_hover: t.CInt - max_hover: t.CInt - is_maximized: t.CInt - orig_x: t.CInt - orig_y: t.CInt - orig_w: t.CInt - orig_h: t.CInt - pid: t.CInt - cursor_type: t.CInt - app_cursor_type: t.CInt - ping_pending: t.CInt - no_resp: t.CInt - no_resp_sec: t.CUInt32T - minimized: t.CInt - resizable_w: t.CInt - resizable_h: t.CInt - resize_w: t.CInt - resize_h: t.CInt + fb_w: int + fb_h: int + z_order: int + style: int + close_hover: int + min_hover: int + max_hover: int + is_maximized: int + orig_x: int + orig_y: int + orig_w: int + orig_h: int + pid: int + cursor_type: int + app_cursor_type: int + ping_pending: int + no_resp: int + no_resp_sec: uint32 + minimized: int + resizable_w: int + resizable_h: int + resize_w: int + resize_h: int old_fb: UINT32PTR _wins: t.CArray[AppWindow, MAX_APP_WINDOWS] -_win_count: t.CInt = 0 -_next_z: t.CInt = 1 -_current_app_pid: t.CInt = 0 -HB_INTERVAL_SEC: t.CUInt32T = 5 -HB_NO_RESP_SEC: t.CUInt32T = 30 -_hb_last_sec: t.CUInt32T = 0 -_dirty_rows: t.CUInt8T | t.CPtr = t.CUInt8T(0, t.CPtr) -_dirty_count: t.CInt = 0 -_dirty_y_min: t.CInt = 0 -_dirty_y_max: t.CInt = -1 -_vblank_ok: t.CInt = -1 -_prev_cursor_x: t.CInt = 512 -_prev_cursor_y: t.CInt = 300 -_cursor_save_buf: t.CArray[t.CUInt32T, 256] -_cursor_saved: t.CInt = 0 +_win_count: int = 0 +_next_z: int = 1 +_current_app_pid: int = 0 +HB_INTERVAL_SEC: uint32 = 5 +HB_NO_RESP_SEC: uint32 = 30 +_hb_last_sec: uint32 = 0 +_dirty_rows: uint8 | t.CPtr = uint8(0, t.CPtr) +_dirty_count: int = 0 +_dirty_y_min: int = 0 +_dirty_y_max: int = -1 +_vblank_ok: int = -1 +_prev_cursor_x: int = 512 +_prev_cursor_y: int = 300 +_cursor_save_buf: t.CArray[uint32, 256] +_cursor_saved: int = 0 -_CURSOR_ARROW: t.CArray[t.CUInt8T, 256] = [ +_CURSOR_ARROW: t.CArray[uint8, 256] = [ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0, @@ -136,7 +136,7 @@ _CURSOR_ARROW: t.CArray[t.CUInt8T, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ] -_CURSOR_IBEAM: t.CArray[t.CUInt8T, 256] = [ +_CURSOR_IBEAM: t.CArray[uint8, 256] = [ 0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, @@ -155,7 +155,7 @@ _CURSOR_IBEAM: t.CArray[t.CUInt8T, 256] = [ 0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0, ] -_CURSOR_RESIZE_EW: t.CArray[t.CUInt8T, 256] = [ +_CURSOR_RESIZE_EW: t.CArray[uint8, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0, @@ -174,7 +174,7 @@ _CURSOR_RESIZE_EW: t.CArray[t.CUInt8T, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ] -_CURSOR_RESIZE_NS: t.CArray[t.CUInt8T, 256] = [ +_CURSOR_RESIZE_NS: t.CArray[uint8, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, 0,0,0,1,2,2,1,0,0,0,0,0,0,0,0,0, @@ -193,7 +193,7 @@ _CURSOR_RESIZE_NS: t.CArray[t.CUInt8T, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ] -_CURSOR_RESIZE_NWSE: t.CArray[t.CUInt8T, 256] = [ +_CURSOR_RESIZE_NWSE: t.CArray[uint8, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,1,1,0,0,0,0,0,0,0,0,0,0,0, @@ -211,8 +211,8 @@ _CURSOR_RESIZE_NWSE: t.CArray[t.CUInt8T, 256] = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ] -_last_clock_sec: t.CUInt32T = 0 -_prev_btn: t.CUInt8T = 0 +_last_clock_sec: uint32 = 0 +_prev_btn: uint8 = 0 EVENT_QUEUE_SIZE: t.CDefine = 32 EVENT_TYPE_NONE: t.CDefine = 0 @@ -249,41 +249,41 @@ TYPEMATIC_RATE: t.CDefine = 40 HELD_KEY_MAX: t.CDefine = 8 class held_key_info(t.CStruct): - keycode: t.CUInt8T - is_usb: t.CUInt8T - press_time: t.CUInt64T - last_repeat: t.CUInt64T + keycode: uint8 + is_usb: uint8 + press_time: uint64 + last_repeat: uint64 _held_keys: t.CArray[held_key_info, HELD_KEY_MAX] -_held_key_count: t.CInt = 0 +_held_key_count: int = 0 @c.Attribute(t.attr.packed) class InputEvent: - type: t.CUInt32T - win_id: t.CInt - x: t.CInt - y: t.CInt - button: t.CUInt8T - _pad0: t.CUInt8T - _pad1: t.CUInt8T - _pad2: t.CUInt8T + type: uint32 + win_id: int + x: int + y: int + button: uint8 + _pad0: uint8 + _pad1: uint8 + _pad2: uint8 INPUT_EVENT_SIZE: t.CDefine = 20 _event_queue: t.CArray[InputEvent, EVENT_QUEUE_SIZE] -_event_head: t.CInt = 0 -_event_tail: t.CInt = 0 -_last_hover_win: t.CInt = -1 -_focused_win: t.CInt = -1 +_event_head: int = 0 +_event_tail: int = 0 +_last_hover_win: int = -1 +_focused_win: int = -1 KBD_DEV_PS2: t.CDefine = 0 KBD_DEV_USB: t.CDefine = 1 -_ps2_shift_l: t.CUInt8T = 0 -_ps2_shift_r: t.CUInt8T = 0 -_ps2_caps: t.CUInt8T = 0 -_ps2_e0_pending: t.CUInt8T = 0 -_kbd_irq_masked: t.CInt = 0 +_ps2_shift_l: uint8 = 0 +_ps2_shift_r: uint8 = 0 +_ps2_caps: uint8 = 0 +_ps2_e0_pending: uint8 = 0 +_kbd_irq_masked: int = 0 VK_LEFT: t.CDefine = -1 VK_RIGHT: t.CDefine = -2 @@ -317,43 +317,43 @@ _ps2_set1_shift: t.CArray[t.CChar, 128] = [ '\0' ] -def _ps2_scancode_to_ascii(scancode: t.CUInt8T) -> t.CInt: - code: t.CUInt8T = scancode & t.CUInt8T(0x7F) +def _ps2_scancode_to_ascii(scancode: uint8) -> int: + code: uint8 = scancode & uint8(0x7F) if code >= 128: return 0 - shifted: t.CInt = 0 + shifted: int = 0 if (_ps2_shift_l or _ps2_shift_r) != 0: shifted = 1 if _ps2_caps != 0: if code >= 0x10 and code <= 0x32: shifted = shifted ^ 1 if shifted: - return t.CInt(_ps2_set1_shift[code]) - return t.CInt(_ps2_set1[code]) + return int(_ps2_set1_shift[code]) + return int(_ps2_set1[code]) def _push_event(evt: InputEvent): global _event_head, _event_tail if evt.type == EVENT_TYPE_RESIZE: - i: t.CInt = _event_head + i: int = _event_head while i != _event_tail: if _event_queue[i].type == EVENT_TYPE_RESIZE and _event_queue[i].win_id == evt.win_id: _event_queue[i].type = EVENT_TYPE_NONE i = (i + 1) % EVENT_QUEUE_SIZE - next_tail: t.CInt = (_event_tail + 1) % EVENT_QUEUE_SIZE + next_tail: int = (_event_tail + 1) % EVENT_QUEUE_SIZE if next_tail == _event_head: _event_head = (_event_head + 1) % EVENT_QUEUE_SIZE string.memcpy(c.Addr(_event_queue[_event_tail]), c.Addr(evt), INPUT_EVENT_SIZE) _event_tail = next_tail -def poll_event(buf_ptr: t.CPtr, caller_pid: t.CInt) -> t.CInt: +def poll_event(buf_ptr: t.CPtr, caller_pid: int) -> int: global _event_head, _event_tail while _event_head != _event_tail: if _event_queue[_event_head].type == EVENT_TYPE_NONE: _event_head = (_event_head + 1) % EVENT_QUEUE_SIZE continue - evt_win: t.CInt = _event_queue[_event_head].win_id - evt_pid: t.CInt = 0 - win_ok: t.CInt = 0 + evt_win: int = _event_queue[_event_head].win_id + evt_pid: int = 0 + win_ok: int = 0 if evt_win >= 0 and evt_win < _win_count: evt_pid = _wins[evt_win].pid win_ok = 1 @@ -364,20 +364,20 @@ def poll_event(buf_ptr: t.CPtr, caller_pid: t.CInt) -> t.CInt: if win_ok and not _wins[evt_win].active: _event_head = (_event_head + 1) % EVENT_QUEUE_SIZE continue - scan: t.CInt = (_event_head + 1) % EVENT_QUEUE_SIZE + scan: int = (_event_head + 1) % EVENT_QUEUE_SIZE while scan != _event_tail: if _event_queue[scan].type == EVENT_TYPE_NONE: scan = (scan + 1) % EVENT_QUEUE_SIZE continue - evt_win2: t.CInt = _event_queue[scan].win_id - evt_pid2: t.CInt = 0 + evt_win2: int = _event_queue[scan].win_id + evt_pid2: int = 0 if evt_win2 >= 0 and evt_win2 < _win_count: evt_pid2 = _wins[evt_win2].pid if evt_pid2 == caller_pid: string.memcpy(buf_ptr, c.Addr(_event_queue[scan]), INPUT_EVENT_SIZE) - i: t.CInt = scan + i: int = scan while i != _event_tail: - next_i: t.CInt = (i + 1) % EVENT_QUEUE_SIZE + next_i: int = (i + 1) % EVENT_QUEUE_SIZE if next_i != _event_head: string.memcpy(c.Addr(_event_queue[i]), c.Addr(_event_queue[next_i]), INPUT_EVENT_SIZE) i = next_i @@ -390,12 +390,12 @@ def poll_event(buf_ptr: t.CPtr, caller_pid: t.CInt) -> t.CInt: break return 0 -def _get_title_height(style: t.CInt) -> t.CInt: +def _get_title_height(style: int) -> int: if style == STYLE_CLASSIC: return TITLE_HEIGHT_CLASSIC return TITLE_HEIGHT_WIN -def _mark_rows_dirty(start_y: t.CInt, count: t.CInt): +def _mark_rows_dirty(start_y: int, count: int): global _dirty_count, _dirty_y_min, _dirty_y_max for i in range(start_y, start_y + count): if i >= 0 and i < _screen_h: @@ -414,7 +414,7 @@ def _mark_all_dirty(): _dirty_y_min = 0 _dirty_y_max = _screen_h - 1 -def _has_dirty_rows() -> t.CInt: +def _has_dirty_rows() -> int: return _dirty_count def _clear_dirty_flags(): @@ -428,7 +428,7 @@ def _wait_vblank(): global _vblank_ok if _vblank_ok == 0: return - timeout: t.CInt = 50000 + timeout: int = 50000 while (asm.inb(0x3DA) & 0x08) != 0: timeout -= 1 if timeout <= 0: @@ -441,7 +441,7 @@ def _wait_vblank(): return _vblank_ok = 1 -def _fill_rect(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, rx: t.CInt, ry: t.CInt, rw: t.CInt, rh: t.CInt, color: t.CUInt32T): +def _fill_rect(buf: UINT32PTR, bw: int, bh: int, rx: int, ry: int, rw: int, rh: int, color: uint32): if rx < 0: rw += rx; rx = 0 if ry < 0: rh += ry; ry = 0 if rx + rw > bw: rw = bw - rx @@ -450,44 +450,44 @@ def _fill_rect(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, rx: t.CInt, ry: t.CInt, r if _row_buf: for i in range(rw): _row_buf[i] = color - row_bytes: t.CInt = rw * 4 + row_bytes: int = rw * 4 for py in range(ry, ry + rh): - string.memcpy(t.CVoid(t.CUInt64T(buf) + (py * bw + rx) * 4, t.CPtr), _row_buf, row_bytes) + string.memcpy(t.CVoid(uint64(buf) + (py * bw + rx) * 4, t.CPtr), _row_buf, row_bytes) -def _alpha_blend(bg: t.CUInt32T, fg: t.CUInt32T, alpha: t.CInt) -> t.CUInt32T: - a: t.CInt = alpha - ia: t.CInt = 255 - a - bg_r: t.CInt = t.CInt(bg & 0xFF) - bg_g: t.CInt = t.CInt((bg >> 8) & 0xFF) - bg_b: t.CInt = t.CInt((bg >> 16) & 0xFF) - fg_r: t.CInt = t.CInt(fg & 0xFF) - fg_g: t.CInt = t.CInt((fg >> 8) & 0xFF) - fg_b: t.CInt = t.CInt((fg >> 16) & 0xFF) - r: t.CInt = (fg_r * a + bg_r * ia) >> 8 - g: t.CInt = (fg_g * a + bg_g * ia) >> 8 - b: t.CInt = (fg_b * a + bg_b * ia) >> 8 - return t.CUInt32T(r | (g << 8) | (b << 16) | 0xFF000000) +def _alpha_blend(bg: uint32, fg: uint32, alpha: int) -> uint32: + a: int = alpha + ia: int = 255 - a + bg_r: int = int(bg & 0xFF) + bg_g: int = int((bg >> 8) & 0xFF) + bg_b: int = int((bg >> 16) & 0xFF) + fg_r: int = int(fg & 0xFF) + fg_g: int = int((fg >> 8) & 0xFF) + fg_b: int = int((fg >> 16) & 0xFF) + r: int = (fg_r * a + bg_r * ia) >> 8 + g: int = (fg_g * a + bg_g * ia) >> 8 + b: int = (fg_b * a + bg_b * ia) >> 8 + return uint32(r | (g << 8) | (b << 16) | 0xFF000000) -def _is_in_corner(px: t.CInt, py: t.CInt, cx: t.CInt, cy: t.CInt, r: t.CInt) -> t.CInt: - dx: t.CInt = px - cx - dy: t.CInt = py - cy +def _is_in_corner(px: int, py: int, cx: int, cy: int, r: int) -> int: + dx: int = px - cx + dy: int = py - cy if dx < 0: dx = -dx if dy < 0: dy = -dy if dx <= r and dy <= r: - dist2: t.CInt = dx * dx + dy * dy - r2: t.CInt = r * r + dist2: int = dx * dx + dy * dy + r2: int = r * r if dist2 > r2: return 0 return 1 -def _is_on_border(rx: t.CInt, ry: t.CInt, ww: t.CInt, wh: t.CInt, r: t.CInt) -> t.CInt: +def _is_on_border(rx: int, ry: int, ww: int, wh: int, r: int) -> int: if rx == 0 or rx == ww - 1 or ry == 0 or ry == wh - 1: return 1 if ry < r: if rx < r: - dx: t.CInt = rx - r - dy: t.CInt = ry - r - dist2: t.CInt = dx * dx + dy * dy + dx: int = rx - r + dy: int = ry - r + dist2: int = dx * dx + dy * dy if dist2 >= (r - 1) * (r - 1): return 1 elif rx >= ww - r: dx = rx - (ww - r - 1) @@ -507,38 +507,38 @@ def _is_on_border(rx: t.CInt, ry: t.CInt, ww: t.CInt, wh: t.CInt, r: t.CInt) -> if dist2 >= (r - 1) * (r - 1): return 1 return 0 -def _corner_alpha(px: t.CInt, py: t.CInt, cx: t.CInt, cy: t.CInt, r: t.CInt) -> t.CInt: - dx: t.CInt = px - cx - dy: t.CInt = py - cy +def _corner_alpha(px: int, py: int, cx: int, cy: int, r: int) -> int: + dx: int = px - cx + dy: int = py - cy if dx < 0: dx = -dx if dy < 0: dy = -dy if dx <= r and dy <= r: - dist2: t.CInt = dx * dx + dy * dy - r2: t.CInt = r * r + dist2: int = dx * dx + dy * dy + r2: int = r * r if dist2 > r2: return 0 - outer: t.CInt = (r + 1) * (r + 1) + outer: int = (r + 1) * (r + 1) if dist2 >= outer: return 160 return 255 return 255 -def _draw_char(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, x: t.CInt, y: t.CInt, ch: t.CChar, color: t.CUInt32T): - cval: t.CUInt8T = t.CUInt8T(ch) +def _draw_char(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, ch: t.CChar, color: uint32): + cval: uint8 = uint8(ch) if cval >= 128: cval = 0 for fy in range(16): if y + fy < 0 or y + fy >= bh: continue - row: t.CUInt8T = vga.font[cval][fy] + row: uint8 = vga.font[cval][fy] if row == 0: continue for fx in range(8): if row & (0x80 >> fx): - px: t.CInt = x + fx + px: int = x + fx if px >= 0 and px < bw: buf[(y + fy) * bw + px] = color -def _draw_text(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, x: t.CInt, y: t.CInt, s: t.CConst | str, color: t.CUInt32T): - cx: t.CInt = x - cy: t.CInt = y +def _draw_text(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, s: t.CConst | str, color: uint32): + cx: int = x + cy: int = y for ch in s: if ch == 10: cy += 16 @@ -547,29 +547,29 @@ def _draw_text(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, x: t.CInt, y: t.CInt, s: _draw_char(buf, bw, bh, cx, cy, ch, color) cx += 8 -_drag_idx: t.CInt = -1 +_drag_idx: int = -1 -def _eff_w(aw2: AppWindow | t.CPtr) -> t.CInt: +def _eff_w(aw2: AppWindow | t.CPtr) -> int: if aw2.resize_w != 0: return aw2.resize_w return aw2.w -def _eff_h(aw2: AppWindow | t.CPtr) -> t.CInt: +def _eff_h(aw2: AppWindow | t.CPtr) -> int: if aw2.resize_h != 0: return aw2.resize_h return aw2.content_h -_drag_off_x: t.CInt = 0 -_drag_off_y: t.CInt = 0 -_rsz_drag_idx: t.CInt = -1 -_rsz_edge: t.CInt = 0 -_rsz_start_x: t.CInt = 0 -_rsz_start_y: t.CInt = 0 -_rsz_start_w: t.CInt = 0 -_rsz_start_h: t.CInt = 0 -_rsz_last_w: t.CInt = 0 -_rsz_last_h: t.CInt = 0 -_rsz_last_tick: t.CUInt64T = 0 -_mouse_moved: t.CInt = 0 +_drag_off_x: int = 0 +_drag_off_y: int = 0 +_rsz_drag_idx: int = -1 +_rsz_edge: int = 0 +_rsz_start_x: int = 0 +_rsz_start_y: int = 0 +_rsz_start_w: int = 0 +_rsz_start_h: int = 0 +_rsz_last_w: int = 0 +_rsz_last_h: int = 0 +_rsz_last_tick: uint64 = 0 +_mouse_moved: int = 0 -def _bring_to_front(idx: t.CInt): +def _bring_to_front(idx: int): global _next_z if idx < 0 or idx >= _win_count: return aw: AppWindow | t.CPtr = c.Addr(_wins[idx]) @@ -577,29 +577,29 @@ def _bring_to_front(idx: t.CInt): _next_z += 1 aw.z_order = _next_z -def _hit_test_window(mx: t.CInt, my: t.CInt) -> t.CInt: - best: t.CInt = -1 - best_z: t.CInt = -1 +def _hit_test_window(mx: int, my: int) -> int: + best: int = -1 + best_z: int = -1 for ai in range(_win_count): if _wins[ai].active and not _wins[ai].minimized: - ax: t.CInt = _wins[ai].x - ay: t.CInt = _wins[ai].y - aw: t.CInt = _eff_w(c.Addr(_wins[ai])) - ah: t.CInt = _wins[ai].h + ax: int = _wins[ai].x + ay: int = _wins[ai].y + aw: int = _eff_w(c.Addr(_wins[ai])) + ah: int = _wins[ai].h if mx >= ax and mx < ax + aw and my >= ay and my < ay + ah: - z: t.CInt = _wins[ai].z_order + z: int = _wins[ai].z_order if z > best_z: best_z = z best = ai return best -def _hit_test_resize(mx: t.CInt, my: t.CInt, idx: t.CInt) -> t.CInt: +def _hit_test_resize(mx: int, my: int, idx: int) -> int: if idx < 0 or idx >= _win_count: return RESIZE_EDGE_NONE aw: AppWindow | t.CPtr = c.Addr(_wins[idx]) if not aw.active or aw.minimized: return RESIZE_EDGE_NONE if not aw.resizable_w and not aw.resizable_h: return RESIZE_EDGE_NONE - on_right: t.CInt = 0 - on_bottom: t.CInt = 0 + on_right: int = 0 + on_bottom: int = 0 if aw.resizable_w: if mx >= aw.x + _eff_w(aw) - RESIZE_BORDER and mx < aw.x + _eff_w(aw): on_right = 1 @@ -611,12 +611,12 @@ def _hit_test_resize(mx: t.CInt, my: t.CInt, idx: t.CInt) -> t.CInt: if on_bottom: return RESIZE_EDGE_BOTTOM return RESIZE_EDGE_NONE -def _hid_to_ascii(keycode: t.CUInt8T, modifier: t.CUInt8T) -> t.CInt: +def _hid_to_ascii(keycode: uint8, modifier: uint8) -> int: global _ps2_caps - shift: t.CInt = 0 + shift: int = 0 if (modifier & 0x22) != 0: shift = 1 - kc: t.CInt = t.CInt(keycode) + kc: int = int(keycode) if kc >= 4 and kc <= 29: if _ps2_caps != 0: shift = shift ^ 1 @@ -625,7 +625,7 @@ def _hid_to_ascii(keycode: t.CUInt8T, modifier: t.CUInt8T) -> t.CInt: return kc - 4 + 97 if kc >= 30 and kc <= 38: if shift: - shifts9: t.CArray[t.CInt, 9] + shifts9: t.CArray[int, 9] shifts9[0] = 33; shifts9[1] = 64; shifts9[2] = 35 shifts9[3] = 36; shifts9[4] = 37; shifts9[5] = 94 shifts9[6] = 38; shifts9[7] = 42; shifts9[8] = 40 @@ -674,20 +674,20 @@ def _hid_to_ascii(keycode: t.CUInt8T, modifier: t.CUInt8T) -> t.CInt: return 47 return 0 -def _held_key_add(keycode: t.CUInt8T, is_usb: t.CUInt8T): +def _held_key_add(keycode: uint8, is_usb: uint8): global _held_key_count if _held_key_count >= HELD_KEY_MAX: return for i in range(_held_key_count): if _held_keys[i].keycode == keycode and _held_keys[i].is_usb == is_usb: return - now: t.CUInt64T = timer.timer_get_ticks() + now: uint64 = timer.timer_get_ticks() _held_keys[_held_key_count].keycode = keycode _held_keys[_held_key_count].is_usb = is_usb _held_keys[_held_key_count].press_time = now _held_keys[_held_key_count].last_repeat = now _held_key_count += 1 -def _held_key_remove(keycode: t.CUInt8T, is_usb: t.CUInt8T): +def _held_key_remove(keycode: uint8, is_usb: uint8): global _held_key_count for i in range(_held_key_count): if _held_keys[i].keycode == keycode and _held_keys[i].is_usb == is_usb: @@ -703,18 +703,18 @@ def _check_key_repeat(): global _held_key_count if _focused_win < 0 or _focused_win >= _win_count: return if not _wins[_focused_win].active: return - now: t.CUInt64T = timer.timer_get_ticks() + now: uint64 = timer.timer_get_ticks() for i in range(_held_key_count): hk: held_key_info | t.CPtr = c.Addr(_held_keys[i]) - elapsed: t.CUInt64T = now - hk.press_time - if elapsed < t.CUInt64T(TYPEMATIC_DELAY): + elapsed: uint64 = now - hk.press_time + if elapsed < uint64(TYPEMATIC_DELAY): continue - since_last: t.CUInt64T = now - hk.last_repeat - if since_last >= t.CUInt64T(TYPEMATIC_RATE): + since_last: uint64 = now - hk.last_repeat + if since_last >= uint64(TYPEMATIC_RATE): hk.last_repeat = now - ascii_ch: t.CInt = 0 + ascii_ch: int = 0 if hk.is_usb: - mod: t.CUInt8T = 0 + mod: uint8 = 0 if _ps2_shift_l or _ps2_shift_r: mod = mod | 0x22 if _ps2_caps: @@ -727,7 +727,7 @@ def _check_key_repeat(): rep_evt.type = EVENT_TYPE_KEY rep_evt.win_id = _focused_win rep_evt.x = ascii_ch - rep_evt.y = t.CInt(hk.keycode) + rep_evt.y = int(hk.keycode) rep_evt.button = KEY_STATE_REPEAT rep_evt._pad0 = 0 rep_evt._pad1 = 0 @@ -739,25 +739,25 @@ def _update_keyboard(): global _ps2_shift_l, _ps2_shift_r, _ps2_caps global _ps2_e0_pending # Quick check: skip if no PS/2 data and no USB data - ps2_status: t.CUInt8T = asm.inb(0x64) + ps2_status: uint8 = asm.inb(0x64) if (ps2_status & 0x01) == 0 and not usb_kbd.has_data(): _check_key_repeat() return if _kbd_irq_masked == 0: pic.clearMask(1) _kbd_irq_masked = 1 - kbd_cnt: t.CInt = 0 + kbd_cnt: int = 0 while usb_kbd.has_data() and kbd_cnt < 32: kbd_cnt += 1 kevt: usb_kbd.usb_kbd_event usb_kbd.read_event(c.Addr(kevt)) if kevt.keycode == 0x39 and kevt.event_type == usb_kbd.KBD_EVT_PRESS: - _ps2_caps = _ps2_caps ^ t.CUInt8T(1) + _ps2_caps = _ps2_caps ^ uint8(1) if kevt.event_type == usb_kbd.KBD_EVT_PRESS: _held_key_add(kevt.keycode, 1) - usb_ascii: t.CInt = _hid_to_ascii(kevt.keycode, kevt.modifier) + usb_ascii: int = _hid_to_ascii(kevt.keycode, kevt.modifier) if usb_ascii == 0: - kc2: t.CInt = t.CInt(kevt.keycode) + kc2: int = int(kevt.keycode) if kc2 == 0x50: usb_ascii = VK_LEFT elif kc2 == 0x4F: usb_ascii = VK_RIGHT elif kc2 == 0x52: usb_ascii = VK_UP @@ -770,7 +770,7 @@ def _update_keyboard(): usb_evt.type = EVENT_TYPE_KEY usb_evt.win_id = _focused_win usb_evt.x = usb_ascii - usb_evt.y = t.CInt(kevt.keycode) + usb_evt.y = int(kevt.keycode) usb_evt.button = KEY_STATE_PRESS usb_evt._pad0 = 0 usb_evt._pad1 = 0 @@ -783,22 +783,22 @@ def _update_keyboard(): rel_evt.type = EVENT_TYPE_KEY_RELEASE rel_evt.win_id = _focused_win rel_evt.x = 0 - rel_evt.y = t.CInt(kevt.keycode) + rel_evt.y = int(kevt.keycode) rel_evt.button = KEY_STATE_RELEASE rel_evt._pad0 = 0 rel_evt._pad1 = 0 rel_evt._pad2 = 0 _push_event(rel_evt) - ps2_poll_count: t.CInt = 0 + ps2_poll_count: int = 0 while ps2_poll_count < 16: - ps2_status: t.CUInt8T = asm.inb(0x64) + ps2_status: uint8 = asm.inb(0x64) if (ps2_status & 0x01) == 0: break if (ps2_status & 0x20) != 0: asm.inb(0x60) ps2_poll_count += 1 continue - sc: t.CUInt8T = asm.inb(0x60) + sc: uint8 = asm.inb(0x60) ps2_poll_count += 1 if sc == 0x00 or sc == 0xFA or sc == 0xFE or sc == 0xFF: _ps2_e0_pending = 0 @@ -811,7 +811,7 @@ def _update_keyboard(): continue if _ps2_e0_pending != 0: _ps2_e0_pending = 0 - e0_code: t.CUInt8T = sc & t.CUInt8T(0x7F) + e0_code: uint8 = sc & uint8(0x7F) if (sc & 0x80) != 0: _held_key_remove(e0_code | 0x80, 0) if _focused_win >= 0 and _focused_win < _win_count and _wins[_focused_win].active: @@ -819,14 +819,14 @@ def _update_keyboard(): ps2_rel2.type = EVENT_TYPE_KEY_RELEASE ps2_rel2.win_id = _focused_win ps2_rel2.x = 0 - ps2_rel2.y = t.CInt(e0_code | 0x80) + ps2_rel2.y = int(e0_code | 0x80) ps2_rel2.button = KEY_STATE_RELEASE ps2_rel2._pad0 = 0 ps2_rel2._pad1 = 0 ps2_rel2._pad2 = 0 _push_event(ps2_rel2) continue - vk: t.CInt = 0 + vk: int = 0 if e0_code == 0x4B: vk = VK_LEFT elif e0_code == 0x4D: vk = VK_RIGHT elif e0_code == 0x48: vk = VK_UP @@ -841,7 +841,7 @@ def _update_keyboard(): e0_evt.type = EVENT_TYPE_KEY e0_evt.win_id = _focused_win e0_evt.x = vk - e0_evt.y = t.CInt(e0_code | 0x80) + e0_evt.y = int(e0_code | 0x80) e0_evt.button = KEY_STATE_PRESS e0_evt._pad0 = 0 e0_evt._pad1 = 0 @@ -861,17 +861,17 @@ def _update_keyboard(): _ps2_shift_r = 0 continue if sc == 0x3A: - _ps2_caps = _ps2_caps ^ t.CUInt8T(1) + _ps2_caps = _ps2_caps ^ uint8(1) continue if (sc & 0x80) != 0: - release_sc: t.CUInt8T = sc & t.CUInt8T(0x7F) + release_sc: uint8 = sc & uint8(0x7F) _held_key_remove(release_sc, 0) if _focused_win >= 0 and _focused_win < _win_count and _wins[_focused_win].active: ps2_rel: InputEvent ps2_rel.type = EVENT_TYPE_KEY_RELEASE ps2_rel.win_id = _focused_win ps2_rel.x = 0 - ps2_rel.y = t.CInt(release_sc) + ps2_rel.y = int(release_sc) ps2_rel.button = KEY_STATE_RELEASE ps2_rel._pad0 = 0 ps2_rel._pad1 = 0 @@ -879,13 +879,13 @@ def _update_keyboard(): _push_event(ps2_rel) continue _held_key_add(sc, 0) - ascii_ch: t.CInt = _ps2_scancode_to_ascii(sc) + ascii_ch: int = _ps2_scancode_to_ascii(sc) if ascii_ch != 0 and _focused_win >= 0 and _focused_win < _win_count and _wins[_focused_win].active: push_evt: InputEvent push_evt.type = EVENT_TYPE_KEY push_evt.win_id = _focused_win push_evt.x = ascii_ch - push_evt.y = t.CInt(sc) + push_evt.y = int(sc) push_evt.button = KEY_STATE_PRESS push_evt._pad0 = 0 push_evt._pad1 = 0 @@ -893,35 +893,35 @@ def _update_keyboard(): _push_event(push_evt) _check_key_repeat() -def set_cursor_type(win_id: t.CInt, cursor_t: t.CInt): +def set_cursor_type(win_id: int, cursor_t: int): if win_id >= 0 and win_id < _win_count: _wins[win_id].app_cursor_type = cursor_t _wins[win_id].cursor_type = cursor_t -def _update_mouse() -> t.CInt: +def _update_mouse() -> int: global _cursor_x, _cursor_y, _cursor_buttons global _drag_idx, _drag_off_x, _drag_off_y global _mouse_moved, _prev_btn, _last_hover_win, _focused_win global _rsz_drag_idx, _rsz_edge, _rsz_start_x, _rsz_start_y global _rsz_start_w, _rsz_start_h, _rsz_last_w, _rsz_last_h, _rsz_last_tick - moved: t.CInt = 0 - poll_cnt: t.CInt = 0 + moved: int = 0 + poll_cnt: int = 0 while (mouse.has_data() or usb_mouse.has_data()) and poll_cnt < 32: poll_cnt += 1 - pkt_dx: t.CInt32T = 0 - pkt_dy: t.CInt32T = 0 - pkt_btn: t.CUInt8T = 0 + pkt_dx: int32 = 0 + pkt_dy: int32 = 0 + pkt_btn: uint8 = 0 if mouse.has_data(): pkt: mouse.mouse_packet mouse.read_packet(c.Addr(pkt)) - pkt_dx = t.CInt32T(pkt.dx) - pkt_dy = -t.CInt32T(pkt.dy) + pkt_dx = int32(pkt.dx) + pkt_dy = -int32(pkt.dy) pkt_btn = pkt.buttons elif usb_mouse.has_data(): upkt: usb_mouse.usb_mouse_packet usb_mouse.read_packet(c.Addr(upkt)) - pkt_dx = t.CInt32T(upkt.dx) - pkt_dy = -t.CInt32T(upkt.dy) + pkt_dx = int32(upkt.dx) + pkt_dy = -int32(upkt.dy) pkt_btn = upkt.buttons if pkt_dx != 0 or pkt_dy != 0: _cursor_x = _cursor_x + pkt_dx @@ -932,20 +932,20 @@ def _update_mouse() -> t.CInt: if _cursor_y >= _screen_h: _cursor_y = _screen_h - 1 moved = 1 _mouse_moved = 1 - btn_down: t.CUInt8T = pkt_btn & 0x01 - prev_down: t.CUInt8T = _prev_btn & 0x01 + btn_down: uint8 = pkt_btn & 0x01 + prev_down: uint8 = _prev_btn & 0x01 _cursor_buttons = pkt_btn _prev_btn = pkt_btn if btn_down and not prev_down: - hit_app: t.CInt = _hit_test_window(_cursor_x, _cursor_y) + hit_app: int = _hit_test_window(_cursor_x, _cursor_y) if hit_app >= 0: aw: AppWindow | t.CPtr = c.Addr(_wins[hit_app]) - th: t.CInt = _get_title_height(aw.style) - btn_w: t.CInt = CLOSE_BTN_SIZE - btn_h: t.CInt = CLOSE_BTN_SIZE - ew: t.CInt = _eff_w(aw) - btn_x: t.CInt = aw.x + ew - btn_w - 4 - btn_y: t.CInt = aw.y + (th - btn_h) // 2 + th: int = _get_title_height(aw.style) + btn_w: int = CLOSE_BTN_SIZE + btn_h: int = CLOSE_BTN_SIZE + ew: int = _eff_w(aw) + btn_x: int = aw.x + ew - btn_w - 4 + btn_y: int = aw.y + (th - btn_h) // 2 if aw.style == STYLE_WIN7: btn_w = CLOSE_BTN_W7_W btn_h = CLOSE_BTN_W7_H @@ -965,7 +965,7 @@ def _update_mouse() -> t.CInt: aw.active = 0 if _focused_win == hit_app: _focused_win = -1 - j: t.CInt = _win_count - 1 + j: int = _win_count - 1 while j >= 0: if _wins[j].active and not _wins[j].minimized: _focused_win = j @@ -975,7 +975,7 @@ def _update_mouse() -> t.CInt: _last_hover_win = -1 _mark_all_dirty() else: - max_bx2: t.CInt = btn_x - btn_w + max_bx2: int = btn_x - btn_w if aw.style == STYLE_WIN7 or aw.style == STYLE_WINXP: max_bx2 = btn_x - btn_w - 1 if _cursor_x >= max_bx2 and _cursor_x < max_bx2 + btn_w and _cursor_y >= btn_y and _cursor_y < btn_y + btn_h: @@ -994,7 +994,7 @@ def _update_mouse() -> t.CInt: aw.orig_h = aw.h aw.x = 0 aw.y = 0 - tb_h_mx: t.CInt = TASKBAR_HEIGHT + tb_h_mx: int = TASKBAR_HEIGHT aw.h = _screen_h - tb_h_mx aw.resize_w = _screen_w aw.resize_h = _screen_h - tb_h_mx - _get_title_height(aw.style) - 2 @@ -1010,14 +1010,14 @@ def _update_mouse() -> t.CInt: _push_event(rs_evt3) _mark_all_dirty() else: - min_bx2: t.CInt = max_bx2 - btn_w + min_bx2: int = max_bx2 - btn_w if aw.style == STYLE_WIN7 or aw.style == STYLE_WINXP: min_bx2 = max_bx2 - btn_w - 1 if _cursor_x >= min_bx2 and _cursor_x < min_bx2 + btn_w and _cursor_y >= btn_y and _cursor_y < btn_y + btn_h: aw.minimized = 1 if _focused_win == hit_app: _focused_win = -1 - j2: t.CInt = _win_count - 1 + j2: int = _win_count - 1 while j2 >= 0: if _wins[j2].active and not _wins[j2].minimized: _focused_win = j2 @@ -1025,7 +1025,7 @@ def _update_mouse() -> t.CInt: j2 -= 1 _mark_all_dirty() else: - re: t.CInt = _hit_test_resize(_cursor_x, _cursor_y, hit_app) + re: int = _hit_test_resize(_cursor_x, _cursor_y, hit_app) if re != RESIZE_EDGE_NONE: _rsz_drag_idx = hit_app _rsz_edge = re @@ -1061,13 +1061,13 @@ def _update_mouse() -> t.CInt: evt._pad2 = 0 _push_event(evt) else: - tb_h_cl: t.CInt = TASKBAR_HEIGHT - bar_y2: t.CInt = _screen_h - tb_h_cl + tb_h_cl: int = TASKBAR_HEIGHT + bar_y2: int = _screen_h - tb_h_cl if _cursor_y >= bar_y2: - logo_x2: t.CInt = 4 - logo_sz2: t.CInt = TASKBAR_LOGO_SZ - logo_r2: t.CInt = logo_x2 + logo_sz2 - logo_b2: t.CInt = bar_y2 + tb_h_cl + logo_x2: int = 4 + logo_sz2: int = TASKBAR_LOGO_SZ + logo_r2: int = logo_x2 + logo_sz2 + logo_b2: int = bar_y2 + tb_h_cl if _cursor_x >= logo_x2 and _cursor_x < logo_r2 and _cursor_y >= bar_y2 and _cursor_y < logo_b2: if _focused_win >= 0 and _focused_win < _win_count: if _wins[_focused_win].active: @@ -1075,14 +1075,14 @@ def _update_mouse() -> t.CInt: _focused_win = -1 _mark_all_dirty() else: - icon_sz2: t.CInt = TASKBAR_ICON_SZ - icon_pad2: t.CInt = TASKBAR_ICON_PAD - icon_x2: t.CInt = logo_x2 + logo_sz2 + 80 - icon_cnt2: t.CInt = 0 + icon_sz2: int = TASKBAR_ICON_SZ + icon_pad2: int = TASKBAR_ICON_PAD + icon_x2: int = logo_x2 + logo_sz2 + 80 + icon_cnt2: int = 0 for ti2 in range(_win_count): if _wins[ti2].active: - ix2: t.CInt = icon_x2 + icon_cnt2 * (icon_sz2 + icon_pad2) - iy2: t.CInt = bar_y2 + (tb_h_cl - icon_sz2) // 2 + ix2: int = icon_x2 + icon_cnt2 * (icon_sz2 + icon_pad2) + iy2: int = bar_y2 + (tb_h_cl - icon_sz2) // 2 if _cursor_x >= ix2 and _cursor_x < ix2 + icon_sz2 and _cursor_y >= iy2 and _cursor_y < iy2 + icon_sz2: if _wins[ti2].minimized: _wins[ti2].minimized = 0 @@ -1105,11 +1105,11 @@ def _update_mouse() -> t.CInt: if prev_down: if _rsz_drag_idx >= 0: rs_aw: AppWindow | t.CPtr = c.Addr(_wins[_rsz_drag_idx]) - final_w: t.CInt = _rsz_last_w - final_h: t.CInt = _rsz_last_h - old_h_mu: t.CInt = _eff_h(rs_aw) + _get_title_height(rs_aw.style) + 2 + final_w: int = _rsz_last_w + final_h: int = _rsz_last_h + old_h_mu: int = _eff_h(rs_aw) + _get_title_height(rs_aw.style) + 2 _mark_rows_dirty(rs_aw.y, old_h_mu) - final_ch: t.CInt = final_h - _get_title_height(rs_aw.style) - 2 + final_ch: int = final_h - _get_title_height(rs_aw.style) - 2 rs_aw.resize_w = final_w rs_aw.resize_h = final_ch rs_aw.h = final_h @@ -1127,7 +1127,7 @@ def _update_mouse() -> t.CInt: _rsz_drag_idx = -1 _rsz_edge = RESIZE_EDGE_NONE else: - rel_hit: t.CInt = _hit_test_window(_cursor_x, _cursor_y) + rel_hit: int = _hit_test_window(_cursor_x, _cursor_y) if rel_hit >= 0: aw_rel: AppWindow | t.CPtr = c.Addr(_wins[rel_hit]) rel_evt: InputEvent @@ -1145,7 +1145,7 @@ def _update_mouse() -> t.CInt: _mark_rows_dirty(_wins[_drag_idx].y, _wins[_drag_idx].h) _drag_idx = -1 if moved and _drag_idx < 0: - hit_hov: t.CInt = _hit_test_window(_cursor_x, _cursor_y) + hit_hov: int = _hit_test_window(_cursor_x, _cursor_y) if hit_hov >= 0: if _last_hover_win >= 0 and _last_hover_win != hit_hov and _last_hover_win < _win_count: if _wins[_last_hover_win].active: @@ -1160,7 +1160,7 @@ def _update_mouse() -> t.CInt: leave_evt3._pad2 = 0 _push_event(leave_evt3) aw_hov: AppWindow | t.CPtr = c.Addr(_wins[hit_hov]) - th_hov: t.CInt = _get_title_height(aw_hov.style) + th_hov: int = _get_title_height(aw_hov.style) hov_evt: InputEvent hov_evt.type = EVENT_TYPE_HOVER hov_evt.win_id = hit_hov @@ -1172,7 +1172,7 @@ def _update_mouse() -> t.CInt: hov_evt._pad2 = 0 _push_event(hov_evt) _last_hover_win = hit_hov - re_hov: t.CInt = _hit_test_resize(_cursor_x, _cursor_y, hit_hov) + re_hov: int = _hit_test_resize(_cursor_x, _cursor_y, hit_hov) if re_hov == RESIZE_EDGE_RIGHT: aw_hov.cursor_type = CURSOR_RESIZE_EW elif re_hov == RESIZE_EDGE_BOTTOM: @@ -1197,17 +1197,17 @@ def _update_mouse() -> t.CInt: _last_hover_win = -1 if _drag_idx >= 0: aw2: AppWindow | t.CPtr = c.Addr(_wins[_drag_idx]) - _drag_old_y: t.CInt = aw2.y + _drag_old_y: int = aw2.y _mark_rows_dirty(_drag_old_y, aw2.h) aw2.x = _cursor_x - _drag_off_x aw2.y = _cursor_y - _drag_off_y _mark_rows_dirty(aw2.y, aw2.h) if _rsz_drag_idx >= 0: rs_aw2: AppWindow | t.CPtr = c.Addr(_wins[_rsz_drag_idx]) - dx: t.CInt = _cursor_x - _rsz_start_x - dy: t.CInt = _cursor_y - _rsz_start_y - new_w: t.CInt = _rsz_start_w - new_h: t.CInt = _rsz_start_h + dx: int = _cursor_x - _rsz_start_x + dy: int = _cursor_y - _rsz_start_y + new_w: int = _rsz_start_w + new_h: int = _rsz_start_h if _rsz_edge == RESIZE_EDGE_RIGHT or _rsz_edge == RESIZE_EDGE_CORNER: new_w = _rsz_start_w + dx if new_w < RESIZE_MIN_W: new_w = RESIZE_MIN_W @@ -1215,13 +1215,13 @@ def _update_mouse() -> t.CInt: new_h = _rsz_start_h + dy if new_h < RESIZE_MIN_H: new_h = RESIZE_MIN_H if new_w != rs_aw2.w or new_h != rs_aw2.h: - dw: t.CInt = new_w - _rsz_last_w + dw: int = new_w - _rsz_last_w if dw < 0: dw = -dw - dh: t.CInt = new_h - _rsz_last_h + dh: int = new_h - _rsz_last_h if dh < 0: dh = -dh - now_tick: t.CUInt64T = timer.timer_get_ticks() - elapsed: t.CUInt64T = now_tick - _rsz_last_tick - need_update: t.CInt = 0 + now_tick: uint64 = timer.timer_get_ticks() + elapsed: uint64 = now_tick - _rsz_last_tick + need_update: int = 0 if dw >= 32 or dh >= 32: need_update = 1 elif elapsed >= 100 and (dw >= 4 or dh >= 4): @@ -1230,9 +1230,9 @@ def _update_mouse() -> t.CInt: _rsz_last_w = new_w _rsz_last_h = new_h _rsz_last_tick = now_tick - old_h_rs: t.CInt = _eff_h(rs_aw2) + _get_title_height(rs_aw2.style) + 2 + old_h_rs: int = _eff_h(rs_aw2) + _get_title_height(rs_aw2.style) + 2 _mark_rows_dirty(rs_aw2.y, old_h_rs) - new_ch: t.CInt = new_h - _get_title_height(rs_aw2.style) - 2 + new_ch: int = new_h - _get_title_height(rs_aw2.style) - 2 rs_aw2.resize_w = new_w rs_aw2.resize_h = new_ch rs_aw2.h = new_h @@ -1248,10 +1248,10 @@ def _update_mouse() -> t.CInt: rs_evt2._pad2 = 0 _push_event(rs_evt2) if not moved and _last_hover_win < 0: - hit_hov2: t.CInt = _hit_test_window(_cursor_x, _cursor_y) + hit_hov2: int = _hit_test_window(_cursor_x, _cursor_y) if hit_hov2 >= 0 and _wins[hit_hov2].active: aw_hov2: AppWindow | t.CPtr = c.Addr(_wins[hit_hov2]) - th_hov2: t.CInt = _get_title_height(aw_hov2.style) + th_hov2: int = _get_title_height(aw_hov2.style) hov_evt2: InputEvent hov_evt2.type = EVENT_TYPE_HOVER hov_evt2.win_id = hit_hov2 @@ -1278,120 +1278,120 @@ def _update_mouse() -> t.CInt: _last_hover_win = -1 return moved -_render_count: t.CInt = 0 -_cached_top_win: t.CInt = -1 -_perf_t_mouse: t.CUInt64T = 0 -_perf_t_kbd: t.CUInt64T = 0 -_perf_t_render: t.CUInt64T = 0 -_perf_t_flush: t.CUInt64T = 0 -_perf_t_total: t.CUInt64T = 0 -_perf_frames: t.CUInt32T = 0 -_perf_start_ticks: t.CUInt64T = 0 -_perf_t_bg: t.CUInt64T = 0 -_perf_t_win: t.CUInt64T = 0 -_perf_t_cur: t.CUInt64T = 0 -_perf_t_fb: t.CUInt64T = 0 +_render_count: int = 0 +_cached_top_win: int = -1 +_perf_t_mouse: uint64 = 0 +_perf_t_kbd: uint64 = 0 +_perf_t_render: uint64 = 0 +_perf_t_flush: uint64 = 0 +_perf_t_total: uint64 = 0 +_perf_frames: uint32 = 0 +_perf_start_ticks: uint64 = 0 +_perf_t_bg: uint64 = 0 +_perf_t_win: uint64 = 0 +_perf_t_cur: uint64 = 0 +_perf_t_fb: uint64 = 0 def _render(): global _render_count, _cached_top_win global _perf_t_bg, _perf_t_win, _perf_t_cur, _perf_t_fb - w: t.CInt = _screen_w - h: t.CInt = _screen_h - pitch: t.CInt = _fb_pitch + w: int = _screen_w + h: int = _screen_h + pitch: int = _fb_pitch back: UINT32PTR = _back_fb _cached_top_win = _get_top_window() # No need to erase cursor - dirty row mechanism redraws background + windows from scratch - t0: t.CUInt64T = timer.timer_get_ticks() - row_bytes: t.CInt = w * 4 + t0: uint64 = timer.timer_get_ticks() + row_bytes: int = w * 4 if _bg_row_buf and _dirty_count > 0: - py_bg: t.CInt = _dirty_y_min + py_bg: int = _dirty_y_min while py_bg <= _dirty_y_max: if _dirty_rows[py_bg]: - string.memcpy(t.CVoid(t.CUInt64T(back) + py_bg * row_bytes, t.CPtr), _bg_row_buf, row_bytes) + string.memcpy(t.CVoid(uint64(back) + py_bg * row_bytes, t.CPtr), _bg_row_buf, row_bytes) py_bg += 1 - t1: t.CUInt64T = timer.timer_get_ticks() + t1: uint64 = timer.timer_get_ticks() _perf_t_bg += (t1 - t0) _draw_taskbar(back) - t2: t.CUInt64T = timer.timer_get_ticks() - sorted: t.CArray[t.CInt, MAX_APP_WINDOWS] - cnt: t.CInt = 0 + t2: uint64 = timer.timer_get_ticks() + sorted: t.CArray[int, MAX_APP_WINDOWS] + cnt: int = 0 for si in range(_win_count): if _wins[si].active and not _wins[si].minimized: sorted[cnt] = si cnt += 1 for si in range(cnt - 1): for sj in range(si + 1, cnt): - zi: t.CInt = _wins[sorted[si]].z_order - zj: t.CInt = _wins[sorted[sj]].z_order + zi: int = _wins[sorted[si]].z_order + zj: int = _wins[sorted[sj]].z_order if zi > zj: - tmp: t.CInt = sorted[si] + tmp: int = sorted[si] sorted[si] = sorted[sj] sorted[sj] = tmp for si in range(cnt): _draw_app_window(back, c.Addr(_wins[sorted[si]])) - t3: t.CUInt64T = timer.timer_get_ticks() + t3: uint64 = timer.timer_get_ticks() _perf_t_win += (t3 - t2) # Mark cursor rows as dirty so cursor gets flushed to framebuffer _mark_rows_dirty(_cursor_y, CURSOR_H) _draw_cursor(back) - t4: t.CUInt64T = timer.timer_get_ticks() + t4: uint64 = timer.timer_get_ticks() _perf_t_cur += (t4 - t3) _wait_vblank() if _dirty_count > 0: - py_fb: t.CInt = _dirty_y_min + py_fb: int = _dirty_y_min while py_fb <= _dirty_y_max: if _dirty_rows[py_fb]: - run_start: t.CInt = py_fb + run_start: int = py_fb while py_fb <= _dirty_y_max and _dirty_rows[py_fb]: py_fb += 1 - run_bytes: t.CInt = (py_fb - run_start) * row_bytes - string.memcpy(t.CVoid(t.CUInt64T(_fb) + run_start * pitch, t.CPtr), t.CVoid(t.CUInt64T(back) + run_start * row_bytes, t.CPtr), run_bytes) + run_bytes: int = (py_fb - run_start) * row_bytes + string.memcpy(t.CVoid(uint64(_fb) + run_start * pitch, t.CPtr), t.CVoid(uint64(back) + run_start * row_bytes, t.CPtr), run_bytes) else: py_fb += 1 - t5: t.CUInt64T = timer.timer_get_ticks() + t5: uint64 = timer.timer_get_ticks() _perf_t_fb += (t5 - t4) _render_count += 1 def _draw_taskbar(back: UINT32PTR): - w: t.CInt = _screen_w - h: t.CInt = _screen_h - tb_h: t.CInt = TASKBAR_HEIGHT - bar_y: t.CInt = h - tb_h + w: int = _screen_w + h: int = _screen_h + tb_h: int = TASKBAR_HEIGHT + bar_y: int = h - tb_h if bar_y + tb_h <= _dirty_y_min or bar_y > _dirty_y_max: return - bar_col: t.CUInt32T = gfx.COLOR_RGB(32, 32, 32) - line_col: t.CUInt32T = gfx.COLOR_RGB(60, 60, 60) + bar_col: uint32 = gfx.COLOR_RGB(32, 32, 32) + line_col: uint32 = gfx.COLOR_RGB(60, 60, 60) _fill_rect(back, w, h, 0, bar_y, w, tb_h, bar_col) _fill_rect(back, w, h, 0, bar_y, w, 1, line_col) - logo_x: t.CInt = 4 - logo_sz: t.CInt = TASKBAR_LOGO_SZ - logo_y: t.CInt = bar_y + (tb_h - logo_sz) // 2 - lc1: t.CUInt32T = gfx.COLOR_RGB(80, 120, 220) - lc2: t.CUInt32T = gfx.COLOR_RGB(50, 80, 180) - lc3: t.CUInt32T = gfx.COLOR_RGB(100, 160, 255) + logo_x: int = 4 + logo_sz: int = TASKBAR_LOGO_SZ + logo_y: int = bar_y + (tb_h - logo_sz) // 2 + lc1: uint32 = gfx.COLOR_RGB(80, 120, 220) + lc2: uint32 = gfx.COLOR_RGB(50, 80, 180) + lc3: uint32 = gfx.COLOR_RGB(100, 160, 255) for lx in range(logo_sz): for ly in range(logo_sz): - px: t.CInt = logo_x + lx - py: t.CInt = logo_y + ly + px: int = logo_x + lx + py: int = logo_y + ly if px >= 0 and px < w and py >= 0 and py < h: - col: t.CUInt32T = lc2 - cx: t.CInt = logo_sz // 2 - cy: t.CInt = logo_sz // 2 - dx: t.CInt = lx - cx - dy: t.CInt = ly - cy - dist: t.CInt = dx * dx + dy * dy - r2: t.CInt = cx * cx + col: uint32 = lc2 + cx: int = logo_sz // 2 + cy: int = logo_sz // 2 + dx: int = lx - cx + dy: int = ly - cy + dist: int = dx * dx + dy * dy + r2: int = cx * cx if dist <= r2: col = lc1 if dist <= r2 // 2: @@ -1400,23 +1400,23 @@ def _draw_taskbar(back: UINT32PTR): _draw_text(back, w, h, logo_x + logo_sz + 8, bar_y + (tb_h - 16) // 2, "ViperOS", 0xFFFFFFFF) - icon_sz: t.CInt = TASKBAR_ICON_SZ - icon_pad: t.CInt = TASKBAR_ICON_PAD - icon_x: t.CInt = logo_x + logo_sz + 80 - icon_cnt: t.CInt = 0 + icon_sz: int = TASKBAR_ICON_SZ + icon_pad: int = TASKBAR_ICON_PAD + icon_x: int = logo_x + logo_sz + 80 + icon_cnt: int = 0 for ti in range(_win_count): if _wins[ti].active: - ix: t.CInt = icon_x + icon_cnt * (icon_sz + icon_pad) - iy: t.CInt = bar_y + (tb_h - icon_sz) // 2 - is_focused: t.CInt = 1 if ti == _focused_win else 0 - is_minimized: t.CInt = _wins[ti].minimized - ic_bg: t.CUInt32T = gfx.COLOR_RGB(40, 40, 70) + ix: int = icon_x + icon_cnt * (icon_sz + icon_pad) + iy: int = bar_y + (tb_h - icon_sz) // 2 + is_focused: int = 1 if ti == _focused_win else 0 + is_minimized: int = _wins[ti].minimized + ic_bg: uint32 = gfx.COLOR_RGB(40, 40, 70) if is_focused: ic_bg = gfx.COLOR_RGB(60, 60, 120) elif is_minimized: ic_bg = gfx.COLOR_RGB(30, 30, 50) _fill_rect(back, w, h, ix, iy, icon_sz, icon_sz, ic_bg) - ic_border: t.CUInt32T = gfx.COLOR_RGB(80, 80, 140) + ic_border: uint32 = gfx.COLOR_RGB(80, 80, 140) if is_focused: ic_border = gfx.COLOR_RGB(120, 120, 220) _fill_rect(back, w, h, ix, iy, icon_sz, 1, ic_border) @@ -1425,49 +1425,49 @@ def _draw_taskbar(back: UINT32PTR): _fill_rect(back, w, h, ix + icon_sz - 1, iy, 1, icon_sz, ic_border) if _wins[ti].title[0] != 0: first_ch: t.CChar = _wins[ti].title[0] - ch_col: t.CUInt32T = 0xFFFFFFFF + ch_col: uint32 = 0xFFFFFFFF if not is_focused: ch_col = gfx.COLOR_RGB(180, 180, 200) - ch_x: t.CInt = ix + (icon_sz - 8) // 2 - ch_y: t.CInt = iy + (icon_sz - 16) // 2 + ch_x: int = ix + (icon_sz - 8) // 2 + ch_y: int = iy + (icon_sz - 16) // 2 _draw_char(back, w, h, ch_x, ch_y, first_ch, ch_col) icon_cnt += 1 if _render_count % 30 == 0: rtc.rtc_read_time() - hr: t.CUInt8T = rtc.rtc_get_hours() - mn: t.CUInt8T = rtc.rtc_get_minutes() - sc: t.CUInt8T = rtc.rtc_get_seconds() - day: t.CUInt8T = rtc.rtc_get_day() - mon: t.CUInt8T = rtc.rtc_get_month() - yr: t.CUInt16T = rtc.rtc_get_year() + hr: uint8 = rtc.rtc_get_hours() + mn: uint8 = rtc.rtc_get_minutes() + sc: uint8 = rtc.rtc_get_seconds() + day: uint8 = rtc.rtc_get_day() + mon: uint8 = rtc.rtc_get_month() + yr: uint16 = rtc.rtc_get_year() time_buf: t.CArray[t.CChar, 64] string.memset(c.Addr(time_buf), 0, 64) viperlib.snprintf(c.Addr(time_buf), 64, "%04u-%02u-%02u %02u:%02u:%02u", t.CUnsignedInt(yr), t.CUnsignedInt(mon), t.CUnsignedInt(day), t.CUnsignedInt(hr), t.CUnsignedInt(mn), t.CUnsignedInt(sc)) - time_str_x: t.CInt = w - 180 + time_str_x: int = w - 180 _draw_text(back, w, h, time_str_x, bar_y + (tb_h - 16) // 2, time_buf, 0xFFFFFFFF) -def _draw_window_shadow(back: UINT32PTR, bw: t.CInt, bh: t.CInt, wx: t.CInt, wy: t.CInt, ww: t.CInt, wh: t.CInt, is_rounded: t.CInt, rad: t.CInt): +def _draw_window_shadow(back: UINT32PTR, bw: int, bh: int, wx: int, wy: int, ww: int, wh: int, is_rounded: int, rad: int): if not SHADOW_ENABLED: return - sl: t.CInt = SHADOW_LEFT - sr: t.CInt = SHADOW_RIGHT - st: t.CInt = SHADOW_TOP - sb: t.CInt = SHADOW_BOTTOM - sa: t.CInt = SHADOW_ALPHA - shadow_col: t.CUInt32T = gfx.COLOR_RGB(0, 0, 0) + sl: int = SHADOW_LEFT + sr: int = SHADOW_RIGHT + st: int = SHADOW_TOP + sb: int = SHADOW_BOTTOM + sa: int = SHADOW_ALPHA + shadow_col: uint32 = gfx.COLOR_RGB(0, 0, 0) for py in range(wy - st, wy + wh + sb): if py >= 0 and py < bh: if not _dirty_rows[py]: continue for px in range(wx - sl, wx + ww + sr): if px >= 0 and px < bw: - in_win: t.CInt = 0 + in_win: int = 0 if px >= wx and px < wx + ww and py >= wy and py < wy + wh: in_win = 1 if is_rounded: - rx: t.CInt = px - wx - ry: t.CInt = py - wy + rx: int = px - wx + ry: int = py - wy if rx < rad and ry < rad: if (rx - rad) * (rx - rad) + (ry - rad) * (ry - rad) > rad * rad: in_win = 0 @@ -1482,29 +1482,29 @@ def _draw_window_shadow(back: UINT32PTR, bw: t.CInt, bh: t.CInt, wx: t.CInt, wy: in_win = 0 if in_win: continue - cpx: t.CInt = px + cpx: int = px if cpx < wx: cpx = wx elif cpx > wx + ww - 1: cpx = wx + ww - 1 - cpy: t.CInt = py + cpy: int = py if cpy < wy: cpy = wy elif cpy > wy + wh - 1: cpy = wy + wh - 1 if is_rounded and rad > 0: if cpx < wx + rad and cpy < wy + rad: - acx: t.CInt = wx + rad - acy: t.CInt = wy + rad - adx: t.CInt = cpx - acx - ady: t.CInt = cpy - acy - ad_sq: t.CInt = adx * adx + ady * ady + acx: int = wx + rad + acy: int = wy + rad + adx: int = cpx - acx + ady: int = cpy - acy + ad_sq: int = adx * adx + ady * ady if ad_sq > rad * rad and ad_sq > 0: - aax: t.CInt = adx + aax: int = adx if aax < 0: aax = 0 - aax - aay: t.CInt = ady + aay: int = ady if aay < 0: aay = 0 - aay - am: t.CInt = aax + am: int = aax if aay > am: am = aay - an: t.CInt = aax + an: int = aax if aay < an: an = aay - ad: t.CInt = am + (an * 3) / 8 + ad: int = am + (an * 3) / 8 if ad > 0: cpx = acx + (adx * rad) / ad cpy = acy + (ady * rad) / ad @@ -1565,92 +1565,92 @@ def _draw_window_shadow(back: UINT32PTR, bw: t.CInt, bh: t.CInt, wx: t.CInt, wy: if ad > 0: cpx = acx + (adx * rad) / ad cpy = acy + (ady * rad) / ad - dx: t.CInt = px - cpx - dy: t.CInt = py - cpy - adx_d: t.CInt = dx + dx: int = px - cpx + dy: int = py - cpy + adx_d: int = dx if adx_d < 0: adx_d = 0 - adx_d - ady_d: t.CInt = dy + ady_d: int = dy if ady_d < 0: ady_d = 0 - ady_d - dist: t.CInt = adx_d + dist: int = adx_d if ady_d > dist: dist = ady_d dist = dist + ((adx_d + ady_d - dist) * 3) / 8 - me_x: t.CInt = sl + me_x: int = sl if dx > 0: me_x = sr - me_y: t.CInt = st + me_y: int = st if dy > 0: me_y = sb - me: t.CInt = me_x + me: int = me_x if adx_d + ady_d > 0: me = (me_x * adx_d + me_y * ady_d) / (adx_d + ady_d) if me > 0 and dist > 0 and dist < me: - t_val: t.CInt = (256 * dist) / me - t_inv: t.CInt = 256 - t_val - a: t.CInt = (sa * t_inv * t_inv) / 65536 + t_val: int = (256 * dist) / me + t_inv: int = 256 - t_val + a: int = (sa * t_inv * t_inv) / 65536 if a > 0: back[py * bw + px] = _alpha_blend(back[py * bw + px], shadow_col, a) -def _cursor_save_bg(back: UINT32PTR, cx: t.CInt, cy: t.CInt, w: t.CInt, h: t.CInt): +def _cursor_save_bg(back: UINT32PTR, cx: int, cy: int, w: int, h: int): global _cursor_saved - cw: t.CInt = CURSOR_W - ch: t.CInt = CURSOR_H + cw: int = CURSOR_W + ch: int = CURSOR_H for dy in range(ch): for dx in range(cw): - sx: t.CInt = cx + dx - sy: t.CInt = cy + dy + sx: int = cx + dx + sy: int = cy + dy if sx >= 0 and sx < w and sy >= 0 and sy < h: _cursor_save_buf[dy * cw + dx] = back[sy * w + sx] else: _cursor_save_buf[dy * cw + dx] = 0 _cursor_saved = 1 -def _cursor_restore_bg(back: UINT32PTR, cx: t.CInt, cy: t.CInt, w: t.CInt, h: t.CInt): +def _cursor_restore_bg(back: UINT32PTR, cx: int, cy: int, w: int, h: int): global _cursor_saved if _cursor_saved == 0: return - cw: t.CInt = CURSOR_W - ch: t.CInt = CURSOR_H + cw: int = CURSOR_W + ch: int = CURSOR_H for dy in range(ch): for dx in range(cw): - sx: t.CInt = cx + dx - sy: t.CInt = cy + dy + sx: int = cx + dx + sy: int = cy + dy if sx >= 0 and sx < w and sy >= 0 and sy < h: back[sy * w + sx] = _cursor_save_buf[dy * cw + dx] _cursor_saved = 0 -def _cursor_draw_bitmap(back: UINT32PTR, cx: t.CInt, cy: t.CInt, w: t.CInt, h: t.CInt, bmp: t.CArray[t.CUInt8T, 256]): - cw: t.CInt = CURSOR_W - ch: t.CInt = CURSOR_H - white: t.CUInt32T = gfx.COLOR_RGB(255, 255, 255) - black: t.CUInt32T = gfx.COLOR_RGB(0, 0, 0) +def _cursor_draw_bitmap(back: UINT32PTR, cx: int, cy: int, w: int, h: int, bmp: t.CArray[uint8, 256]): + cw: int = CURSOR_W + ch: int = CURSOR_H + white: uint32 = gfx.COLOR_RGB(255, 255, 255) + black: uint32 = gfx.COLOR_RGB(0, 0, 0) for dy in range(ch): for dx in range(cw): - pixel: t.CUInt8T = bmp[dy * cw + dx] + pixel: uint8 = bmp[dy * cw + dx] if pixel != 0: - px: t.CInt = cx + dx - py: t.CInt = cy + dy + px: int = cx + dx + py: int = cy + dy if px >= 0 and px < w and py >= 0 and py < h: if pixel == 1: back[py * w + px] = black elif pixel == 2: back[py * w + px] = white -def _cursor_draw_xor(back: UINT32PTR, cx: t.CInt, cy: t.CInt, w: t.CInt, h: t.CInt, bmp: t.CArray[t.CUInt8T, 256]): - cw: t.CInt = CURSOR_W - ch: t.CInt = CURSOR_H - xor_val: t.CUInt32T = t.CUInt32T(0x00FFFFFF) +def _cursor_draw_xor(back: UINT32PTR, cx: int, cy: int, w: int, h: int, bmp: t.CArray[uint8, 256]): + cw: int = CURSOR_W + ch: int = CURSOR_H + xor_val: uint32 = uint32(0x00FFFFFF) for dy in range(ch): for dx in range(cw): - pixel: t.CUInt8T = bmp[dy * cw + dx] + pixel: uint8 = bmp[dy * cw + dx] if pixel != 0: - px: t.CInt = cx + dx - py: t.CInt = cy + dy + px: int = cx + dx + py: int = cy + dy if px >= 0 and px < w and py >= 0 and py < h: back[py * w + px] = back[py * w + px] ^ xor_val def _draw_cursor(back: UINT32PTR): - cx: t.CInt = _cursor_x - cy: t.CInt = _cursor_y - w: t.CInt = _screen_w - h: t.CInt = _screen_h - cur_type: t.CInt = CURSOR_DEFAULT + cx: int = _cursor_x + cy: int = _cursor_y + w: int = _screen_w + h: int = _screen_h + cur_type: int = CURSOR_DEFAULT if _last_hover_win >= 0 and _last_hover_win < _win_count: cur_type = _wins[_last_hover_win].cursor_type if cur_type == CURSOR_IBEAM: @@ -1669,61 +1669,61 @@ def _erase_cursor(back: UINT32PTR): if _cursor_saved == 0: return _cursor_restore_bg(back, _prev_cursor_x, _prev_cursor_y, _screen_w, _screen_h) -def desktop_thread(arg: t.CPtr) -> t.CInt: +def desktop_thread(arg: t.CPtr) -> int: global _last_clock_sec, _mouse_moved global _prev_cursor_x, _prev_cursor_y global _perf_t_mouse, _perf_t_kbd, _perf_t_render, _perf_t_flush, _perf_t_total, _perf_frames, _perf_start_ticks global _perf_t_bg, _perf_t_win, _perf_t_cur, _perf_t_fb serial.puts("[desktop] thread started\n") _mark_all_dirty() - _dt_hb_sec: t.CUInt32T = 0 - tb_h_dt: t.CInt = TASKBAR_HEIGHT + _dt_hb_sec: uint32 = 0 + tb_h_dt: int = TASKBAR_HEIGHT _perf_buf: t.CArray[t.CChar, 256] _perf_start_ticks = timer.timer_get_ticks() - _kbd_poll_ticks: t.CUInt64T = 0 - _mouse_poll_ticks: t.CUInt64T = 0 + _kbd_poll_ticks: uint64 = 0 + _mouse_poll_ticks: uint64 = 0 while True: - _loop_t0: t.CUInt64T = timer.timer_get_ticks() + _loop_t0: uint64 = timer.timer_get_ticks() # Poll mouse at most every 4ms to avoid excessive I/O port overhead - _now_ticks: t.CUInt64T = timer.timer_get_ticks() + _now_ticks: uint64 = timer.timer_get_ticks() if _now_ticks - _mouse_poll_ticks >= 4: _mouse_poll_ticks = _now_ticks - _mt0: t.CUInt64T = timer.timer_get_ticks() - mouse_active: t.CInt = _update_mouse() - _mt1: t.CUInt64T = timer.timer_get_ticks() + _mt0: uint64 = timer.timer_get_ticks() + mouse_active: int = _update_mouse() + _mt1: uint64 = timer.timer_get_ticks() _perf_t_mouse += (_mt1 - _mt0) # Poll keyboard at most every 4ms to avoid excessive I/O port overhead if _now_ticks - _kbd_poll_ticks >= 4: _kbd_poll_ticks = _now_ticks - _kt0: t.CUInt64T = timer.timer_get_ticks() + _kt0: uint64 = timer.timer_get_ticks() _update_keyboard() - _kt1: t.CUInt64T = timer.timer_get_ticks() + _kt1: uint64 = timer.timer_get_ticks() _perf_t_kbd += (_kt1 - _kt0) _heartbeat_check() sched.Scheduler.try_reschedule() - _dt_cur_sec: t.CUInt32T = timer.timer_get_seconds() + _dt_cur_sec: uint32 = timer.timer_get_seconds() if _dt_cur_sec != _dt_hb_sec: _dt_hb_sec = _dt_cur_sec - cur_sec: t.CUInt32T = timer.timer_get_seconds() + cur_sec: uint32 = timer.timer_get_seconds() if cur_sec != _last_clock_sec: _last_clock_sec = cur_sec _mark_rows_dirty(_screen_h - tb_h_dt, tb_h_dt) if _mouse_moved: _mouse_moved = 0 - sz: t.CInt = CURSOR_H + sz: int = CURSOR_H _mark_rows_dirty(_prev_cursor_y, sz) _mark_rows_dirty(_cursor_y, sz) _prev_cursor_x = _cursor_x _prev_cursor_y = _cursor_y - top_win: t.CInt = _hit_test_window(_cursor_x, _cursor_y) + top_win: int = _hit_test_window(_cursor_x, _cursor_y) for ai in range(_win_count): if _wins[ai].active and not _wins[ai].minimized: - th: t.CInt = _get_title_height(_wins[ai].style) - btn_w: t.CInt = CLOSE_BTN_SIZE - btn_h: t.CInt = CLOSE_BTN_SIZE - ew_hov: t.CInt = _eff_w(c.Addr(_wins[ai])) - btn_x: t.CInt = _wins[ai].x + ew_hov - btn_w - 4 - btn_y: t.CInt = _wins[ai].y + (th - btn_h) // 2 + th: int = _get_title_height(_wins[ai].style) + btn_w: int = CLOSE_BTN_SIZE + btn_h: int = CLOSE_BTN_SIZE + ew_hov: int = _eff_w(c.Addr(_wins[ai])) + btn_x: int = _wins[ai].x + ew_hov - btn_w - 4 + btn_y: int = _wins[ai].y + (th - btn_h) // 2 if _wins[ai].style == STYLE_WIN7: btn_w = CLOSE_BTN_W7_W btn_h = CLOSE_BTN_W7_H @@ -1739,15 +1739,15 @@ def desktop_thread(arg: t.CPtr) -> t.CInt: btn_h = th - 2 btn_x = _wins[ai].x + ew_hov - btn_w btn_y = _wins[ai].y + 1 - max_bx3: t.CInt = btn_x - btn_w + max_bx3: int = btn_x - btn_w if _wins[ai].style == STYLE_WIN7 or _wins[ai].style == STYLE_WINXP: max_bx3 = btn_x - btn_w - 1 - min_bx3: t.CInt = max_bx3 - btn_w + min_bx3: int = max_bx3 - btn_w if _wins[ai].style == STYLE_WIN7 or _wins[ai].style == STYLE_WINXP: min_bx3 = max_bx3 - btn_w - 1 - is_over_close: t.CInt = 0 - is_over_max: t.CInt = 0 - is_over_min: t.CInt = 0 + is_over_close: int = 0 + is_over_max: int = 0 + is_over_min: int = 0 if ai == top_win: if _cursor_x >= btn_x and _cursor_x < btn_x + btn_w and _cursor_y >= btn_y and _cursor_y < btn_y + btn_h: is_over_close = 1 @@ -1756,79 +1756,79 @@ def desktop_thread(arg: t.CPtr) -> t.CInt: elif _cursor_x >= min_bx3 and _cursor_x < min_bx3 + btn_w and _cursor_y >= btn_y and _cursor_y < btn_y + btn_h: is_over_min = 1 if is_over_close and _wins[ai].close_hover < 255: - _old_hov: t.CInt = _wins[ai].close_hover + _old_hov: int = _wins[ai].close_hover _wins[ai].close_hover += 60 if _wins[ai].close_hover > 255: _wins[ai].close_hover = 255 if _wins[ai].close_hover != _old_hov: _mark_rows_dirty(btn_y, btn_h) elif not is_over_close and _wins[ai].close_hover > 0: - _old_hov2: t.CInt = _wins[ai].close_hover + _old_hov2: int = _wins[ai].close_hover _wins[ai].close_hover -= 45 if _wins[ai].close_hover < 0: _wins[ai].close_hover = 0 if _wins[ai].close_hover != _old_hov2: _mark_rows_dirty(btn_y, btn_h) if is_over_max and _wins[ai].max_hover < 255: - _old_mh: t.CInt = _wins[ai].max_hover + _old_mh: int = _wins[ai].max_hover _wins[ai].max_hover += 60 if _wins[ai].max_hover > 255: _wins[ai].max_hover = 255 if _wins[ai].max_hover != _old_mh: _mark_rows_dirty(btn_y, btn_h) elif not is_over_max and _wins[ai].max_hover > 0: - _old_mh2: t.CInt = _wins[ai].max_hover + _old_mh2: int = _wins[ai].max_hover _wins[ai].max_hover -= 45 if _wins[ai].max_hover < 0: _wins[ai].max_hover = 0 if _wins[ai].max_hover != _old_mh2: _mark_rows_dirty(btn_y, btn_h) if is_over_min and _wins[ai].min_hover < 255: - _old_nh: t.CInt = _wins[ai].min_hover + _old_nh: int = _wins[ai].min_hover _wins[ai].min_hover += 60 if _wins[ai].min_hover > 255: _wins[ai].min_hover = 255 if _wins[ai].min_hover != _old_nh: _mark_rows_dirty(btn_y, btn_h) elif not is_over_min and _wins[ai].min_hover > 0: - _old_nh2: t.CInt = _wins[ai].min_hover + _old_nh2: int = _wins[ai].min_hover _wins[ai].min_hover -= 45 if _wins[ai].min_hover < 0: _wins[ai].min_hover = 0 if _wins[ai].min_hover != _old_nh2: _mark_rows_dirty(btn_y, btn_h) if _has_dirty_rows(): - _rt0: t.CUInt64T = timer.timer_get_ticks() + _rt0: uint64 = timer.timer_get_ticks() _render() - _rt1: t.CUInt64T = timer.timer_get_ticks() + _rt1: uint64 = timer.timer_get_ticks() _perf_t_render += (_rt1 - _rt0) - _ft0: t.CUInt64T = timer.timer_get_ticks() + _ft0: uint64 = timer.timer_get_ticks() _clear_dirty_flags() - _ft1: t.CUInt64T = timer.timer_get_ticks() + _ft1: uint64 = timer.timer_get_ticks() _perf_t_flush += (_ft1 - _ft0) _perf_frames += 1 - _loop_t1: t.CUInt64T = timer.timer_get_ticks() + _loop_t1: uint64 = timer.timer_get_ticks() _perf_t_total += (_loop_t1 - _loop_t0) - _now_ticks: t.CUInt64T = timer.timer_get_ticks() - _elapsed_ms: t.CUInt64T = _now_ticks - _perf_start_ticks + _now_ticks: uint64 = timer.timer_get_ticks() + _elapsed_ms: uint64 = _now_ticks - _perf_start_ticks if _elapsed_ms >= 1000: - _fps_val: t.CUInt32T = 0 + _fps_val: uint32 = 0 if _elapsed_ms > 0: - _fps_val = t.CUInt32T(t.CUInt64T(_perf_frames) * 1000 / _elapsed_ms) + _fps_val = uint32(uint64(_perf_frames) * 1000 / _elapsed_ms) string.memset(c.Addr(_perf_buf), 0, 256) # [DIAG] .rodata 格式串校验:win=%lu/work=%lu 曾出现 ' / , 字节破坏(越界写)。 # 校验和变化 → 确认为真实内存破坏(配合 .rodata 只读后 #PF 定位写源); # 校验和不变 → 疑似 printf/串口输出伪影,走另一条排查线。 _perf_fmt_str: str = "[perf] fps=%u wall=%lu work=%lu mouse=%lu kbd=%lu render=%lu(bg=%lu win=%lu cur=%lu fb=%lu) dirty=%d vsync=%d sh=%d dc=%d ki=%lu mi=%lu\n" - _fmt_sum: t.CUInt32T = 0 - _fi: t.CInt = 0 + _fmt_sum: uint32 = 0 + _fi: int = 0 while _fi < 110: - _fmt_sum = _fmt_sum + t.CUInt32T(t.CUInt8T(_perf_fmt_str[_fi])) + _fmt_sum = _fmt_sum + uint32(uint8(_perf_fmt_str[_fi])) _fi += 1 _chk_buf: t.CArray[t.CChar, 48] viperlib.snprintf(c.Addr(_chk_buf), 48, "[chk] sum=%u\n", _fmt_sum) serial.puts(c.Addr(_chk_buf)) - viperlib.snprintf(c.Addr(_perf_buf), 256, _perf_fmt_str, _fps_val, t.CUInt64T(_elapsed_ms), t.CUInt64T(_perf_t_total), t.CUInt64T(_perf_t_mouse), t.CUInt64T(_perf_t_kbd), t.CUInt64T(_perf_t_render), t.CUInt64T(_perf_t_bg), t.CUInt64T(_perf_t_win), t.CUInt64T(_perf_t_cur), t.CUInt64T(_perf_t_fb), _dirty_count, _vblank_ok, _screen_h, _dirty_count, keyboard.kbd_irq_cnt, mouse.mse_irq_cnt) + viperlib.snprintf(c.Addr(_perf_buf), 256, _perf_fmt_str, _fps_val, uint64(_elapsed_ms), uint64(_perf_t_total), uint64(_perf_t_mouse), uint64(_perf_t_kbd), uint64(_perf_t_render), uint64(_perf_t_bg), uint64(_perf_t_win), uint64(_perf_t_cur), uint64(_perf_t_fb), _dirty_count, _vblank_ok, _screen_h, _dirty_count, keyboard.kbd_irq_cnt, mouse.mse_irq_cnt) serial.puts(_perf_buf) _perf_t_mouse = 0 _perf_t_kbd = 0 @@ -1844,7 +1844,7 @@ def desktop_thread(arg: t.CPtr) -> t.CInt: sched.Scheduler.try_reschedule() return 0 -def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thread | t.CPtr: +def start(fb_ptr: t.CPtr, w: int, h: int, pitch: int = 0) -> sched.Thread | t.CPtr: global _fb, _screen_w, _screen_h, _fb_pitch, _cursor_x, _cursor_y global _bg_row_buf, _back_fb, _row_buf global _dirty_rows, _prev_cursor_x, _prev_cursor_y @@ -1860,16 +1860,16 @@ def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thre _prev_cursor_x = _cursor_x _prev_cursor_y = _cursor_y - _dirty_rows = mm.malloc(t.CUInt64T(h)) + _dirty_rows = mm.malloc(uint64(h)) if _dirty_rows: string.memset(_dirty_rows, 0, h) else: serial.puts("[desktop] dirty_rows malloc FAILED\n") return None - _back_fb = mm.malloc(t.CUInt64T(w) * t.CUInt64T(h) * 4) + _back_fb = mm.malloc(uint64(w) * uint64(h) * 4) _dbg_bf: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbg_bf), 96, "[dbg] back_fb ret=0x%lx w=%d h=%d\n", t.CUInt64T(_back_fb), w, h) + viperlib.snprintf(c.Addr(_dbg_bf), 96, "[dbg] back_fb ret=0x%lx w=%d h=%d\n", uint64(_back_fb), w, h) serial.puts(c.Addr(_dbg_bf)) if _back_fb: string.memset(_back_fb, 0, w * h * 4) @@ -1877,9 +1877,9 @@ def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thre serial.puts("[desktop] back_fb malloc FAILED\n") return None - _row_buf = mm.malloc(t.CUInt64T(w) * 4) + _row_buf = mm.malloc(uint64(w) * 4) _dbg_rb: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbg_rb), 96, "[dbg] row_buf ret=0x%lx\n", t.CUInt64T(_row_buf)) + viperlib.snprintf(c.Addr(_dbg_rb), 96, "[dbg] row_buf ret=0x%lx\n", uint64(_row_buf)) serial.puts(c.Addr(_dbg_rb)) if _row_buf: string.memset(_row_buf, 0, w * 4) @@ -1888,12 +1888,12 @@ def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thre # mm.malloc(w*4) 走裸名回退生成 call @malloc(i32),形参 i64 不匹配(第 4 次 # 调用 RAX 返回值被破坏收到 0)。显式 CUInt64T 让参数按 i64 传递。 - _bg_row_buf = mm.malloc(t.CUInt64T(w) * 4) + _bg_row_buf = mm.malloc(uint64(w) * 4) _dbg_br: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbg_br), 96, "[dbg] bg_row_buf ret=0x%lx\n", t.CUInt64T(_bg_row_buf)) + viperlib.snprintf(c.Addr(_dbg_br), 96, "[dbg] bg_row_buf ret=0x%lx\n", uint64(_bg_row_buf)) serial.puts(c.Addr(_dbg_br)) if _bg_row_buf: - desktop_init_col: t.CUInt32T = gfx.COLOR_RGB(25, 25, 35) + desktop_init_col: uint32 = gfx.COLOR_RGB(25, 25, 35) for ri in range(w): _bg_row_buf[ri] = desktop_init_col else: @@ -1901,7 +1901,7 @@ def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thre _mark_all_dirty() p: process.Process | t.CPtr = process.ProcessManager.create_process("desktop", None) - desktop_pid: t.CInt = 0 + desktop_pid: int = 0 if p: desktop_pid = p.pid th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(desktop_thread, None, desktop_pid) @@ -1909,20 +1909,20 @@ def start(fb_ptr: t.CPtr, w: t.CInt, h: t.CInt, pitch: t.CInt = 0) -> sched.Thre p.addThread(th.tid) return th -def _get_top_window() -> t.CInt: - best: t.CInt = -1 - best_z: t.CInt = -1 +def _get_top_window() -> int: + best: int = -1 + best_z: int = -1 for ai in range(_win_count): if _wins[ai].active and not _wins[ai].minimized: - z: t.CInt = _wins[ai].z_order + z: int = _wins[ai].z_order if z > best_z: best_z = z best = ai return best -def _draw_min_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CInt, btn_w: t.CInt, btn_h: t.CInt, hover_alpha: t.CInt, style: t.CInt): +def _draw_min_btn(back: UINT32PTR, bw: int, bh: int, bx: int, by: int, btn_w: int, btn_h: int, hover_alpha: int, style: int): if hover_alpha > 0: - hover_col: t.CUInt32T = gfx.COLOR_RGB(80, 80, 80) + hover_col: uint32 = gfx.COLOR_RGB(80, 80, 80) if style == STYLE_WIN7: hover_col = gfx.COLOR_RGB(200, 220, 240) elif style == STYLE_WINXP: @@ -1931,25 +1931,25 @@ def _draw_min_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CIn if py >= 0 and py < bh: for px in range(bx, bx + btn_w): if px >= 0 and px < bw: - bg_pixel: t.CUInt32T = back[py * bw + px] + bg_pixel: uint32 = back[py * bw + px] back[py * bw + px] = _alpha_blend(bg_pixel, hover_col, hover_alpha) - line_col: t.CUInt32T = gfx.COLOR_RGB(180, 180, 180) + line_col: uint32 = gfx.COLOR_RGB(180, 180, 180) if hover_alpha > 0: line_col = gfx.COLOR_RGB(255, 255, 255) - cx: t.CInt = bx + btn_w // 2 - cy: t.CInt = by + btn_h // 2 - lw: t.CInt = 5 + cx: int = bx + btn_w // 2 + cy: int = by + btn_h // 2 + lw: int = 5 if btn_w >= 30: lw = 8 - ly: t.CInt = cy + 3 + ly: int = cy + 3 if ly >= 0 and ly < bh: for lx in range(cx - lw, cx + lw + 1): if lx >= 0 and lx < bw: back[ly * bw + lx] = line_col -def _draw_max_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CInt, btn_w: t.CInt, btn_h: t.CInt, hover_alpha: t.CInt, style: t.CInt, is_maximized: t.CInt): +def _draw_max_btn(back: UINT32PTR, bw: int, bh: int, bx: int, by: int, btn_w: int, btn_h: int, hover_alpha: int, style: int, is_maximized: int): if hover_alpha > 0: - hover_col2: t.CUInt32T = gfx.COLOR_RGB(80, 80, 80) + hover_col2: uint32 = gfx.COLOR_RGB(80, 80, 80) if style == STYLE_WIN7: hover_col2 = gfx.COLOR_RGB(200, 220, 240) elif style == STYLE_WINXP: @@ -1958,26 +1958,26 @@ def _draw_max_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CIn if py2 >= 0 and py2 < bh: for px2 in range(bx, bx + btn_w): if px2 >= 0 and px2 < bw: - bg_pixel2: t.CUInt32T = back[py2 * bw + px2] + bg_pixel2: uint32 = back[py2 * bw + px2] back[py2 * bw + px2] = _alpha_blend(bg_pixel2, hover_col2, hover_alpha) - rect_col: t.CUInt32T = gfx.COLOR_RGB(180, 180, 180) + rect_col: uint32 = gfx.COLOR_RGB(180, 180, 180) if hover_alpha > 0: rect_col = gfx.COLOR_RGB(255, 255, 255) - cx2: t.CInt = bx + btn_w // 2 - cy2: t.CInt = by + btn_h // 2 - sz: t.CInt = 4 + cx2: int = bx + btn_w // 2 + cy2: int = by + btn_h // 2 + sz: int = 4 if btn_w >= 30: sz = 6 if is_maximized: - off: t.CInt = 2 + off: int = 2 for ry1 in range(cy2 - sz + off, cy2 + sz + off + 1): if ry1 >= 0 and ry1 < bh: for rx1 in range(cx2 - sz + off, cx2 + sz + off + 1): if rx1 >= 0 and rx1 < bw: - is_top: t.CInt = 0 + is_top: int = 0 if ry1 == cy2 - sz + off or ry1 == cy2 - sz + off + 1: is_top = 1 - is_border: t.CInt = 0 + is_border: int = 0 if ry1 == cy2 - sz + off or ry1 == cy2 + sz + off or rx1 == cx2 - sz + off or rx1 == cx2 + sz + off: is_border = 1 if is_top or is_border: @@ -1995,7 +1995,7 @@ def _draw_max_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CIn if rx3 >= 0 and rx3 < bw: if ry3 == cy2 - sz or ry3 == cy2 + sz or rx3 == cx2 - sz or rx3 == cx2 + sz: back[ry3 * bw + rx3] = rect_col - top_y: t.CInt = cy2 - sz + top_y: int = cy2 - sz if top_y >= 0 and top_y < bh: for tx in range(cx2 - sz, cx2 + sz + 1): if tx >= 0 and tx < bw: @@ -2005,32 +2005,32 @@ def _draw_max_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CIn if tx2 >= 0 and tx2 < bw: back[(top_y + 1) * bw + tx2] = rect_col -def _draw_close_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.CInt, btn_w: t.CInt, btn_h: t.CInt, hover_alpha: t.CInt, style: t.CInt, clip_wx: t.CInt, clip_wy: t.CInt, clip_ww: t.CInt, clip_r: t.CInt): - x_col: t.CUInt32T = gfx.COLOR_RGB(200, 200, 200) +def _draw_close_btn(back: UINT32PTR, bw: int, bh: int, bx: int, by: int, btn_w: int, btn_h: int, hover_alpha: int, style: int, clip_wx: int, clip_wy: int, clip_ww: int, clip_r: int): + x_col: uint32 = gfx.COLOR_RGB(200, 200, 200) if style == STYLE_CLASSIC: - bg: t.CUInt32T = gfx.COLOR_RGB(40, 40, 70) + bg: uint32 = gfx.COLOR_RGB(40, 40, 70) if hover_alpha > 0: - red: t.CUInt32T = gfx.COLOR_RGB(200, 50, 50) + red: uint32 = gfx.COLOR_RGB(200, 50, 50) bg = _alpha_blend(bg, red, hover_alpha) _fill_rect(back, bw, bh, bx, by, btn_w, btn_h, bg) if hover_alpha > 128: x_col = gfx.COLOR_RGB(255, 255, 255) elif style == STYLE_WIN7: - br: t.CInt = CLOSE_BTN_W7_R - bg_r: t.CInt = 200 - bg_g: t.CInt = 50 - bg_b: t.CInt = 50 + br: int = CLOSE_BTN_W7_R + bg_r: int = 200 + bg_g: int = 50 + bg_b: int = 50 if hover_alpha > 0: bg_r = 200 + ((232 - 200) * hover_alpha) / 255 bg_g = 50 + ((17 - 50) * hover_alpha) / 255 bg_b = 50 + ((35 - 50) * hover_alpha) / 255 - bg_col7: t.CUInt32T = gfx.COLOR_RGB(bg_r, bg_g, bg_b) + bg_col7: uint32 = gfx.COLOR_RGB(bg_r, bg_g, bg_b) for py2 in range(by, by + btn_h): if py2 >= 0 and py2 < bh: for px2 in range(bx, bx + btn_w): if px2 >= 0 and px2 < bw: - lrx: t.CInt = px2 - bx - lry: t.CInt = py2 - by + lrx: int = px2 - bx + lry: int = py2 - by if lry < br: if lrx < br: if (lrx - br) * (lrx - br) + (lry - br) * (lry - br) > br * br: @@ -2046,11 +2046,11 @@ def _draw_close_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.C if (lrx - (btn_w - br - 1)) * (lrx - (btn_w - br - 1)) + (lry - (btn_h - br - 1)) * (lry - (btn_h - br - 1)) > br * br: continue if clip_r > 0: - crx: t.CInt = px2 - clip_wx - cry: t.CInt = py2 - clip_wy + crx: int = px2 - clip_wx + cry: int = py2 - clip_wy if cry < clip_r and crx >= clip_ww - clip_r: - cdx: t.CInt = crx - (clip_ww - clip_r - 1) - cdy: t.CInt = cry - clip_r + cdx: int = crx - (clip_ww - clip_r - 1) + cdy: int = cry - clip_r if cdx * cdx + cdy * cdy > clip_r * clip_r: continue back[py2 * bw + px2] = bg_col7 @@ -2058,21 +2058,21 @@ def _draw_close_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.C if hover_alpha > 0: x_col = _alpha_blend(gfx.COLOR_RGB(255, 255, 255), gfx.COLOR_RGB(255, 240, 240), hover_alpha) elif style == STYLE_WINXP: - br_xp: t.CInt = 3 - bg_r_xp: t.CInt = 200 - bg_g_xp: t.CInt = 50 - bg_b_xp: t.CInt = 50 + br_xp: int = 3 + bg_r_xp: int = 200 + bg_g_xp: int = 50 + bg_b_xp: int = 50 if hover_alpha > 0: bg_r_xp = 200 + ((232 - 200) * hover_alpha) / 255 bg_g_xp = 50 + ((17 - 50) * hover_alpha) / 255 bg_b_xp = 50 + ((35 - 50) * hover_alpha) / 255 - bg_col_xp: t.CUInt32T = gfx.COLOR_RGB(bg_r_xp, bg_g_xp, bg_b_xp) + bg_col_xp: uint32 = gfx.COLOR_RGB(bg_r_xp, bg_g_xp, bg_b_xp) for py_xp in range(by, by + btn_h): if py_xp >= 0 and py_xp < bh: for px_xp in range(bx, bx + btn_w): if px_xp >= 0 and px_xp < bw: - lrx_xp: t.CInt = px_xp - bx - lry_xp: t.CInt = py_xp - by + lrx_xp: int = px_xp - bx + lry_xp: int = py_xp - by if lry_xp < br_xp: if lrx_xp < br_xp: if (lrx_xp - br_xp) * (lrx_xp - br_xp) + (lry_xp - br_xp) * (lry_xp - br_xp) > br_xp * br_xp: @@ -2099,47 +2099,47 @@ def _draw_close_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.C for px3 in range(bx, bx + btn_w): if px3 >= 0 and px3 < bw: if clip_r > 0: - crx3: t.CInt = px3 - clip_wx - cry3: t.CInt = py3 - clip_wy + crx3: int = px3 - clip_wx + cry3: int = py3 - clip_wy if cry3 < clip_r and crx3 >= clip_ww - clip_r: - cdx3: t.CInt = crx3 - (clip_ww - clip_r - 1) - cdy3: t.CInt = cry3 - clip_r + cdx3: int = crx3 - (clip_ww - clip_r - 1) + cdy3: int = cry3 - clip_r if cdx3 * cdx3 + cdy3 * cdy3 > clip_r * clip_r: continue - bg_pixel: t.CUInt32T = back[py3 * bw + px3] + bg_pixel: uint32 = back[py3 * bw + px3] back[py3 * bw + px3] = _alpha_blend(bg_pixel, red, hover_alpha) x_col = gfx.COLOR_RGB(150, 150, 150) if hover_alpha > 0: x_col = _alpha_blend(gfx.COLOR_RGB(150, 150, 150), gfx.COLOR_RGB(255, 255, 255), hover_alpha) - cx: t.CInt = bx + btn_w // 2 - cy: t.CInt = by + btn_h // 2 - d: t.CInt = 3 + cx: int = bx + btn_w // 2 + cy: int = by + btn_h // 2 + d: int = 3 if btn_w >= 30: d = 4 - i: t.CInt = -d + i: int = -d while i <= d: - px1: t.CInt = cx + i - py1: t.CInt = cy + i - px2b: t.CInt = cx + i - py2b: t.CInt = cy - i + px1: int = cx + i + py1: int = cy + i + px2b: int = cx + i + py2b: int = cy - i if px1 >= 0 and px1 < bw and py1 >= 0 and py1 < bh: if clip_r > 0: - crx1: t.CInt = px1 - clip_wx - cry1: t.CInt = py1 - clip_wy + crx1: int = px1 - clip_wx + cry1: int = py1 - clip_wy if cry1 < clip_r and crx1 >= clip_ww - clip_r: - cdx1: t.CInt = crx1 - (clip_ww - clip_r - 1) - cdy1: t.CInt = cry1 - clip_r + cdx1: int = crx1 - (clip_ww - clip_r - 1) + cdy1: int = cry1 - clip_r if cdx1 * cdx1 + cdy1 * cdy1 > clip_r * clip_r: i += 1 continue back[py1 * bw + px1] = x_col if px2b >= 0 and px2b < bw and py2b >= 0 and py2b < bh: if clip_r > 0: - crx2: t.CInt = px2b - clip_wx - cry2: t.CInt = py2b - clip_wy + crx2: int = px2b - clip_wx + cry2: int = py2b - clip_wy if cry2 < clip_r and crx2 >= clip_ww - clip_r: - cdx2: t.CInt = crx2 - (clip_ww - clip_r - 1) - cdy2: t.CInt = cry2 - clip_r + cdx2: int = crx2 - (clip_ww - clip_r - 1) + cdy2: int = cry2 - clip_r if cdx2 * cdx2 + cdy2 * cdy2 > clip_r * clip_r: i += 1 continue @@ -2147,32 +2147,32 @@ def _draw_close_btn(back: UINT32PTR, bw: t.CInt, bh: t.CInt, bx: t.CInt, by: t.C i += 1 def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): - w: t.CInt = _screen_w - h: t.CInt = _screen_h - wx: t.CInt = win.x - wy: t.CInt = win.y - ww: t.CInt = _eff_w(win) - wh: t.CInt = win.h - ch: t.CInt = _eff_h(win) - style: t.CInt = win.style - th: t.CInt = _get_title_height(style) + w: int = _screen_w + h: int = _screen_h + wx: int = win.x + wy: int = win.y + ww: int = _eff_w(win) + wh: int = win.h + ch: int = _eff_h(win) + style: int = win.style + th: int = _get_title_height(style) if wy + wh <= _dirty_y_min or wy > _dirty_y_max: return - top_idx: t.CInt = _cached_top_win - is_active: t.CInt = 0 + top_idx: int = _cached_top_win + is_active: int = 0 if top_idx >= 0: - top_z: t.CInt = _wins[top_idx].z_order + top_z: int = _wins[top_idx].z_order if win.z_order == top_z: is_active = 1 - title_col: t.CUInt32T = gfx.COLOR_RGB(50, 50, 90) - border_col: t.CUInt32T = gfx.COLOR_RGB(100, 100, 180) - content_col: t.CUInt32T = gfx.COLOR_RGB(30, 30, 50) - outline_col: t.CUInt32T = gfx.COLOR_RGB(100, 100, 180) - title_alpha: t.CInt = 255 - has_separator: t.CInt = 1 + title_col: uint32 = gfx.COLOR_RGB(50, 50, 90) + border_col: uint32 = gfx.COLOR_RGB(100, 100, 180) + content_col: uint32 = gfx.COLOR_RGB(30, 30, 50) + outline_col: uint32 = gfx.COLOR_RGB(100, 100, 180) + title_alpha: int = 255 + has_separator: int = 1 if style == STYLE_WIN10: has_separator = 0 if is_active: @@ -2228,10 +2228,10 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): border_col = gfx.COLOR_RGB(130, 130, 220) outline_col = gfx.COLOR_RGB(130, 130, 220) - rounded: t.CInt = 0 + rounded: int = 0 if style == STYLE_WIN11 or style == STYLE_WIN7 or style == STYLE_WINXP: rounded = 1 - r: t.CInt = WIN_RADIUS + r: int = WIN_RADIUS _draw_window_shadow(back, w, h, wx, wy, ww, wh, rounded, r) @@ -2239,19 +2239,19 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): for py in range(wy, wy + wh): if py < 0 or py >= h: continue if not _dirty_rows[py]: continue - ry: t.CInt = py - wy - row_col: t.CUInt32T = content_col - row_is_title: t.CInt = 0 - row_is_sep: t.CInt = 0 + ry: int = py - wy + row_col: uint32 = content_col + row_is_title: int = 0 + row_is_sep: int = 0 if ry < th: row_is_title = 1 if style == STYLE_WIN7: - ratio: t.CInt = (ry * 100) / th + ratio: int = (ry * 100) / th if ratio > 100: ratio = 100 if is_active: - gr: t.CInt = 156 + ((186 - 156) * ratio) / 100 - gg: t.CInt = 181 + ((209 - 181) * ratio) / 100 - gb: t.CInt = 209 + ((233 - 209) * ratio) / 100 + gr: int = 156 + ((186 - 156) * ratio) / 100 + gg: int = 181 + ((209 - 181) * ratio) / 100 + gb: int = 209 + ((233 - 209) * ratio) / 100 else: gr = 180 + ((200 - 180) * ratio) / 100 gg = 195 + ((210 - 195) * ratio) / 100 @@ -2286,34 +2286,34 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): elif ry == th and has_separator: row_is_sep = 1 row_col = outline_col - in_corner_zone: t.CInt = 0 + in_corner_zone: int = 0 if ry < r or ry >= wh - r: in_corner_zone = 1 if not in_corner_zone: - left_border: t.CInt = wx - right_border: t.CInt = wx + ww - 1 + left_border: int = wx + right_border: int = wx + ww - 1 if left_border >= 0 and left_border < w: back[py * w + left_border] = outline_col if right_border >= 0 and right_border < w: back[py * w + right_border] = outline_col - fill_left: t.CInt = wx + 1 - fill_right: t.CInt = wx + ww - 1 + fill_left: int = wx + 1 + fill_right: int = wx + ww - 1 if fill_left < 0: fill_left = 0 if fill_right > w: fill_right = w - fill_w: t.CInt = fill_right - fill_left + fill_w: int = fill_right - fill_left if fill_w > 0: if row_is_title and (style == STYLE_WIN7 or style == STYLE_WINXP) and title_alpha < 255: for fx in range(fill_left, fill_right): - bg_p: t.CUInt32T = back[py * w + fx] + bg_p: uint32 = back[py * w + fx] back[py * w + fx] = _alpha_blend(bg_p, row_col, title_alpha) else: _fill_rect(back, w, h, fill_left, py, fill_w, 1, row_col) else: for px in range(wx, wx + ww): if px < 0 or px >= w: continue - rx: t.CInt = px - wx - in_corner: t.CInt = 1 - on_border: t.CInt = 0 + rx: int = px - wx + in_corner: int = 1 + on_border: int = 0 if ry < r: if rx < r: in_corner = _is_in_corner(rx, ry, r, r, r) @@ -2328,12 +2328,12 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): on_border = _is_on_border(rx, ry, ww, wh, r) if not on_border: continue - col: t.CUInt32T = row_col - is_border_pixel: t.CInt = 0 + col: uint32 = row_col + is_border_pixel: int = 0 if on_border or _is_on_border(rx, ry, ww, wh, r): col = outline_col is_border_pixel = 1 - ca: t.CInt = 255 + ca: int = 255 if ry < r: if rx < r: ca = _corner_alpha(rx, ry, r, r, r) @@ -2349,7 +2349,7 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): if row_is_title and (style == STYLE_WIN7 or style == STYLE_WINXP) and ry >= 1 and rx >= 1 and rx < ww - 1 and ca == 255 and not is_border_pixel: ca = title_alpha if ca < 255: - bg_pixel: t.CUInt32T = back[py * w + px] + bg_pixel: uint32 = back[py * w + px] col = _alpha_blend(bg_pixel, col, ca) back[py * w + px] = col else: @@ -2372,39 +2372,39 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): win_fb: UINT32PTR = win.fb if win_fb: - fb_stride: t.CInt = win.fb_w - fbh: t.CInt = win.fb_h + fb_stride: int = win.fb_w + fbh: int = win.fb_h if fb_stride <= 0 or fbh <= 0: win_fb = t.CVoid(0, t.CPtr) if win_fb: - draw_rows: t.CInt = ch + draw_rows: int = ch if draw_rows > fbh: draw_rows = fbh if draw_rows < 0: draw_rows = 0 - content_y: t.CInt = wy + th + 1 - fb_total: t.CInt = fb_stride * fbh + content_y: int = wy + th + 1 + fb_total: int = fb_stride * fbh for row in range(draw_rows): - dst_y: t.CInt = content_y + row + dst_y: int = content_y + row if dst_y < 0 or dst_y >= h: continue if not _dirty_rows[dst_y]: continue - ry: t.CInt = th + 1 + row + ry: int = th + 1 + row if rounded: if ry >= r and ry < wh - r: - src_x: t.CInt = 1 - dst_x: t.CInt = wx + 1 + src_x: int = 1 + dst_x: int = wx + 1 if dst_x < 0: src_x = src_x - dst_x dst_x = 0 - end_x: t.CInt = wx + ww - 1 + end_x: int = wx + ww - 1 if end_x > w: end_x = w - actual_w: t.CInt = end_x - dst_x + actual_w: int = end_x - dst_x if actual_w <= 0: continue if src_x + actual_w > fb_stride: actual_w = fb_stride - src_x if actual_w <= 0: continue - src_off: t.CInt = row * fb_stride + src_x + src_off: int = row * fb_stride + src_x if src_off + actual_w > fb_total: continue - string.memcpy(t.CVoid(t.CUInt64T(back) + (dst_y * w + dst_x) * 4, t.CPtr), t.CVoid(t.CUInt64T(win_fb) + src_off * 4, t.CPtr), actual_w * 4) + string.memcpy(t.CVoid(uint64(back) + (dst_y * w + dst_x) * 4, t.CPtr), t.CVoid(uint64(win_fb) + src_off * 4, t.CPtr), actual_w * 4) else: - copy_w: t.CInt = fb_stride - 1 + copy_w: int = fb_stride - 1 if copy_w > ww - 1: copy_w = ww - 1 for col_px in range(1, copy_w): if ry < r: @@ -2418,33 +2418,33 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): elif col_px >= ww - r: if not _is_in_corner(col_px, ry, ww - r - 1, wh - r - 1, r): continue if _is_on_border(col_px, ry, ww, wh, r): continue - dst_x2: t.CInt = wx + col_px + dst_x2: int = wx + col_px if dst_x2 < 0 or dst_x2 >= w: continue if col_px >= fb_stride: continue - px_off: t.CInt = row * fb_stride + col_px + px_off: int = row * fb_stride + col_px if px_off < 0 or px_off >= fb_total: continue back[dst_y * w + dst_x2] = win_fb[px_off] else: - src_x2: t.CInt = 1 - dst_x3: t.CInt = wx + 1 + src_x2: int = 1 + dst_x3: int = wx + 1 if dst_x3 < 0: src_x2 = src_x2 - dst_x3 dst_x3 = 0 - end_x2: t.CInt = wx + ww - 1 + end_x2: int = wx + ww - 1 if end_x2 > w: end_x2 = w - actual_w2: t.CInt = end_x2 - dst_x3 + actual_w2: int = end_x2 - dst_x3 if actual_w2 <= 0: continue if src_x2 + actual_w2 > fb_stride: actual_w2 = fb_stride - src_x2 if actual_w2 <= 0: continue - src_off2: t.CInt = row * fb_stride + src_x2 + src_off2: int = row * fb_stride + src_x2 if src_off2 + actual_w2 > fb_total: continue - string.memcpy(t.CVoid(t.CUInt64T(back) + (dst_y * w + dst_x3) * 4, t.CPtr), t.CVoid(t.CUInt64T(win_fb) + src_off2 * 4, t.CPtr), actual_w2 * 4) + string.memcpy(t.CVoid(uint64(back) + (dst_y * w + dst_x3) * 4, t.CPtr), t.CVoid(uint64(win_fb) + src_off2 * 4, t.CPtr), actual_w2 * 4) - btn_w: t.CInt = CLOSE_BTN_SIZE - btn_h: t.CInt = CLOSE_BTN_SIZE - btn_x: t.CInt = wx + ww - btn_w - 4 - btn_y: t.CInt = wy + (th - btn_h) // 2 - clip_r: t.CInt = 0 + btn_w: int = CLOSE_BTN_SIZE + btn_h: int = CLOSE_BTN_SIZE + btn_x: int = wx + ww - btn_w - 4 + btn_y: int = wy + (th - btn_h) // 2 + clip_r: int = 0 if style == STYLE_WIN7: btn_w = CLOSE_BTN_W7_W btn_h = CLOSE_BTN_W7_H @@ -2465,25 +2465,25 @@ def _draw_app_window(back: UINT32PTR, win: AppWindow | t.CPtr): if rounded: clip_r = r _draw_close_btn(back, w, h, btn_x, btn_y, btn_w, btn_h, win.close_hover, style, wx, wy, ww, clip_r) - max_bx: t.CInt = btn_x - btn_w + max_bx: int = btn_x - btn_w if style == STYLE_WIN7 or style == STYLE_WINXP: max_bx = btn_x - btn_w - 1 _draw_max_btn(back, w, h, max_bx, btn_y, btn_w, btn_h, win.max_hover, style, win.is_maximized) - min_bx: t.CInt = max_bx - btn_w + min_bx: int = max_bx - btn_w if style == STYLE_WIN7 or style == STYLE_WINXP: min_bx = max_bx - btn_w - 1 _draw_min_btn(back, w, h, min_bx, btn_y, btn_w, btn_h, win.min_hover, style) - text_col: t.CUInt32T = 0xFFFFFFFF + text_col: uint32 = 0xFFFFFFFF if not is_active: text_col = gfx.COLOR_RGB(170, 170, 170) - text_y: t.CInt = wy + (th - 16) // 2 + text_y: int = wy + (th - 16) // 2 _draw_text(back, w, h, wx + 8, text_y, c.Addr(win.title[0]), text_col) -def create(x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | t.CChar | t.CPtr, style: t.CInt) -> t.CInt: +def create(x: int, y: int, w: int, h: int, title: t.CConst | t.CChar | t.CPtr, style: int) -> int: global _win_count, _next_z, _focused_win if _win_count >= MAX_APP_WINDOWS: return -1 - idx: t.CInt = _win_count + idx: int = _win_count _win_count += 1 aw: AppWindow | t.CPtr = c.Addr(_wins[idx]) aw.active = 1 @@ -2528,35 +2528,35 @@ def create(x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | t.CChar aw.fb_w = w aw.fb_h = aw.content_h if aw.fb: - bg_col: t.CUInt32T = gfx.COLOR_RGB(25, 25, 35) - fb_size: t.CInt = w * aw.content_h + bg_col: uint32 = gfx.COLOR_RGB(25, 25, 35) + fb_size: int = w * aw.content_h for fi in range(fb_size): aw.fb[fi] = bg_col _mark_rows_dirty(y, h) _focused_win = idx return idx -def draw_text(win_id: t.CInt, x: t.CInt, y: t.CInt, text: t.CConst | t.CChar | t.CPtr, color: t.CUInt32T) -> t.CInt: +def draw_text(win_id: int, x: int, y: int, text: t.CConst | t.CChar | t.CPtr, color: uint32) -> int: if win_id < 0 or win_id >= _win_count: return -1 aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return -1 win_fb: UINT32PTR = aw.fb if not win_fb: return -1 - fbw: t.CInt = aw.fb_w - fbh: t.CInt = aw.fb_h + fbw: int = aw.fb_w + fbh: int = aw.fb_h _draw_text(win_fb, fbw, fbh, x, y, text, color) _mark_rows_dirty(aw.y + _get_title_height(aw.style) + 1 + y, 16) return 0 -def set_app_pid(pid: t.CInt): +def set_app_pid(pid: int): global _current_app_pid _current_app_pid = pid -def is_active(win_id: t.CInt) -> t.CInt: +def is_active(win_id: int) -> int: if win_id < 0 or win_id >= _win_count: return 0 return _wins[win_id].active -def get_fb(win_id: t.CInt) -> UINT32PTR: +def get_fb(win_id: int) -> UINT32PTR: if win_id < 0 or win_id >= _win_count: return t.CVoid(0, t.CPtr) aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return t.CVoid(0, t.CPtr) @@ -2564,21 +2564,21 @@ def get_fb(win_id: t.CInt) -> UINT32PTR: mm.free(aw.old_fb) aw.old_fb = t.CVoid(0, t.CPtr) if aw.resize_w != 0 and (aw.fb_w != aw.resize_w or aw.fb_h != aw.resize_h): - target_w: t.CInt = aw.resize_w - target_h: t.CInt = aw.resize_h + target_w: int = aw.resize_w + target_h: int = aw.resize_h if target_w <= 0 or target_h <= 0: aw.resize_w = 0 aw.resize_h = 0 return aw.fb - new_fb_sz_gf: t.CInt = target_w * target_h + new_fb_sz_gf: int = target_w * target_h new_fb_gf: UINT32PTR = mm.malloc(new_fb_sz_gf * 4) if not new_fb_gf: aw.resize_w = 0 aw.resize_h = 0 return aw.fb old_fb_gf: UINT32PTR = aw.fb - old_fbw_gf: t.CInt = aw.fb_w - old_fbh_gf: t.CInt = aw.fb_h + old_fbw_gf: int = aw.fb_w + old_fbh_gf: int = aw.fb_h aw.fb = new_fb_gf aw.fb_w = target_w aw.fb_h = target_h @@ -2586,22 +2586,22 @@ def get_fb(win_id: t.CInt) -> UINT32PTR: aw.content_h = target_h aw.resize_w = 0 aw.resize_h = 0 - bg_gf: t.CUInt32T = gfx.COLOR_RGB(30, 30, 50) + bg_gf: uint32 = gfx.COLOR_RGB(30, 30, 50) for fi_gf in range(new_fb_sz_gf): aw.fb[fi_gf] = bg_gf if old_fb_gf: - cph_gf: t.CInt = old_fbh_gf + cph_gf: int = old_fbh_gf if cph_gf > target_h: cph_gf = target_h for ri_gf in range(cph_gf): - rb_gf: t.CInt = old_fbw_gf + rb_gf: int = old_fbw_gf if rb_gf > target_w: rb_gf = target_w - string.memcpy(t.CVoid(t.CUInt64T(aw.fb) + ri_gf * target_w * 4, t.CPtr), t.CVoid(t.CUInt64T(old_fb_gf) + ri_gf * old_fbw_gf * 4, t.CPtr), rb_gf * 4) + string.memcpy(t.CVoid(uint64(aw.fb) + ri_gf * target_w * 4, t.CPtr), t.CVoid(uint64(old_fb_gf) + ri_gf * old_fbw_gf * 4, t.CPtr), rb_gf * 4) if aw.old_fb: mm.free(aw.old_fb) aw.old_fb = old_fb_gf return aw.fb -def get_size(win_id: t.CInt) -> t.CInt: +def get_size(win_id: int) -> int: if win_id < 0 or win_id >= _win_count: return 0 aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return 0 @@ -2609,13 +2609,13 @@ def get_size(win_id: t.CInt) -> t.CInt: _NO_RESP_SUFFIX: t.CArray[t.CChar, 14] = " - (No Resp)" -def _update_no_resp_title(win_id: t.CInt, mark: t.CInt): +def _update_no_resp_title(win_id: int, mark: int): if win_id < 0 or win_id >= _win_count: return aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return string.memset(c.Addr(aw.title), 0, 32) if mark: - j: t.CInt = 0 + j: int = 0 for ch in aw.orig_title: if j >= 31: break if ch == 0: break @@ -2628,7 +2628,7 @@ def _update_no_resp_title(win_id: t.CInt, mark: t.CInt): aw.title[j] = sc j += 1 else: - j2: t.CInt = 0 + j2: int = 0 for ch2 in aw.orig_title: if j2 >= 31: break if ch2 == 0: break @@ -2638,7 +2638,7 @@ def _update_no_resp_title(win_id: t.CInt, mark: t.CInt): def _heartbeat_check(): global _hb_last_sec - cur_sec: t.CUInt32T = timer.timer_get_seconds() + cur_sec: uint32 = timer.timer_get_seconds() if cur_sec - _hb_last_sec < HB_INTERVAL_SEC: return _hb_last_sec = cur_sec for i in range(_win_count): @@ -2653,7 +2653,7 @@ def _heartbeat_check(): aw.no_resp_sec = cur_sec _update_no_resp_title(i, 1) else: - elapsed: t.CUInt32T = cur_sec - aw.no_resp_sec + elapsed: uint32 = cur_sec - aw.no_resp_sec if elapsed >= HB_NO_RESP_SEC: aw.active = 0 _mark_rows_dirty(aw.y, aw.h) @@ -2668,7 +2668,7 @@ def _heartbeat_check(): evt.win_id = i _push_event(evt) -def flush(win_id: t.CInt): +def flush(win_id: int): if win_id < 0 or win_id >= _win_count: return aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return @@ -2683,7 +2683,7 @@ def flush(win_id: t.CInt): _update_no_resp_title(win_id, 0) _mark_rows_dirty(aw.y + _get_title_height(aw.style) + 1, _eff_h(aw)) -def set_title(win_id: t.CInt, title: t.CConst | t.CChar | t.CPtr) -> t.CInt: +def set_title(win_id: int, title: t.CConst | t.CChar | t.CPtr) -> int: if win_id < 0 or win_id >= _win_count: return -1 aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return -1 @@ -2697,12 +2697,12 @@ def set_title(win_id: t.CInt, title: t.CConst | t.CChar | t.CPtr) -> t.CInt: _mark_rows_dirty(aw.y, _get_title_height(aw.style) + 2) return 0 -def set_geometry(win_id: t.CInt, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt) -> t.CInt: +def set_geometry(win_id: int, x: int, y: int, w: int, h: int) -> int: if win_id < 0 or win_id >= _win_count: return -1 aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return -1 - old_y: t.CInt = aw.y - old_h: t.CInt = aw.h + old_y: int = aw.y + old_h: int = aw.h aw.x = x aw.y = y aw.resize_w = w @@ -2712,7 +2712,7 @@ def set_geometry(win_id: t.CInt, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt) -> _mark_rows_dirty(y, h) return 0 -def set_resizable(win_id: t.CInt, rw: t.CInt, rh: t.CInt) -> t.CInt: +def set_resizable(win_id: int, rw: int, rh: int) -> int: if win_id < 0 or win_id >= _win_count: return -1 aw: AppWindow | t.CPtr = c.Addr(_wins[win_id]) if not aw.active: return -1 @@ -2720,7 +2720,7 @@ def set_resizable(win_id: t.CInt, rw: t.CInt, rh: t.CInt) -> t.CInt: aw.resizable_h = rh return 0 -def destroy_by_pid(pid: t.CInt): +def destroy_by_pid(pid: int): global _focused_win, _last_hover_win for i in range(_win_count): if _wins[i].pid == pid and _wins[i].active: diff --git a/VKernel/Kernel/services/keyboard.vp b/VKernel/Kernel/services/keyboard.vp index e7aae90..a5049f5 100644 --- a/VKernel/Kernel/services/keyboard.vp +++ b/VKernel/Kernel/services/keyboard.vp @@ -10,7 +10,7 @@ SERVICE_KEYBOARD: t.CDefine = 1 @t.Object class KeyboardService: th: sched.Thread | t.CPtr - running: t.CInt + running: int usb_kbd_th: sched.Thread | t.CPtr def __init__(self): @@ -21,16 +21,16 @@ class KeyboardService: kbd_svc: KeyboardService -def kbd_thread(arg: t.CVoid | t.CPtr) -> t.CInt: +def kbd_thread(arg: t.CPtr) -> int: serial.puts("[kbd_svc] started\n") while True: if keyboard.has_data(): - sc: t.CUInt8T = keyboard.read_scancode() + sc: uint8 = keyboard.read_scancode() else: sched.Scheduler._yield() return 0 -def usb_kbd_thread(arg: t.CVoid | t.CPtr) -> t.CInt: +def usb_kbd_thread(arg: t.CPtr) -> int: serial.puts("[usb_kbd_svc] started\n") evt: usb_kbd.usb_kbd_event while True: @@ -40,7 +40,7 @@ def usb_kbd_thread(arg: t.CVoid | t.CPtr) -> t.CInt: sched.Scheduler._yield() return 0 -def start() -> t.CInt: +def start() -> int: global kbd_svc kbd_svc = KeyboardService() keyboard.init() diff --git a/VKernel/Kernel/services/mouse.vp b/VKernel/Kernel/services/mouse.vp index 53e07f8..4f68a64 100644 --- a/VKernel/Kernel/services/mouse.vp +++ b/VKernel/Kernel/services/mouse.vp @@ -1,13 +1,13 @@ -import t, c -import drivers.input.mouse.mouse as mouse -import drivers.usb.hid.usb_mouse as usb_mouse -import drivers.serial.uart.serial as serial -import sched.sched as sched - -SERVICE_MOUSE: t.CDefine = 2 - -def start() -> t.CInt: - serial.puts("[mse_svc] mouse initialized\n") - if usb_mouse.init() == 0: - serial.puts("[mse_svc] usb mouse initialized\n") - return 0 +import t, c +import drivers.input.mouse.mouse as mouse +import drivers.usb.hid.usb_mouse as usb_mouse +import drivers.serial.uart.serial as serial +import sched.sched as sched + +SERVICE_MOUSE: t.CDefine = 2 + +def start() -> int: + serial.puts("[mse_svc] mouse initialized\n") + if usb_mouse.init() == 0: + serial.puts("[mse_svc] usb mouse initialized\n") + return 0 diff --git a/vpsdk/dynlib.vp b/vpsdk/dynlib.vp index 0dce7dd..eef32f1 100644 --- a/vpsdk/dynlib.vp +++ b/vpsdk/dynlib.vp @@ -1,8 +1,8 @@ -import t, c -from . import syscall as syscall - -def load_so(path: t.CConst | t.CChar | t.CPtr) -> t.CUInt64T: - return syscall._syscall1(t.CUInt64T(syscall.LOAD_SO), t.CUInt64T(path)) - -def so_call1(sym_name: t.CConst | t.CChar | t.CPtr, arg1: t.CVoid | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.SO_CALL1), t.CUInt64T(sym_name), t.CUInt64T(arg1))) +import t, c +from . import syscall as syscall + +def load_so(path: t.CConst | t.CChar | t.CPtr) -> uint64: + return syscall._syscall1(uint64(syscall.LOAD_SO), uint64(path)) + +def so_call1(sym_name: t.CConst | t.CChar | t.CPtr, arg1: t.CPtr) -> int: + return int(syscall._syscall2(uint64(syscall.SO_CALL1), uint64(sym_name), uint64(arg1))) diff --git a/vpsdk/fs.vp b/vpsdk/fs.vp index 3ad03bd..9d55634 100644 --- a/vpsdk/fs.vp +++ b/vpsdk/fs.vp @@ -16,126 +16,126 @@ DT_UNKNOWN: t.CDefine = 0 DT_FILE: t.CDefine = 1 DT_DIR: t.CDefine = 2 -def open(path: t.CConst | t.CChar | t.CPtr, flags: t.CUInt32T) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.OPEN), t.CUInt64T(path), t.CUInt64T(flags), 0)) +def open(path: t.CConst | t.CChar | t.CPtr, flags: uint32) -> int: + return int(syscall._syscall3(uint64(syscall.OPEN), uint64(path), uint64(flags), 0)) -def close(fd: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall1(t.CUInt64T(syscall.CLOSE), t.CUInt64T(fd))) +def close(fd: int) -> int: + return int(syscall._syscall1(uint64(syscall.CLOSE), uint64(fd))) -def read(fd: t.CInt, buf: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.READ), t.CUInt64T(fd), t.CUInt64T(buf), t.CUInt64T(count))) +def read(fd: int, buf: t.CPtr, count: uint32) -> int: + return int(syscall._syscall3(uint64(syscall.READ), uint64(fd), uint64(buf), uint64(count))) -def write(fd: t.CInt, buf: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.WRITE), t.CUInt64T(fd), t.CUInt64T(buf), t.CUInt64T(count))) +def write(fd: int, buf: t.CPtr, count: uint32) -> int: + return int(syscall._syscall3(uint64(syscall.WRITE), uint64(fd), uint64(buf), uint64(count))) -def seek(fd: t.CInt, offset: t.CUInt32T) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.SEEK), t.CUInt64T(fd), t.CUInt64T(offset), 0)) +def seek(fd: int, offset: uint32) -> int: + return int(syscall._syscall3(uint64(syscall.SEEK), uint64(fd), uint64(offset), 0)) -def tell(fd: t.CInt) -> t.CUInt32T: - return t.CUInt32T(syscall._syscall1(t.CUInt64T(syscall.TELL), t.CUInt64T(fd))) +def tell(fd: int) -> uint32: + return uint32(syscall._syscall1(uint64(syscall.TELL), uint64(fd))) -def fsize(fd: t.CInt) -> t.CUInt32T: - return t.CUInt32T(syscall._syscall1(t.CUInt64T(syscall.SIZE), t.CUInt64T(fd))) +def fsize(fd: int) -> uint32: + return uint32(syscall._syscall1(uint64(syscall.SIZE), uint64(fd))) -def mkdir(path: t.CConst | t.CChar | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.MKDIR), t.CUInt64T(path), 0, 0)) +def mkdir(path: t.CConst | t.CChar | t.CPtr) -> int: + return int(syscall._syscall3(uint64(syscall.MKDIR), uint64(path), 0, 0)) -def remove(path: t.CConst | t.CChar | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.REMOVE), t.CUInt64T(path), 0, 0)) +def remove(path: t.CConst | t.CChar | t.CPtr) -> int: + return int(syscall._syscall3(uint64(syscall.REMOVE), uint64(path), 0, 0)) -def opendir(path: t.CConst | t.CChar | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.OPENDIR), t.CUInt64T(path), 0, 0)) +def opendir(path: t.CConst | t.CChar | t.CPtr) -> int: + return int(syscall._syscall3(uint64(syscall.OPENDIR), uint64(path), 0, 0)) -def readdir(dd: t.CInt, info: t.CVoid | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.READDIR), t.CUInt64T(dd), t.CUInt64T(info), 0)) +def readdir(dd: int, info: t.CPtr) -> int: + return int(syscall._syscall3(uint64(syscall.READDIR), uint64(dd), uint64(info), 0)) -def closedir(dd: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall1(t.CUInt64T(syscall.CLOSEDIR), t.CUInt64T(dd))) +def closedir(dd: int) -> int: + return int(syscall._syscall1(uint64(syscall.CLOSEDIR), uint64(dd))) -def stat(path: t.CConst | t.CChar | t.CPtr, info: t.CVoid | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.STAT), t.CUInt64T(path), t.CUInt64T(info), 0)) +def stat(path: t.CConst | t.CChar | t.CPtr, info: t.CPtr) -> int: + return int(syscall._syscall3(uint64(syscall.STAT), uint64(path), uint64(info), 0)) @t.Object class FileIO: - _fd: t.CInt - _pos: t.CUInt32T - _size: t.CUInt32T - _flags: t.CUInt32T - _closed: t.CInt + _fd: int + _pos: uint32 + _size: uint32 + _flags: uint32 + _closed: int - def __init__(self, fd: t.CInt, flags: t.CUInt32T): + def __init__(self, fd: int, flags: uint32): self._fd = fd self._flags = flags self._pos = 0 self._size = fsize(fd) self._closed = 0 - def read(self, buf: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: + def read(self, buf: t.CPtr, count: uint32) -> int: if self._closed: return -1 - n: t.CInt = read(self._fd, buf, count) + n: int = read(self._fd, buf, count) if n > 0: - self._pos = self._pos + t.CUInt32T(n) + self._pos = self._pos + uint32(n) return n - def write(self, buf: t.CVoid | t.CPtr, count: t.CUInt32T) -> t.CInt: + def write(self, buf: t.CPtr, count: uint32) -> int: if self._closed: return -1 - n: t.CInt = write(self._fd, buf, count) + n: int = write(self._fd, buf, count) if n > 0: - self._pos = self._pos + t.CUInt32T(n) + self._pos = self._pos + uint32(n) if self._pos > self._size: self._size = self._pos return n - def seek(self, offset: t.CUInt32T) -> t.CInt: + def seek(self, offset: uint32) -> int: if self._closed: return -1 - res: t.CInt = seek(self._fd, offset) + res: int = seek(self._fd, offset) if res == 0: self._pos = offset return res - def tell(self) -> t.CUInt32T: + def tell(self) -> uint32: return self._pos - def size(self) -> t.CUInt32T: + def size(self) -> uint32: return self._size - def close(self) -> t.CInt: + def close(self) -> int: if self._closed: return 0 self._closed = 1 return close(self._fd) - def is_closed(self) -> t.CInt: + def is_closed(self) -> int: return self._closed @t.Object class DirIO: - _dd: t.CInt - _closed: t.CInt + _dd: int + _closed: int - def __init__(self, dd: t.CInt): + def __init__(self, dd: int): self._dd = dd self._closed = 0 - def read(self, info: t.CVoid | t.CPtr) -> t.CInt: + def read(self, info: t.CPtr) -> int: if self._closed: return -1 return readdir(self._dd, info) - def close(self) -> t.CInt: + def close(self) -> int: if self._closed: return 0 self._closed = 1 return closedir(self._dd) - def is_closed(self) -> t.CInt: + def is_closed(self) -> int: return self._closed -def open_file(path: t.CConst | t.CChar | t.CPtr, flags: t.CUInt32T) -> FileIO | t.CPtr: - fd: t.CInt = open(path, flags) +def open_file(path: t.CConst | t.CChar | t.CPtr, flags: uint32) -> FileIO | t.CPtr: + fd: int = open(path, flags) if fd < 0: return None return FileIO(fd, flags) def open_dir(path: t.CConst | t.CChar | t.CPtr) -> DirIO | t.CPtr: - dd: t.CInt = opendir(path) + dd: int = opendir(path) if dd < 0: return None return DirIO(dd) diff --git a/vpsdk/process.vp b/vpsdk/process.vp index 3ac7755..e4cd13a 100644 --- a/vpsdk/process.vp +++ b/vpsdk/process.vp @@ -1,65 +1,65 @@ -import t, c -from . import syscall as syscall - -def exit(code: t.CInt) -> t.CVoid: - syscall._syscall1(t.CUInt64T(syscall.EXIT), t.CUInt64T(code)) - -def yield_cpu() -> t.CVoid: - syscall._syscall2(t.CUInt64T(syscall.WAIT_WINDOW), t.CUInt64T(0), t.CUInt64T(2)) - -def spawn(path: t.CConst | t.CChar | t.CPtr, blocking: t.CInt = 0) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.SPAWN), t.CUInt64T(path), t.CUInt64T(blocking))) - -def thread_create(func: t.CVoid | t.CPtr, arg: t.CVoid | t.CPtr = None) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.THREAD_CREATE), t.CUInt64T(func), t.CUInt64T(arg))) - -@t.Object -class Thread: - _tid: t.CInt - _func: t.CVoid | t.CPtr - _arg: t.CVoid | t.CPtr - _running: t.CInt - - def __init__(self, func: t.CVoid | t.CPtr, arg: t.CVoid | t.CPtr = None): - self._func = func - self._arg = arg - self._tid = -1 - self._running = 0 - - def start(self) -> t.CInt: - if self._running: return -1 - self._tid = thread_create(self._func, self._arg) - if self._tid < 0: return -1 - self._running = 1 - return 0 - - def is_alive(self) -> t.CInt: - return self._running - - def get_tid(self) -> t.CInt: - return self._tid - -@t.Object -class Process: - _pid: t.CInt - _path: t.CArray[t.CChar, 128] - - def __init__(self, path: t.CConst | t.CChar | t.CPtr): - self._pid = -1 - i: t.CInt = 0 - for ch in path: - if i >= 127: break - self._path[i] = ch - i += 1 - self._path[i] = 0 - - def start(self) -> t.CInt: - self._pid = spawn(c.Addr(self._path[0]), 0) - return self._pid - - def start_blocking(self) -> t.CInt: - self._pid = spawn(c.Addr(self._path[0]), 1) - return self._pid - - def get_pid(self) -> t.CInt: - return self._pid +import t, c +from . import syscall as syscall + +def exit(code: int) -> t.CVoid: + syscall._syscall1(uint64(syscall.EXIT), uint64(code)) + +def yield_cpu() -> t.CVoid: + syscall._syscall2(uint64(syscall.WAIT_WINDOW), uint64(0), uint64(2)) + +def spawn(path: t.CConst | t.CChar | t.CPtr, blocking: int = 0) -> int: + return int(syscall._syscall2(uint64(syscall.SPAWN), uint64(path), uint64(blocking))) + +def thread_create(func: t.CPtr, arg: t.CPtr = None) -> int: + return int(syscall._syscall2(uint64(syscall.THREAD_CREATE), uint64(func), uint64(arg))) + +@t.Object +class Thread: + _tid: int + _func: t.CPtr + _arg: t.CPtr + _running: int + + def __init__(self, func: t.CPtr, arg: t.CPtr = None): + self._func = func + self._arg = arg + self._tid = -1 + self._running = 0 + + def start(self) -> int: + if self._running: return -1 + self._tid = thread_create(self._func, self._arg) + if self._tid < 0: return -1 + self._running = 1 + return 0 + + def is_alive(self) -> int: + return self._running + + def get_tid(self) -> int: + return self._tid + +@t.Object +class Process: + _pid: int + _path: t.CArray[t.CChar, 128] + + def __init__(self, path: t.CConst | t.CChar | t.CPtr): + self._pid = -1 + i: int = 0 + for ch in path: + if i >= 127: break + self._path[i] = ch + i += 1 + self._path[i] = 0 + + def start(self) -> int: + self._pid = spawn(c.Addr(self._path[0]), 0) + return self._pid + + def start_blocking(self) -> int: + self._pid = spawn(c.Addr(self._path[0]), 1) + return self._pid + + def get_pid(self) -> int: + return self._pid diff --git a/vpsdk/stdio.vp b/vpsdk/stdio.vp index 15adfed..a36026d 100644 --- a/vpsdk/stdio.vp +++ b/vpsdk/stdio.vp @@ -1,33 +1,33 @@ -import vpsdk.syscall as _syscall -import t, c -import viperlib - -# ============================================================ -# vpsdk.stdio - 用户态 printf/exit(CExport 裸名,供内核侧代码 -# 如 includes/memhub.vp 跨模块引用解析) -# -# 裸机 App 无 libc:printf 走 viperlib.vsnprintf 格式化 + SERIAL_PUTS -# syscall 输出到串口;exit 走 EXIT syscall 通知内核销毁本进程窗口。 -# ============================================================ - -def printf(fmt: t.CConst | str, *args) -> t.CInt | t.CExport: - """格式化输出到串口(SERIAL_PUTS syscall),返回输出字节数""" - if fmt is None: - return 0 - buf: t.CArray[t.CChar, 1024] - n: t.CInt = viperlib.vsnprintf(c.Addr(buf), 1024, fmt, args) - _syscall._syscall1(t.CUInt64T(_syscall.SERIAL_PUTS), t.CUInt64T(c.Addr(buf))) - return n - -def exit(status: t.CInt) -> t.CVoid | t.CExport: - """终止当前进程(EXIT syscall:销毁本进程窗口)""" - _syscall._syscall1(t.CUInt64T(_syscall.EXIT), t.CUInt64T(status)) - - -def fflush(stream: t.CConst | t.CVoid | t.CPtr) -> t.CInt | t.CExport: - """刷新输出流:串口/控制台输出都是直写,无缓冲可刷,空操作返回 0 - - 覆盖 libc fflush 的裸机缺失(includes/memhub.vp 的诊断/终止路径 call @fflush); - 与 printf/exit 同为 CExport 裸名,供内核侧 includes 跨模块引用解析。 - """ - return 0 +import vpsdk.syscall as _syscall +import t, c +import viperlib + +# ============================================================ +# vpsdk.stdio - 用户态 printf/exit(CExport 裸名,供内核侧代码 +# 如 includes/memhub.vp 跨模块引用解析) +# +# 裸机 App 无 libc:printf 走 viperlib.vsnprintf 格式化 + SERIAL_PUTS +# syscall 输出到串口;exit 走 EXIT syscall 通知内核销毁本进程窗口。 +# ============================================================ + +def printf(fmt: t.CConst | str, *args) -> int | t.CExport: + """格式化输出到串口(SERIAL_PUTS syscall),返回输出字节数""" + if fmt is None: + return 0 + buf: t.CArray[t.CChar, 1024] + n: int = viperlib.vsnprintf(c.Addr(buf), 1024, fmt, args) + _syscall._syscall1(uint64(_syscall.SERIAL_PUTS), uint64(c.Addr(buf))) + return n + +def exit(status: int) -> t.CVoid | t.CExport: + """终止当前进程(EXIT syscall:销毁本进程窗口)""" + _syscall._syscall1(uint64(_syscall.EXIT), uint64(status)) + + +def fflush(stream: t.CConst | t.CPtr) -> int | t.CExport: + """刷新输出流:串口/控制台输出都是直写,无缓冲可刷,空操作返回 0 + + 覆盖 libc fflush 的裸机缺失(includes/memhub.vp 的诊断/终止路径 call @fflush); + 与 printf/exit 同为 CExport 裸名,供内核侧 includes 跨模块引用解析。 + """ + return 0 diff --git a/vpsdk/stdlib.vp b/vpsdk/stdlib.vp index 397df55..6118d55 100644 --- a/vpsdk/stdlib.vp +++ b/vpsdk/stdlib.vp @@ -1,59 +1,59 @@ -import vpsdk.syscall as _sc -import string -import t, c - -HEAP_BLOCK_MAGIC: t.CDefine = 0x48454150 - -@t.Object -class _heap_hdr: - magic: t.CUInt32T - size: t.CUInt32T - -_heap_inited: t.CInt = 0 - -def _heap_init(): - global _heap_inited - _heap_inited = 1 - -def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: - global _heap_inited - if size == 0: return None - if _heap_inited == 0: - _heap_init() - hdr_size: t.CSizeT = _heap_hdr.__sizeof__() - total: t.CSizeT = hdr_size + size - ptr: t.CUInt64T = _sc._syscall1(t.CUInt64T(_sc.SYSCALL_MMAP), t.CUInt64T(total)) - if ptr == 0: return None - hdr: _heap_hdr | t.CPtr = t.CVoid(ptr, t.CPtr) - hdr.magic = HEAP_BLOCK_MAGIC - hdr.size = t.CUInt32T(size) - return t.CVoid(ptr + hdr_size, t.CPtr) - -def free(ptr: t.CVoid | t.CPtr) -> t.CExport: - if ptr is None: return - hdr_size: t.CSizeT = _heap_hdr.__sizeof__() - hdr: _heap_hdr | t.CPtr = t.CVoid(t.CUInt64T(ptr) - hdr_size, t.CPtr) - if hdr.magic != HEAP_BLOCK_MAGIC: return - -def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: - total: t.CSizeT = nmemb * size - p: t.CVoid | t.CPtr = malloc(total) - if p: - string.memset(p, 0, total) - return p - -def realloc(ptr: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: - if ptr is None: return malloc(size) - if size == 0: - free(ptr) - return None - hdr_size: t.CSizeT = _heap_hdr.__sizeof__() - hdr: _heap_hdr | t.CPtr = t.CVoid(t.CUInt64T(ptr) - hdr_size, t.CPtr) - if hdr.magic != HEAP_BLOCK_MAGIC: return None - old_size: t.CSizeT = hdr.size - new_ptr: t.CVoid | t.CPtr = malloc(size) - if new_ptr is None: return None - copy_size: t.CSizeT = old_size if old_size < size else size - string.memcpy(new_ptr, ptr, copy_size) - free(ptr) - return new_ptr +import vpsdk.syscall as _sc +import string +import t, c + +HEAP_BLOCK_MAGIC: t.CDefine = 0x48454150 + +@t.Object +class _heap_hdr: + magic: uint32 + size: uint32 + +_heap_inited: int = 0 + +def _heap_init(): + global _heap_inited + _heap_inited = 1 + +def malloc(size: t.CSizeT) -> t.CPtr | t.CExport: + global _heap_inited + if size == 0: return None + if _heap_inited == 0: + _heap_init() + hdr_size: t.CSizeT = _heap_hdr.__sizeof__() + total: t.CSizeT = hdr_size + size + ptr: uint64 = _sc._syscall1(uint64(_sc.SYSCALL_MMAP), uint64(total)) + if ptr == 0: return None + hdr: _heap_hdr | t.CPtr = t.CVoid(ptr, t.CPtr) + hdr.magic = HEAP_BLOCK_MAGIC + hdr.size = uint32(size) + return t.CVoid(ptr + hdr_size, t.CPtr) + +def free(ptr: t.CPtr) -> t.CExport: + if ptr is None: return + hdr_size: t.CSizeT = _heap_hdr.__sizeof__() + hdr: _heap_hdr | t.CPtr = t.CVoid(uint64(ptr) - hdr_size, t.CPtr) + if hdr.magic != HEAP_BLOCK_MAGIC: return + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CPtr | t.CExport: + total: t.CSizeT = nmemb * size + p: t.CPtr = malloc(total) + if p: + string.memset(p, 0, total) + return p + +def realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr | t.CExport: + if ptr is None: return malloc(size) + if size == 0: + free(ptr) + return None + hdr_size: t.CSizeT = _heap_hdr.__sizeof__() + hdr: _heap_hdr | t.CPtr = t.CVoid(uint64(ptr) - hdr_size, t.CPtr) + if hdr.magic != HEAP_BLOCK_MAGIC: return None + old_size: t.CSizeT = hdr.size + new_ptr: t.CPtr = malloc(size) + if new_ptr is None: return None + copy_size: t.CSizeT = old_size if old_size < size else size + string.memcpy(new_ptr, ptr, copy_size) + free(ptr) + return new_ptr diff --git a/vpsdk/syscall.vp b/vpsdk/syscall.vp index af129d6..85db03f 100644 --- a/vpsdk/syscall.vp +++ b/vpsdk/syscall.vp @@ -1,117 +1,117 @@ -import t, c - -CREATE_WINDOW: t.CDefine = 1 -DRAW_TEXT: t.CDefine = 2 -EXIT: t.CDefine = 3 -OPEN: t.CDefine = 4 -CLOSE: t.CDefine = 5 -READ: t.CDefine = 6 -WRITE: t.CDefine = 7 -SEEK: t.CDefine = 8 -TELL: t.CDefine = 9 -SIZE: t.CDefine = 10 -MKDIR: t.CDefine = 11 -REMOVE: t.CDefine = 12 -OPENDIR: t.CDefine = 13 -READDIR: t.CDefine = 14 -CLOSEDIR: t.CDefine = 15 -STAT: t.CDefine = 16 -WAIT_WINDOW: t.CDefine = 17 -SERIAL_PUTS: t.CDefine = 18 -LOAD_SO: t.CDefine = 19 -SO_CALL1: t.CDefine = 20 -GET_WINBUF: t.CDefine = 21 -WIN_FLUSH: t.CDefine = 22 -POLL_EVENT: t.CDefine = 23 -SET_CURSOR: t.CDefine = 24 - -YIELD: t.CDefine = 25 -SET_TITLE: t.CDefine = 26 -SET_GEOMETRY: t.CDefine = 27 -SPAWN: t.CDefine = 28 -MMAP: t.CDefine = 29 -MUNMAP: t.CDefine = 30 -SET_RESIZABLE: t.CDefine = 31 -GET_WIN_SIZE: t.CDefine = 32 -THREAD_CREATE: t.CDefine = 33 - -# SYSCALL_* 别名(vpsdk.stdlib 等模块引用;数值与内核 VKernel/intr/syscall.vp 一致) -SYSCALL_MMAP: t.CDefine = 29 - -def _syscall0(num: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11]) - return ret - -def _syscall1(num: t.CUInt64T, a1: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} - mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI]) - return ret - -def _syscall2(num: t.CUInt64T, a1: t.CUInt64T, a2: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} - mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} - mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_RSI]) - return ret - -def _syscall3(num: t.CUInt64T, a1: t.CUInt64T, a2: t.CUInt64T, a3: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} - mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} - mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} - mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX]) - return ret - -def _syscall5(num: t.CUInt64T, a1: t.CUInt64T, a2: t.CUInt64T, a3: t.CUInt64T, a4: t.CUInt64T, a5: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} - mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} - mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} - mov r10, {c.AsmInp(a4, t.ASM_DESCR.REG_ANY)} - mov r8, {c.AsmInp(a5, t.ASM_DESCR.REG_ANY)} - mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R8]) - return ret - -def _syscall6(num: t.CUInt64T, a1: t.CUInt64T, a2: t.CUInt64T, a3: t.CUInt64T, a4: t.CUInt64T, a5: t.CUInt64T, a6: t.CUInt64T) -> t.CUInt64T: - ret: t.CUInt64T - c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} - mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} - mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} - mov r10, {c.AsmInp(a4, t.ASM_DESCR.REG_ANY)} - mov r8, {c.AsmInp(a5, t.ASM_DESCR.REG_ANY)} - mov r9, {c.AsmInp(a6, t.ASM_DESCR.REG_ANY)} - mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} - syscall""", - out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], - op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R8, - t.ASM_DESCR.CLOBBER_R9]) - return ret +import t, c + +CREATE_WINDOW: t.CDefine = 1 +DRAW_TEXT: t.CDefine = 2 +EXIT: t.CDefine = 3 +OPEN: t.CDefine = 4 +CLOSE: t.CDefine = 5 +READ: t.CDefine = 6 +WRITE: t.CDefine = 7 +SEEK: t.CDefine = 8 +TELL: t.CDefine = 9 +SIZE: t.CDefine = 10 +MKDIR: t.CDefine = 11 +REMOVE: t.CDefine = 12 +OPENDIR: t.CDefine = 13 +READDIR: t.CDefine = 14 +CLOSEDIR: t.CDefine = 15 +STAT: t.CDefine = 16 +WAIT_WINDOW: t.CDefine = 17 +SERIAL_PUTS: t.CDefine = 18 +LOAD_SO: t.CDefine = 19 +SO_CALL1: t.CDefine = 20 +GET_WINBUF: t.CDefine = 21 +WIN_FLUSH: t.CDefine = 22 +POLL_EVENT: t.CDefine = 23 +SET_CURSOR: t.CDefine = 24 + +YIELD: t.CDefine = 25 +SET_TITLE: t.CDefine = 26 +SET_GEOMETRY: t.CDefine = 27 +SPAWN: t.CDefine = 28 +MMAP: t.CDefine = 29 +MUNMAP: t.CDefine = 30 +SET_RESIZABLE: t.CDefine = 31 +GET_WIN_SIZE: t.CDefine = 32 +THREAD_CREATE: t.CDefine = 33 + +# SYSCALL_* 别名(vpsdk.stdlib 等模块引用;数值与内核 VKernel/intr/syscall.vp 一致) +SYSCALL_MMAP: t.CDefine = 29 + +def _syscall0(num: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11]) + return ret + +def _syscall1(num: uint64, a1: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} + mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI]) + return ret + +def _syscall2(num: uint64, a1: uint64, a2: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} + mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} + mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_RSI]) + return ret + +def _syscall3(num: uint64, a1: uint64, a2: uint64, a3: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} + mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} + mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} + mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX]) + return ret + +def _syscall5(num: uint64, a1: uint64, a2: uint64, a3: uint64, a4: uint64, a5: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} + mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} + mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} + mov r10, {c.AsmInp(a4, t.ASM_DESCR.REG_ANY)} + mov r8, {c.AsmInp(a5, t.ASM_DESCR.REG_ANY)} + mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R8]) + return ret + +def _syscall6(num: uint64, a1: uint64, a2: uint64, a3: uint64, a4: uint64, a5: uint64, a6: uint64) -> uint64: + ret: uint64 + c.Asm(f"""mov rdi, {c.AsmInp(a1, t.ASM_DESCR.REG_ANY)} + mov rsi, {c.AsmInp(a2, t.ASM_DESCR.REG_ANY)} + mov rdx, {c.AsmInp(a3, t.ASM_DESCR.REG_ANY)} + mov r10, {c.AsmInp(a4, t.ASM_DESCR.REG_ANY)} + mov r8, {c.AsmInp(a5, t.ASM_DESCR.REG_ANY)} + mov r9, {c.AsmInp(a6, t.ASM_DESCR.REG_ANY)} + mov rax, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} + syscall""", + out=[c.AsmOut(ret, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDX, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R8, + t.ASM_DESCR.CLOBBER_R9]) + return ret diff --git a/vpsdk/vpui.vp b/vpsdk/vpui.vp index 998c844..f315790 100644 --- a/vpsdk/vpui.vp +++ b/vpsdk/vpui.vp @@ -1,1557 +1,1557 @@ -import vpsdk.window as window -import vpsdk.process as process -import vpsdk.syscall as _syscall -from stdint import * -import t, c -import string - -TITLE_H: t.CDefine = 32 -MAX_WIDGETS: t.CDefine = 24 -CHAR_W: t.CDefine = 8 -CHAR_H: t.CDefine = 16 - -WIDGET_LABEL: t.CDefine = 1 -WIDGET_BUTTON: t.CDefine = 2 -WIDGET_ENTRY: t.CDefine = 3 -WIDGET_TEXT: t.CDefine = 4 -WIDGET_SCROLLBAR: t.CDefine = 5 -WIDGET_FBCANVAS: t.CDefine = 6 - -VERTICAL: t.CDefine = 1 -HORIZONTAL: t.CDefine = 2 -TEXT_MAX_LINES: t.CDefine = 200 - -PACK_TOP: t.CDefine = 1 -PACK_BOTTOM: t.CDefine = 2 -PACK_LEFT: t.CDefine = 3 -PACK_RIGHT: t.CDefine = 4 - -FILL_NONE: t.CDefine = 0 -FILL_X: t.CDefine = 1 -FILL_Y: t.CDefine = 2 -FILL_BOTH: t.CDefine = 3 - -STICKY_NONE: t.CDefine = 0 -STICKY_W: t.CDefine = 1 -STICKY_E: t.CDefine = 2 -STICKY_N: t.CDefine = 4 -STICKY_S: t.CDefine = 8 -STICKY_NSEW: t.CDefine = 15 - -_g_wl_type: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_side: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_fill: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_expand: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_padx: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_pady: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_row: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_col: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_rowspan: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_colspan: t.CArray[t.CInt, MAX_WIDGETS] -_g_wl_sticky: t.CArray[t.CInt, MAX_WIDGETS] -_g_layout_init: t.CInt - -_hex_tbl: t.CArray[t.CChar, 17] = "0123456789ABCDEF" -_hex_buf: t.CArray[t.CChar, 20] = "0000000000000000000" - -def _serial_puts(s: t.CConst | t.CChar | t.CPtr) -> t.CVoid: - _syscall._syscall1(t.CUInt64T(_syscall.SERIAL_PUTS), t.CUInt64T(s)) - -def _ptr_to_hex(val: t.CUInt64T, buf: t.CVoid | t.CPtr) -> t.CVoid: - buf[0] = 48 - buf[1] = 120 - i: t.CInt = 15 - while i >= 0: - nibble: t.CInt = t.CInt(val & t.CUInt64T(0xF)) - buf[2 + i] = _hex_tbl[nibble] - val = val >> 4 - i -= 1 - buf[18] = 0 - -def _fill_rect(fb: UINT32PTR, fw: t.CInt, fh: t.CInt, x1: t.CInt, y1: t.CInt, w: t.CInt, h: t.CInt, color: t.CUInt32T): - if not fb: return - if x1 < 0: w += x1; x1 = 0 - if y1 < 0: h += y1; y1 = 0 - if w <= 0 or h <= 0: return - for py in range(y1, y1 + h): - if py >= 0 and py < fh: - for px in range(x1, x1 + w): - if px >= 0 and px < fw: - fb[py * fw + px] = color - -def _draw_hline(fb: UINT32PTR, fw: t.CInt, fh: t.CInt, x1: t.CInt, y: t.CInt, w: t.CInt, color: t.CUInt32T): - if not fb: return - if y < 0 or y >= fh: return - for px in range(x1, x1 + w): - if px >= 0 and px < fw: - fb[y * fw + px] = color - -def _draw_vline(fb: UINT32PTR, fw: t.CInt, fh: t.CInt, x: t.CInt, y1: t.CInt, h: t.CInt, color: t.CUInt32T): - if not fb: return - if x < 0 or x >= fw: return - for py in range(y1, y1 + h): - if py >= 0 and py < fh: - fb[py * fw + x] = color - -def _lighten(color: t.CUInt32T, amount: t.CInt) -> t.CUInt32T: - r: t.CInt = t.CInt(color & 0xFF) - g: t.CInt = t.CInt((color >> 8) & 0xFF) - b: t.CInt = t.CInt((color >> 16) & 0xFF) - r = r + ((255 - r) * amount) / 256 - g = g + ((255 - g) * amount) / 256 - b = b + ((255 - b) * amount) / 256 - return t.CUInt32T(r | (g << 8) | (b << 16)) - -def _darken(color: t.CUInt32T, amount: t.CInt) -> t.CUInt32T: - r: t.CInt = t.CInt(color & 0xFF) - g: t.CInt = t.CInt((color >> 8) & 0xFF) - b: t.CInt = t.CInt((color >> 16) & 0xFF) - r = r - (r * amount) / 256 - g = g - (g * amount) / 256 - b = b - (b * amount) / 256 - return t.CUInt32T(r | (g << 8) | (b << 16)) - - -font: t.CArray[t.CArray[t.CUInt8T, 16], 256] = [ - {0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x02,0x56,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x42,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x55,0x55,0x57,0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x54,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x51,0x52,0x72,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x56,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x54,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x50,0x50,0x57,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x51,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x74,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x53,0x54,0x56,0x74,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x15,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x32,0x16,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x20,0x6E,0x22,0x2E,0x28,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x11,0x13,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x35,0x15,0x17,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x14,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x11,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x36,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x34,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x30,0x10,0x17,0x14,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x31,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x14,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x33,0x14,0x16,0x14,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, - {0x6C,0x6C,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x00,0x00,0x00}, - {0x0C,0x0C,0x3E,0x7F,0x68,0x68,0x3E,0x0B,0x0B,0x7F,0x3E,0x18,0x18,0x00,0x00,0x00}, - {0x60,0x60,0x66,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x66,0x06,0x06,0x00,0x00,0x00}, - {0x38,0x6C,0x6C,0x6C,0x6C,0x6C,0x38,0x6C,0x6D,0x66,0x66,0x6F,0x3B,0x00,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x1C,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00}, - {0x38,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x38,0x00,0x00}, - {0x00,0x00,0x18,0x18,0x7E,0x3C,0x3C,0x3C,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x18,0x18,0x18,0x7E,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x6E,0x6E,0x7E,0x76,0x76,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x18,0x38,0x78,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x06,0x0E,0x1C,0x38,0x70,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x06,0x1C,0x1C,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x0C,0x0C,0x1C,0x1C,0x3C,0x2C,0x6C,0x7E,0x7E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x06,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3C,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, - {0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x40,0x60,0x30,0x18,0x0C,0x06,0x06,0x0C,0x18,0x30,0x60,0x40,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x6E,0x6A,0x6A,0x6A,0x6E,0x60,0x60,0x7C,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7C,0x7C,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x78,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0x7C,0x78,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x60,0x6E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x3E,0x3E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x7C,0x38,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x6C,0x6C,0x78,0x78,0x78,0x6C,0x6C,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x76,0x76,0x7E,0x6E,0x6E,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x6A,0x6A,0x6C,0x7E,0x36,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x78,0x3C,0x0E,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, - {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x77,0x77,0x22,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x7E,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x78,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x78,0x00,0x00}, - {0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x0C,0x0C,0x06,0x06,0x03,0x03,0x00,0x00,0x00}, - {0x1E,0x1E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x1E,0x1E,0x00,0x00}, - {0x3C,0x7E,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00}, - {0x30,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x3E,0x06,0x3E,0x7E,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x06,0x06,0x06,0x06,0x3E,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x7E,0x7E,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x1C,0x3E,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x3E,0x3C,0x00}, - {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x18,0x18,0x00,0x00,0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x0C,0x0C,0x00,0x00,0x3C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C,0x78,0x00}, - {0x60,0x60,0x60,0x60,0x66,0x66,0x6C,0x78,0x78,0x6C,0x6C,0x66,0x66,0x00,0x00,0x00}, - {0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x36,0x7F,0x6B,0x6B,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x00}, - {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x07,0x07,0x00}, - {0x00,0x00,0x00,0x00,0x6C,0x7E,0x76,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x62,0x70,0x3C,0x0E,0x46,0x7E,0x3C,0x00,0x00,0x00}, - {0x30,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x7F,0x36,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x7E,0x7C,0x00}, - {0x00,0x00,0x00,0x00,0x7E,0x7E,0x0C,0x0C,0x18,0x30,0x30,0x7E,0x7E,0x00,0x00,0x00}, - {0x0E,0x1E,0x18,0x18,0x18,0x18,0x30,0x30,0x18,0x18,0x18,0x18,0x1E,0x0E,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00}, - {0x70,0x78,0x18,0x18,0x18,0x18,0x0C,0x0C,0x18,0x18,0x18,0x18,0x78,0x70,0x00,0x00}, - {0x31,0x79,0x6B,0x4F,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x13,0x24,0x26,0x24,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -] - -def _draw_char(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, x: t.CInt, y: t.CInt, ch: t.CChar, color: t.CUInt32T): - if not buf: return - if bw <= 0 or bh <= 0: return - ci: t.CUInt8T = t.CUInt8T(ch) - if ci >= 128: ci = 0 - fy: t.CInt = 0 - while fy < CHAR_H: - if y + fy < 0 or y + fy >= bh: - fy += 1 - continue - row: t.CUInt8T = font[ci][fy] - if row == 0: - fy += 1 - continue - fx: t.CInt = 0 - while fx < CHAR_W: - if row & (0x80 >> fx): - px: t.CInt = x + fx - if px >= 0 and px < bw: - buf[(y + fy) * bw + px] = color - fx += 1 - fy += 1 - -def _draw_text(buf: UINT32PTR, bw: t.CInt, bh: t.CInt, x: t.CInt, y: t.CInt, s: t.CConst | str, color: t.CUInt32T): - if not buf: return - if bw <= 0 or bh <= 0: return - cx: t.CInt = x - cy: t.CInt = y - i: t.CInt = 0 - while True: - ch: t.CChar = s[i] - if ch == 0: break - if ch == 10: - cy += 16 - cx = x - else: - _draw_char(buf, bw, bh, cx, cy, ch, color) - cx += 8 - i += 1 - -def _register_widget(master: t.CVoid | t.CPtr, widget: Widget | t.CPtr) -> t.CInt: - tk: Tk | t.CPtr = t.CType(master, Tk, t.CPtr) - idx: t.CInt = tk.widget_count - if idx < MAX_WIDGETS: - tk.widgets[idx] = widget - tk.widget_count = idx + 1 - return idx - -@t.Object -@t.CVTable -class Widget: - x: t.CInt - y: t.CInt - w: t.CInt - h: t.CInt - visible: t.CInt - master: t.CVoid | t.CPtr - widget_type: t.CInt - focused: t.CInt - hovered: t.CInt - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - pass - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - return 0 - - def contains(self, px: t.CInt, py: t.CInt) -> t.CInt: - if px >= self.x and px < self.x + self.w and py >= self.y and py < self.y + self.h: - return 1 - return 0 - - def place(self, x: t.CInt = 0, y: t.CInt = 0, w: t.CInt = 0, h: t.CInt = 0): - self.x = x - self.y = y - if w > 0: - self.w = w - if h > 0: - self.h = h - -@t.Object -@t.CVTable -class Label(Widget): - text: t.CArray[t.CChar, 64] - color: t.CUInt32T - - def __init__(self, master: t.CVoid | t.CPtr, text: str, color: t.CUInt32T): - self.x = 0 - self.y = 0 - self.w = 0 - self.h = 0 - self.visible = 1 - self.master = master - self.widget_type = WIDGET_LABEL - self.focused = 0 - self.hovered = 0 - self.color = color - i: t.CInt = 0 - for ch in text: - if i >= 63: break - self.text[i] = ch - i += 1 - self.text[i] = 0 - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - _draw_text(fb, fw, fh, self.x, self.y, c.Addr(self.text[0]), self.color) - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - return 0 - - def config(self, text: t.CConst | t.CChar | t.CPtr = None, color: t.CUInt32T = None): - if text is not None: - i: t.CInt = 0 - while i < 63: - ch: t.CChar = c.Deref(text + i) - self.text[i] = ch - if ch == 0: break - i += 1 - self.text[i] = 0 - if color is not None: - self.color = color - -@t.Object -@t.CVTable -class Button(Widget): - text: t.CArray[t.CChar, 32] - fill_color: t.CUInt32T - text_color: t.CUInt32T - pressed: t.CInt - callback: t.CVoid | t.CPtr - - def __init__(self, master: t.CVoid | t.CPtr, w: t.CInt, h: t.CInt, text: str, callback: t.CVoid | t.CPtr): - self.x = 0 - self.y = 0 - self.w = w - self.h = h - self.visible = 1 - self.master = master - self.widget_type = WIDGET_BUTTON - self.focused = 0 - self.hovered = 0 - self.fill_color = t.CUInt32T(0x3C3C5A) - self.text_color = t.CUInt32T(0xFFFFFFFF) - self.pressed = 0 - self.callback = callback - i: t.CInt = 0 - for ch in text: - if i >= 31: break - self.text[i] = ch - i += 1 - self.text[i] = 0 - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - fill: t.CUInt32T = self.fill_color - border: t.CUInt32T = t.CUInt32T(0x8080B0) - if self.pressed: - fill = _lighten(self.fill_color, 60) - border = t.CUInt32T(0xA0A0D0) - elif self.hovered: - fill = _lighten(self.fill_color, 30) - border = t.CUInt32T(0xA0A0D0) - _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, fill) - top_left: t.CUInt32T = _lighten(fill, 80) - bottom_right: t.CUInt32T = _darken(fill, 80) - if self.pressed: - top_left = _darken(fill, 60) - bottom_right = _lighten(fill, 40) - _draw_hline(fb, fw, fh, self.x, self.y, self.w, top_left) - _draw_hline(fb, fw, fh, self.x, self.y + 1, self.w, top_left) - _draw_vline(fb, fw, fh, self.x, self.y, self.h, top_left) - _draw_vline(fb, fw, fh, self.x + 1, self.y, self.h, top_left) - _draw_hline(fb, fw, fh, self.x, self.y + self.h - 1, self.w, bottom_right) - _draw_hline(fb, fw, fh, self.x, self.y + self.h - 2, self.w, bottom_right) - _draw_vline(fb, fw, fh, self.x + self.w - 1, self.y, self.h, bottom_right) - _draw_vline(fb, fw, fh, self.x + self.w - 2, self.y, self.h, bottom_right) - _draw_hline(fb, fw, fh, self.x - 1, self.y - 1, self.w + 2, border) - _draw_hline(fb, fw, fh, self.x - 1, self.y + self.h, self.w + 2, border) - _draw_vline(fb, fw, fh, self.x - 1, self.y - 1, self.h + 2, border) - _draw_vline(fb, fw, fh, self.x + self.w, self.y - 1, self.h + 2, border) - tl: t.CInt = string.strlen(c.Addr(self.text[0])) - tx: t.CInt = self.x + (self.w - 8 * tl) / 2 - ty: t.CInt = self.y + (self.h - CHAR_H) / 2 - _draw_text(fb, fw, fh, tx, ty, c.Addr(self.text[0]), self.text_color) - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - etype: t.CUInt32T = evt.type - ex: t.CInt = evt.x - ey: t.CInt = evt.y - if etype == window.EVENT_TYPE_HOVER: - if self.contains(ex, ey): - if not self.hovered: - self.hovered = 1 - return 1 - else: - if self.hovered and not self.pressed: - self.hovered = 0 - return 1 - elif etype == window.EVENT_TYPE_HOVER_LEAVE: - if self.hovered: - self.hovered = 0 - return 1 - elif etype == window.EVENT_TYPE_CLICK: - if self.contains(ex, ey): - self.pressed = 1 - return 1 - elif etype == window.EVENT_TYPE_RELEASE: - if self.pressed: - self.pressed = 0 - if self.contains(ex, ey) and self.callback is not None: - c.Asm(f"""push r12 -push r13 -mov r13, {c.AsmInp(self.callback, t.ASM_DESCR.REG_ANY)} -mov r12, rsp -and rsp, -16 -call r13 -mov rsp, r12 -pop r13 -pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) - return 1 - return 0 - - def config(self, text: t.CConst | t.CChar | t.CPtr = None, fill_color: t.CUInt32T = None, text_color: t.CUInt32T = None, callback: t.CVoid | t.CPtr = None): - if text is not None: - i: t.CInt = 0 - while i < 31: - ch: t.CChar = c.Deref(text + i) - self.text[i] = ch - if ch == 0: break - i += 1 - self.text[i] = 0 - if fill_color is not None: - self.fill_color = fill_color - if text_color is not None: - self.text_color = text_color - if callback is not None: - self.callback = callback - -@t.Object -@t.CVTable -class Entry(Widget): - text: t.CArray[t.CChar, 64] - text_len: t.CInt - cursor_pos: t.CInt - max_len: t.CInt - bg_color: t.CUInt32T - border_color: t.CUInt32T - text_color: t.CUInt32T - cursor_color: t.CUInt32T - - def __init__(self, master: t.CVoid | t.CPtr, w: t.CInt, h: t.CInt): - self.x = 0 - self.y = 0 - self.w = w - self.h = h - self.visible = 1 - self.master = master - self.widget_type = WIDGET_ENTRY - self.focused = 0 - self.hovered = 0 - self.text_len = 0 - self.cursor_pos = 0 - self.max_len = 30 - self.bg_color = t.CUInt32T(0xFF231919) - self.border_color = t.CUInt32T(0x606080) - self.text_color = t.CUInt32T(0x000000) - self.cursor_color = t.CUInt32T(0x000000) - for i in range(64): - self.text[i] = 0 - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - bg: t.CUInt32T = self.bg_color - bdr: t.CUInt32T = self.border_color - if self.focused: - bg = t.CUInt32T(0xFFFFFF) - bdr = t.CUInt32T(0x4488FF) - elif self.hovered: - bdr = t.CUInt32T(0x8080B0) - _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, bg) - _draw_hline(fb, fw, fh, self.x, self.y, self.w, bdr) - _draw_hline(fb, fw, fh, self.x, self.y + self.h - 1, self.w, bdr) - _draw_vline(fb, fw, fh, self.x, self.y, self.h, bdr) - _draw_vline(fb, fw, fh, self.x + self.w - 1, self.y, self.h, bdr) - if self.text_len > 0: - tc: t.CUInt32T = self.text_color - if not self.focused: - tc = t.CUInt32T(0xCCCCCC) - _draw_text(fb, fw, fh, self.x + 6, self.y + 7, c.Addr(self.text[0]), tc) - elif not self.focused: - _draw_text(fb, fw, fh, self.x + 6, self.y + 7, "Type here...", t.CUInt32T(0x888888)) - if self.focused: - cx_pos: t.CInt = self.x + 6 + self.cursor_pos * CHAR_W - if cx_pos < self.x + self.w - 2: - _draw_vline(fb, fw, fh, cx_pos, self.y + 5, self.h - 10, self.cursor_color) - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - etype: t.CUInt32T = evt.type - ex: t.CInt = evt.x - ey: t.CInt = evt.y - if etype == window.EVENT_TYPE_HOVER: - if self.contains(ex, ey): - if not self.hovered: - self.hovered = 1 - tk: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - window.set_cursor_type(tk.win_id, window.CURSOR_IBEAM) - return 1 - else: - if self.hovered: - self.hovered = 0 - tk2: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - window.set_cursor_type(tk2.win_id, window.CURSOR_DEFAULT) - return 1 - elif etype == window.EVENT_TYPE_HOVER_LEAVE: - if self.hovered: - self.hovered = 0 - tk3: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - window.set_cursor_type(tk3.win_id, window.CURSOR_DEFAULT) - return 1 - elif etype == window.EVENT_TYPE_CLICK: - if self.contains(ex, ey): - if not self.focused: - self.focused = 1 - tk4: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - tk4.focused_widget = t.CType(self, Widget, t.CPtr) - rel_x: t.CInt = ex - self.x - 6 - if rel_x < 0: rel_x = 0 - new_pos: t.CInt = (rel_x + CHAR_W / 2) / CHAR_W - if new_pos > self.text_len: new_pos = self.text_len - self.cursor_pos = new_pos - return 1 - else: - if self.focused: - self.focused = 0 - tk5: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - tk5.focused_widget = None - return 1 - elif etype == window.EVENT_TYPE_KEY: - if self.focused: - ebtn: t.CUInt8T = evt.button - if ebtn == window.KEY_STATE_RELEASE: - return 0 - ch: t.CInt = ex - if ch == 8: - if self.cursor_pos > 0: - for i in range(self.cursor_pos, self.text_len): - self.text[i - 1] = self.text[i] - self.text_len -= 1 - self.cursor_pos -= 1 - self.text[self.text_len] = 0 - return 1 - elif ch == window.VK_LEFT: - if self.cursor_pos > 0: - self.cursor_pos -= 1 - return 1 - elif ch == window.VK_RIGHT: - if self.cursor_pos < self.text_len: - self.cursor_pos += 1 - return 1 - elif ch == window.VK_HOME: - self.cursor_pos = 0 - return 1 - elif ch == window.VK_END: - self.cursor_pos = self.text_len - return 1 - elif ch == window.VK_DELETE: - if self.cursor_pos < self.text_len: - for i in range(self.cursor_pos, self.text_len - 1): - self.text[i] = self.text[i + 1] - self.text_len -= 1 - self.text[self.text_len] = 0 - return 1 - elif ch >= 32 and ch < 127: - if self.text_len < self.max_len: - i: t.CInt = self.text_len - while i > self.cursor_pos: - self.text[i] = self.text[i - 1] - i -= 1 - self.text[self.cursor_pos] = t.CChar(ch) - self.text_len += 1 - self.cursor_pos += 1 - self.text[self.text_len] = 0 - return 1 - return 0 - - def get(self) -> t.CConst | t.CChar | t.CPtr: - return c.Addr(self.text[0]) - - def delete(self, start: t.CInt, end: t.CInt): - self.text_len = 0 - for i in range(64): - self.text[i] = 0 - - def config(self, bg_color: t.CUInt32T = None, text_color: t.CUInt32T = None, border_color: t.CUInt32T = None): - if bg_color is not None: - self.bg_color = bg_color - if text_color is not None: - self.text_color = text_color - if border_color is not None: - self.border_color = border_color - -@t.Object -@t.CVTable -class Scrollbar(Widget): - orient: t.CInt - command: t.CVoid | t.CPtr - slider_first: t.CInt - slider_last: t.CInt - action: t.CInt - action_value: t.CInt - pressed: t.CInt - dragging: t.CInt - drag_start_y: t.CInt - drag_start_first: t.CInt - trough_color: t.CUInt32T - slider_color: t.CUInt32T - arrow_color: t.CUInt32T - slider_hover: t.CInt - - def __init__(self, master: t.CVoid | t.CPtr, w: t.CInt, h: t.CInt, orient: t.CInt): - self.x = 0 - self.y = 0 - self.w = w - self.h = h - self.visible = 1 - self.master = master - self.widget_type = WIDGET_SCROLLBAR - self.focused = 0 - self.hovered = 0 - self.orient = orient - self.command = None - self.slider_first = 0 - self.slider_last = 1000 - self.action = 0 - self.action_value = 0 - self.pressed = 0 - self.dragging = 0 - self.drag_start_y = 0 - self.drag_start_first = 0 - self.trough_color = t.CUInt32T(0x1E1E2E) - self.slider_color = t.CUInt32T(0x4A4A6A) - self.arrow_color = t.CUInt32T(0xAAAAAA) - self.slider_hover = 0 - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.trough_color) - if self.orient != VERTICAL: return - arrow_sz: t.CInt = self.w - if arrow_sz > 16: arrow_sz = 16 - self._draw_arrow_btn(fb, fw, fh, self.x, self.y, self.w, arrow_sz, 0, 1 if self.pressed == 1 else 0) - self._draw_arrow_btn(fb, fw, fh, self.x, self.y + self.h - arrow_sz, self.w, arrow_sz, 1, 1 if self.pressed == 2 else 0) - trough_y: t.CInt = self.y + arrow_sz - trough_h: t.CInt = self.h - 2 * arrow_sz - if trough_h <= 0: return - if self.slider_last > self.slider_first: - sl_h: t.CInt = (self.slider_last - self.slider_first) * trough_h / 1000 - if sl_h < 8: sl_h = 8 - sl_y: t.CInt = trough_y + self.slider_first * trough_h / 1000 - if sl_y + sl_h > trough_y + trough_h: - sl_y = trough_y + trough_h - sl_h - if sl_y < trough_y: sl_y = trough_y - color: t.CUInt32T = self.slider_color - if self.dragging: - color = _lighten(self.slider_color, 40) - elif self.slider_hover: - color = _lighten(self.slider_color, 20) - _fill_rect(fb, fw, fh, self.x + 1, sl_y, self.w - 2, sl_h, color) - top_c: t.CUInt32T = _lighten(color, 60) - bot_c: t.CUInt32T = _darken(color, 60) - _draw_hline(fb, fw, fh, self.x + 1, sl_y, self.w - 2, top_c) - _draw_hline(fb, fw, fh, self.x + 1, sl_y + sl_h - 1, self.w - 2, bot_c) - _draw_vline(fb, fw, fh, self.x + 1, sl_y, sl_h, top_c) - _draw_vline(fb, fw, fh, self.x + self.w - 2, sl_y, sl_h, bot_c) - - def _draw_arrow_btn(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt, bx: t.CInt, by: t.CInt, bw: t.CInt, bh: t.CInt, direction: t.CInt, is_pressed: t.CInt): - color: t.CUInt32T = self.slider_color - if is_pressed: - color = _lighten(self.slider_color, 30) - _fill_rect(fb, fw, fh, bx, by, bw, bh, color) - top_c: t.CUInt32T = _lighten(color, 60) - bot_c: t.CUInt32T = _darken(color, 60) - if is_pressed: - top_c = _darken(color, 40) - bot_c = _lighten(color, 30) - _draw_hline(fb, fw, fh, bx, by, bw, top_c) - _draw_hline(fb, fw, fh, bx, by + bh - 1, bw, bot_c) - _draw_vline(fb, fw, fh, bx, by, bh, top_c) - _draw_vline(fb, fw, fh, bx + bw - 1, by, bh, bot_c) - cx: t.CInt = bx + bw / 2 - cy: t.CInt = by + bh / 2 - if direction == 0: - _fill_rect(fb, fw, fh, cx - 1, cy - 3, 3, 1, self.arrow_color) - _fill_rect(fb, fw, fh, cx - 2, cy - 2, 5, 1, self.arrow_color) - _fill_rect(fb, fw, fh, cx - 3, cy - 1, 7, 1, self.arrow_color) - else: - _fill_rect(fb, fw, fh, cx - 3, cy - 1, 7, 1, self.arrow_color) - _fill_rect(fb, fw, fh, cx - 2, cy, 5, 1, self.arrow_color) - _fill_rect(fb, fw, fh, cx - 1, cy + 1, 3, 1, self.arrow_color) - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - etype: t.CUInt32T = evt.type - ex: t.CInt = evt.x - ey: t.CInt = evt.y - if etype == window.EVENT_TYPE_HOVER: - if self.dragging: - self._handle_drag(ey) - return 1 - if self.contains(ex, ey): - if not self.slider_hover: - self.slider_hover = 1 - return 1 - else: - if self.slider_hover and self.pressed == 0: - self.slider_hover = 0 - return 1 - return 0 - elif etype == window.EVENT_TYPE_HOVER_LEAVE: - if self.slider_hover: - self.slider_hover = 0 - if not self.dragging: - self.pressed = 0 - return 1 - return 0 - elif etype == window.EVENT_TYPE_CLICK: - if self.contains(ex, ey): - if self.orient == VERTICAL: - arrow_sz: t.CInt = self.w - if arrow_sz > 16: arrow_sz = 16 - if ey < self.y + arrow_sz: - self.pressed = 1 - self.action = 1 - self._fire_command() - return 1 - elif ey >= self.y + self.h - arrow_sz: - self.pressed = 2 - self.action = 2 - self._fire_command() - return 1 - else: - trough_y: t.CInt = self.y + arrow_sz - trough_h: t.CInt = self.h - 2 * arrow_sz - if trough_h <= 0: return 1 - sl_h: t.CInt = (self.slider_last - self.slider_first) * trough_h / 1000 - if sl_h < 8: sl_h = 8 - sl_y: t.CInt = trough_y + self.slider_first * trough_h / 1000 - if sl_y + sl_h > trough_y + trough_h: - sl_y = trough_y + trough_h - sl_h - if ey >= sl_y and ey < sl_y + sl_h: - self.pressed = 4 - self.dragging = 1 - self.drag_start_y = ey - self.drag_start_first = self.slider_first - else: - self.pressed = 3 - if ey < sl_y: - self.action = 3 - else: - self.action = 4 - self._fire_command() - return 1 - return 0 - elif etype == window.EVENT_TYPE_RELEASE: - if self.pressed: - self.pressed = 0 - self.dragging = 0 - return 1 - return 0 - return 0 - - def _handle_drag(self, ey: t.CInt): - arrow_sz: t.CInt = self.w - if arrow_sz > 16: arrow_sz = 16 - trough_y: t.CInt = self.y + arrow_sz - trough_h: t.CInt = self.h - 2 * arrow_sz - if trough_h <= 0: return - delta_y: t.CInt = ey - self.drag_start_y - delta_first: t.CInt = delta_y * 1000 / trough_h - new_first: t.CInt = self.drag_start_first + delta_first - slider_size: t.CInt = self.slider_last - self.slider_first - if slider_size <= 0: slider_size = 1 - if new_first < 0: new_first = 0 - if new_first + slider_size > 1000: new_first = 1000 - slider_size - if new_first != self.slider_first: - self.slider_first = new_first - self.slider_last = new_first + slider_size - self.action = 5 - self.action_value = new_first - self._fire_command() - - def _fire_command(self): - if self.command is not None: - c.Asm(f"""push r12 -push r13 -mov r13, {c.AsmInp(self.command, t.ASM_DESCR.REG_ANY)} -mov r12, rsp -and rsp, -16 -call r13 -mov rsp, r12 -pop r13 -pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) - - def set(self, first: t.CInt, last: t.CInt): - self.slider_first = first - self.slider_last = last - -@t.Object -@t.CVTable -class FBCanvas(Widget): - _fb: UINT32PTR - _cw: t.CInt - _ch: t.CInt - - def __init__(self, master: t.CVoid | t.CPtr, w: t.CInt, h: t.CInt): - self.x = 0 - self.y = 0 - self.w = w - self.h = h - self.visible = 1 - self.master = master - self.widget_type = WIDGET_FBCANVAS - self.focused = 0 - self.hovered = 0 - self._fb = None - self._cw = w - self._ch = h - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - if not self._fb: return - if self._cw <= 0 or self._ch <= 0: return - copy_w: t.CInt = self._cw - if copy_w > self.w: copy_w = self.w - copy_h: t.CInt = self._ch - if copy_h > self.h: copy_h = self.h - for py in range(copy_h): - ty: t.CInt = self.y + py - if ty < 0 or ty >= fh: continue - for px in range(copy_w): - tx: t.CInt = self.x + px - if tx < 0 or tx >= fw: continue - fb[ty * fw + tx] = self._fb[py * self._cw + px] - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - return 0 - - def set_fb(self, fb: UINT32PTR, cw: t.CInt, ch: t.CInt): - self._fb = fb - self._cw = cw - self._ch = ch - - def get_fb(self) -> UINT32PTR: - return self._fb - - def get_w(self) -> t.CInt: - return self._cw - - def get_h(self) -> t.CInt: - return self._ch - -@t.Object -@t.CVTable -class Text(Widget): - lines: t.CArray[t.CArray[t.CChar, 80], TEXT_MAX_LINES] - line_count: t.CInt - input_buf: t.CArray[t.CChar, 80] - input_len: t.CInt - cursor_pos: t.CInt - bg_color: t.CUInt32T - text_color: t.CUInt32T - prompt_color: t.CUInt32T - cursor_color: t.CUInt32T - border_color: t.CUInt32T - on_command: t.CVoid | t.CPtr - history: t.CArray[t.CArray[t.CChar, 80], 16] - history_count: t.CInt - history_idx: t.CInt - scroll_offset: t.CInt - max_lines: t.CInt - yscrollbar: t.CVoid | t.CPtr - - def __init__(self, master: t.CVoid | t.CPtr, w: t.CInt, h: t.CInt): - self.x = 0 - self.y = 0 - self.w = w - self.h = h - self.visible = 1 - self.master = master - self.widget_type = WIDGET_TEXT - self.focused = 0 - self.hovered = 0 - self.line_count = 0 - self.input_len = 0 - self.cursor_pos = 0 - self.bg_color = t.CUInt32T(0x0C0C0C) - self.text_color = t.CUInt32T(0xCCCCCC) - self.prompt_color = t.CUInt32T(0x00FF00) - self.cursor_color = t.CUInt32T(0x00FF00) - self.border_color = t.CUInt32T(0x333333) - self.on_command = None - self.history_count = 0 - self.history_idx = 0 - self.scroll_offset = 0 - self.max_lines = TEXT_MAX_LINES - self.yscrollbar = None - i: t.CInt = 0 - while i < TEXT_MAX_LINES: - j: t.CInt = 0 - while j <= 79: - self.lines[i][j] = 0 - j += 1 - i += 1 - i = 0 - while i < 80: - self.input_buf[i] = 0 - i += 1 - _register_widget(master, t.CType(self, Widget, t.CPtr)) - - def draw(self, fb: UINT32PTR, fw: t.CInt, fh: t.CInt): - self._update_scrollbar() - _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.bg_color) - _fill_rect(fb, fw, fh, self.x, self.y + self.h - 2, self.w, 2, self.border_color) - visible: t.CInt = self._visible_lines() - for i in range(visible): - line_idx: t.CInt = self.scroll_offset + i - if line_idx < self.line_count: - _draw_text(fb, fw, fh, self.x + 4, self.y + i * CHAR_H, c.Addr(self.lines[line_idx][0]), self.text_color) - prompt_y: t.CInt = self.y + self.h - CHAR_H - 4 - _draw_text(fb, fw, fh, self.x + 4, prompt_y, "> ", self.prompt_color) - if self.input_len > 0: - _draw_text(fb, fw, fh, self.x + 4 + 2 * CHAR_W, prompt_y, c.Addr(self.input_buf[0]), t.CUInt32T(0xFFFFFF)) - cx_pos: t.CInt = self.x + 4 + (2 + self.cursor_pos) * CHAR_W - if cx_pos < self.x + self.w - 4: - _fill_rect(fb, fw, fh, cx_pos, prompt_y, CHAR_W // 2, CHAR_H, self.cursor_color) - - def handle_event(self, evt: window.InputEvent | t.CPtr) -> t.CInt: - etype: t.CUInt32T = evt.type - ex: t.CInt = evt.x - ey: t.CInt = evt.y - if etype == window.EVENT_TYPE_CLICK: - if self.contains(ex, ey): - if not self.focused: - self.focused = 1 - tk: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - tk.focused_widget = t.CType(self, Widget, t.CPtr) - prompt_y: t.CInt = self.y + self.h - CHAR_H - 4 - if ey >= prompt_y and ey < prompt_y + CHAR_H: - rel_x: t.CInt = ex - self.x - 4 - 2 * CHAR_W - if rel_x < 0: rel_x = 0 - new_pos: t.CInt = (rel_x + CHAR_W / 2) / CHAR_W - if new_pos > self.input_len: new_pos = self.input_len - self.cursor_pos = new_pos - return 1 - else: - if self.focused: - self.focused = 0 - tk2: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) - tk2.focused_widget = None - return 1 - elif etype == window.EVENT_TYPE_KEY: - if self.focused: - ebtn2: t.CUInt8T = evt.button - if ebtn2 == window.KEY_STATE_RELEASE: - return 0 - ch: t.CInt = ex - if ch == 8: - if self.cursor_pos > 0: - i: t.CInt = self.cursor_pos - while i < self.input_len: - self.input_buf[i - 1] = self.input_buf[i] - i += 1 - self.input_len -= 1 - self.cursor_pos -= 1 - self.input_buf[self.input_len] = 0 - return 1 - elif ch == 13: - self._exec_input() - self.input_len = 0 - self.cursor_pos = 0 - for i in range(80): - self.input_buf[i] = 0 - return 1 - elif ch == window.VK_LEFT: - if self.cursor_pos > 0: - self.cursor_pos -= 1 - return 1 - elif ch == window.VK_RIGHT: - if self.cursor_pos < self.input_len: - self.cursor_pos += 1 - return 1 - elif ch == window.VK_UP: - if self.history_count > 0: - if self.history_idx < self.history_count: - self.history_idx += 1 - hi: t.CInt = self.history_count - self.history_idx - if hi < 0: hi = 0 - for j in range(80): - self.input_buf[j] = self.history[hi][j] - self.input_len = 0 - while self.input_len < 79 and self.input_buf[self.input_len] != 0: - self.input_len += 1 - self.cursor_pos = self.input_len - return 1 - elif ch == window.VK_DOWN: - if self.history_count > 0: - if self.history_idx > 0: - self.history_idx -= 1 - if self.history_idx == 0: - self.input_len = 0 - self.cursor_pos = 0 - for j2 in range(80): - self.input_buf[j2] = 0 - else: - hi2: t.CInt = self.history_count - self.history_idx - for j3 in range(80): - self.input_buf[j3] = self.history[hi2][j3] - self.input_len = 0 - while self.input_len < 79 and self.input_buf[self.input_len] != 0: - self.input_len += 1 - self.cursor_pos = self.input_len - return 1 - elif ch == window.VK_HOME: - self.cursor_pos = 0 - return 1 - elif ch == window.VK_END: - self.cursor_pos = self.input_len - return 1 - elif ch == window.VK_DELETE: - if self.cursor_pos < self.input_len: - i: t.CInt = self.cursor_pos - while i < self.input_len - 1: - self.input_buf[i] = self.input_buf[i + 1] - i += 1 - self.input_len -= 1 - self.input_buf[self.input_len] = 0 - return 1 - elif ch == window.VK_PRIOR: - if self.scroll_offset > 0: - vis: t.CInt = self._visible_lines() - self.scroll_offset -= vis - if self.scroll_offset < 0: self.scroll_offset = 0 - self._update_scrollbar() - return 1 - elif ch == window.VK_NEXT: - vis2: t.CInt = self._visible_lines() - max_off: t.CInt = self.line_count - vis2 - if max_off < 0: max_off = 0 - if self.scroll_offset < max_off: - self.scroll_offset += vis2 - if self.scroll_offset > max_off: self.scroll_offset = max_off - self._update_scrollbar() - return 1 - elif ch >= 32 and ch < 127: - if self.input_len < 79: - i: t.CInt = self.input_len - while i > self.cursor_pos: - self.input_buf[i] = self.input_buf[i - 1] - i -= 1 - self.input_buf[self.cursor_pos] = t.CChar(ch) - self.input_len += 1 - self.cursor_pos += 1 - self.input_buf[self.input_len] = 0 - return 1 - return 0 - - def _exec_input(self): - self.insert("> ") - if self.input_len > 0: - last: t.CInt = self.line_count - 1 - j: t.CInt = 0 - while j < self.input_len and j < 77: - self.lines[last][2 + j] = self.input_buf[j] - j += 1 - self.lines[last][2 + j] = 0 - if self.history_count < 16: - k: t.CInt = 0 - while k < 80: - self.history[self.history_count][k] = self.input_buf[k] - k += 1 - self.history_count += 1 - else: - i: t.CInt = 0 - while i < 15: - k2: t.CInt = 0 - while k2 < 80: - self.history[i][k2] = self.history[i + 1][k2] - k2 += 1 - i += 1 - k3: t.CInt = 0 - while k3 < 80: - self.history[15][k3] = self.input_buf[k3] - k3 += 1 - self.history_idx = 0 - - cmd: t.CVoid | t.CPtr = self.on_command - if cmd is not None: - c.Asm(f"""push r12 -push r13 -mov r13, {c.AsmInp(cmd, t.ASM_DESCR.REG_ANY)} -mov r12, rsp -and rsp, -16 -call r13 -mov rsp, r12 -pop r13 -pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) - else: - self.insert("(no callback)") - - def insert(self, text: str): - start: t.CInt = 0 - pos: t.CInt = 0 - while True: - ch: t.CChar = c.Deref(text + pos) - if ch == 0: - if pos > start: - self._insert_substring(text, start, pos) - break - if ch == 10: - self._insert_substring(text, start, pos) - start = pos + 1 - pos += 1 - - def insert_ptr(self, text: t.CConst | t.CChar | t.CPtr): - start: t.CInt = 0 - pos: t.CInt = 0 - while True: - ch: t.CChar = c.Deref(text + pos) - if ch == 0: - if pos > start: - self._insert_substring(text, start, pos) - break - if ch == 10: - self._insert_substring(text, start, pos) - start = pos + 1 - pos += 1 - - def _insert_substring(self, text: t.CConst | t.CChar | t.CPtr, start: t.CInt, end: t.CInt): - if self.line_count >= self.max_lines: - i: t.CInt = 0 - while i < self.max_lines - 1: - j: t.CInt = 0 - while j <= 79: - self.lines[i][j] = self.lines[i + 1][j] - j += 1 - i += 1 - self.line_count -= 1 - if self.scroll_offset > 0: - self.scroll_offset -= 1 - idx: t.CInt = self.line_count - j: t.CInt = 0 - k: t.CInt = start - while k < end and j < 79: - ch: t.CChar = c.Deref(text + k) - if ch == 9: - tab_stop: t.CInt = 8 - (j % 8) - while tab_stop > 0 and j < 79: - self.lines[idx][j] = 32 - j += 1 - tab_stop -= 1 - elif ch == 13: - pass - else: - self.lines[idx][j] = ch - j += 1 - k += 1 - self.lines[idx][j] = 0 - self.line_count += 1 - vis: t.CInt = self._visible_lines() - if self.line_count > vis: - self.scroll_offset = self.line_count - vis - else: - self.scroll_offset = 0 - self._update_scrollbar() - - def delete(self, start: t.CInt, end: t.CInt): - self.line_count = 0 - self.scroll_offset = 0 - self._update_scrollbar() - - def get(self) -> t.CConst | t.CChar | t.CPtr: - return c.Addr(self.input_buf[0]) - - def config(self, text_color: t.CUInt32T = None, bg_color: t.CUInt32T = None, prompt_color: t.CUInt32T = None, cursor_color: t.CUInt32T = None, border_color: t.CUInt32T = None): - if text_color is not None: - self.text_color = text_color - if bg_color is not None: - self.bg_color = bg_color - if prompt_color is not None: - self.prompt_color = prompt_color - if cursor_color is not None: - self.cursor_color = cursor_color - if border_color is not None: - self.border_color = border_color - - def _visible_lines(self) -> t.CInt: - return (self.h - CHAR_H - 4) / CHAR_H - - def _update_scrollbar(self): - vis: t.CInt = self._visible_lines() - if self.line_count <= vis: - self.scroll_offset = 0 - else: - max_off: t.CInt = self.line_count - vis - if self.scroll_offset > max_off: - self.scroll_offset = max_off - if self.yscrollbar is not None: - sb: Scrollbar | t.CPtr = t.CType(self.yscrollbar, Scrollbar, t.CPtr) - if self.line_count <= vis: - sb.set(0, 1000) - else: - first: t.CInt = self.scroll_offset * 1000 / self.line_count - last: t.CInt = (self.scroll_offset + vis) * 1000 / self.line_count - sb.set(first, last) - -@t.Object -class Tk: - win_id: t.CInt - buf: UINT32PTR - bw: t.CInt - bh: t.CInt - style: t.CInt - bg_color: t.CUInt32T - widgets: t.CArray[Widget | t.CPtr, MAX_WIDGETS] - widget_count: t.CInt - focused_widget: Widget | t.CPtr - _win_x: t.CInt - _win_y: t.CInt - _title: t.CArray[t.CChar, 32] - resizable_w: t.CInt - resizable_h: t.CInt - _grid_rows: t.CInt - _grid_cols: t.CInt - - def __init__(self): - global _g_layout_init - self.widget_count = 0 - self.focused_widget = None - self.win_id = -1 - self._win_x = 0 - self._win_y = 0 - self.style = 0 - self.bg_color = t.CUInt32T(0xFF231919) - self.resizable_w = 1 - self.resizable_h = 1 - self._grid_rows = 0 - self._grid_cols = 0 - if _g_layout_init == 0: - i: t.CInt = 0 - while i < MAX_WIDGETS: - _g_wl_type[i] = 0 - _g_wl_side[i] = 0 - _g_wl_fill[i] = 0 - _g_wl_expand[i] = 0 - _g_wl_padx[i] = 0 - _g_wl_pady[i] = 0 - _g_wl_row[i] = 0 - _g_wl_col[i] = 0 - _g_wl_rowspan[i] = 0 - _g_wl_colspan[i] = 1 - _g_wl_sticky[i] = 0 - i += 1 - _g_layout_init = 1 - j: t.CInt = 0 - while j < 32: - self._title[j] = 0 - j += 1 - - def pack(self, idx: t.CInt, side: t.CInt, fill: t.CInt, expand: t.CInt, padx: t.CInt, pady: t.CInt): - _g_wl_type[idx] = 2 - _g_wl_side[idx] = side - _g_wl_fill[idx] = fill - _g_wl_expand[idx] = expand - _g_wl_padx[idx] = padx - _g_wl_pady[idx] = pady - - def grid(self, idx: t.CInt, row: t.CInt, col: t.CInt, rowspan: t.CInt, colspan: t.CInt, sticky: t.CInt): - _g_wl_type[idx] = 3 - _g_wl_row[idx] = row - _g_wl_col[idx] = col - _g_wl_rowspan[idx] = rowspan - _g_wl_colspan[idx] = colspan - _g_wl_sticky[idx] = sticky - - def title(self, text: str): - i: t.CInt = 0 - while i < 31: - ch: t.CChar = text[i] - if ch == 0: break - self._title[i] = ch - i += 1 - self._title[i] = 0 - if self.win_id >= 0: - window.set_title(self.win_id, c.Addr(self._title[0])) - - def set_style(self, s: t.CInt): - self.style = s - - def resizable(self, rw: t.CInt, rh: t.CInt): - self.resizable_w = rw - self.resizable_h = rh - if self.win_id >= 0: - window.set_resizable(self.win_id, rw, rh) - - def geometry(self, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt): - self._win_x = x - self._win_y = y - self.bw = w - self.bh = h - TITLE_H - 2 - if self.win_id < 0: - self.win_id = window.create_window(x, y, w, h, c.Addr(self._title[0]), self.style) - self.buf = window.get_winbuf(self.win_id) - window.set_resizable(self.win_id, self.resizable_w, self.resizable_h) - else: - window.set_geometry(self.win_id, x, y, w, h) - self.buf = window.get_winbuf(self.win_id) - - def setup(self, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | t.CChar | t.CPtr, style: t.CInt): - self._win_x = x - self._win_y = y - self.win_id = window.create_window(x, y, w, h, title, style) - self.buf = window.get_winbuf(self.win_id) - self.bw = w - self.bh = h - TITLE_H - 2 - self.style = style - self.bg_color = t.CUInt32T(0xFF231919) - - def redraw(self): - self._do_layout() - self.buf = window.get_winbuf(self.win_id) - sz: t.CInt = window.get_win_size(self.win_id) - if sz != 0: - self.bw = sz >> 16 - self.bh = sz & 0xFFFF - if not self.buf: return - if self.bw <= 0 or self.bh <= 0: return - _fill_rect(self.buf, self.bw, self.bh, 0, 0, self.bw, self.bh, self.bg_color) - i: t.CInt = 0 - while i < self.widget_count: - w: Widget | t.CPtr = self.widgets[i] - if w.visible: - w.draw(self.buf, self.bw, self.bh) - i += 1 - window.flush(self.win_id) - - def _do_layout(self): - self._grid_rows = 0 - self._grid_cols = 0 - cav_x: t.CInt = 0 - cav_y: t.CInt = 0 - cav_w: t.CInt = self.bw - cav_h: t.CInt = self.bh - i: t.CInt = 0 - while i < self.widget_count: - w: Widget | t.CPtr = self.widgets[i] - lt: t.CInt = _g_wl_type[i] - if lt == 2: - side: t.CInt = _g_wl_side[i] - fill: t.CInt = _g_wl_fill[i] - expand: t.CInt = _g_wl_expand[i] - px: t.CInt = _g_wl_padx[i] - py: t.CInt = _g_wl_pady[i] - ww: t.CInt = w.w - wh: t.CInt = w.h - if side == PACK_TOP: - if fill == FILL_X or fill == FILL_BOTH: - ww = cav_w - 2 * px - if expand: - if fill == FILL_Y or fill == FILL_BOTH: - wh = cav_h - 2 * py - w.x = cav_x + px - w.y = cav_y + py - w.w = ww - w.h = wh - cav_y += wh + 2 * py - cav_h -= wh + 2 * py - elif side == PACK_BOTTOM: - if fill == FILL_X or fill == FILL_BOTH: - ww = cav_w - 2 * px - if expand: - if fill == FILL_Y or fill == FILL_BOTH: - wh = cav_h - 2 * py - w.x = cav_x + px - w.y = cav_y + cav_h - wh - py - w.w = ww - w.h = wh - cav_h -= wh + 2 * py - elif side == PACK_LEFT: - if fill == FILL_Y or fill == FILL_BOTH: - wh = cav_h - 2 * py - if expand: - if fill == FILL_X or fill == FILL_BOTH: - ww = cav_w - 2 * px - w.x = cav_x + px - w.y = cav_y + py - w.w = ww - w.h = wh - cav_x += ww + 2 * px - cav_w -= ww + 2 * px - elif side == PACK_RIGHT: - if fill == FILL_Y or fill == FILL_BOTH: - wh = cav_h - 2 * py - if expand: - if fill == FILL_X or fill == FILL_BOTH: - ww = cav_w - 2 * px - w.x = cav_x + cav_w - ww - px - w.y = cav_y + py - w.w = ww - w.h = wh - cav_w -= ww + 2 * px - elif lt == 3: - r: t.CInt = _g_wl_row[i] + _g_wl_rowspan[i] - c: t.CInt = _g_wl_col[i] + _g_wl_colspan[i] - if r > self._grid_rows: self._grid_rows = r - if c > self._grid_cols: self._grid_cols = c - i += 1 - i = 0 - while i < self.widget_count: - w: Widget | t.CPtr = self.widgets[i] - if _g_wl_type[i] == 3: - if self._grid_rows <= 0: self._grid_rows = 1 - if self._grid_cols <= 0: self._grid_cols = 1 - cell_w: t.CInt = self.bw / self._grid_cols - cell_h: t.CInt = self.bh / self._grid_rows - wx: t.CInt = _g_wl_col[i] * cell_w - wy: t.CInt = _g_wl_row[i] * cell_h - ww: t.CInt = _g_wl_colspan[i] * cell_w - wh: t.CInt = _g_wl_rowspan[i] * cell_h - sticky: t.CInt = _g_wl_sticky[i] - if sticky == 0: - ox: t.CInt = (ww - w.w) / 2 - oy: t.CInt = (wh - w.h) / 2 - w.x = wx + ox - w.y = wy + oy - else: - w.x = wx - w.y = wy - if (sticky & 1) != 0: - w.w = ww - if (sticky & 2) != 0: - w.h = wh - i += 1 - - def update(self): - self.redraw() - - def winfo_exists(self) -> t.CInt: - if self.win_id < 0: return 0 - return window.is_active(self.win_id) - - def mainloop(self): - self.redraw() - evt: window.InputEvent - while window.is_active(self.win_id): - result: t.CInt = window.poll_event(c.Addr(evt)) - if result != 0: - if evt.win_id == self.win_id: - need_redraw: t.CInt = 0 - etype: t.CUInt32T = evt.type - if etype == window.EVENT_TYPE_PING: - window.flush(self.win_id) - elif etype == window.EVENT_TYPE_RESIZE: - self.buf = window.get_winbuf(self.win_id) - sz: t.CInt = window.get_win_size(self.win_id) - self.bw = sz >> 16 - self.bh = sz & 0xFFFF - need_redraw = 1 - elif etype == window.EVENT_TYPE_KEY or etype == window.EVENT_TYPE_KEY_RELEASE: - if self.focused_widget is not None: - handled: t.CInt = self.focused_widget.handle_event(c.Addr(evt)) - if handled: need_redraw = 1 - else: - if etype == window.EVENT_TYPE_HOVER: - i: t.CInt = self.widget_count - 1 - while i >= 0: - w: Widget | t.CPtr = self.widgets[i] - if w.visible: - handled2: t.CInt = w.handle_event(c.Addr(evt)) - if handled2: - need_redraw = 1 - break - i -= 1 - else: - i: t.CInt = 0 - while i < self.widget_count: - w: Widget | t.CPtr = self.widgets[i] - if w.visible: - handled2: t.CInt = w.handle_event(c.Addr(evt)) - if handled2: need_redraw = 1 - i += 1 - if need_redraw: - self.redraw() - else: - process.yield_cpu() +import vpsdk.window as window +import vpsdk.process as process +import vpsdk.syscall as _syscall +from stdint import * +import t, c +import string + +TITLE_H: t.CDefine = 32 +MAX_WIDGETS: t.CDefine = 24 +CHAR_W: t.CDefine = 8 +CHAR_H: t.CDefine = 16 + +WIDGET_LABEL: t.CDefine = 1 +WIDGET_BUTTON: t.CDefine = 2 +WIDGET_ENTRY: t.CDefine = 3 +WIDGET_TEXT: t.CDefine = 4 +WIDGET_SCROLLBAR: t.CDefine = 5 +WIDGET_FBCANVAS: t.CDefine = 6 + +VERTICAL: t.CDefine = 1 +HORIZONTAL: t.CDefine = 2 +TEXT_MAX_LINES: t.CDefine = 200 + +PACK_TOP: t.CDefine = 1 +PACK_BOTTOM: t.CDefine = 2 +PACK_LEFT: t.CDefine = 3 +PACK_RIGHT: t.CDefine = 4 + +FILL_NONE: t.CDefine = 0 +FILL_X: t.CDefine = 1 +FILL_Y: t.CDefine = 2 +FILL_BOTH: t.CDefine = 3 + +STICKY_NONE: t.CDefine = 0 +STICKY_W: t.CDefine = 1 +STICKY_E: t.CDefine = 2 +STICKY_N: t.CDefine = 4 +STICKY_S: t.CDefine = 8 +STICKY_NSEW: t.CDefine = 15 + +_g_wl_type: t.CArray[int, MAX_WIDGETS] +_g_wl_side: t.CArray[int, MAX_WIDGETS] +_g_wl_fill: t.CArray[int, MAX_WIDGETS] +_g_wl_expand: t.CArray[int, MAX_WIDGETS] +_g_wl_padx: t.CArray[int, MAX_WIDGETS] +_g_wl_pady: t.CArray[int, MAX_WIDGETS] +_g_wl_row: t.CArray[int, MAX_WIDGETS] +_g_wl_col: t.CArray[int, MAX_WIDGETS] +_g_wl_rowspan: t.CArray[int, MAX_WIDGETS] +_g_wl_colspan: t.CArray[int, MAX_WIDGETS] +_g_wl_sticky: t.CArray[int, MAX_WIDGETS] +_g_layout_init: int + +_hex_tbl: t.CArray[t.CChar, 17] = "0123456789ABCDEF" +_hex_buf: t.CArray[t.CChar, 20] = "0000000000000000000" + +def _serial_puts(s: t.CConst | t.CChar | t.CPtr) -> t.CVoid: + _syscall._syscall1(uint64(_syscall.SERIAL_PUTS), uint64(s)) + +def _ptr_to_hex(val: uint64, buf: t.CPtr) -> t.CVoid: + buf[0] = 48 + buf[1] = 120 + i: int = 15 + while i >= 0: + nibble: int = int(val & uint64(0xF)) + buf[2 + i] = _hex_tbl[nibble] + val = val >> 4 + i -= 1 + buf[18] = 0 + +def _fill_rect(fb: UINT32PTR, fw: int, fh: int, x1: int, y1: int, w: int, h: int, color: uint32): + if not fb: return + if x1 < 0: w += x1; x1 = 0 + if y1 < 0: h += y1; y1 = 0 + if w <= 0 or h <= 0: return + for py in range(y1, y1 + h): + if py >= 0 and py < fh: + for px in range(x1, x1 + w): + if px >= 0 and px < fw: + fb[py * fw + px] = color + +def _draw_hline(fb: UINT32PTR, fw: int, fh: int, x1: int, y: int, w: int, color: uint32): + if not fb: return + if y < 0 or y >= fh: return + for px in range(x1, x1 + w): + if px >= 0 and px < fw: + fb[y * fw + px] = color + +def _draw_vline(fb: UINT32PTR, fw: int, fh: int, x: int, y1: int, h: int, color: uint32): + if not fb: return + if x < 0 or x >= fw: return + for py in range(y1, y1 + h): + if py >= 0 and py < fh: + fb[py * fw + x] = color + +def _lighten(color: uint32, amount: int) -> uint32: + r: int = int(color & 0xFF) + g: int = int((color >> 8) & 0xFF) + b: int = int((color >> 16) & 0xFF) + r = r + ((255 - r) * amount) / 256 + g = g + ((255 - g) * amount) / 256 + b = b + ((255 - b) * amount) / 256 + return uint32(r | (g << 8) | (b << 16)) + +def _darken(color: uint32, amount: int) -> uint32: + r: int = int(color & 0xFF) + g: int = int((color >> 8) & 0xFF) + b: int = int((color >> 16) & 0xFF) + r = r - (r * amount) / 256 + g = g - (g * amount) / 256 + b = b - (b * amount) / 256 + return uint32(r | (g << 8) | (b << 16)) + + +font: t.CArray[t.CArray[uint8, 16], 256] = [ + {0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x02,0x56,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x42,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x55,0x55,0x57,0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x54,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x51,0x52,0x72,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x55,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x55,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x56,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x54,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x50,0x50,0x57,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x51,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x57,0x55,0x57,0x74,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x53,0x54,0x56,0x74,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x15,0x15,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x32,0x16,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x20,0x6E,0x22,0x2E,0x28,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x11,0x13,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x35,0x15,0x17,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x14,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x11,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x15,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x15,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x36,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x34,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x30,0x10,0x17,0x14,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x31,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x37,0x15,0x17,0x14,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x33,0x14,0x16,0x14,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, + {0x6C,0x6C,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x00,0x00,0x00}, + {0x0C,0x0C,0x3E,0x7F,0x68,0x68,0x3E,0x0B,0x0B,0x7F,0x3E,0x18,0x18,0x00,0x00,0x00}, + {0x60,0x60,0x66,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x66,0x06,0x06,0x00,0x00,0x00}, + {0x38,0x6C,0x6C,0x6C,0x6C,0x6C,0x38,0x6C,0x6D,0x66,0x66,0x6F,0x3B,0x00,0x00,0x00}, + {0x18,0x18,0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x1C,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00}, + {0x38,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x38,0x00,0x00}, + {0x00,0x00,0x18,0x18,0x7E,0x3C,0x3C,0x3C,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x18,0x18,0x18,0x7E,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, + {0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x6E,0x6E,0x7E,0x76,0x76,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x18,0x38,0x78,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x06,0x06,0x0E,0x1C,0x38,0x70,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x06,0x06,0x1C,0x1C,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x0C,0x0C,0x1C,0x1C,0x3C,0x2C,0x6C,0x7E,0x7E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00}, + {0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x06,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3C,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, + {0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x40,0x60,0x30,0x18,0x0C,0x06,0x06,0x0C,0x18,0x30,0x60,0x40,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x6E,0x6A,0x6A,0x6A,0x6E,0x60,0x60,0x7C,0x3C,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x7C,0x7E,0x66,0x66,0x66,0x7C,0x7C,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x78,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0x7C,0x78,0x00,0x00,0x00}, + {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, + {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x60,0x60,0x60,0x6E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, + {0x3E,0x3E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x7C,0x38,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x6C,0x6C,0x78,0x78,0x78,0x6C,0x6C,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, + {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x76,0x76,0x7E,0x6E,0x6E,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x6A,0x6A,0x6C,0x7E,0x36,0x00,0x00,0x00}, + {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x3C,0x7E,0x66,0x60,0x60,0x78,0x3C,0x0E,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, + {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x77,0x77,0x22,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x66,0x66,0x66,0x66,0x7E,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, + {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, + {0x78,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x78,0x00,0x00}, + {0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x0C,0x0C,0x06,0x06,0x03,0x03,0x00,0x00,0x00}, + {0x1E,0x1E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x1E,0x1E,0x00,0x00}, + {0x3C,0x7E,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00}, + {0x30,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3C,0x3E,0x06,0x3E,0x7E,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, + {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x06,0x06,0x06,0x06,0x3E,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x7E,0x7E,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x1C,0x3E,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x3E,0x3C,0x00}, + {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x18,0x18,0x00,0x00,0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, + {0x0C,0x0C,0x00,0x00,0x3C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C,0x78,0x00}, + {0x60,0x60,0x60,0x60,0x66,0x66,0x6C,0x78,0x78,0x6C,0x6C,0x66,0x66,0x00,0x00,0x00}, + {0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x36,0x7F,0x6B,0x6B,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x00}, + {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x07,0x07,0x00}, + {0x00,0x00,0x00,0x00,0x6C,0x7E,0x76,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x3C,0x7E,0x62,0x70,0x3C,0x0E,0x46,0x7E,0x3C,0x00,0x00,0x00}, + {0x30,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x7F,0x36,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x7E,0x7C,0x00}, + {0x00,0x00,0x00,0x00,0x7E,0x7E,0x0C,0x0C,0x18,0x30,0x30,0x7E,0x7E,0x00,0x00,0x00}, + {0x0E,0x1E,0x18,0x18,0x18,0x18,0x30,0x30,0x18,0x18,0x18,0x18,0x1E,0x0E,0x00,0x00}, + {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00}, + {0x70,0x78,0x18,0x18,0x18,0x18,0x0C,0x0C,0x18,0x18,0x18,0x18,0x78,0x70,0x00,0x00}, + {0x31,0x79,0x6B,0x4F,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x70,0x13,0x24,0x26,0x24,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +] + +def _draw_char(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, ch: t.CChar, color: uint32): + if not buf: return + if bw <= 0 or bh <= 0: return + ci: uint8 = uint8(ch) + if ci >= 128: ci = 0 + fy: int = 0 + while fy < CHAR_H: + if y + fy < 0 or y + fy >= bh: + fy += 1 + continue + row: uint8 = font[ci][fy] + if row == 0: + fy += 1 + continue + fx: int = 0 + while fx < CHAR_W: + if row & (0x80 >> fx): + px: int = x + fx + if px >= 0 and px < bw: + buf[(y + fy) * bw + px] = color + fx += 1 + fy += 1 + +def _draw_text(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, s: t.CConst | str, color: uint32): + if not buf: return + if bw <= 0 or bh <= 0: return + cx: int = x + cy: int = y + i: int = 0 + while True: + ch: t.CChar = s[i] + if ch == 0: break + if ch == 10: + cy += 16 + cx = x + else: + _draw_char(buf, bw, bh, cx, cy, ch, color) + cx += 8 + i += 1 + +def _register_widget(master: t.CPtr, widget: Widget | t.CPtr) -> int: + tk: Tk | t.CPtr = t.CType(master, Tk, t.CPtr) + idx: int = tk.widget_count + if idx < MAX_WIDGETS: + tk.widgets[idx] = widget + tk.widget_count = idx + 1 + return idx + +@t.Object +@t.CVTable +class Widget: + x: int + y: int + w: int + h: int + visible: int + master: t.CPtr + widget_type: int + focused: int + hovered: int + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + pass + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + return 0 + + def contains(self, px: int, py: int) -> int: + if px >= self.x and px < self.x + self.w and py >= self.y and py < self.y + self.h: + return 1 + return 0 + + def place(self, x: int = 0, y: int = 0, w: int = 0, h: int = 0): + self.x = x + self.y = y + if w > 0: + self.w = w + if h > 0: + self.h = h + +@t.Object +@t.CVTable +class Label(Widget): + text: t.CArray[t.CChar, 64] + color: uint32 + + def __init__(self, master: t.CPtr, text: str, color: uint32): + self.x = 0 + self.y = 0 + self.w = 0 + self.h = 0 + self.visible = 1 + self.master = master + self.widget_type = WIDGET_LABEL + self.focused = 0 + self.hovered = 0 + self.color = color + i: int = 0 + for ch in text: + if i >= 63: break + self.text[i] = ch + i += 1 + self.text[i] = 0 + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + _draw_text(fb, fw, fh, self.x, self.y, c.Addr(self.text[0]), self.color) + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + return 0 + + def config(self, text: t.CConst | t.CChar | t.CPtr = None, color: uint32 = None): + if text is not None: + i: int = 0 + while i < 63: + ch: t.CChar = c.Deref(text + i) + self.text[i] = ch + if ch == 0: break + i += 1 + self.text[i] = 0 + if color is not None: + self.color = color + +@t.Object +@t.CVTable +class Button(Widget): + text: t.CArray[t.CChar, 32] + fill_color: uint32 + text_color: uint32 + pressed: int + callback: t.CPtr + + def __init__(self, master: t.CPtr, w: int, h: int, text: str, callback: t.CPtr): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self.master = master + self.widget_type = WIDGET_BUTTON + self.focused = 0 + self.hovered = 0 + self.fill_color = uint32(0x3C3C5A) + self.text_color = uint32(0xFFFFFFFF) + self.pressed = 0 + self.callback = callback + i: int = 0 + for ch in text: + if i >= 31: break + self.text[i] = ch + i += 1 + self.text[i] = 0 + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + fill: uint32 = self.fill_color + border: uint32 = uint32(0x8080B0) + if self.pressed: + fill = _lighten(self.fill_color, 60) + border = uint32(0xA0A0D0) + elif self.hovered: + fill = _lighten(self.fill_color, 30) + border = uint32(0xA0A0D0) + _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, fill) + top_left: uint32 = _lighten(fill, 80) + bottom_right: uint32 = _darken(fill, 80) + if self.pressed: + top_left = _darken(fill, 60) + bottom_right = _lighten(fill, 40) + _draw_hline(fb, fw, fh, self.x, self.y, self.w, top_left) + _draw_hline(fb, fw, fh, self.x, self.y + 1, self.w, top_left) + _draw_vline(fb, fw, fh, self.x, self.y, self.h, top_left) + _draw_vline(fb, fw, fh, self.x + 1, self.y, self.h, top_left) + _draw_hline(fb, fw, fh, self.x, self.y + self.h - 1, self.w, bottom_right) + _draw_hline(fb, fw, fh, self.x, self.y + self.h - 2, self.w, bottom_right) + _draw_vline(fb, fw, fh, self.x + self.w - 1, self.y, self.h, bottom_right) + _draw_vline(fb, fw, fh, self.x + self.w - 2, self.y, self.h, bottom_right) + _draw_hline(fb, fw, fh, self.x - 1, self.y - 1, self.w + 2, border) + _draw_hline(fb, fw, fh, self.x - 1, self.y + self.h, self.w + 2, border) + _draw_vline(fb, fw, fh, self.x - 1, self.y - 1, self.h + 2, border) + _draw_vline(fb, fw, fh, self.x + self.w, self.y - 1, self.h + 2, border) + tl: int = string.strlen(c.Addr(self.text[0])) + tx: int = self.x + (self.w - 8 * tl) / 2 + ty: int = self.y + (self.h - CHAR_H) / 2 + _draw_text(fb, fw, fh, tx, ty, c.Addr(self.text[0]), self.text_color) + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + etype: uint32 = evt.type + ex: int = evt.x + ey: int = evt.y + if etype == window.EVENT_TYPE_HOVER: + if self.contains(ex, ey): + if not self.hovered: + self.hovered = 1 + return 1 + else: + if self.hovered and not self.pressed: + self.hovered = 0 + return 1 + elif etype == window.EVENT_TYPE_HOVER_LEAVE: + if self.hovered: + self.hovered = 0 + return 1 + elif etype == window.EVENT_TYPE_CLICK: + if self.contains(ex, ey): + self.pressed = 1 + return 1 + elif etype == window.EVENT_TYPE_RELEASE: + if self.pressed: + self.pressed = 0 + if self.contains(ex, ey) and self.callback is not None: + c.Asm(f"""push r12 +push r13 +mov r13, {c.AsmInp(self.callback, t.ASM_DESCR.REG_ANY)} +mov r12, rsp +and rsp, -16 +call r13 +mov rsp, r12 +pop r13 +pop r12""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, + t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, + t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + return 1 + return 0 + + def config(self, text: t.CConst | t.CChar | t.CPtr = None, fill_color: uint32 = None, text_color: uint32 = None, callback: t.CPtr = None): + if text is not None: + i: int = 0 + while i < 31: + ch: t.CChar = c.Deref(text + i) + self.text[i] = ch + if ch == 0: break + i += 1 + self.text[i] = 0 + if fill_color is not None: + self.fill_color = fill_color + if text_color is not None: + self.text_color = text_color + if callback is not None: + self.callback = callback + +@t.Object +@t.CVTable +class Entry(Widget): + text: t.CArray[t.CChar, 64] + text_len: int + cursor_pos: int + max_len: int + bg_color: uint32 + border_color: uint32 + text_color: uint32 + cursor_color: uint32 + + def __init__(self, master: t.CPtr, w: int, h: int): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self.master = master + self.widget_type = WIDGET_ENTRY + self.focused = 0 + self.hovered = 0 + self.text_len = 0 + self.cursor_pos = 0 + self.max_len = 30 + self.bg_color = uint32(0xFF231919) + self.border_color = uint32(0x606080) + self.text_color = uint32(0x000000) + self.cursor_color = uint32(0x000000) + for i in range(64): + self.text[i] = 0 + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + bg: uint32 = self.bg_color + bdr: uint32 = self.border_color + if self.focused: + bg = uint32(0xFFFFFF) + bdr = uint32(0x4488FF) + elif self.hovered: + bdr = uint32(0x8080B0) + _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, bg) + _draw_hline(fb, fw, fh, self.x, self.y, self.w, bdr) + _draw_hline(fb, fw, fh, self.x, self.y + self.h - 1, self.w, bdr) + _draw_vline(fb, fw, fh, self.x, self.y, self.h, bdr) + _draw_vline(fb, fw, fh, self.x + self.w - 1, self.y, self.h, bdr) + if self.text_len > 0: + tc: uint32 = self.text_color + if not self.focused: + tc = uint32(0xCCCCCC) + _draw_text(fb, fw, fh, self.x + 6, self.y + 7, c.Addr(self.text[0]), tc) + elif not self.focused: + _draw_text(fb, fw, fh, self.x + 6, self.y + 7, "Type here...", uint32(0x888888)) + if self.focused: + cx_pos: int = self.x + 6 + self.cursor_pos * CHAR_W + if cx_pos < self.x + self.w - 2: + _draw_vline(fb, fw, fh, cx_pos, self.y + 5, self.h - 10, self.cursor_color) + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + etype: uint32 = evt.type + ex: int = evt.x + ey: int = evt.y + if etype == window.EVENT_TYPE_HOVER: + if self.contains(ex, ey): + if not self.hovered: + self.hovered = 1 + tk: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + window.set_cursor_type(tk.win_id, window.CURSOR_IBEAM) + return 1 + else: + if self.hovered: + self.hovered = 0 + tk2: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + window.set_cursor_type(tk2.win_id, window.CURSOR_DEFAULT) + return 1 + elif etype == window.EVENT_TYPE_HOVER_LEAVE: + if self.hovered: + self.hovered = 0 + tk3: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + window.set_cursor_type(tk3.win_id, window.CURSOR_DEFAULT) + return 1 + elif etype == window.EVENT_TYPE_CLICK: + if self.contains(ex, ey): + if not self.focused: + self.focused = 1 + tk4: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + tk4.focused_widget = t.CType(self, Widget, t.CPtr) + rel_x: int = ex - self.x - 6 + if rel_x < 0: rel_x = 0 + new_pos: int = (rel_x + CHAR_W / 2) / CHAR_W + if new_pos > self.text_len: new_pos = self.text_len + self.cursor_pos = new_pos + return 1 + else: + if self.focused: + self.focused = 0 + tk5: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + tk5.focused_widget = None + return 1 + elif etype == window.EVENT_TYPE_KEY: + if self.focused: + ebtn: uint8 = evt.button + if ebtn == window.KEY_STATE_RELEASE: + return 0 + ch: int = ex + if ch == 8: + if self.cursor_pos > 0: + for i in range(self.cursor_pos, self.text_len): + self.text[i - 1] = self.text[i] + self.text_len -= 1 + self.cursor_pos -= 1 + self.text[self.text_len] = 0 + return 1 + elif ch == window.VK_LEFT: + if self.cursor_pos > 0: + self.cursor_pos -= 1 + return 1 + elif ch == window.VK_RIGHT: + if self.cursor_pos < self.text_len: + self.cursor_pos += 1 + return 1 + elif ch == window.VK_HOME: + self.cursor_pos = 0 + return 1 + elif ch == window.VK_END: + self.cursor_pos = self.text_len + return 1 + elif ch == window.VK_DELETE: + if self.cursor_pos < self.text_len: + for i in range(self.cursor_pos, self.text_len - 1): + self.text[i] = self.text[i + 1] + self.text_len -= 1 + self.text[self.text_len] = 0 + return 1 + elif ch >= 32 and ch < 127: + if self.text_len < self.max_len: + i: int = self.text_len + while i > self.cursor_pos: + self.text[i] = self.text[i - 1] + i -= 1 + self.text[self.cursor_pos] = t.CChar(ch) + self.text_len += 1 + self.cursor_pos += 1 + self.text[self.text_len] = 0 + return 1 + return 0 + + def get(self) -> t.CConst | t.CChar | t.CPtr: + return c.Addr(self.text[0]) + + def delete(self, start: int, end: int): + self.text_len = 0 + for i in range(64): + self.text[i] = 0 + + def config(self, bg_color: uint32 = None, text_color: uint32 = None, border_color: uint32 = None): + if bg_color is not None: + self.bg_color = bg_color + if text_color is not None: + self.text_color = text_color + if border_color is not None: + self.border_color = border_color + +@t.Object +@t.CVTable +class Scrollbar(Widget): + orient: int + command: t.CPtr + slider_first: int + slider_last: int + action: int + action_value: int + pressed: int + dragging: int + drag_start_y: int + drag_start_first: int + trough_color: uint32 + slider_color: uint32 + arrow_color: uint32 + slider_hover: int + + def __init__(self, master: t.CPtr, w: int, h: int, orient: int): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self.master = master + self.widget_type = WIDGET_SCROLLBAR + self.focused = 0 + self.hovered = 0 + self.orient = orient + self.command = None + self.slider_first = 0 + self.slider_last = 1000 + self.action = 0 + self.action_value = 0 + self.pressed = 0 + self.dragging = 0 + self.drag_start_y = 0 + self.drag_start_first = 0 + self.trough_color = uint32(0x1E1E2E) + self.slider_color = uint32(0x4A4A6A) + self.arrow_color = uint32(0xAAAAAA) + self.slider_hover = 0 + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.trough_color) + if self.orient != VERTICAL: return + arrow_sz: int = self.w + if arrow_sz > 16: arrow_sz = 16 + self._draw_arrow_btn(fb, fw, fh, self.x, self.y, self.w, arrow_sz, 0, 1 if self.pressed == 1 else 0) + self._draw_arrow_btn(fb, fw, fh, self.x, self.y + self.h - arrow_sz, self.w, arrow_sz, 1, 1 if self.pressed == 2 else 0) + trough_y: int = self.y + arrow_sz + trough_h: int = self.h - 2 * arrow_sz + if trough_h <= 0: return + if self.slider_last > self.slider_first: + sl_h: int = (self.slider_last - self.slider_first) * trough_h / 1000 + if sl_h < 8: sl_h = 8 + sl_y: int = trough_y + self.slider_first * trough_h / 1000 + if sl_y + sl_h > trough_y + trough_h: + sl_y = trough_y + trough_h - sl_h + if sl_y < trough_y: sl_y = trough_y + color: uint32 = self.slider_color + if self.dragging: + color = _lighten(self.slider_color, 40) + elif self.slider_hover: + color = _lighten(self.slider_color, 20) + _fill_rect(fb, fw, fh, self.x + 1, sl_y, self.w - 2, sl_h, color) + top_c: uint32 = _lighten(color, 60) + bot_c: uint32 = _darken(color, 60) + _draw_hline(fb, fw, fh, self.x + 1, sl_y, self.w - 2, top_c) + _draw_hline(fb, fw, fh, self.x + 1, sl_y + sl_h - 1, self.w - 2, bot_c) + _draw_vline(fb, fw, fh, self.x + 1, sl_y, sl_h, top_c) + _draw_vline(fb, fw, fh, self.x + self.w - 2, sl_y, sl_h, bot_c) + + def _draw_arrow_btn(self, fb: UINT32PTR, fw: int, fh: int, bx: int, by: int, bw: int, bh: int, direction: int, is_pressed: int): + color: uint32 = self.slider_color + if is_pressed: + color = _lighten(self.slider_color, 30) + _fill_rect(fb, fw, fh, bx, by, bw, bh, color) + top_c: uint32 = _lighten(color, 60) + bot_c: uint32 = _darken(color, 60) + if is_pressed: + top_c = _darken(color, 40) + bot_c = _lighten(color, 30) + _draw_hline(fb, fw, fh, bx, by, bw, top_c) + _draw_hline(fb, fw, fh, bx, by + bh - 1, bw, bot_c) + _draw_vline(fb, fw, fh, bx, by, bh, top_c) + _draw_vline(fb, fw, fh, bx + bw - 1, by, bh, bot_c) + cx: int = bx + bw / 2 + cy: int = by + bh / 2 + if direction == 0: + _fill_rect(fb, fw, fh, cx - 1, cy - 3, 3, 1, self.arrow_color) + _fill_rect(fb, fw, fh, cx - 2, cy - 2, 5, 1, self.arrow_color) + _fill_rect(fb, fw, fh, cx - 3, cy - 1, 7, 1, self.arrow_color) + else: + _fill_rect(fb, fw, fh, cx - 3, cy - 1, 7, 1, self.arrow_color) + _fill_rect(fb, fw, fh, cx - 2, cy, 5, 1, self.arrow_color) + _fill_rect(fb, fw, fh, cx - 1, cy + 1, 3, 1, self.arrow_color) + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + etype: uint32 = evt.type + ex: int = evt.x + ey: int = evt.y + if etype == window.EVENT_TYPE_HOVER: + if self.dragging: + self._handle_drag(ey) + return 1 + if self.contains(ex, ey): + if not self.slider_hover: + self.slider_hover = 1 + return 1 + else: + if self.slider_hover and self.pressed == 0: + self.slider_hover = 0 + return 1 + return 0 + elif etype == window.EVENT_TYPE_HOVER_LEAVE: + if self.slider_hover: + self.slider_hover = 0 + if not self.dragging: + self.pressed = 0 + return 1 + return 0 + elif etype == window.EVENT_TYPE_CLICK: + if self.contains(ex, ey): + if self.orient == VERTICAL: + arrow_sz: int = self.w + if arrow_sz > 16: arrow_sz = 16 + if ey < self.y + arrow_sz: + self.pressed = 1 + self.action = 1 + self._fire_command() + return 1 + elif ey >= self.y + self.h - arrow_sz: + self.pressed = 2 + self.action = 2 + self._fire_command() + return 1 + else: + trough_y: int = self.y + arrow_sz + trough_h: int = self.h - 2 * arrow_sz + if trough_h <= 0: return 1 + sl_h: int = (self.slider_last - self.slider_first) * trough_h / 1000 + if sl_h < 8: sl_h = 8 + sl_y: int = trough_y + self.slider_first * trough_h / 1000 + if sl_y + sl_h > trough_y + trough_h: + sl_y = trough_y + trough_h - sl_h + if ey >= sl_y and ey < sl_y + sl_h: + self.pressed = 4 + self.dragging = 1 + self.drag_start_y = ey + self.drag_start_first = self.slider_first + else: + self.pressed = 3 + if ey < sl_y: + self.action = 3 + else: + self.action = 4 + self._fire_command() + return 1 + return 0 + elif etype == window.EVENT_TYPE_RELEASE: + if self.pressed: + self.pressed = 0 + self.dragging = 0 + return 1 + return 0 + return 0 + + def _handle_drag(self, ey: int): + arrow_sz: int = self.w + if arrow_sz > 16: arrow_sz = 16 + trough_y: int = self.y + arrow_sz + trough_h: int = self.h - 2 * arrow_sz + if trough_h <= 0: return + delta_y: int = ey - self.drag_start_y + delta_first: int = delta_y * 1000 / trough_h + new_first: int = self.drag_start_first + delta_first + slider_size: int = self.slider_last - self.slider_first + if slider_size <= 0: slider_size = 1 + if new_first < 0: new_first = 0 + if new_first + slider_size > 1000: new_first = 1000 - slider_size + if new_first != self.slider_first: + self.slider_first = new_first + self.slider_last = new_first + slider_size + self.action = 5 + self.action_value = new_first + self._fire_command() + + def _fire_command(self): + if self.command is not None: + c.Asm(f"""push r12 +push r13 +mov r13, {c.AsmInp(self.command, t.ASM_DESCR.REG_ANY)} +mov r12, rsp +and rsp, -16 +call r13 +mov rsp, r12 +pop r13 +pop r12""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, + t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, + t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + + def set(self, first: int, last: int): + self.slider_first = first + self.slider_last = last + +@t.Object +@t.CVTable +class FBCanvas(Widget): + _fb: UINT32PTR + _cw: int + _ch: int + + def __init__(self, master: t.CPtr, w: int, h: int): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self.master = master + self.widget_type = WIDGET_FBCANVAS + self.focused = 0 + self.hovered = 0 + self._fb = None + self._cw = w + self._ch = h + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + if not self._fb: return + if self._cw <= 0 or self._ch <= 0: return + copy_w: int = self._cw + if copy_w > self.w: copy_w = self.w + copy_h: int = self._ch + if copy_h > self.h: copy_h = self.h + for py in range(copy_h): + ty: int = self.y + py + if ty < 0 or ty >= fh: continue + for px in range(copy_w): + tx: int = self.x + px + if tx < 0 or tx >= fw: continue + fb[ty * fw + tx] = self._fb[py * self._cw + px] + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + return 0 + + def set_fb(self, fb: UINT32PTR, cw: int, ch: int): + self._fb = fb + self._cw = cw + self._ch = ch + + def get_fb(self) -> UINT32PTR: + return self._fb + + def get_w(self) -> int: + return self._cw + + def get_h(self) -> int: + return self._ch + +@t.Object +@t.CVTable +class Text(Widget): + lines: t.CArray[t.CArray[t.CChar, 80], TEXT_MAX_LINES] + line_count: int + input_buf: t.CArray[t.CChar, 80] + input_len: int + cursor_pos: int + bg_color: uint32 + text_color: uint32 + prompt_color: uint32 + cursor_color: uint32 + border_color: uint32 + on_command: t.CPtr + history: t.CArray[t.CArray[t.CChar, 80], 16] + history_count: int + history_idx: int + scroll_offset: int + max_lines: int + yscrollbar: t.CPtr + + def __init__(self, master: t.CPtr, w: int, h: int): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self.master = master + self.widget_type = WIDGET_TEXT + self.focused = 0 + self.hovered = 0 + self.line_count = 0 + self.input_len = 0 + self.cursor_pos = 0 + self.bg_color = uint32(0x0C0C0C) + self.text_color = uint32(0xCCCCCC) + self.prompt_color = uint32(0x00FF00) + self.cursor_color = uint32(0x00FF00) + self.border_color = uint32(0x333333) + self.on_command = None + self.history_count = 0 + self.history_idx = 0 + self.scroll_offset = 0 + self.max_lines = TEXT_MAX_LINES + self.yscrollbar = None + i: int = 0 + while i < TEXT_MAX_LINES: + j: int = 0 + while j <= 79: + self.lines[i][j] = 0 + j += 1 + i += 1 + i = 0 + while i < 80: + self.input_buf[i] = 0 + i += 1 + _register_widget(master, t.CType(self, Widget, t.CPtr)) + + def draw(self, fb: UINT32PTR, fw: int, fh: int): + self._update_scrollbar() + _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.bg_color) + _fill_rect(fb, fw, fh, self.x, self.y + self.h - 2, self.w, 2, self.border_color) + visible: int = self._visible_lines() + for i in range(visible): + line_idx: int = self.scroll_offset + i + if line_idx < self.line_count: + _draw_text(fb, fw, fh, self.x + 4, self.y + i * CHAR_H, c.Addr(self.lines[line_idx][0]), self.text_color) + prompt_y: int = self.y + self.h - CHAR_H - 4 + _draw_text(fb, fw, fh, self.x + 4, prompt_y, "> ", self.prompt_color) + if self.input_len > 0: + _draw_text(fb, fw, fh, self.x + 4 + 2 * CHAR_W, prompt_y, c.Addr(self.input_buf[0]), uint32(0xFFFFFF)) + cx_pos: int = self.x + 4 + (2 + self.cursor_pos) * CHAR_W + if cx_pos < self.x + self.w - 4: + _fill_rect(fb, fw, fh, cx_pos, prompt_y, CHAR_W // 2, CHAR_H, self.cursor_color) + + def handle_event(self, evt: window.InputEvent | t.CPtr) -> int: + etype: uint32 = evt.type + ex: int = evt.x + ey: int = evt.y + if etype == window.EVENT_TYPE_CLICK: + if self.contains(ex, ey): + if not self.focused: + self.focused = 1 + tk: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + tk.focused_widget = t.CType(self, Widget, t.CPtr) + prompt_y: int = self.y + self.h - CHAR_H - 4 + if ey >= prompt_y and ey < prompt_y + CHAR_H: + rel_x: int = ex - self.x - 4 - 2 * CHAR_W + if rel_x < 0: rel_x = 0 + new_pos: int = (rel_x + CHAR_W / 2) / CHAR_W + if new_pos > self.input_len: new_pos = self.input_len + self.cursor_pos = new_pos + return 1 + else: + if self.focused: + self.focused = 0 + tk2: Tk | t.CPtr = t.CType(self.master, Tk, t.CPtr) + tk2.focused_widget = None + return 1 + elif etype == window.EVENT_TYPE_KEY: + if self.focused: + ebtn2: uint8 = evt.button + if ebtn2 == window.KEY_STATE_RELEASE: + return 0 + ch: int = ex + if ch == 8: + if self.cursor_pos > 0: + i: int = self.cursor_pos + while i < self.input_len: + self.input_buf[i - 1] = self.input_buf[i] + i += 1 + self.input_len -= 1 + self.cursor_pos -= 1 + self.input_buf[self.input_len] = 0 + return 1 + elif ch == 13: + self._exec_input() + self.input_len = 0 + self.cursor_pos = 0 + for i in range(80): + self.input_buf[i] = 0 + return 1 + elif ch == window.VK_LEFT: + if self.cursor_pos > 0: + self.cursor_pos -= 1 + return 1 + elif ch == window.VK_RIGHT: + if self.cursor_pos < self.input_len: + self.cursor_pos += 1 + return 1 + elif ch == window.VK_UP: + if self.history_count > 0: + if self.history_idx < self.history_count: + self.history_idx += 1 + hi: int = self.history_count - self.history_idx + if hi < 0: hi = 0 + for j in range(80): + self.input_buf[j] = self.history[hi][j] + self.input_len = 0 + while self.input_len < 79 and self.input_buf[self.input_len] != 0: + self.input_len += 1 + self.cursor_pos = self.input_len + return 1 + elif ch == window.VK_DOWN: + if self.history_count > 0: + if self.history_idx > 0: + self.history_idx -= 1 + if self.history_idx == 0: + self.input_len = 0 + self.cursor_pos = 0 + for j2 in range(80): + self.input_buf[j2] = 0 + else: + hi2: int = self.history_count - self.history_idx + for j3 in range(80): + self.input_buf[j3] = self.history[hi2][j3] + self.input_len = 0 + while self.input_len < 79 and self.input_buf[self.input_len] != 0: + self.input_len += 1 + self.cursor_pos = self.input_len + return 1 + elif ch == window.VK_HOME: + self.cursor_pos = 0 + return 1 + elif ch == window.VK_END: + self.cursor_pos = self.input_len + return 1 + elif ch == window.VK_DELETE: + if self.cursor_pos < self.input_len: + i: int = self.cursor_pos + while i < self.input_len - 1: + self.input_buf[i] = self.input_buf[i + 1] + i += 1 + self.input_len -= 1 + self.input_buf[self.input_len] = 0 + return 1 + elif ch == window.VK_PRIOR: + if self.scroll_offset > 0: + vis: int = self._visible_lines() + self.scroll_offset -= vis + if self.scroll_offset < 0: self.scroll_offset = 0 + self._update_scrollbar() + return 1 + elif ch == window.VK_NEXT: + vis2: int = self._visible_lines() + max_off: int = self.line_count - vis2 + if max_off < 0: max_off = 0 + if self.scroll_offset < max_off: + self.scroll_offset += vis2 + if self.scroll_offset > max_off: self.scroll_offset = max_off + self._update_scrollbar() + return 1 + elif ch >= 32 and ch < 127: + if self.input_len < 79: + i: int = self.input_len + while i > self.cursor_pos: + self.input_buf[i] = self.input_buf[i - 1] + i -= 1 + self.input_buf[self.cursor_pos] = t.CChar(ch) + self.input_len += 1 + self.cursor_pos += 1 + self.input_buf[self.input_len] = 0 + return 1 + return 0 + + def _exec_input(self): + self.insert("> ") + if self.input_len > 0: + last: int = self.line_count - 1 + j: int = 0 + while j < self.input_len and j < 77: + self.lines[last][2 + j] = self.input_buf[j] + j += 1 + self.lines[last][2 + j] = 0 + if self.history_count < 16: + k: int = 0 + while k < 80: + self.history[self.history_count][k] = self.input_buf[k] + k += 1 + self.history_count += 1 + else: + i: int = 0 + while i < 15: + k2: int = 0 + while k2 < 80: + self.history[i][k2] = self.history[i + 1][k2] + k2 += 1 + i += 1 + k3: int = 0 + while k3 < 80: + self.history[15][k3] = self.input_buf[k3] + k3 += 1 + self.history_idx = 0 + + cmd: t.CPtr = self.on_command + if cmd is not None: + c.Asm(f"""push r12 +push r13 +mov r13, {c.AsmInp(cmd, t.ASM_DESCR.REG_ANY)} +mov r12, rsp +and rsp, -16 +call r13 +mov rsp, r12 +pop r13 +pop r12""", + op=[t.ASM_DESCR.CLOBBER_MEMORY, + t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, + t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, + t.ASM_DESCR.CLOBBER_RDI, + t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, + t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + else: + self.insert("(no callback)") + + def insert(self, text: str): + start: int = 0 + pos: int = 0 + while True: + ch: t.CChar = c.Deref(text + pos) + if ch == 0: + if pos > start: + self._insert_substring(text, start, pos) + break + if ch == 10: + self._insert_substring(text, start, pos) + start = pos + 1 + pos += 1 + + def insert_ptr(self, text: t.CConst | t.CChar | t.CPtr): + start: int = 0 + pos: int = 0 + while True: + ch: t.CChar = c.Deref(text + pos) + if ch == 0: + if pos > start: + self._insert_substring(text, start, pos) + break + if ch == 10: + self._insert_substring(text, start, pos) + start = pos + 1 + pos += 1 + + def _insert_substring(self, text: t.CConst | t.CChar | t.CPtr, start: int, end: int): + if self.line_count >= self.max_lines: + i: int = 0 + while i < self.max_lines - 1: + j: int = 0 + while j <= 79: + self.lines[i][j] = self.lines[i + 1][j] + j += 1 + i += 1 + self.line_count -= 1 + if self.scroll_offset > 0: + self.scroll_offset -= 1 + idx: int = self.line_count + j: int = 0 + k: int = start + while k < end and j < 79: + ch: t.CChar = c.Deref(text + k) + if ch == 9: + tab_stop: int = 8 - (j % 8) + while tab_stop > 0 and j < 79: + self.lines[idx][j] = 32 + j += 1 + tab_stop -= 1 + elif ch == 13: + pass + else: + self.lines[idx][j] = ch + j += 1 + k += 1 + self.lines[idx][j] = 0 + self.line_count += 1 + vis: int = self._visible_lines() + if self.line_count > vis: + self.scroll_offset = self.line_count - vis + else: + self.scroll_offset = 0 + self._update_scrollbar() + + def delete(self, start: int, end: int): + self.line_count = 0 + self.scroll_offset = 0 + self._update_scrollbar() + + def get(self) -> t.CConst | t.CChar | t.CPtr: + return c.Addr(self.input_buf[0]) + + def config(self, text_color: uint32 = None, bg_color: uint32 = None, prompt_color: uint32 = None, cursor_color: uint32 = None, border_color: uint32 = None): + if text_color is not None: + self.text_color = text_color + if bg_color is not None: + self.bg_color = bg_color + if prompt_color is not None: + self.prompt_color = prompt_color + if cursor_color is not None: + self.cursor_color = cursor_color + if border_color is not None: + self.border_color = border_color + + def _visible_lines(self) -> int: + return (self.h - CHAR_H - 4) / CHAR_H + + def _update_scrollbar(self): + vis: int = self._visible_lines() + if self.line_count <= vis: + self.scroll_offset = 0 + else: + max_off: int = self.line_count - vis + if self.scroll_offset > max_off: + self.scroll_offset = max_off + if self.yscrollbar is not None: + sb: Scrollbar | t.CPtr = t.CType(self.yscrollbar, Scrollbar, t.CPtr) + if self.line_count <= vis: + sb.set(0, 1000) + else: + first: int = self.scroll_offset * 1000 / self.line_count + last: int = (self.scroll_offset + vis) * 1000 / self.line_count + sb.set(first, last) + +@t.Object +class Tk: + win_id: int + buf: UINT32PTR + bw: int + bh: int + style: int + bg_color: uint32 + widgets: t.CArray[Widget | t.CPtr, MAX_WIDGETS] + widget_count: int + focused_widget: Widget | t.CPtr + _win_x: int + _win_y: int + _title: t.CArray[t.CChar, 32] + resizable_w: int + resizable_h: int + _grid_rows: int + _grid_cols: int + + def __init__(self): + global _g_layout_init + self.widget_count = 0 + self.focused_widget = None + self.win_id = -1 + self._win_x = 0 + self._win_y = 0 + self.style = 0 + self.bg_color = uint32(0xFF231919) + self.resizable_w = 1 + self.resizable_h = 1 + self._grid_rows = 0 + self._grid_cols = 0 + if _g_layout_init == 0: + i: int = 0 + while i < MAX_WIDGETS: + _g_wl_type[i] = 0 + _g_wl_side[i] = 0 + _g_wl_fill[i] = 0 + _g_wl_expand[i] = 0 + _g_wl_padx[i] = 0 + _g_wl_pady[i] = 0 + _g_wl_row[i] = 0 + _g_wl_col[i] = 0 + _g_wl_rowspan[i] = 0 + _g_wl_colspan[i] = 1 + _g_wl_sticky[i] = 0 + i += 1 + _g_layout_init = 1 + j: int = 0 + while j < 32: + self._title[j] = 0 + j += 1 + + def pack(self, idx: int, side: int, fill: int, expand: int, padx: int, pady: int): + _g_wl_type[idx] = 2 + _g_wl_side[idx] = side + _g_wl_fill[idx] = fill + _g_wl_expand[idx] = expand + _g_wl_padx[idx] = padx + _g_wl_pady[idx] = pady + + def grid(self, idx: int, row: int, col: int, rowspan: int, colspan: int, sticky: int): + _g_wl_type[idx] = 3 + _g_wl_row[idx] = row + _g_wl_col[idx] = col + _g_wl_rowspan[idx] = rowspan + _g_wl_colspan[idx] = colspan + _g_wl_sticky[idx] = sticky + + def title(self, text: str): + i: int = 0 + while i < 31: + ch: t.CChar = text[i] + if ch == 0: break + self._title[i] = ch + i += 1 + self._title[i] = 0 + if self.win_id >= 0: + window.set_title(self.win_id, c.Addr(self._title[0])) + + def set_style(self, s: int): + self.style = s + + def resizable(self, rw: int, rh: int): + self.resizable_w = rw + self.resizable_h = rh + if self.win_id >= 0: + window.set_resizable(self.win_id, rw, rh) + + def geometry(self, x: int, y: int, w: int, h: int): + self._win_x = x + self._win_y = y + self.bw = w + self.bh = h - TITLE_H - 2 + if self.win_id < 0: + self.win_id = window.create_window(x, y, w, h, c.Addr(self._title[0]), self.style) + self.buf = window.get_winbuf(self.win_id) + window.set_resizable(self.win_id, self.resizable_w, self.resizable_h) + else: + window.set_geometry(self.win_id, x, y, w, h) + self.buf = window.get_winbuf(self.win_id) + + def setup(self, x: int, y: int, w: int, h: int, title: t.CConst | t.CChar | t.CPtr, style: int): + self._win_x = x + self._win_y = y + self.win_id = window.create_window(x, y, w, h, title, style) + self.buf = window.get_winbuf(self.win_id) + self.bw = w + self.bh = h - TITLE_H - 2 + self.style = style + self.bg_color = uint32(0xFF231919) + + def redraw(self): + self._do_layout() + self.buf = window.get_winbuf(self.win_id) + sz: int = window.get_win_size(self.win_id) + if sz != 0: + self.bw = sz >> 16 + self.bh = sz & 0xFFFF + if not self.buf: return + if self.bw <= 0 or self.bh <= 0: return + _fill_rect(self.buf, self.bw, self.bh, 0, 0, self.bw, self.bh, self.bg_color) + i: int = 0 + while i < self.widget_count: + w: Widget | t.CPtr = self.widgets[i] + if w.visible: + w.draw(self.buf, self.bw, self.bh) + i += 1 + window.flush(self.win_id) + + def _do_layout(self): + self._grid_rows = 0 + self._grid_cols = 0 + cav_x: int = 0 + cav_y: int = 0 + cav_w: int = self.bw + cav_h: int = self.bh + i: int = 0 + while i < self.widget_count: + w: Widget | t.CPtr = self.widgets[i] + lt: int = _g_wl_type[i] + if lt == 2: + side: int = _g_wl_side[i] + fill: int = _g_wl_fill[i] + expand: int = _g_wl_expand[i] + px: int = _g_wl_padx[i] + py: int = _g_wl_pady[i] + ww: int = w.w + wh: int = w.h + if side == PACK_TOP: + if fill == FILL_X or fill == FILL_BOTH: + ww = cav_w - 2 * px + if expand: + if fill == FILL_Y or fill == FILL_BOTH: + wh = cav_h - 2 * py + w.x = cav_x + px + w.y = cav_y + py + w.w = ww + w.h = wh + cav_y += wh + 2 * py + cav_h -= wh + 2 * py + elif side == PACK_BOTTOM: + if fill == FILL_X or fill == FILL_BOTH: + ww = cav_w - 2 * px + if expand: + if fill == FILL_Y or fill == FILL_BOTH: + wh = cav_h - 2 * py + w.x = cav_x + px + w.y = cav_y + cav_h - wh - py + w.w = ww + w.h = wh + cav_h -= wh + 2 * py + elif side == PACK_LEFT: + if fill == FILL_Y or fill == FILL_BOTH: + wh = cav_h - 2 * py + if expand: + if fill == FILL_X or fill == FILL_BOTH: + ww = cav_w - 2 * px + w.x = cav_x + px + w.y = cav_y + py + w.w = ww + w.h = wh + cav_x += ww + 2 * px + cav_w -= ww + 2 * px + elif side == PACK_RIGHT: + if fill == FILL_Y or fill == FILL_BOTH: + wh = cav_h - 2 * py + if expand: + if fill == FILL_X or fill == FILL_BOTH: + ww = cav_w - 2 * px + w.x = cav_x + cav_w - ww - px + w.y = cav_y + py + w.w = ww + w.h = wh + cav_w -= ww + 2 * px + elif lt == 3: + r: int = _g_wl_row[i] + _g_wl_rowspan[i] + c: int = _g_wl_col[i] + _g_wl_colspan[i] + if r > self._grid_rows: self._grid_rows = r + if c > self._grid_cols: self._grid_cols = c + i += 1 + i = 0 + while i < self.widget_count: + w: Widget | t.CPtr = self.widgets[i] + if _g_wl_type[i] == 3: + if self._grid_rows <= 0: self._grid_rows = 1 + if self._grid_cols <= 0: self._grid_cols = 1 + cell_w: int = self.bw / self._grid_cols + cell_h: int = self.bh / self._grid_rows + wx: int = _g_wl_col[i] * cell_w + wy: int = _g_wl_row[i] * cell_h + ww: int = _g_wl_colspan[i] * cell_w + wh: int = _g_wl_rowspan[i] * cell_h + sticky: int = _g_wl_sticky[i] + if sticky == 0: + ox: int = (ww - w.w) / 2 + oy: int = (wh - w.h) / 2 + w.x = wx + ox + w.y = wy + oy + else: + w.x = wx + w.y = wy + if (sticky & 1) != 0: + w.w = ww + if (sticky & 2) != 0: + w.h = wh + i += 1 + + def update(self): + self.redraw() + + def winfo_exists(self) -> int: + if self.win_id < 0: return 0 + return window.is_active(self.win_id) + + def mainloop(self): + self.redraw() + evt: window.InputEvent + while window.is_active(self.win_id): + result: int = window.poll_event(c.Addr(evt)) + if result != 0: + if evt.win_id == self.win_id: + need_redraw: int = 0 + etype: uint32 = evt.type + if etype == window.EVENT_TYPE_PING: + window.flush(self.win_id) + elif etype == window.EVENT_TYPE_RESIZE: + self.buf = window.get_winbuf(self.win_id) + sz: int = window.get_win_size(self.win_id) + self.bw = sz >> 16 + self.bh = sz & 0xFFFF + need_redraw = 1 + elif etype == window.EVENT_TYPE_KEY or etype == window.EVENT_TYPE_KEY_RELEASE: + if self.focused_widget is not None: + handled: int = self.focused_widget.handle_event(c.Addr(evt)) + if handled: need_redraw = 1 + else: + if etype == window.EVENT_TYPE_HOVER: + i: int = self.widget_count - 1 + while i >= 0: + w: Widget | t.CPtr = self.widgets[i] + if w.visible: + handled2: int = w.handle_event(c.Addr(evt)) + if handled2: + need_redraw = 1 + break + i -= 1 + else: + i: int = 0 + while i < self.widget_count: + w: Widget | t.CPtr = self.widgets[i] + if w.visible: + handled2: int = w.handle_event(c.Addr(evt)) + if handled2: need_redraw = 1 + i += 1 + if need_redraw: + self.redraw() + else: + process.yield_cpu() diff --git a/vpsdk/window.vp b/vpsdk/window.vp index 453dd1e..a669f48 100644 --- a/vpsdk/window.vp +++ b/vpsdk/window.vp @@ -1,93 +1,93 @@ -import t, c -from . import syscall as syscall -from stdint import * - -STYLE_CLASSIC: t.CDefine = 0 -STYLE_WIN10: t.CDefine = 1 -STYLE_WIN11: t.CDefine = 2 -STYLE_WIN7: t.CDefine = 3 -STYLE_WINXP: t.CDefine = 4 - -EVENT_TYPE_NONE: t.CDefine = 0 -EVENT_TYPE_CLICK: t.CDefine = 1 -EVENT_TYPE_HOVER: t.CDefine = 2 -EVENT_TYPE_RELEASE: t.CDefine = 3 -EVENT_TYPE_HOVER_LEAVE: t.CDefine = 4 -EVENT_TYPE_KEY: t.CDefine = 5 -EVENT_TYPE_KEY_RELEASE: t.CDefine = 6 -EVENT_TYPE_PING: t.CDefine = 7 -EVENT_TYPE_RESIZE: t.CDefine = 8 - -KEY_STATE_PRESS: t.CDefine = 1 -KEY_STATE_RELEASE: t.CDefine = 2 -KEY_STATE_REPEAT: t.CDefine = 3 - -CURSOR_DEFAULT: t.CDefine = 0 -CURSOR_IBEAM: t.CDefine = 1 -CURSOR_RESIZE_EW: t.CDefine = 2 -CURSOR_RESIZE_NS: t.CDefine = 3 -CURSOR_RESIZE_NWSE: t.CDefine = 4 - -VK_LEFT: t.CDefine = -1 -VK_RIGHT: t.CDefine = -2 -VK_UP: t.CDefine = -3 -VK_DOWN: t.CDefine = -4 -VK_HOME: t.CDefine = -5 -VK_END: t.CDefine = -6 -VK_DELETE: t.CDefine = -7 -VK_PRIOR: t.CDefine = -8 -VK_NEXT: t.CDefine = -9 - -@c.Attribute(t.attr.packed) -@t.Object -class InputEvent: - type: t.CUInt32T - win_id: t.CInt - x: t.CInt - y: t.CInt - button: t.CUInt8T - _pad0: t.CUInt8T - _pad1: t.CUInt8T - _pad2: t.CUInt8T - -def create_window(x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | t.CChar | t.CPtr, style: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall6(t.CUInt64T(syscall.CREATE_WINDOW), t.CUInt64T(x), t.CUInt64T(y), t.CUInt64T(w), t.CUInt64T(h), t.CUInt64T(title), t.CUInt64T(style))) - -def draw_text(win_id: t.CInt, x: t.CInt, y: t.CInt, text: t.CConst | t.CChar | t.CPtr, color: t.CUInt32T) -> t.CInt: - return t.CInt(syscall._syscall5(t.CUInt64T(syscall.DRAW_TEXT), t.CUInt64T(win_id), t.CUInt64T(x), t.CUInt64T(y), t.CUInt64T(text), t.CUInt64T(color))) - -def get_winbuf(win_id: t.CInt) -> UINT32PTR: - return t.CVoid(syscall._syscall2(t.CUInt64T(syscall.GET_WINBUF), t.CUInt64T(win_id), 0), t.CPtr) - -def get_win_size(win_id: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.GET_WIN_SIZE), t.CUInt64T(win_id), 0)) - -def flush(win_id: t.CInt) -> t.CVoid: - syscall._syscall2(t.CUInt64T(syscall.WIN_FLUSH), t.CUInt64T(win_id), 0) - -def mainloop(win_id: t.CInt) -> t.CVoid: - syscall._syscall1(t.CUInt64T(syscall.WAIT_WINDOW), t.CUInt64T(win_id)) - -def poll_event(evt: InputEvent | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall1(t.CUInt64T(syscall.POLL_EVENT), t.CUInt64T(evt))) - -def is_active(win_id: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.WAIT_WINDOW), t.CUInt64T(win_id), 1)) - -def set_cursor_type(win_id: t.CInt, cursor_t: t.CInt) -> t.CVoid: - syscall._syscall2(t.CUInt64T(syscall.SET_CURSOR), t.CUInt64T(win_id), t.CUInt64T(cursor_t)) - -def set_title(win_id: t.CInt, title: t.CConst | t.CChar | t.CPtr) -> t.CInt: - return t.CInt(syscall._syscall2(t.CUInt64T(syscall.SET_TITLE), t.CUInt64T(win_id), t.CUInt64T(title))) - -def set_geometry(win_id: t.CInt, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall5(t.CUInt64T(syscall.SET_GEOMETRY), t.CUInt64T(win_id), t.CUInt64T(x), t.CUInt64T(y), t.CUInt64T(w), t.CUInt64T(h))) - -def set_resizable(win_id: t.CInt, rw: t.CInt, rh: t.CInt) -> t.CInt: - return t.CInt(syscall._syscall3(t.CUInt64T(syscall.SET_RESIZABLE), t.CUInt64T(win_id), t.CUInt64T(rw), t.CUInt64T(rh))) - -#class Window: -# HWND: t.CInt -# def __init__(self): -# self.HWND = create_window(100, 100, 100, 100) - +import t, c +from . import syscall as syscall +from stdint import * + +STYLE_CLASSIC: t.CDefine = 0 +STYLE_WIN10: t.CDefine = 1 +STYLE_WIN11: t.CDefine = 2 +STYLE_WIN7: t.CDefine = 3 +STYLE_WINXP: t.CDefine = 4 + +EVENT_TYPE_NONE: t.CDefine = 0 +EVENT_TYPE_CLICK: t.CDefine = 1 +EVENT_TYPE_HOVER: t.CDefine = 2 +EVENT_TYPE_RELEASE: t.CDefine = 3 +EVENT_TYPE_HOVER_LEAVE: t.CDefine = 4 +EVENT_TYPE_KEY: t.CDefine = 5 +EVENT_TYPE_KEY_RELEASE: t.CDefine = 6 +EVENT_TYPE_PING: t.CDefine = 7 +EVENT_TYPE_RESIZE: t.CDefine = 8 + +KEY_STATE_PRESS: t.CDefine = 1 +KEY_STATE_RELEASE: t.CDefine = 2 +KEY_STATE_REPEAT: t.CDefine = 3 + +CURSOR_DEFAULT: t.CDefine = 0 +CURSOR_IBEAM: t.CDefine = 1 +CURSOR_RESIZE_EW: t.CDefine = 2 +CURSOR_RESIZE_NS: t.CDefine = 3 +CURSOR_RESIZE_NWSE: t.CDefine = 4 + +VK_LEFT: t.CDefine = -1 +VK_RIGHT: t.CDefine = -2 +VK_UP: t.CDefine = -3 +VK_DOWN: t.CDefine = -4 +VK_HOME: t.CDefine = -5 +VK_END: t.CDefine = -6 +VK_DELETE: t.CDefine = -7 +VK_PRIOR: t.CDefine = -8 +VK_NEXT: t.CDefine = -9 + +@c.Attribute(t.attr.packed) +@t.Object +class InputEvent: + type: uint32 + win_id: int + x: int + y: int + button: uint8 + _pad0: uint8 + _pad1: uint8 + _pad2: uint8 + +def create_window(x: int, y: int, w: int, h: int, title: t.CConst | t.CChar | t.CPtr, style: int) -> int: + return int(syscall._syscall6(uint64(syscall.CREATE_WINDOW), uint64(x), uint64(y), uint64(w), uint64(h), uint64(title), uint64(style))) + +def draw_text(win_id: int, x: int, y: int, text: t.CConst | t.CChar | t.CPtr, color: uint32) -> int: + return int(syscall._syscall5(uint64(syscall.DRAW_TEXT), uint64(win_id), uint64(x), uint64(y), uint64(text), uint64(color))) + +def get_winbuf(win_id: int) -> UINT32PTR: + return t.CVoid(syscall._syscall2(uint64(syscall.GET_WINBUF), uint64(win_id), 0), t.CPtr) + +def get_win_size(win_id: int) -> int: + return int(syscall._syscall2(uint64(syscall.GET_WIN_SIZE), uint64(win_id), 0)) + +def flush(win_id: int) -> t.CVoid: + syscall._syscall2(uint64(syscall.WIN_FLUSH), uint64(win_id), 0) + +def mainloop(win_id: int) -> t.CVoid: + syscall._syscall1(uint64(syscall.WAIT_WINDOW), uint64(win_id)) + +def poll_event(evt: InputEvent | t.CPtr) -> int: + return int(syscall._syscall1(uint64(syscall.POLL_EVENT), uint64(evt))) + +def is_active(win_id: int) -> int: + return int(syscall._syscall2(uint64(syscall.WAIT_WINDOW), uint64(win_id), 1)) + +def set_cursor_type(win_id: int, cursor_t: int) -> t.CVoid: + syscall._syscall2(uint64(syscall.SET_CURSOR), uint64(win_id), uint64(cursor_t)) + +def set_title(win_id: int, title: t.CConst | t.CChar | t.CPtr) -> int: + return int(syscall._syscall2(uint64(syscall.SET_TITLE), uint64(win_id), uint64(title))) + +def set_geometry(win_id: int, x: int, y: int, w: int, h: int) -> int: + return int(syscall._syscall5(uint64(syscall.SET_GEOMETRY), uint64(win_id), uint64(x), uint64(y), uint64(w), uint64(h))) + +def set_resizable(win_id: int, rw: int, rh: int) -> int: + return int(syscall._syscall3(uint64(syscall.SET_RESIZABLE), uint64(win_id), uint64(rw), uint64(rh))) + +#class Window: +# HWND: int +# def __init__(self): +# self.HWND = create_window(100, 100, 100, 100) +