Skip to content

Commit 4d89235

Browse files
committed
wa wemu 模拟器增加 VGA 设备
1 parent ca42562 commit 4d89235

File tree

1 file changed

+110
-0
lines changed
  • internal/native/wemu/device/vga

1 file changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright (C) 2025 武汉凹语言科技有限公司
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
package vga
5+
6+
import (
7+
"fmt"
8+
)
9+
10+
// 设备的默认映射地址
11+
const VGA_BASE = 0x100000
12+
13+
// 显示器
14+
type VGA struct {
15+
name string
16+
addr uint64
17+
width int
18+
height int
19+
data []byte // 内存数据
20+
palette []byte // data[:256*4]
21+
screen []uint8 // data[256*4:]
22+
}
23+
24+
// 构造 VGA 显示器
25+
func NewVGA(name string, addr uint64, width, height int) *VGA {
26+
p := &VGA{
27+
name: name,
28+
addr: addr,
29+
width: width,
30+
height: height,
31+
data: make([]byte, 256*4+width*height),
32+
}
33+
34+
p.palette = p.data[:256*4]
35+
p.screen = p.data[256*4:]
36+
37+
for i := 0; i < 256; i++ {
38+
p.palette[i+0] = uint8(i)
39+
p.palette[i+1] = uint8(i)
40+
p.palette[i+2] = uint8(i)
41+
p.palette[i+3] = 255
42+
}
43+
44+
return p
45+
}
46+
47+
func (p *VGA) Name() string { return p.name }
48+
func (p *VGA) AddrBegin() uint64 { return p.addr }
49+
func (p *VGA) AddrEnd() uint64 { return p.addr + uint64(len(p.data)) }
50+
51+
// 读颜色表
52+
func (p *VGA) ReadPalette(offset uint64) uint32 {
53+
v := uint32(p.palette[offset+2]) // B
54+
v |= uint32(p.palette[offset+1]) << 8 // G
55+
v |= uint32(p.palette[offset+0]) << 16 // R
56+
v |= uint32(p.palette[offset+3]) << 24
57+
return v
58+
}
59+
60+
// 写颜色表
61+
func (p *VGA) WritePalette(offset uint64, value uint32) {
62+
p.palette[offset+2] = uint8((value >> 0) & 0xFF) // B
63+
p.palette[offset+1] = uint8((value >> 8) & 0xFF) // G
64+
p.palette[offset+0] = uint8((value >> 16) & 0xFF) // R
65+
p.palette[offset+3] = 255
66+
}
67+
68+
// 读帧缓存
69+
func (p *VGA) ReadScreen(offset uint64) (value uint32) {
70+
v := uint32(p.screen[offset+2]) // B
71+
v |= uint32(p.screen[offset+1]) << 8 // G
72+
v |= uint32(p.screen[offset+0]) << 16 // R
73+
v |= uint32(p.screen[offset+3]) << 24
74+
return v
75+
}
76+
77+
// 写帧缓存(offset不是内存地址, 而是帧缓存内部偏移)
78+
func (vga *VGA) WriteScreen(offset uint64, value uint32) {
79+
vga.screen[offset+0] = uint8(value & 0xFF)
80+
vga.screen[offset+1] = uint8((value & 0xFF00) >> 8)
81+
vga.screen[offset+2] = uint8((value & 0xFF0000) >> 16)
82+
vga.screen[offset+3] = uint8((value & 0xFF000000) >> 24)
83+
}
84+
85+
func (p *VGA) Read(addr, size uint64) (uint64, error) {
86+
if addr < p.AddrBegin() || addr >= p.AddrEnd() {
87+
return 0, fmt.Errorf("%s: bad address [0x%08X, 0x%x08X)", p.name, addr, addr+size)
88+
}
89+
switch off := addr - p.addr; true {
90+
case off < 256*4:
91+
return uint64(p.ReadPalette(off)), nil
92+
default:
93+
return uint64(p.ReadScreen(off)), nil
94+
}
95+
}
96+
97+
func (p *VGA) Write(addr, size, value uint64) error {
98+
if addr < p.AddrBegin() || addr >= p.AddrEnd() {
99+
return fmt.Errorf("%s: bad address [0x%08X, 0x%x08X)", p.name, addr, addr+size)
100+
}
101+
102+
switch off := addr - p.addr; true {
103+
case off < 256*4:
104+
p.WritePalette(off, uint32(value))
105+
return nil
106+
default:
107+
p.WriteScreen(off, uint32(value))
108+
return nil
109+
}
110+
}

0 commit comments

Comments
 (0)