mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-14 23:30:31 +00:00
Move disk related code to a separate package
This commit is contained in:
parent
7329d4f042
commit
18e0363d84
@ -219,8 +219,6 @@ Only valid on SDL mode
|
||||
dump to the console the sofswitch registrations
|
||||
-vidHDSlot int
|
||||
slot for the VidHD card, only for //e models. -1 for none (default 2)
|
||||
-woz string
|
||||
show WOZ file information
|
||||
|
||||
|
||||
```
|
||||
|
@ -148,10 +148,10 @@ func (a *Apple2) executeCommand(command int) {
|
||||
switch command {
|
||||
case CommandToggleSpeed:
|
||||
if a.cycleDurationNs == 0 {
|
||||
fmt.Println("Slow")
|
||||
//fmt.Println("Slow")
|
||||
a.cycleDurationNs = 1000.0 / CPUClockMhz
|
||||
} else {
|
||||
fmt.Println("Fast")
|
||||
//fmt.Println("Fast")
|
||||
a.cycleDurationNs = 0
|
||||
}
|
||||
case CommandShowSpeed:
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/ivanizag/izapple2/core6502"
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
func newApple2() *Apple2 {
|
||||
@ -71,7 +72,7 @@ const (
|
||||
|
||||
// LoadRom loads a standard Apple2+ or 2e ROM
|
||||
func (a *Apple2) LoadRom(filename string) error {
|
||||
data, err := loadResource(filename)
|
||||
data, err := storage.LoadResource(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -92,7 +93,7 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
||||
a.insertCard(c, slot)
|
||||
|
||||
if diskImage != "" {
|
||||
diskette, err := loadDiskette(diskImage)
|
||||
diskette, err := storage.LoadDiskette(diskImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -100,7 +101,7 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
||||
}
|
||||
|
||||
if diskBImage != "" {
|
||||
diskette, err := loadDiskette(diskBImage)
|
||||
diskette, err := storage.LoadDiskette(diskBImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package izapple2
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
const defaultInternal = "<default>"
|
||||
@ -25,10 +27,6 @@ func MainApple() *Apple2 {
|
||||
"diskb",
|
||||
"",
|
||||
"file to load on the second disk drive")
|
||||
wozImage := flag.String(
|
||||
"woz",
|
||||
"",
|
||||
"show WOZ file information")
|
||||
hardDiskImage := flag.String(
|
||||
"hd",
|
||||
"",
|
||||
@ -133,23 +131,13 @@ func MainApple() *Apple2 {
|
||||
diskImageFinal := *diskImage
|
||||
hardDiskImageFinal := *hardDiskImage
|
||||
if filename != "" {
|
||||
if isDiskette(filename) {
|
||||
if storage.IsDiskette(filename) {
|
||||
diskImageFinal = filename
|
||||
} else {
|
||||
hardDiskImageFinal = filename
|
||||
}
|
||||
}
|
||||
|
||||
if *wozImage != "" {
|
||||
f, err := loadFileWoz(*wozImage)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f.dump()
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
a := newApple2()
|
||||
a.setup(*cpuClock, *fastDisk, *traceMLI)
|
||||
a.io.setTrace(*traceSS)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ivanizag/izapple2/core6502"
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -35,7 +36,7 @@ func loadBase64aRom(a *Apple2) error {
|
||||
|
||||
for i := 0; i < base64aRomChipCount; i++ {
|
||||
filename := fmt.Sprintf("<internal>/BASE64A_%X.BIN", 0xd0+i*0x08)
|
||||
data, err := loadResource(filename)
|
||||
data, err := storage.LoadResource(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package izapple2
|
||||
|
||||
import "github.com/ivanizag/izapple2/storage"
|
||||
|
||||
// Card represents an Apple II card to be inserted in a slot
|
||||
type Card interface {
|
||||
loadRom(data []uint8)
|
||||
@ -32,7 +34,7 @@ func (c *cardBase) GetInfo() map[string]string {
|
||||
}
|
||||
|
||||
func (c *cardBase) loadRomFromResource(resource string) {
|
||||
data, err := loadResource(resource)
|
||||
data, err := storage.LoadResource(resource)
|
||||
if err != nil {
|
||||
// The resource should be internal and never fail
|
||||
panic(err)
|
||||
|
14
cardDisk2.go
14
cardDisk2.go
@ -3,6 +3,8 @@ package izapple2
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -33,7 +35,7 @@ type CardDisk2 struct {
|
||||
|
||||
type cardDisk2Drive struct {
|
||||
name string
|
||||
diskette diskette
|
||||
diskette storage.Diskette
|
||||
power bool // q4
|
||||
phases uint8 // q3, q2, q1 and q0 with q0 on the LSB. Magnets that are active on the stepper motor
|
||||
tracksStep int // Stepmotor for tracks position. 4 steps per track
|
||||
@ -102,7 +104,7 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
||||
drive.power = false
|
||||
c.a.releaseFastMode()
|
||||
if drive.diskette != nil {
|
||||
drive.diskette.powerOff(c.a.cpu.GetCycles())
|
||||
drive.diskette.PowerOff(c.a.cpu.GetCycles())
|
||||
}
|
||||
}
|
||||
return c.dataLatch
|
||||
@ -113,7 +115,7 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
||||
drive.power = true
|
||||
c.a.requestFastMode()
|
||||
if drive.diskette != nil {
|
||||
drive.diskette.powerOn(c.a.cpu.GetCycles())
|
||||
drive.diskette.PowerOn(c.a.cpu.GetCycles())
|
||||
}
|
||||
}
|
||||
return 0
|
||||
@ -173,9 +175,9 @@ func (c *CardDisk2) processQ6Q7(in uint8) {
|
||||
}
|
||||
if !c.q6 { // shift
|
||||
if !c.q7 { // Q6L-Q7L: Read
|
||||
c.dataLatch = d.diskette.read(d.tracksStep, c.a.cpu.GetCycles())
|
||||
c.dataLatch = d.diskette.Read(d.tracksStep, c.a.cpu.GetCycles())
|
||||
} else { // Q6L-Q7H: Write the dataLatch value to disk. Shift data out
|
||||
d.diskette.write(d.tracksStep, c.dataLatch, c.a.cpu.GetCycles())
|
||||
d.diskette.Write(d.tracksStep, c.dataLatch, c.a.cpu.GetCycles())
|
||||
}
|
||||
} else { // load
|
||||
if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state
|
||||
@ -269,7 +271,7 @@ func moveStep(phases uint8, prevStep int) int {
|
||||
return nextStep
|
||||
}
|
||||
|
||||
func (d *cardDisk2Drive) insertDiskette(name string, dt diskette) {
|
||||
func (d *cardDisk2Drive) insertDiskette(name string, dt storage.Diskette) {
|
||||
d.name = name
|
||||
d.diskette = dt
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package izapple2
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -24,7 +26,7 @@ type CardHardDisk struct {
|
||||
filename string
|
||||
trace bool
|
||||
|
||||
disk *blockDisk
|
||||
disk *storage.BlockDisk
|
||||
mliParams uint16
|
||||
}
|
||||
|
||||
@ -45,7 +47,7 @@ func (c *CardHardDisk) GetInfo() map[string]string {
|
||||
|
||||
// LoadImage loads a disk image
|
||||
func (c *CardHardDisk) LoadImage(filename string) error {
|
||||
hd, err := openBlockDisk(filename)
|
||||
hd, err := storage.OpenBlockDisk(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -95,11 +97,11 @@ func (c *CardHardDisk) assign(a *Apple2, slot int) {
|
||||
}, "HDCOMMAND")
|
||||
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
|
||||
// Blocks available, low byte
|
||||
return uint8(c.disk.blocks)
|
||||
return uint8(c.disk.GetSizeInBlocks())
|
||||
}, "HDBLOCKSLO")
|
||||
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
|
||||
// Blocks available, high byte
|
||||
return uint8(c.disk.blocks >> 8)
|
||||
return uint8(c.disk.GetSizeInBlocks() >> 8)
|
||||
}, "HDBLOCKHI")
|
||||
|
||||
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 {
|
||||
@ -146,12 +148,12 @@ func (c *CardHardDisk) readBlock(block uint16, dest uint16) uint8 {
|
||||
fmt.Printf("[CardHardDisk] Read block %v into $%x.\n", block, dest)
|
||||
}
|
||||
|
||||
data, err := c.disk.read(uint32(block))
|
||||
data, err := c.disk.Read(uint32(block))
|
||||
if err != nil {
|
||||
return proDosDeviceErrorIO
|
||||
}
|
||||
// Byte by byte transfer to memory using the full Poke code path
|
||||
for i := uint16(0); i < uint16(proDosBlockSize); i++ {
|
||||
for i := uint16(0); i < uint16(len(data)); i++ {
|
||||
c.a.mmu.Poke(dest+i, data[i])
|
||||
}
|
||||
|
||||
@ -163,17 +165,17 @@ func (c *CardHardDisk) writeBlock(block uint16, source uint16) uint8 {
|
||||
fmt.Printf("[CardHardDisk] Write block %v from $%x.\n", block, source)
|
||||
}
|
||||
|
||||
if c.disk.readOnly {
|
||||
if c.disk.IsReadOnly() {
|
||||
return proDosDeviceErrorWriteProtected
|
||||
}
|
||||
|
||||
// Byte by byte transfer from memory using the full Peek code path
|
||||
buf := make([]uint8, proDosBlockSize)
|
||||
for i := uint16(0); i < uint16(proDosBlockSize); i++ {
|
||||
buf := make([]uint8, storage.ProDosBlockSize)
|
||||
for i := uint16(0); i < uint16(len(buf)); i++ {
|
||||
buf[i] = c.a.mmu.Peek(source + i)
|
||||
}
|
||||
|
||||
err := c.disk.write(uint32(block), buf)
|
||||
err := c.disk.Write(uint32(block), buf)
|
||||
if err != nil {
|
||||
return proDosDeviceErrorIO
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package izapple2
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ivanizag/izapple2/storage"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -43,7 +45,7 @@ func newCharacterGenerator(filename string, order charColumnMap) (*CharacterGene
|
||||
}
|
||||
|
||||
func (cg *CharacterGenerator) load(filename string) error {
|
||||
bytes, err := loadResource(filename)
|
||||
bytes, err := storage.LoadResource(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -99,9 +99,6 @@ func fyneRun(s *state) {
|
||||
})
|
||||
|
||||
s.win.Show()
|
||||
|
||||
fmt.Printf("%v\n", s.win.Canvas().Scale())
|
||||
|
||||
s.app.Run()
|
||||
}
|
||||
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -7,23 +7,26 @@ import (
|
||||
)
|
||||
|
||||
/*
|
||||
Valid for ProDos disks with 512 bytes blocks. Can be diskettes or hard disks
|
||||
Valid for ProDOS disks with 512 bytes blocks. Can be diskettes or hard disks
|
||||
*/
|
||||
|
||||
const (
|
||||
proDosBlockSize = uint32(512)
|
||||
// ProDosBlockSize is the size of the blocks on the ProDOS devices
|
||||
ProDosBlockSize = uint32(512)
|
||||
proDosMaxBlocks = uint32(65536)
|
||||
)
|
||||
|
||||
type blockDisk struct {
|
||||
// BlockDisk is any block device with 512 bytes blocks
|
||||
type BlockDisk struct {
|
||||
file *os.File
|
||||
readOnly bool
|
||||
dataOffset uint32
|
||||
blocks uint32
|
||||
}
|
||||
|
||||
func openBlockDisk(filename string) (*blockDisk, error) {
|
||||
var bd blockDisk
|
||||
// OpenBlockDisk creates a new block device links to a file
|
||||
func OpenBlockDisk(filename string) (*BlockDisk, error) {
|
||||
var bd BlockDisk
|
||||
|
||||
bd.readOnly = false
|
||||
file, err := os.OpenFile(filename, os.O_RDWR, 0)
|
||||
@ -49,29 +52,39 @@ func openBlockDisk(filename string) (*blockDisk, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fileInfo.Size() > int64(proDosBlockSize*proDosMaxBlocks) {
|
||||
if fileInfo.Size() > int64(ProDosBlockSize*proDosMaxBlocks) {
|
||||
return nil, fmt.Errorf("File is too big OR %s", err2mg.Error())
|
||||
}
|
||||
|
||||
size := uint32(fileInfo.Size())
|
||||
if size%proDosBlockSize != 0 {
|
||||
if size%ProDosBlockSize != 0 {
|
||||
return nil, fmt.Errorf("File size os invalid OR %s", err2mg.Error())
|
||||
}
|
||||
|
||||
// It's a valid raw file
|
||||
bd.blocks = size / proDosBlockSize
|
||||
bd.blocks = size / ProDosBlockSize
|
||||
bd.dataOffset = 0
|
||||
return &bd, nil
|
||||
}
|
||||
|
||||
func (bd *blockDisk) read(block uint32) ([]uint8, error) {
|
||||
// GetSizeInBlocks returns the number of blocks of the device
|
||||
func (bd *BlockDisk) GetSizeInBlocks() uint32 {
|
||||
return bd.blocks
|
||||
}
|
||||
|
||||
// IsReadOnly returns true if the device is read only
|
||||
func (bd *BlockDisk) IsReadOnly() bool {
|
||||
return bd.readOnly
|
||||
}
|
||||
|
||||
func (bd *BlockDisk) Read(block uint32) ([]uint8, error) {
|
||||
if block >= bd.blocks {
|
||||
return nil, errors.New("disk block number is too big")
|
||||
}
|
||||
|
||||
buf := make([]uint8, proDosBlockSize)
|
||||
buf := make([]uint8, ProDosBlockSize)
|
||||
|
||||
offset := int64(bd.dataOffset + block*proDosBlockSize)
|
||||
offset := int64(bd.dataOffset + block*ProDosBlockSize)
|
||||
_, err := bd.file.ReadAt(buf, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -80,7 +93,7 @@ func (bd *blockDisk) read(block uint32) ([]uint8, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (bd *blockDisk) write(block uint32, data []uint8) error {
|
||||
func (bd *BlockDisk) Write(block uint32, data []uint8) error {
|
||||
if bd.readOnly {
|
||||
return errors.New("can't write in a readonly disk")
|
||||
}
|
||||
@ -88,7 +101,7 @@ func (bd *blockDisk) write(block uint32, data []uint8) error {
|
||||
return errors.New("disk block number is too big")
|
||||
}
|
||||
|
||||
offset := int64(bd.dataOffset + block*proDosBlockSize)
|
||||
offset := int64(bd.dataOffset + block*ProDosBlockSize)
|
||||
_, err := bd.file.WriteAt(data, offset)
|
||||
if err != nil {
|
||||
return err
|
@ -1,18 +1,20 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type diskette interface {
|
||||
powerOn(cycle uint64)
|
||||
powerOff(cycle uint64)
|
||||
read(quarterTrack int, cycle uint64) uint8
|
||||
write(quarterTrack int, value uint8, cycle uint64)
|
||||
// Diskette represents a diskette and it's RW mechanism
|
||||
type Diskette interface {
|
||||
PowerOn(cycle uint64)
|
||||
PowerOff(cycle uint64)
|
||||
Read(quarterTrack int, cycle uint64) uint8
|
||||
Write(quarterTrack int, value uint8, cycle uint64)
|
||||
}
|
||||
|
||||
func isDiskette(filename string) bool {
|
||||
data, err := loadResource(filename)
|
||||
// IsDiskette returns true if the files looks like a 5 1/4 diskette
|
||||
func IsDiskette(filename string) bool {
|
||||
data, err := LoadResource(filename)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@ -20,8 +22,9 @@ func isDiskette(filename string) bool {
|
||||
return isFileNib(data) || isFileDsk(data) || isFileWoz(data)
|
||||
}
|
||||
|
||||
func loadDiskette(filename string) (diskette, error) {
|
||||
data, err := loadResource(filename)
|
||||
// LoadDiskette returns a Diskette by detecting the format
|
||||
func LoadDiskette(filename string) (Diskette, error) {
|
||||
data, err := LoadResource(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
/*
|
||||
See:
|
||||
@ -11,23 +11,23 @@ type diskette16sector struct {
|
||||
position int
|
||||
}
|
||||
|
||||
func (d *diskette16sector) powerOn(cycle uint64) {
|
||||
func (d *diskette16sector) PowerOn(cycle uint64) {
|
||||
// Not used
|
||||
}
|
||||
func (d *diskette16sector) powerOff(_ uint64) {
|
||||
func (d *diskette16sector) PowerOff(_ uint64) {
|
||||
// Not used
|
||||
}
|
||||
|
||||
func (d *diskette16sector) read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/stepsPerTrack]
|
||||
func (d *diskette16sector) Read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/4]
|
||||
value := track[d.position]
|
||||
d.position = (d.position + 1) % nibBytesPerTrack
|
||||
//fmt.Printf("%v, %v, %v, %x\n", 0, 0, d.position, uint8(value))
|
||||
return value
|
||||
}
|
||||
|
||||
func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) {
|
||||
track := quarterTrack / stepsPerTrack
|
||||
func (d *diskette16sector) Write(quarterTrack int, value uint8, _ uint64) {
|
||||
track := quarterTrack / 4
|
||||
d.nib.track[track][d.position] = value
|
||||
d.position = (d.position + 1) % nibBytesPerTrack
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
type diskette16sectorTimed struct {
|
||||
nib *fileNib
|
||||
cycleOn uint64 // Cycle when the disk was last turned on
|
||||
}
|
||||
|
||||
func (d *diskette16sectorTimed) powerOn(cycle uint64) {
|
||||
func (d *diskette16sectorTimed) PowerOn(cycle uint64) {
|
||||
d.cycleOn = cycle
|
||||
}
|
||||
func (d *diskette16sectorTimed) powerOff(_ uint64) {
|
||||
func (d *diskette16sectorTimed) PowerOff(_ uint64) {
|
||||
// Not needed
|
||||
}
|
||||
|
||||
@ -20,8 +20,8 @@ func (d *diskette16sectorTimed) getBitPositionInTrack(cycle uint64) int {
|
||||
return int(position % (8 * nibBytesPerTrack)) // Ignore full turns
|
||||
}
|
||||
|
||||
func (d *diskette16sectorTimed) read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/stepsPerTrack]
|
||||
func (d *diskette16sectorTimed) Read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/4]
|
||||
bitPosition := d.getBitPositionInTrack(cycle)
|
||||
bytePosition := bitPosition / 8
|
||||
shift := uint(bitPosition % 8)
|
||||
@ -35,6 +35,6 @@ func (d *diskette16sectorTimed) read(quarterTrack int, cycle uint64) uint8 {
|
||||
return value
|
||||
}
|
||||
|
||||
func (d *diskette16sectorTimed) write(quarterTrack int, value uint8, _ uint64) {
|
||||
func (d *diskette16sectorTimed) Write(quarterTrack int, value uint8, _ uint64) {
|
||||
panic("Write not implemented on time based disk implementation")
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
/*
|
||||
See:
|
||||
@ -15,22 +15,22 @@ type diskette16sectorWritable struct {
|
||||
dirtyTrack int
|
||||
}
|
||||
|
||||
func (d *diskette16sectorWritable) powerOn(cycle uint64) {
|
||||
func (d *diskette16sectorWritable) PowerOn(cycle uint64) {
|
||||
// Not used
|
||||
}
|
||||
func (d *diskette16sectorWritable) powerOff(_ uint64) {
|
||||
func (d *diskette16sectorWritable) PowerOff(_ uint64) {
|
||||
d.commit()
|
||||
}
|
||||
|
||||
func (d *diskette16sectorWritable) read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/stepsPerTrack]
|
||||
func (d *diskette16sectorWritable) Read(quarterTrack int, cycle uint64) uint8 {
|
||||
track := d.nib.track[quarterTrack/4]
|
||||
value := track[d.position]
|
||||
d.position = (d.position + 1) % nibBytesPerTrack
|
||||
return value
|
||||
}
|
||||
|
||||
func (d *diskette16sectorWritable) write(quarterTrack int, value uint8, _ uint64) {
|
||||
track := quarterTrack / stepsPerTrack
|
||||
func (d *diskette16sectorWritable) Write(quarterTrack int, value uint8, _ uint64) {
|
||||
track := quarterTrack / 4
|
||||
|
||||
if d.hasDirtyTrack && track != d.dirtyTrack {
|
||||
d.commit()
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -71,16 +71,16 @@ func newDisquetteWoz(f *fileWoz) (*disketteWoz, error) {
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (d *disketteWoz) powerOn(cycle uint64) {
|
||||
func (d *disketteWoz) PowerOn(cycle uint64) {
|
||||
d.turning = true
|
||||
d.cycleOn = cycle
|
||||
}
|
||||
|
||||
func (d *disketteWoz) powerOff(_ uint64) {
|
||||
func (d *disketteWoz) PowerOff(_ uint64) {
|
||||
d.turning = false
|
||||
}
|
||||
|
||||
func (d *disketteWoz) read(quarterTrack int, cycle uint64) uint8 {
|
||||
func (d *disketteWoz) Read(quarterTrack int, cycle uint64) uint8 {
|
||||
// Count cycles to know how many bits have been read
|
||||
cycles := cycle - d.cycle
|
||||
deltaBits := cycles / cyclesPerBit // TODO: Use Woz optimal bit timing
|
||||
@ -123,6 +123,6 @@ func (d *disketteWoz) read(quarterTrack int, cycle uint64) uint8 {
|
||||
return d.visibleLatch
|
||||
}
|
||||
|
||||
func (d *disketteWoz) write(quarterTrack int, value uint8, _ uint64) {
|
||||
func (d *disketteWoz) Write(quarterTrack int, value uint8, _ uint64) {
|
||||
panic("Write not implemented on woz disk implementation")
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@ -35,7 +35,7 @@ type file2mgHeader struct {
|
||||
LengthCreator uint32
|
||||
}
|
||||
|
||||
func parse2mg(bd *blockDisk) error {
|
||||
func parse2mg(bd *BlockDisk) error {
|
||||
fileInfo, err := bd.file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -55,7 +55,7 @@ func parse2mg(bd *blockDisk) error {
|
||||
bd.blocks = header.Blocks
|
||||
bd.dataOffset = header.OffsetData
|
||||
|
||||
if fileInfo.Size() < int64(bd.dataOffset+bd.blocks*proDosBlockSize) {
|
||||
if fileInfo.Size() < int64(bd.dataOffset+bd.blocks*ProDosBlockSize) {
|
||||
return errors.New("The 2MG file is too small")
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -86,15 +86,6 @@ func (f *fileWoz) getBit(position uint32, quarterTrack int) uint8 {
|
||||
return trackWoz.data[position/8] >> (7 - position%8) & 1
|
||||
}
|
||||
|
||||
func loadFileWoz(filename string) (*fileWoz, error) {
|
||||
data, err := loadResource(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newFileWoz(data)
|
||||
}
|
||||
|
||||
func isFileWoz(data []uint8) bool {
|
||||
header := data[:len(headerWoz2)]
|
||||
if bytes.Equal(headerWoz1, header) {
|
@ -1,4 +1,4 @@
|
||||
package izapple2
|
||||
package storage
|
||||
|
||||
import (
|
||||
"io"
|
||||
@ -25,7 +25,8 @@ func isHTTPResource(filename string) bool {
|
||||
strings.HasPrefix(filename, httpsPrefix)
|
||||
}
|
||||
|
||||
func loadResource(filename string) ([]uint8, error) {
|
||||
// LoadResource loads in memory a file from the filesystem, http or embedded
|
||||
func LoadResource(filename string) ([]uint8, error) {
|
||||
var file io.Reader
|
||||
if isInternalResource(filename) {
|
||||
// load from embedded resource
|
Loading…
x
Reference in New Issue
Block a user