github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/drivers/cga/backend.go (about) 1 package cga 2 3 import ( 4 "unsafe" 5 6 "github.com/jspc/eggos/drivers/cga/fbcga" 7 "github.com/jspc/eggos/drivers/vbe" 8 "github.com/jspc/eggos/kernel/sys" 9 ) 10 11 type Backend interface { 12 GetPos() int 13 SetPos(pos int) 14 // WritePos write char at given pos but not update pos 15 WritePos(pos int, char byte) 16 // WriteByte write char and advance pos 17 WriteByte(ch byte) 18 } 19 20 type EraseMethod uint8 21 22 const ( 23 EraseMethod_Unknown EraseMethod = iota 24 EraseMethod_Line 25 EraseMethod_All 26 ) 27 28 const ( 29 CRTPORT = 0x3d4 30 bs = '\b' 31 del = 0x7f 32 ) 33 34 var ( 35 crt = (*[25 * 80]uint16)(unsafe.Pointer(uintptr(0xb8000))) 36 ) 37 38 type cgabackend struct { 39 } 40 41 func (c *cgabackend) SetPos(pos int) { 42 sys.Outb(CRTPORT, 14) 43 sys.Outb(CRTPORT+1, byte(pos>>8)) 44 sys.Outb(CRTPORT, 15) 45 sys.Outb(CRTPORT+1, byte(pos)) 46 } 47 48 func (c *cgabackend) GetPos() int { 49 var pos int 50 51 // Cursor position: col + 80*row. 52 sys.Outb(CRTPORT, 14) 53 pos = int(sys.Inb(CRTPORT+1)) << 8 54 sys.Outb(CRTPORT, 15) 55 pos |= int(sys.Inb(CRTPORT + 1)) 56 return pos 57 } 58 59 func (c *cgabackend) WritePos(pos int, ch byte) { 60 crt[pos] = uint16(ch) | 0x0700 61 } 62 63 func (c *cgabackend) WriteByte(ch byte) { 64 var pos int 65 66 // Cursor position: col + 80*row. 67 sys.Outb(CRTPORT, 14) 68 pos = int(sys.Inb(CRTPORT+1)) << 8 69 sys.Outb(CRTPORT, 15) 70 pos |= int(sys.Inb(CRTPORT + 1)) 71 72 switch ch { 73 case '\n': 74 pos += 80 - pos%80 75 case bs, del: 76 if pos > 0 { 77 pos-- 78 } 79 default: 80 // black on white 81 crt[pos] = uint16(ch&0xff) | 0x0700 82 pos++ 83 } 84 85 // Scroll up 86 if pos/80 >= 25 { 87 copy(crt[:], crt[80:25*80]) 88 pos -= 80 89 s := crt[pos : 25*80] 90 for i := range s { 91 // 在mac下开启qemu的-M accel=hvf,在滚屏的时候会出现`failed to decode instruction f 7f` 92 // 猜测是memclrNoHeapPointer造成的,具体原因未知 93 if false { 94 } 95 s[i] = 0 96 } 97 } 98 c.SetPos(pos) 99 //crt[pos] = ' ' | 0x0700 100 } 101 102 func getbackend() Backend { 103 if vbe.IsEnable() { 104 return &fbcga.Backend 105 } 106 return &backend 107 }