256b disk sec

This commit is contained in:
Роман Бойков 2026-03-06 22:31:52 +03:00
parent b133807f05
commit 50f4e2521f
9 changed files with 69 additions and 60 deletions

24
main.go
View File

@ -23,7 +23,7 @@ var BuildTime = "2026-03-01"
//go:embed hex/format.hex //go:embed hex/format.hex
var serialBytes []byte var serialBytes []byte
//go:embed bin/TYPE.COM //go:embed bin/MB.COM
var ramBytes []byte var ramBytes []byte
var needReset = false var needReset = false
@ -72,7 +72,13 @@ func mainWindow(computer *okean240.ComputerType, emuConfig *config.OkEmuConfig)
raster := canvas.NewRasterWithPixels( raster := canvas.NewRasterWithPixels(
func(x, y, w, h int) color.Color { func(x, y, w, h int) color.Color {
return computer.GetPixel(uint16(x/2), uint16(y/2)) var xx uint16
if computer.ScreenWidth() == 512 {
xx = uint16(x)
} else {
xx = uint16(x) / 2
}
return computer.GetPixel(xx, uint16(y/2))
}) })
raster.Resize(fyne.NewSize(512, 512)) raster.Resize(fyne.NewSize(512, 512))
raster.SetMinSize(fyne.NewSize(512, 512)) raster.SetMinSize(fyne.NewSize(512, 512))
@ -130,7 +136,7 @@ func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *wid
var freq uint64 = 0 var freq uint64 = 0
nextSecond := time.Now().Add(time.Second).UnixMicro() nextSecond := time.Now().Add(time.Second).UnixMicro()
curScrWidth := 256 //curScrWidth := 256
for range ticker.C { for range ticker.C {
if needReset { if needReset {
computer.Reset(emuConfig) computer.Reset(emuConfig)
@ -159,12 +165,12 @@ func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *wid
// redraw screen here // redraw screen here
fyne.Do(func() { fyne.Do(func() {
// check for screen mode changed // check for screen mode changed
if computer.ScreenWidth() != curScrWidth { //if computer.ScreenWidth() != curScrWidth {
curScrWidth = computer.ScreenWidth() // curScrWidth = computer.ScreenWidth()
newSize := fyne.NewSize(float32(curScrWidth*2), float32(computer.ScreenHeight()*2)) // newSize := fyne.NewSize(float32(curScrWidth*2), float32(computer.ScreenHeight()*2))
raster.SetMinSize(newSize) // raster.SetMinSize(newSize)
raster.Resize(newSize) // raster.Resize(newSize)
} //}
// status for every 25 frames // status for every 25 frames
if frame%50 == 0 { if frame%50 == 0 {
label.SetText(fmt.Sprintf("Screen size: %dx%d F: %d", computer.ScreenWidth(), computer.ScreenHeight(), freq)) label.SetText(fmt.Sprintf("Screen size: %dx%d F: %d", computer.ScreenWidth(), computer.ScreenHeight(), freq))

View File

@ -5,7 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"image/color" "image/color"
"okemu/config" "okemu/config"
fdc2 "okemu/okean240/fdc" "okemu/okean240/fdc"
"okemu/okean240/pic" "okemu/okean240/pic"
"okemu/okean240/pit" "okemu/okean240/pit"
"okemu/okean240/usart" "okemu/okean240/usart"
@ -17,7 +17,7 @@ import (
) )
type ComputerType struct { type ComputerType struct {
cpu z80em.Z80Type cpu *z80em.Z80Type
memory Memory memory Memory
ioPorts [256]byte ioPorts [256]byte
cycles uint64 cycles uint64
@ -28,10 +28,10 @@ type ComputerType struct {
vRAM *RamBlock vRAM *RamBlock
palette byte palette byte
bgColor byte bgColor byte
dd70 *pit.I8253 pit *pit.I8253
dd72 *usart.I8251 usart *usart.I8251
dd75 *pic.I8259 pic *pic.I8259
fdc *fdc2.FloppyDriveController fdc *fdc.FloppyDriveController
kbdBuffer []byte kbdBuffer []byte
vShift byte vShift byte
hShift byte hShift byte
@ -41,7 +41,6 @@ const VRAMBlock0 = 3
const VRAMBlock1 = 7 const VRAMBlock1 = 7
const VidVsuBit = 0x80 const VidVsuBit = 0x80
const VidColorBit = 0x40 const VidColorBit = 0x40
const KbdBufferSize = 3
type ComputerInterface interface { type ComputerInterface interface {
Run() Run()
@ -75,7 +74,7 @@ func New(cfg *config.OkEmuConfig) *ComputerType {
c.memory = Memory{} c.memory = Memory{}
c.memory.Init(cfg.MonitorFile, cfg.CPMFile) c.memory.Init(cfg.MonitorFile, cfg.CPMFile)
c.cpu = *z80em.New(&c) c.cpu = z80em.New(&c)
c.cycles = 0 c.cycles = 0
c.dd17EnableOut = false c.dd17EnableOut = false
@ -88,10 +87,10 @@ func New(cfg *config.OkEmuConfig) *ComputerType {
c.vShift = 0 c.vShift = 0
c.hShift = 0 c.hShift = 0
c.dd70 = pit.NewI8253() c.pit = pit.New()
c.dd72 = usart.NewI8251() c.usart = usart.New()
c.dd75 = pic.NewI8259() c.pic = pic.New()
c.fdc = fdc2.NewFDCType() c.fdc = fdc.New()
return &c return &c
} }
@ -120,9 +119,9 @@ func (c *ComputerType) Do() int {
//} //}
ticks := uint64(c.cpu.RunInstruction()) ticks := uint64(c.cpu.RunInstruction())
c.cycles += ticks c.cycles += ticks
//if c.cpu.PC == 0x2C2 { if c.cpu.PC == 0xFF26 {
// log.Debugf("%4X: H:%X L:%X", c.cpu.PC, c.cpu.H, c.cpu.L) log.Debugf("%4X: H:%X L:%X A:%X B: %X C: %X D: %X E: %X", c.cpu.PC, c.cpu.H, c.cpu.L, c.cpu.A, c.cpu.B, c.cpu.C, c.cpu.D, c.cpu.E)
//} }
return int(ticks) return int(ticks)
} }
@ -140,16 +139,16 @@ func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
} }
y += uint16(c.vShift) & 0x00ff y += uint16(c.vShift) & 0x00ff
x += uint16(c.hShift) & 0x00ff x += uint16(c.hShift-7) & 0x00ff
// Color 256x256 mode // Color 256x256 mode
addr = ((x & 0xf8) << 6) | (y & 0xff) addr = ((x & 0xf8) << 6) | y
if c.vShift != 0 { //if c.vShift != 0 {
addr -= 8 // addr -= 8
} //}
cl := (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1 cl := (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1
cl |= (c.vRAM.memory[(addr+0x100)&0x3fff] >> (x & 0x07)) & 1 << 1 cl |= ((c.vRAM.memory[(addr+0x100)&0x3fff] >> (x & 0x07)) & 1) << 1
if cl == 0 { if cl == 0 {
resColor = BgColorPalette[c.bgColor] resColor = BgColorPalette[c.bgColor]
} else { } else {
@ -159,18 +158,22 @@ func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
if x > 511 { if x > 511 {
return CWhite return CWhite
} }
// Shifts
y += uint16(c.vShift) & 0x00ff
x += uint16(c.hShift-7) & 0x001ff
// Mono 512x256 mode // Mono 512x256 mode
y += uint16(c.vShift) addr = ((x & 0x1f8) << 5) | y
addr = ((x & 0xf8) << 5) | (y & 0xff) pix := c.vRAM.memory[addr] >> (x & 0x07) & 1
pix := c.vRAM.memory[addr]&(1<<x) != 0
if c.palette == 6 { if c.palette == 6 {
if !pix { if pix == 0 {
resColor = CBlack resColor = CBlack
} else { } else {
resColor = CLGreen resColor = CLGreen
} }
} else { } else {
if !pix { if pix == 0 {
resColor = BgColorPalette[c.bgColor] resColor = BgColorPalette[c.bgColor]
} else { } else {
resColor = MonoPalette[c.bgColor] resColor = MonoPalette[c.bgColor]
@ -194,17 +197,17 @@ func (c *ComputerType) Cycles() uint64 {
func (c *ComputerType) TimerClk() { func (c *ComputerType) TimerClk() {
// DD70 KR580VI53 CLK0, CKL1 @ 1.5MHz // DD70 KR580VI53 CLK0, CKL1 @ 1.5MHz
c.dd70.Tick(0) c.pit.Tick(0)
c.dd70.Tick(1) c.pit.Tick(1)
// IRQ from timer // IRQ from timer
if c.dd70.Fired(0) { if c.pit.Fired(0) {
c.dd75.SetIRQ(RstTimerNo) c.pic.SetIRQ(RstTimerNo)
//c.ioPorts[PIC_DD75RS] |= Rst4Mask //c.ioPorts[PIC_DD75RS] |= Rst4Mask
} }
// clock for SIO KR580VV51 // clock for SIO KR580VV51
if c.dd70.Fired(1) { if c.pit.Fired(1) {
c.dd72.Tick() c.usart.Tick()
} }
} }
@ -217,7 +220,7 @@ func (c *ComputerType) SaveFloppy() {
} }
func (c *ComputerType) SetSerialBytes(bytes []byte) { func (c *ComputerType) SetSerialBytes(bytes []byte) {
c.dd72.SetRxBytes(bytes) c.usart.SetRxBytes(bytes)
} }
func (c *ComputerType) SetRamBytes(bytes []byte) { func (c *ComputerType) SetRamBytes(bytes []byte) {

View File

@ -321,7 +321,7 @@ func (f *FloppyDriveController) SaveFloppy() {
} }
func NewFDCType() *FloppyDriveController { func New() *FloppyDriveController {
sec := [SizeInSectors]SectorType{} sec := [SizeInSectors]SectorType{}
for i := 0; i < SizeInSectors; i++ { for i := 0; i < SizeInSectors; i++ {
sec[i] = make([]byte, SectorSize) sec[i] = make([]byte, SectorSize)

View File

@ -14,13 +14,13 @@ func (c *ComputerType) IORead(port uint16) byte {
switch port & 0x00ff { switch port & 0x00ff {
case PIC_DD75A: case PIC_DD75A:
// PIO xx59, get IRR register // PIO xx59, get IRR register
return c.dd75.IRR() return c.pic.IRR()
case UART_DD72RR: case UART_DD72RR:
// USART VV51 CMD // USART VV51 CMD
return c.dd72.Status() return c.usart.Status()
case UART_DD72RD: case UART_DD72RD:
// USART VV51 Data // USART VV51 Data
return c.dd72.Receive() return c.usart.Receive()
case KBD_DD78PA: case KBD_DD78PA:
// Keyboard data // Keyboard data
return c.ioPorts[KBD_DD78PA] return c.ioPorts[KBD_DD78PA]
@ -79,23 +79,23 @@ func (c *ComputerType) IOWrite(port uint16, val byte) {
c.hShift = val c.hShift = val
case TMR_DD70CTR: case TMR_DD70CTR:
// Timer VI63 config register // Timer VI63 config register
c.dd70.Configure(val) c.pit.Configure(val)
case TMR_DD70C1: case TMR_DD70C1:
// Timer VI63 counter0 register // Timer VI63 counter0 register
c.dd70.Load(0, val) c.pit.Load(0, val)
case TMR_DD70C2: case TMR_DD70C2:
// Timer VI63 counter1 register // Timer VI63 counter1 register
c.dd70.Load(1, val) c.pit.Load(1, val)
case TMR_DD70C3: case TMR_DD70C3:
// Timer VI63 counter2 register // Timer VI63 counter2 register
c.dd70.Load(2, val) c.pit.Load(2, val)
case UART_DD72RR: case UART_DD72RR:
// USART VV51 CMD // USART VV51 CMD
c.dd72.Command(val) c.usart.Command(val)
case UART_DD72RD: case UART_DD72RD:
// USART VV51 Data // USART VV51 Data
c.dd72.Send(val) c.usart.Send(val)
case FDC_CMD: case FDC_CMD:
c.fdc.SetCmd(val) c.fdc.SetCmd(val)
case FDC_DATA: case FDC_DATA:

View File

@ -10,7 +10,7 @@ func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
if code > 0 { if code > 0 {
//log.Debugf("PutKey keyName: %s", key.Name) //log.Debugf("PutKey keyName: %s", key.Name)
c.ioPorts[KBD_DD78PA] = code c.ioPorts[KBD_DD78PA] = code
c.dd75.SetIRQ(RstKbdNo) c.pic.SetIRQ(RstKbdNo)
} }
} }
@ -20,7 +20,7 @@ func (c *ComputerType) PutRune(key rune) {
//log.Debugf("Put Rune: %c Lo: %x, Hi: %x", key, key&0xff, key>>8) //log.Debugf("Put Rune: %c Lo: %x, Hi: %x", key, key&0xff, key>>8)
c.ioPorts[KBD_DD78PA] = byte(key & 0xff) c.ioPorts[KBD_DD78PA] = byte(key & 0xff)
c.dd75.SetIRQ(RstKbdNo) c.pic.SetIRQ(RstKbdNo)
} }
/* /*
@ -38,7 +38,7 @@ func (c *ComputerType) PutRune(key rune) {
func (c *ComputerType) PutCtrlKey(key byte) { func (c *ComputerType) PutCtrlKey(key byte) {
c.ioPorts[KBD_DD78PA] = key c.ioPorts[KBD_DD78PA] = key
c.dd75.SetIRQ(RstKbdNo) c.pic.SetIRQ(RstKbdNo)
//c.ioPorts[PIC_DD75RS] |= Rst1Mask //c.ioPorts[PIC_DD75RS] |= Rst1Mask
c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20 c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20
} }

View File

@ -47,7 +47,7 @@ func (c *I8259) SetIRQ(irq byte) {
} }
} }
func NewI8259() *I8259 { func New() *I8259 {
return &I8259{ return &I8259{
irr: 0, irr: 0,
} }

View File

@ -47,7 +47,7 @@ type I8253Interface interface {
Start(chNo int) bool Start(chNo int) bool
} }
func NewI8253() *I8253 { func New() *I8253 {
return &I8253{ return &I8253{
//chNo: 0, //chNo: 0,
channel: [3]Timer8253Ch{ channel: [3]Timer8253Ch{

View File

@ -4,7 +4,7 @@ import "fyne.io/fyne/v2"
var RemapCmdKey = map[fyne.KeyName]byte{ var RemapCmdKey = map[fyne.KeyName]byte{
fyne.KeyEscape: 0x1B, fyne.KeyEscape: 0x1B,
fyne.KeyReturn: 0x0A, fyne.KeyReturn: 0x0D,
fyne.KeyTab: 0x09, fyne.KeyTab: 0x09,
fyne.KeyBackspace: 0x08, fyne.KeyBackspace: 0x08,
fyne.KeyInsert: 0x00, fyne.KeyInsert: 0x00,
@ -29,7 +29,7 @@ var RemapCmdKey = map[fyne.KeyName]byte{
fyne.KeyF10: 0x00, fyne.KeyF10: 0x00,
fyne.KeyF11: 0x00, fyne.KeyF11: 0x00,
fyne.KeyF12: 0x00, fyne.KeyF12: 0x00,
fyne.KeyEnter: 0x0D, fyne.KeyEnter: 0x0A,
fyne.KeyUnknown: 0x00, fyne.KeyUnknown: 0x00,
} }

View File

@ -47,7 +47,7 @@ type I8251Interface interface {
Receive() byte Receive() byte
} }
func NewI8251() *I8251 { func New() *I8251 {
return &I8251{ return &I8251{
counter: 0, counter: 0,
mode: 0, mode: 0,