Move disk related code to a separate package

This commit is contained in:
Ivan Izaguirre 2020-10-17 20:10:48 +02:00
parent 7329d4f042
commit 18e0363d84
22 changed files with 111 additions and 110 deletions

View File

@ -219,8 +219,6 @@ Only valid on SDL mode
dump to the console the sofswitch registrations dump to the console the sofswitch registrations
-vidHDSlot int -vidHDSlot int
slot for the VidHD card, only for //e models. -1 for none (default 2) slot for the VidHD card, only for //e models. -1 for none (default 2)
-woz string
show WOZ file information
``` ```

View File

@ -148,10 +148,10 @@ func (a *Apple2) executeCommand(command int) {
switch command { switch command {
case CommandToggleSpeed: case CommandToggleSpeed:
if a.cycleDurationNs == 0 { if a.cycleDurationNs == 0 {
fmt.Println("Slow") //fmt.Println("Slow")
a.cycleDurationNs = 1000.0 / CPUClockMhz a.cycleDurationNs = 1000.0 / CPUClockMhz
} else { } else {
fmt.Println("Fast") //fmt.Println("Fast")
a.cycleDurationNs = 0 a.cycleDurationNs = 0
} }
case CommandShowSpeed: case CommandShowSpeed:

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"github.com/ivanizag/izapple2/core6502" "github.com/ivanizag/izapple2/core6502"
"github.com/ivanizag/izapple2/storage"
) )
func newApple2() *Apple2 { func newApple2() *Apple2 {
@ -71,7 +72,7 @@ const (
// LoadRom loads a standard Apple2+ or 2e ROM // LoadRom loads a standard Apple2+ or 2e ROM
func (a *Apple2) LoadRom(filename string) error { func (a *Apple2) LoadRom(filename string) error {
data, err := loadResource(filename) data, err := storage.LoadResource(filename)
if err != nil { if err != nil {
return err return err
} }
@ -92,7 +93,7 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
a.insertCard(c, slot) a.insertCard(c, slot)
if diskImage != "" { if diskImage != "" {
diskette, err := loadDiskette(diskImage) diskette, err := storage.LoadDiskette(diskImage)
if err != nil { if err != nil {
return err return err
} }
@ -100,7 +101,7 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
} }
if diskBImage != "" { if diskBImage != "" {
diskette, err := loadDiskette(diskBImage) diskette, err := storage.LoadDiskette(diskBImage)
if err != nil { if err != nil {
return err return err
} }

View File

@ -3,6 +3,8 @@ package izapple2
import ( import (
"flag" "flag"
"os" "os"
"github.com/ivanizag/izapple2/storage"
) )
const defaultInternal = "<default>" const defaultInternal = "<default>"
@ -25,10 +27,6 @@ func MainApple() *Apple2 {
"diskb", "diskb",
"", "",
"file to load on the second disk drive") "file to load on the second disk drive")
wozImage := flag.String(
"woz",
"",
"show WOZ file information")
hardDiskImage := flag.String( hardDiskImage := flag.String(
"hd", "hd",
"", "",
@ -133,23 +131,13 @@ func MainApple() *Apple2 {
diskImageFinal := *diskImage diskImageFinal := *diskImage
hardDiskImageFinal := *hardDiskImage hardDiskImageFinal := *hardDiskImage
if filename != "" { if filename != "" {
if isDiskette(filename) { if storage.IsDiskette(filename) {
diskImageFinal = filename diskImageFinal = filename
} else { } else {
hardDiskImageFinal = filename hardDiskImageFinal = filename
} }
} }
if *wozImage != "" {
f, err := loadFileWoz(*wozImage)
if err != nil {
panic(err)
}
f.dump()
return nil
}
a := newApple2() a := newApple2()
a.setup(*cpuClock, *fastDisk, *traceMLI) a.setup(*cpuClock, *fastDisk, *traceMLI)
a.io.setTrace(*traceSS) a.io.setTrace(*traceSS)

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/ivanizag/izapple2/core6502" "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++ { for i := 0; i < base64aRomChipCount; i++ {
filename := fmt.Sprintf("<internal>/BASE64A_%X.BIN", 0xd0+i*0x08) filename := fmt.Sprintf("<internal>/BASE64A_%X.BIN", 0xd0+i*0x08)
data, err := loadResource(filename) data, err := storage.LoadResource(filename)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,5 +1,7 @@
package izapple2 package izapple2
import "github.com/ivanizag/izapple2/storage"
// Card represents an Apple II card to be inserted in a slot // Card represents an Apple II card to be inserted in a slot
type Card interface { type Card interface {
loadRom(data []uint8) loadRom(data []uint8)
@ -32,7 +34,7 @@ func (c *cardBase) GetInfo() map[string]string {
} }
func (c *cardBase) loadRomFromResource(resource string) { func (c *cardBase) loadRomFromResource(resource string) {
data, err := loadResource(resource) data, err := storage.LoadResource(resource)
if err != nil { if err != nil {
// The resource should be internal and never fail // The resource should be internal and never fail
panic(err) panic(err)

View File

@ -3,6 +3,8 @@ package izapple2
import ( import (
"fmt" "fmt"
"strconv" "strconv"
"github.com/ivanizag/izapple2/storage"
) )
/* /*
@ -33,7 +35,7 @@ type CardDisk2 struct {
type cardDisk2Drive struct { type cardDisk2Drive struct {
name string name string
diskette diskette diskette storage.Diskette
power bool // q4 power bool // q4
phases uint8 // q3, q2, q1 and q0 with q0 on the LSB. Magnets that are active on the stepper motor 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 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 drive.power = false
c.a.releaseFastMode() c.a.releaseFastMode()
if drive.diskette != nil { if drive.diskette != nil {
drive.diskette.powerOff(c.a.cpu.GetCycles()) drive.diskette.PowerOff(c.a.cpu.GetCycles())
} }
} }
return c.dataLatch return c.dataLatch
@ -113,7 +115,7 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
drive.power = true drive.power = true
c.a.requestFastMode() c.a.requestFastMode()
if drive.diskette != nil { if drive.diskette != nil {
drive.diskette.powerOn(c.a.cpu.GetCycles()) drive.diskette.PowerOn(c.a.cpu.GetCycles())
} }
} }
return 0 return 0
@ -173,9 +175,9 @@ func (c *CardDisk2) processQ6Q7(in uint8) {
} }
if !c.q6 { // shift if !c.q6 { // shift
if !c.q7 { // Q6L-Q7L: Read 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 } 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 } else { // load
if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state
@ -269,7 +271,7 @@ func moveStep(phases uint8, prevStep int) int {
return nextStep return nextStep
} }
func (d *cardDisk2Drive) insertDiskette(name string, dt diskette) { func (d *cardDisk2Drive) insertDiskette(name string, dt storage.Diskette) {
d.name = name d.name = name
d.diskette = dt d.diskette = dt
} }

View File

@ -3,6 +3,8 @@ package izapple2
import ( import (
"fmt" "fmt"
"strconv" "strconv"
"github.com/ivanizag/izapple2/storage"
) )
/* /*
@ -24,7 +26,7 @@ type CardHardDisk struct {
filename string filename string
trace bool trace bool
disk *blockDisk disk *storage.BlockDisk
mliParams uint16 mliParams uint16
} }
@ -45,7 +47,7 @@ func (c *CardHardDisk) GetInfo() map[string]string {
// LoadImage loads a disk image // LoadImage loads a disk image
func (c *CardHardDisk) LoadImage(filename string) error { func (c *CardHardDisk) LoadImage(filename string) error {
hd, err := openBlockDisk(filename) hd, err := storage.OpenBlockDisk(filename)
if err != nil { if err != nil {
return err return err
} }
@ -95,11 +97,11 @@ func (c *CardHardDisk) assign(a *Apple2, slot int) {
}, "HDCOMMAND") }, "HDCOMMAND")
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 { c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
// Blocks available, low byte // Blocks available, low byte
return uint8(c.disk.blocks) return uint8(c.disk.GetSizeInBlocks())
}, "HDBLOCKSLO") }, "HDBLOCKSLO")
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 { c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
// Blocks available, high byte // Blocks available, high byte
return uint8(c.disk.blocks >> 8) return uint8(c.disk.GetSizeInBlocks() >> 8)
}, "HDBLOCKHI") }, "HDBLOCKHI")
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 { 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) 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 { if err != nil {
return proDosDeviceErrorIO return proDosDeviceErrorIO
} }
// Byte by byte transfer to memory using the full Poke code path // 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]) 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) fmt.Printf("[CardHardDisk] Write block %v from $%x.\n", block, source)
} }
if c.disk.readOnly { if c.disk.IsReadOnly() {
return proDosDeviceErrorWriteProtected return proDosDeviceErrorWriteProtected
} }
// Byte by byte transfer from memory using the full Peek code path // Byte by byte transfer from memory using the full Peek code path
buf := make([]uint8, proDosBlockSize) buf := make([]uint8, storage.ProDosBlockSize)
for i := uint16(0); i < uint16(proDosBlockSize); i++ { for i := uint16(0); i < uint16(len(buf)); i++ {
buf[i] = c.a.mmu.Peek(source + 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 { if err != nil {
return proDosDeviceErrorIO return proDosDeviceErrorIO
} }

View File

@ -3,6 +3,8 @@ package izapple2
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/ivanizag/izapple2/storage"
) )
/* /*
@ -43,7 +45,7 @@ func newCharacterGenerator(filename string, order charColumnMap) (*CharacterGene
} }
func (cg *CharacterGenerator) load(filename string) error { func (cg *CharacterGenerator) load(filename string) error {
bytes, err := loadResource(filename) bytes, err := storage.LoadResource(filename)
if err != nil { if err != nil {
return err return err
} }

View File

@ -99,9 +99,6 @@ func fyneRun(s *state) {
}) })
s.win.Show() s.win.Show()
fmt.Printf("%v\n", s.win.Canvas().Scale())
s.app.Run() s.app.Run()
} }

Binary file not shown.

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"errors" "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 ( const (
proDosBlockSize = uint32(512) // ProDosBlockSize is the size of the blocks on the ProDOS devices
ProDosBlockSize = uint32(512)
proDosMaxBlocks = uint32(65536) proDosMaxBlocks = uint32(65536)
) )
type blockDisk struct { // BlockDisk is any block device with 512 bytes blocks
type BlockDisk struct {
file *os.File file *os.File
readOnly bool readOnly bool
dataOffset uint32 dataOffset uint32
blocks uint32 blocks uint32
} }
func openBlockDisk(filename string) (*blockDisk, error) { // OpenBlockDisk creates a new block device links to a file
var bd blockDisk func OpenBlockDisk(filename string) (*BlockDisk, error) {
var bd BlockDisk
bd.readOnly = false bd.readOnly = false
file, err := os.OpenFile(filename, os.O_RDWR, 0) file, err := os.OpenFile(filename, os.O_RDWR, 0)
@ -49,29 +52,39 @@ func openBlockDisk(filename string) (*blockDisk, error) {
return nil, err 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()) return nil, fmt.Errorf("File is too big OR %s", err2mg.Error())
} }
size := uint32(fileInfo.Size()) size := uint32(fileInfo.Size())
if size%proDosBlockSize != 0 { if size%ProDosBlockSize != 0 {
return nil, fmt.Errorf("File size os invalid OR %s", err2mg.Error()) return nil, fmt.Errorf("File size os invalid OR %s", err2mg.Error())
} }
// It's a valid raw file // It's a valid raw file
bd.blocks = size / proDosBlockSize bd.blocks = size / ProDosBlockSize
bd.dataOffset = 0 bd.dataOffset = 0
return &bd, nil 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 { if block >= bd.blocks {
return nil, errors.New("disk block number is too big") 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) _, err := bd.file.ReadAt(buf, offset)
if err != nil { if err != nil {
return nil, err return nil, err
@ -80,7 +93,7 @@ func (bd *blockDisk) read(block uint32) ([]uint8, error) {
return buf, nil return buf, nil
} }
func (bd *blockDisk) write(block uint32, data []uint8) error { func (bd *BlockDisk) Write(block uint32, data []uint8) error {
if bd.readOnly { if bd.readOnly {
return errors.New("can't write in a readonly disk") 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") 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) _, err := bd.file.WriteAt(data, offset)
if err != nil { if err != nil {
return err return err

View File

@ -1,18 +1,20 @@
package izapple2 package storage
import ( import (
"errors" "errors"
) )
type diskette interface { // Diskette represents a diskette and it's RW mechanism
powerOn(cycle uint64) type Diskette interface {
powerOff(cycle uint64) PowerOn(cycle uint64)
read(quarterTrack int, cycle uint64) uint8 PowerOff(cycle uint64)
write(quarterTrack int, value uint8, cycle uint64) Read(quarterTrack int, cycle uint64) uint8
Write(quarterTrack int, value uint8, cycle uint64)
} }
func isDiskette(filename string) bool { // IsDiskette returns true if the files looks like a 5 1/4 diskette
data, err := loadResource(filename) func IsDiskette(filename string) bool {
data, err := LoadResource(filename)
if err != nil { if err != nil {
return false return false
} }
@ -20,8 +22,9 @@ func isDiskette(filename string) bool {
return isFileNib(data) || isFileDsk(data) || isFileWoz(data) return isFileNib(data) || isFileDsk(data) || isFileWoz(data)
} }
func loadDiskette(filename string) (diskette, error) { // LoadDiskette returns a Diskette by detecting the format
data, err := loadResource(filename) func LoadDiskette(filename string) (Diskette, error) {
data, err := LoadResource(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,4 +1,4 @@
package izapple2 package storage
/* /*
See: See:
@ -11,23 +11,23 @@ type diskette16sector struct {
position int position int
} }
func (d *diskette16sector) powerOn(cycle uint64) { func (d *diskette16sector) PowerOn(cycle uint64) {
// Not used // Not used
} }
func (d *diskette16sector) powerOff(_ uint64) { func (d *diskette16sector) PowerOff(_ uint64) {
// Not used // Not used
} }
func (d *diskette16sector) read(quarterTrack int, cycle uint64) uint8 { func (d *diskette16sector) Read(quarterTrack int, cycle uint64) uint8 {
track := d.nib.track[quarterTrack/stepsPerTrack] track := d.nib.track[quarterTrack/4]
value := track[d.position] value := track[d.position]
d.position = (d.position + 1) % nibBytesPerTrack d.position = (d.position + 1) % nibBytesPerTrack
//fmt.Printf("%v, %v, %v, %x\n", 0, 0, d.position, uint8(value)) //fmt.Printf("%v, %v, %v, %x\n", 0, 0, d.position, uint8(value))
return value return value
} }
func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) { func (d *diskette16sector) Write(quarterTrack int, value uint8, _ uint64) {
track := quarterTrack / stepsPerTrack track := quarterTrack / 4
d.nib.track[track][d.position] = value d.nib.track[track][d.position] = value
d.position = (d.position + 1) % nibBytesPerTrack d.position = (d.position + 1) % nibBytesPerTrack
} }

View File

@ -1,14 +1,14 @@
package izapple2 package storage
type diskette16sectorTimed struct { type diskette16sectorTimed struct {
nib *fileNib nib *fileNib
cycleOn uint64 // Cycle when the disk was last turned on 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 d.cycleOn = cycle
} }
func (d *diskette16sectorTimed) powerOff(_ uint64) { func (d *diskette16sectorTimed) PowerOff(_ uint64) {
// Not needed // Not needed
} }
@ -20,8 +20,8 @@ func (d *diskette16sectorTimed) getBitPositionInTrack(cycle uint64) int {
return int(position % (8 * nibBytesPerTrack)) // Ignore full turns return int(position % (8 * nibBytesPerTrack)) // Ignore full turns
} }
func (d *diskette16sectorTimed) read(quarterTrack int, cycle uint64) uint8 { func (d *diskette16sectorTimed) Read(quarterTrack int, cycle uint64) uint8 {
track := d.nib.track[quarterTrack/stepsPerTrack] track := d.nib.track[quarterTrack/4]
bitPosition := d.getBitPositionInTrack(cycle) bitPosition := d.getBitPositionInTrack(cycle)
bytePosition := bitPosition / 8 bytePosition := bitPosition / 8
shift := uint(bitPosition % 8) shift := uint(bitPosition % 8)
@ -35,6 +35,6 @@ func (d *diskette16sectorTimed) read(quarterTrack int, cycle uint64) uint8 {
return value 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") panic("Write not implemented on time based disk implementation")
} }

View File

@ -1,4 +1,4 @@
package izapple2 package storage
/* /*
See: See:
@ -15,22 +15,22 @@ type diskette16sectorWritable struct {
dirtyTrack int dirtyTrack int
} }
func (d *diskette16sectorWritable) powerOn(cycle uint64) { func (d *diskette16sectorWritable) PowerOn(cycle uint64) {
// Not used // Not used
} }
func (d *diskette16sectorWritable) powerOff(_ uint64) { func (d *diskette16sectorWritable) PowerOff(_ uint64) {
d.commit() d.commit()
} }
func (d *diskette16sectorWritable) read(quarterTrack int, cycle uint64) uint8 { func (d *diskette16sectorWritable) Read(quarterTrack int, cycle uint64) uint8 {
track := d.nib.track[quarterTrack/stepsPerTrack] track := d.nib.track[quarterTrack/4]
value := track[d.position] value := track[d.position]
d.position = (d.position + 1) % nibBytesPerTrack d.position = (d.position + 1) % nibBytesPerTrack
return value return value
} }
func (d *diskette16sectorWritable) write(quarterTrack int, value uint8, _ uint64) { func (d *diskette16sectorWritable) Write(quarterTrack int, value uint8, _ uint64) {
track := quarterTrack / stepsPerTrack track := quarterTrack / 4
if d.hasDirtyTrack && track != d.dirtyTrack { if d.hasDirtyTrack && track != d.dirtyTrack {
d.commit() d.commit()

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"errors" "errors"
@ -71,16 +71,16 @@ func newDisquetteWoz(f *fileWoz) (*disketteWoz, error) {
return &d, nil return &d, nil
} }
func (d *disketteWoz) powerOn(cycle uint64) { func (d *disketteWoz) PowerOn(cycle uint64) {
d.turning = true d.turning = true
d.cycleOn = cycle d.cycleOn = cycle
} }
func (d *disketteWoz) powerOff(_ uint64) { func (d *disketteWoz) PowerOff(_ uint64) {
d.turning = false 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 // Count cycles to know how many bits have been read
cycles := cycle - d.cycle cycles := cycle - d.cycle
deltaBits := cycles / cyclesPerBit // TODO: Use Woz optimal bit timing 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 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") panic("Write not implemented on woz disk implementation")
} }

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"encoding/binary" "encoding/binary"
@ -35,7 +35,7 @@ type file2mgHeader struct {
LengthCreator uint32 LengthCreator uint32
} }
func parse2mg(bd *blockDisk) error { func parse2mg(bd *BlockDisk) error {
fileInfo, err := bd.file.Stat() fileInfo, err := bd.file.Stat()
if err != nil { if err != nil {
return err return err
@ -55,7 +55,7 @@ func parse2mg(bd *blockDisk) error {
bd.blocks = header.Blocks bd.blocks = header.Blocks
bd.dataOffset = header.OffsetData 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") return errors.New("The 2MG file is too small")
} }

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"errors" "errors"

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"testing" "testing"

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"bytes" "bytes"
@ -86,15 +86,6 @@ func (f *fileWoz) getBit(position uint32, quarterTrack int) uint8 {
return trackWoz.data[position/8] >> (7 - position%8) & 1 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 { func isFileWoz(data []uint8) bool {
header := data[:len(headerWoz2)] header := data[:len(headerWoz2)]
if bytes.Equal(headerWoz1, header) { if bytes.Equal(headerWoz1, header) {

View File

@ -1,4 +1,4 @@
package izapple2 package storage
import ( import (
"io" "io"
@ -25,7 +25,8 @@ func isHTTPResource(filename string) bool {
strings.HasPrefix(filename, httpsPrefix) 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 var file io.Reader
if isInternalResource(filename) { if isInternalResource(filename) {
// load from embedded resource // load from embedded resource