MC6845 Cursor modes

This commit is contained in:
Ivan Izaguirre 2021-03-14 22:38:41 +01:00
parent f15a7bb9d2
commit c390be1ced
2 changed files with 36 additions and 8 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt"
"image"
"image/color"
"time"
"github.com/ivanizag/izapple2/component"
"github.com/ivanizag/izapple2/storage"
@ -125,22 +126,37 @@ func (c *CardVidex) buildImage(light color.Color) *image.RGBA {
img.Set(1, 1, color.White)
return img
}
ms := time.Now().Nanosecond() / (1000 * 1000) // Host time, used for the cursoR blink
size := image.Rect(0, 0, width, height)
img := image.NewRGBA(size)
params.IterateScreen(func(address uint16, charLine uint8,
cursor bool, displayEnable bool,
cursorMode uint8, displayEnable bool,
column uint8, y int) {
bits := uint8(0)
if displayEnable {
char := c.sram[address&0x7ff]
bits = c.charGen[(uint16(char&0x7f)<<4)+uint16(charLine)]
if cursor {
isCursor := false
switch cursorMode {
case component.MC6845CursorFixed:
isCursor = true
case component.MC6845CursorSlow:
// It should be 533ms (32/60, 32 screen refreshes)
// Let's make a 2 blinks per second
isCursor = ms/2 > 1000/4
case component.MC6845CursorFast:
// It should be 266ms (32/60, 16 screen refreshes)
// Let's make a 4 blinks per second
isCursor = ms/4 > 1000/8
}
if isCursor {
bits = ^bits
}
if char >= 128 {
// Inverse
bits = ^bits
}
}

View File

@ -51,10 +51,17 @@ func (m *MC6845) ImageData() MC6845ImageData {
data.cursorPos = uint16(m.reg[14]&0x3f)<<8 + uint16(m.reg[15])
data.cursorStart = m.reg[10] & 0x1f
data.cursorEnd = m.reg[11] & 0x1f
// cursor mode is on bits 6 and 5 of R10
data.cursorMode = (m.reg[10] >> 5) & 0x03 // Bit 6 and 5
return data
}
const (
MC6845CursorFixed = uint8(0)
MC6845CursorNone = uint8(1)
MC6845CursorFast = uint8(2)
MC6845CursorSlow = uint8(3)
)
type MC6845ImageData struct {
firstChar uint16 // 14 bits, address of the firt char on the first line
charLines uint8 // 5 bits, lines par character
@ -64,8 +71,8 @@ type MC6845ImageData struct {
cursorPos uint16 // 14 bits, address? of the cursor position
cursorStart uint8 // 5 bits, cursor starting char row
cursorEnd uint8 // 5 bits, cursos ending char row
// cursor mode
cursorEnd uint8 // 5 bits, cursor ending char row
cursorMode uint8 // 2 bits, cursor mode
}
@ -75,7 +82,7 @@ func (data *MC6845ImageData) DisplayedWidthHeight(charWidth uint8) (int, int) {
}
type MC6845RasterCallBack func(address uint16, charLine uint8, // Lookup in char ROM
cursor bool, displayEnable bool, // Modifiers
cursorMode uint8, displayEnable bool, // Modifiers
column uint8, y int) // Position in screen
func (data *MC6845ImageData) IterateScreen(callBack MC6845RasterCallBack) {
@ -86,10 +93,15 @@ func (data *MC6845ImageData) IterateScreen(callBack MC6845RasterCallBack) {
for charLine := uint8(0); charLine < data.charLines; charLine++ {
address = lineAddress // Back to the first char of the line
for column := uint8(0); column < data.columns; column++ {
cursorMode := MC6845CursorNone
isCursor := (address == data.cursorPos) &&
(charLine >= data.cursorStart) &&
(charLine <= data.cursorEnd)
callBack(address, charLine, isCursor, true, column, y)
if isCursor {
cursorMode = data.cursorMode
}
callBack(address, charLine, cursorMode, true, column, y)
address = (address + 1) & 0x3fff // 14 bits
}
y++
@ -98,7 +110,7 @@ func (data *MC6845ImageData) IterateScreen(callBack MC6845RasterCallBack) {
}
for adjust := uint8(0); adjust <= data.adjustLines; adjust++ {
for column := uint8(0); column < data.columns; column++ {
callBack(0, 0, false, false, column, y) // lines with display not enabled
callBack(0, 0, MC6845CursorNone, false, column, y) // lines with display not enabled
}
y++
}