Files
izapple2/removableMedia.go
Iván Izaguirre 66b5cac559 Show the drives a file can be dropped on
A file dropped on the window went to drive 1 or drive 2 depending on the
half it landed on. There was no way to know beforehand which drive was
which or what each one had inserted, and no sign afterwards of where the
file went. The machines with two Disk II cards have four drives and only
the first two could be reached.

F8 now shows a screen with one area per removable media drive, each with
the name of its drive and the image it has inserted, or EMPTY, and the
same screen appears for a moment after a drop with the drive that got the
file marked. It is a text screen of 80 columns rendered the same way the
help is, so SnapshotMessageGenerator takes the number of columns now.

The drives register with a label and tell the media they have, so the
frontends ask the machine with GetRemovableMediaDrives instead of assuming
two. The name of the media is written by the emulation goroutine and read
by the frontends, hence the atomic access.

The new frontend/shared package holds what the frontends have in common
and the emulator library has no place for: the composition of the screen
and the mapping from a position to a drive.

a2sdl reads the position of the pointer on the desktop when the file is
dropped. The mouse motion events do not arrive while another application
drags a file, so the last known position was stale and the file could land
on the wrong drive.

a2sdl3 shows the areas while the file is being dragged over the window,
which is something only SDL3 reports.

a2ebiten had no drag and drop at all, although the help it shows said
otherwise. Ebitengine hides the paths of the files dropped, but it opens
the real files and the handle tells the path back, so the images are
loaded like on every other frontend, compressed files included.
2026-08-10 21:56:40 +02:00

63 lines
1.8 KiB
Go

package izapple2
import (
"sync/atomic"
)
/*
The removable media drives are the drives a file can be loaded on while the
emulation runs, by command or by dragging a file on the window. They are
registered by the cards that own them, in the order the frontends and the
CommandLoadDisk command use to address them.
*/
// mediaName is the name of the media loaded on a removable media drive. It is
// written by the emulation goroutine when a file is inserted, and read by the
// frontends to show what each drive has, hence the atomic access.
type mediaName struct {
value atomic.Value
}
func (m *mediaName) set(name string) {
m.value.Store(name)
}
func (m *mediaName) get() string {
name, _ := m.value.Load().(string)
return name
}
// removableMediaDrive is a drive registered as a target for the files loaded
// while the emulation runs
type removableMediaDrive struct {
label string // Slot and drive number, for example "S6D1"
drive drive
}
func (a *Apple2) registerRemovableMediaDrive(d drive, label string) {
a.removableMediaDrives = append(a.removableMediaDrives, removableMediaDrive{
label: label,
drive: d,
})
}
// DriveInfo describes a removable media drive as seen from outside
type DriveInfo struct {
Label string // Slot and drive number, for example "S6D1"
Media string // Name of the media inserted, empty when the drive is empty
}
// GetRemovableMediaDrives returns the drives a file can be loaded on, in the
// order SendLoadDisk() addresses them. The frontends use it to show where a
// dragged file can be dropped and what each drive has inserted.
func (a *Apple2) GetRemovableMediaDrives() []DriveInfo {
drives := make([]DriveInfo, len(a.removableMediaDrives))
for i, d := range a.removableMediaDrives {
drives[i] = DriveInfo{
Label: d.label,
Media: d.drive.getMediaName(),
}
}
return drives
}