1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

Use uint32 for console coordinates and fix dimension bug

This commit is contained in:
Achilleas Anagnostopoulos 2017-07-08 08:18:05 +01:00
parent d804b17ed8
commit fd3ca91138
3 changed files with 45 additions and 41 deletions

View File

@ -15,7 +15,7 @@ const (
// consoles. // consoles.
type Device interface { type Device interface {
// Dimensions returns the width and height of the console in characters. // Dimensions returns the width and height of the console in characters.
Dimensions() (uint16, uint16) Dimensions() (uint32, uint32)
// DefaultColors returns the default foreground and background colors // DefaultColors returns the default foreground and background colors
// used by this console. // used by this console.
@ -24,16 +24,16 @@ type Device interface {
// Fill sets the contents of the specified rectangular region to the // Fill sets the contents of the specified rectangular region to the
// requested color. Both x and y coordinates are 1-based (top-left // requested color. Both x and y coordinates are 1-based (top-left
// corner has coordinates 1,1). // corner has coordinates 1,1).
Fill(x, y, width, height uint16, fg, bg uint8) Fill(x, y, width, height uint32, fg, bg uint8)
// Scroll the console contents to the specified direction. The caller // Scroll the console contents to the specified direction. The caller
// is responsible for updating (e.g. clear or replace) the contents of // is responsible for updating (e.g. clear or replace) the contents of
// the region that was scrolled. // the region that was scrolled.
Scroll(dir ScrollDir, lines uint16) Scroll(dir ScrollDir, lines uint32)
// Write a char to the specified location. Both x and y coordinates are // Write a char to the specified location. Both x and y coordinates are
// 1-based (top-left corner has coordinates 1,1). // 1-based (top-left corner has coordinates 1,1).
Write(ch byte, fg, bg uint8, x, y uint16) Write(ch byte, fg, bg uint8, x, y uint32)
// Palette returns the active color palette for this console. // Palette returns the active color palette for this console.
Palette() color.Palette Palette() color.Palette

View File

@ -24,8 +24,8 @@ var portWriteByteFn = cpu.PortWriteByte
// - light gray text (color 7) on black background (color 0). // - light gray text (color 7) on black background (color 0).
// - space as the clear character // - space as the clear character
type VgaTextConsole struct { type VgaTextConsole struct {
width uint16 width uint32
height uint16 height uint32
fb []uint16 fb []uint16
@ -37,15 +37,15 @@ type VgaTextConsole struct {
// NewVgaTextConsole creates an new vga text console with its // NewVgaTextConsole creates an new vga text console with its
// framebuffer mapped to fbPhysAddr. // framebuffer mapped to fbPhysAddr.
func NewVgaTextConsole(columns, rows uint16, fbPhysAddr uintptr) *VgaTextConsole { func NewVgaTextConsole(columns, rows uint32, fbPhysAddr uintptr) *VgaTextConsole {
return &VgaTextConsole{ return &VgaTextConsole{
width: columns, width: columns,
height: rows, height: rows,
clearChar: uint16(' '), clearChar: uint16(' '),
// overlay a 16bit slice over the fbPhysAddr // overlay a 16bit slice over the fbPhysAddr
fb: *(*[]uint16)(unsafe.Pointer(&reflect.SliceHeader{ fb: *(*[]uint16)(unsafe.Pointer(&reflect.SliceHeader{
Len: 80 * 25, Len: int(columns * rows),
Cap: 80 * 25, Cap: int(columns * rows),
Data: fbPhysAddr, Data: fbPhysAddr,
})), })),
palette: color.Palette{ palette: color.Palette{
@ -73,7 +73,7 @@ func NewVgaTextConsole(columns, rows uint16, fbPhysAddr uintptr) *VgaTextConsole
} }
// Dimensions returns the console width and height in characters. // Dimensions returns the console width and height in characters.
func (cons *VgaTextConsole) Dimensions() (uint16, uint16) { func (cons *VgaTextConsole) Dimensions() (uint32, uint32) {
return cons.width, cons.height return cons.width, cons.height
} }
@ -85,10 +85,10 @@ func (cons *VgaTextConsole) DefaultColors() (fg uint8, bg uint8) {
// Fill sets the contents of the specified rectangular region to the requested // Fill sets the contents of the specified rectangular region to the requested
// color. Both x and y coordinates are 1-based. // color. Both x and y coordinates are 1-based.
func (cons *VgaTextConsole) Fill(x, y, width, height uint16, fg, bg uint8) { func (cons *VgaTextConsole) Fill(x, y, width, height uint32, fg, bg uint8) {
var ( var (
clr = (((uint16(bg) << 4) | uint16(fg)) << 8) | cons.clearChar clr = (((uint16(bg) << 4) | uint16(fg)) << 8) | cons.clearChar
rowOffset, colOffset uint16 rowOffset, colOffset uint32
) )
// clip rectangle // clip rectangle
@ -104,12 +104,12 @@ func (cons *VgaTextConsole) Fill(x, y, width, height uint16, fg, bg uint8) {
y = cons.height y = cons.height
} }
if x+width > cons.width { if x+width-1 > cons.width {
width = cons.width - x width = cons.width - x + 1
} }
if y+height > cons.height { if y+height-1 > cons.height {
height = cons.height - y height = cons.height - y + 1
} }
rowOffset = ((y - 1) * cons.width) + (x - 1) rowOffset = ((y - 1) * cons.width) + (x - 1)
@ -123,12 +123,12 @@ func (cons *VgaTextConsole) Fill(x, y, width, height uint16, fg, bg uint8) {
// Scroll the console contents to the specified direction. The caller // Scroll the console contents to the specified direction. The caller
// is responsible for updating (e.g. clear or replace) the contents of // is responsible for updating (e.g. clear or replace) the contents of
// the region that was scrolled. // the region that was scrolled.
func (cons *VgaTextConsole) Scroll(dir ScrollDir, lines uint16) { func (cons *VgaTextConsole) Scroll(dir ScrollDir, lines uint32) {
if lines == 0 || lines > cons.height { if lines == 0 || lines > cons.height {
return return
} }
var i uint16 var i uint32
offset := lines * cons.width offset := lines * cons.width
switch dir { switch dir {
@ -146,7 +146,7 @@ func (cons *VgaTextConsole) Scroll(dir ScrollDir, lines uint16) {
// Write a char to the specified location. If fg or bg exceed the supported // Write a char to the specified location. If fg or bg exceed the supported
// colors for this console, they will be set to their default value. Both x and // colors for this console, they will be set to their default value. Both x and
// y coordinates are 1-based // y coordinates are 1-based
func (cons *VgaTextConsole) Write(ch byte, fg, bg uint8, x, y uint16) { func (cons *VgaTextConsole) Write(ch byte, fg, bg uint8, x, y uint32) {
if x < 1 || x > cons.width || y < 1 || y > cons.height { if x < 1 || x > cons.width || y < 1 || y > cons.height {
return return
} }
@ -205,7 +205,7 @@ func probeForVgaTextConsole() device.Driver {
fbInfo := getFramebufferInfoFn() fbInfo := getFramebufferInfoFn()
if fbInfo.Type == multiboot.FramebufferTypeEGA { if fbInfo.Type == multiboot.FramebufferTypeEGA {
drv = NewVgaTextConsole(uint16(fbInfo.Width), uint16(fbInfo.Height), uintptr(fbInfo.PhysAddr)) drv = NewVgaTextConsole(fbInfo.Width, fbInfo.Height, uintptr(fbInfo.PhysAddr))
} }
return drv return drv

View File

@ -11,8 +11,8 @@ import (
) )
func TestVgaTextDimensions(t *testing.T) { func TestVgaTextDimensions(t *testing.T) {
cons := NewVgaTextConsole(80, 25, 0) var cons Device = NewVgaTextConsole(40, 50, 0)
if w, h := cons.Dimensions(); w != 80 || h != 25 { if w, h := cons.Dimensions(); w != 40 || h != 50 {
t.Fatalf("expected console dimensions to be 80x25; got %dx%d", w, h) t.Fatalf("expected console dimensions to be 80x25; got %dx%d", w, h)
} }
} }
@ -27,34 +27,38 @@ func TestVgaTextDefaultColors(t *testing.T) {
func TestVgaTextFill(t *testing.T) { func TestVgaTextFill(t *testing.T) {
specs := []struct { specs := []struct {
// Input rect // Input rect
x, y, w, h uint16 x, y, w, h uint32
// Expected area to be cleared // Expected area to be cleared
expX, expY, expW, expH uint16 expStartX, expStartY, expEndX, expEndY uint32
}{ }{
{ {
0, 0, 500, 500, 0, 0, 500, 500,
0, 0, 80, 25, 1, 1, 80, 25,
}, },
{ {
10, 10, 11, 50, 10, 10, 11, 50,
10, 10, 11, 15, 10, 10, 20, 25,
}, },
{ {
10, 10, 110, 1, 10, 10, 110, 1,
10, 10, 70, 1, 10, 10, 80, 10,
}, },
{ {
70, 20, 20, 20, 70, 20, 20, 20,
70, 20, 10, 5, 70, 20, 80, 39,
}, },
{ {
90, 25, 20, 20, 90, 25, 20, 20,
0, 0, 0, 0, 80, 25, 80, 25,
}, },
{ {
12, 12, 5, 6, 12, 12, 5, 6,
12, 12, 5, 6, 12, 12, 16, 17,
},
{
80, 25, 1, 1,
80, 25, 80, 25,
}, },
} }
@ -74,12 +78,12 @@ nextSpec:
cons.Fill(spec.x, spec.y, spec.w, spec.h, 0, 0) cons.Fill(spec.x, spec.y, spec.w, spec.h, 0, 0)
var x, y uint16 var x, y uint32
for y = 1; y <= ch; y++ { for y = 1; y <= ch; y++ {
for x = 1; x <= cw; x++ { for x = 1; x <= cw; x++ {
fbVal := fb[((y-1)*cw)+(x-1)] fbVal := fb[((y-1)*cw)+(x-1)]
if x < spec.expX || y < spec.expY || x >= spec.expX+spec.expW || y >= spec.expY+spec.expH { if x < spec.expStartX || y < spec.expStartY || x > spec.expEndX || y > spec.expEndY {
if fbVal != testPat { if fbVal != testPat {
t.Errorf("[spec %d] expected char at (%d, %d) not to be cleared", specIndex, x, y) t.Errorf("[spec %d] expected char at (%d, %d) not to be cleared", specIndex, x, y)
continue nextSpec continue nextSpec
@ -101,7 +105,7 @@ func TestVgaTextScroll(t *testing.T) {
cw, ch := cons.Dimensions() cw, ch := cons.Dimensions()
t.Run("up", func(t *testing.T) { t.Run("up", func(t *testing.T) {
specs := []uint16{ specs := []uint32{
0, 0,
1, 1,
2, 2,
@ -109,10 +113,10 @@ func TestVgaTextScroll(t *testing.T) {
nextSpec: nextSpec:
for specIndex, lines := range specs { for specIndex, lines := range specs {
// Fill buffer with test pattern // Fill buffer with test pattern
var x, y, index uint16 var x, y, index uint32
for y = 0; y < ch; y++ { for y = 0; y < ch; y++ {
for x = 0; x < cw; x++ { for x = 0; x < cw; x++ {
fb[index] = (y << 8) | x fb[index] = uint16((y << 8) | x)
index++ index++
} }
} }
@ -123,7 +127,7 @@ func TestVgaTextScroll(t *testing.T) {
index = 0 index = 0
for y = 0; y < ch-lines; y++ { for y = 0; y < ch-lines; y++ {
for x = 0; x < cw; x++ { for x = 0; x < cw; x++ {
expVal := ((y + lines) << 8) | x expVal := uint16(((y + lines) << 8) | x)
if fb[index] != expVal { if fb[index] != expVal {
t.Errorf("[spec %d] expected value at (%d, %d) to be %d; got %d", specIndex, x, y, expVal, fb[index]) t.Errorf("[spec %d] expected value at (%d, %d) to be %d; got %d", specIndex, x, y, expVal, fb[index])
continue nextSpec continue nextSpec
@ -135,7 +139,7 @@ func TestVgaTextScroll(t *testing.T) {
}) })
t.Run("down", func(t *testing.T) { t.Run("down", func(t *testing.T) {
specs := []uint16{ specs := []uint32{
0, 0,
1, 1,
2, 2,
@ -144,10 +148,10 @@ func TestVgaTextScroll(t *testing.T) {
nextSpec: nextSpec:
for specIndex, lines := range specs { for specIndex, lines := range specs {
// Fill buffer with test pattern // Fill buffer with test pattern
var x, y, index uint16 var x, y, index uint32
for y = 0; y < ch; y++ { for y = 0; y < ch; y++ {
for x = 0; x < cw; x++ { for x = 0; x < cw; x++ {
fb[index] = (y << 8) | x fb[index] = uint16((y << 8) | x)
index++ index++
} }
} }
@ -158,7 +162,7 @@ func TestVgaTextScroll(t *testing.T) {
index = lines * cw index = lines * cw
for y = lines; y < ch-lines; y++ { for y = lines; y < ch-lines; y++ {
for x = 0; x < cw; x++ { for x = 0; x < cw; x++ {
expVal := ((y - lines) << 8) | x expVal := uint16(((y - lines) << 8) | x)
if fb[index] != expVal { if fb[index] != expVal {
t.Errorf("[spec %d] expected value at (%d, %d) to be %d; got %d", specIndex, x, y, expVal, fb[index]) t.Errorf("[spec %d] expected value at (%d, %d) to be %d; got %d", specIndex, x, y, expVal, fb[index])
continue nextSpec continue nextSpec
@ -177,7 +181,7 @@ func TestVgaTextWrite(t *testing.T) {
t.Run("off-screen", func(t *testing.T) { t.Run("off-screen", func(t *testing.T) {
specs := []struct { specs := []struct {
x, y uint16 x, y uint32
}{ }{
{81, 26}, {81, 26},
{90, 24}, {90, 24},