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  }