diff --git a/cartridgeloader/doc.go b/cartridgeloader/doc.go
index d38fcdd1..6f1800bc 100644
--- a/cartridgeloader/doc.go
+++ b/cartridgeloader/doc.go
@@ -13,37 +13,16 @@
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see .
-// Package cartridgeloader is used to specify the cartridge data that is to be
-// attached to the emulated VCS.
-//
-// When the cartridge is ready to be loaded into the emulator, the Load()
-// function should be used. The Load() function handles loading of data from a
-// different sources. Currently on local-file and data over HTTP is supported.
-//
-// As well as the filename, the Loader type allows the cartridge mapping to be
-// specified, if required. The simplest instantiation therefore is:
-//
-// cl := cartridgeloader.Loader{
-// Filename: "roms/Pitfall.bin",
-// }
-//
-// It is stronly preferred however, that the NewLoader() function is used to
-// initialise the Loader or important fields risk being initialised
-// incorrectly.
-//
-// The NewLoader() function accepts two arguments. The filename of the
-// cartridge (which might be a HTTP url) and the cartridge mapper. In most
-// cases the mapper will be "AUTO" to indicate that we don't know (or
-// particular care) what the mapping format is.
+// Package cartridgeloader is used to load cartridge data so that it can be used
+// with the cartridge pacakage
//
// # File Extensions
//
// The file extension of a file will specify the cartridge mapping and will
-// cause the emulation to use that mapping. Most 2600 ROM files have the
-// extension "bin" but sometimes it is necessary to specify explicitly what
-// the mapper is.
+// cause the emulation to use that mapping.
//
-// The following quoted file extensions are recognised (case insenstive):
+// The following file extensions are recognised and force the use of the
+// specified mapper:
//
// Atari 2k "2k"
// Atari 4k "4k"
@@ -59,7 +38,7 @@
// Parker Bros "E0"
// M-Network "E7"
// Tigervision "3F"
-// Supercharger "AR"
+// Supercharger "AR", "MP3, "WAV"
// DF "DF"
// 3E "3E"
// 3E+ "3E+"
@@ -67,64 +46,18 @@
// DPC (Pitfall2) "DPC"
// DPC+ "DP+"
// CDF "CDF" (including CDFJ)
+// MovieCart "MVC"
//
-// In addition to these above there a three "special" mapping formats. Which
-// aren't really mappers in the normal sense but which will none-the-less
-// trigger a particular cartridge emulation path.
+// File extensions are case insensitive.
//
-// "MP3" and "WAV" indicate that the emulation should use the Supercharger
-// mapper but with the understanding that the data will be loaded from audio
-// data.
+// A file extension of "BIN", "ROM", "A26" indicates that the data should be
+// fingerprinted as normal.
//
-// "MVC" indicates that the data is a MovieCart stream. Because of the
-// potential size of these files, data is streamed from the file. Also,
-// steaming over HTTP is not yet currently supported.
+// # Hashes
//
-// Finally a file extension of "BIN", "ROM", "A26" will tell the mapping system
-// to "fingerprint" the cartridge data to ascertain the mapping type.
-//
-// Fingerprinting is not handled by the cartridlgeloader package.
-//
-// # Hash
-//
-// The Hash field of the Loader type contains the SHA1 value of the loaded
-// data. It is valid after the Load() function has completed successfully. If
-// the field is not empty before Load() is called, that value will be compared
-// with the calculated value. An error is returned if the values differ.
-//
-// In most cases you wouldn't want to change the Hash field before calling the
-// Load() function but it is sometimes useful to make sure the correct file is
-// being loaded - for example the recorder package uses it to help make sure
-// playback is correct.
-//
-// The hash value is invalid/unused in the case of streamed data
-//
-// # Streaming
-//
-// For some cartridge types it is necessary to stream bytes from the file
-// rather than load them all at once. For these types of cartridges the Load()
-// function will open a stream and readbable via the StreamedData field.
-//
-// The function IsStreaming() returns true if data is to be read from the
-// StreamedData field rather than the Data field.
-//
-// For streaming to work NewLoader() must have been used to instantiate the
-// Loader type.
-//
-// # Closing
-//
-// Instances of Loader must be closed with Close() when it is no longer
-// required.
-//
-// # OnInserted
-//
-// The OnInserted field is used by some cartridges to indicate when the
-// cartridge data has been loaded into memory and something else needs to
-// happen that is outside of the scope of the cartridge package. Currently,
-// this is used by the Supercharder and PlusROM.
-//
-// # Notification Hook
-//
-// Some cartridge mappers will generate notifications (see notification.Notify type). The
-// NotifcationHook can be specified in order to respond to those events.
+// Creating a cartridge loader with NewLoaderFromFilename() or
+// NewLoaderFromData() will also create a SHA1 and MD5 hash of the data. The
+// amount of data used to create the has is limited to 1MB. For most cartridges
+// this will mean the hash is taken using all the data but some cartridge are
+// likely to have much more data than that.
package cartridgeloader
diff --git a/cartridgeloader/loader.go b/cartridgeloader/loader.go
index 299d5551..a06fdace 100644
--- a/cartridgeloader/loader.go
+++ b/cartridgeloader/loader.go
@@ -34,6 +34,8 @@ import (
// the maximum amount of data to load into the peep slice
const maxPeepLength = 1048576
+// makes sures that data is capped at peep length. use this function when
+// assigning to the Loader.peep field
func peepData(data []byte) []byte {
return data[:min(len(data), maxPeepLength)]
}
@@ -74,8 +76,8 @@ type Loader struct {
// help fingerprinting and for creating the SHA1 and MD5 hashes
//
// in reality, most cartridges are small enough to fit entirely inside the
- // peep slice. currently it is only moviecart data and maybe supercharger
- // sound files that will be larger than the maxPeepLength
+ // peep field. currently it is only moviecart data and supercharger sound
+ // files that are ever arger than maxPeepLength
peep []byte
// data was supplied through NewLoaderFromData()
@@ -256,19 +258,19 @@ func (ld Loader) Size() int {
return ld.size
}
-// Contains returns true if subslice appears anywhere in the data
+// Contains returns true if subslice appears anywhere in the peep data
func (ld Loader) Contains(subslice []byte) bool {
return bytes.Contains(ld.peep, subslice)
}
-// ContainsLimit returns true if subslice appears in the data at an offset between
+// ContainsLimit returns true if subslice appears in the peep data at an offset between
// zero and limit
func (ld Loader) ContainsLimit(limit int, subslice []byte) bool {
limit = min(limit, ld.Size())
return bytes.Contains(ld.peep[:limit], subslice)
}
-// Count returns the number of non-overlapping instances of subslice in the data
+// Count returns the number of non-overlapping instances of subslice in the peep data
func (ld Loader) Count(subslice []byte) int {
return bytes.Count(ld.peep, subslice)
}
diff --git a/comparison/comparison.go b/comparison/comparison.go
index 5cebac31..3c53db4e 100644
--- a/comparison/comparison.go
+++ b/comparison/comparison.go
@@ -177,6 +177,7 @@ func (cmp *Comparison) CreateFromLoader(cartload cartridgeloader.Loader) error {
defer func() {
cmp.driver.quit <- nil
cmp.isEmulating.Store(false)
+ cartload.Close()
}()
// not using setup system to attach cartridge. maybe we should?
diff --git a/debugger/commands.go b/debugger/commands.go
index 6836c281..08d801b8 100644
--- a/debugger/commands.go
+++ b/debugger/commands.go
@@ -25,7 +25,6 @@ import (
"strconv"
"strings"
- "github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/coprocessor"
coproc_breakpoints "github.com/jetsetilly/gopher2600/coprocessor/developer/breakpoints"
"github.com/jetsetilly/gopher2600/coprocessor/developer/callstack"
@@ -472,21 +471,11 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
case cmdInsert:
dbg.unwindLoop(func() error {
- cart, _ := tokens.Get()
- cl, err := cartridgeloader.NewLoaderFromFilename(cart, "AUTO")
+ filename, _ := tokens.Get()
+ err := dbg.insertCartridge(filename)
if err != nil {
return err
}
- err = dbg.attachCartridge(cl)
- if err != nil {
- return err
- }
-
- // use cartridge's idea of the filename. the attach process may have
- // caused a different cartridge to load than the one requested (most
- // typically this will mean that the cartridge has been ejected)
- dbg.printLine(terminal.StyleFeedback, "machine reset with new cartridge (%s)", dbg.vcs.Mem.Cart.Filename)
-
return nil
})
@@ -573,14 +562,6 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
dbg.printLine(terminal.StyleFeedback, "cartridge has no RAM")
}
- case "HOTLOAD":
- err := dbg.hotload()
- if err != nil {
- dbg.printLine(terminal.StyleFeedback, err.Error())
- } else {
- dbg.printLine(terminal.StyleFeedback, "hotload successful")
- }
-
case "DUMP":
romdump, err := dbg.vcs.Mem.Cart.ROMDump()
if err != nil {
@@ -1496,7 +1477,7 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
case "DUMP":
dump := func(name string) {
if data, ok := static.Reference(name); ok {
- fn := unique.Filename(fmt.Sprintf("dump_%s", name), dbg.loader.Name)
+ fn := unique.Filename(fmt.Sprintf("dump_%s", name), dbg.cartload.Name)
fn = fmt.Sprintf("%s.bin", fn)
err := os.WriteFile(fn, data, 0644)
if err != nil {
@@ -1799,7 +1780,7 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
if ok {
switch strings.ToUpper(controller) {
case "AUTO":
- dbg.vcs.FingerprintPeripheral(id, *dbg.loader)
+ dbg.vcs.FingerprintPeripheral(id, *dbg.cartload)
case "STICK":
err = dbg.vcs.RIOT.Ports.Plug(id, controllers.NewStick)
case "PADDLE":
diff --git a/debugger/commands_template.go b/debugger/commands_template.go
index 61f6014e..f390565a 100644
--- a/debugger/commands_template.go
+++ b/debugger/commands_template.go
@@ -96,7 +96,7 @@ var commandTemplate = []string{
cmdGoto + " [%N] (%N) (%N)",
cmdInsert + " %F",
- cmdCartridge + " (PATH|NAME|MAPPER|CONTAINER|MAPPEDBANKS|HASH|STATIC|REGISTERS|RAM|HOTLOAD|DUMP)",
+ cmdCartridge + " (PATH|NAME|MAPPER|CONTAINER|MAPPEDBANKS|HASH|STATIC|REGISTERS|RAM|DUMP)",
cmdPatch + " %S",
cmdDisasm + " (BYTECODE|REDUX)",
cmdGrep + " (OPERATOR|OPERAND|COPROC) %S",
diff --git a/debugger/debugger.go b/debugger/debugger.go
index e4e28969..08aad27b 100644
--- a/debugger/debugger.go
+++ b/debugger/debugger.go
@@ -99,9 +99,8 @@ type Debugger struct {
// components may change (during rewind for example)
vcs *hardware.VCS
- // the last loader to be used. we keep a reference to it so we can make
- // sure Close() is called on end
- loader *cartridgeloader.Loader
+ // keep a reference to the current cartridgeloader to make sure Close() is called
+ cartload *cartridgeloader.Loader
// preview emulation is used to gather information about a ROM before
// running it fully
@@ -707,6 +706,8 @@ func (dbg *Debugger) StartInDebugMode(filename string) error {
}
}
+ // cartload is should be passed to attachCartridge() almost immediately. the
+ // closure of cartload will then be handled for us
err = dbg.attachCartridge(cartload)
if err != nil {
return fmt.Errorf("debugger: %w", err)
@@ -778,24 +779,25 @@ func (dbg *Debugger) StartInPlayMode(filename string) error {
// set running flag as early as possible
dbg.running = true
- var err error
- var cartload cartridgeloader.Loader
-
- if filename == "" {
- cartload = cartridgeloader.Loader{}
- } else {
- cartload, err = cartridgeloader.NewLoaderFromFilename(filename, dbg.opts.Mapping)
- if err != nil {
- return fmt.Errorf("debugger: %w", err)
- }
- }
-
- err = recorder.IsPlaybackFile(filename)
+ err := recorder.IsPlaybackFile(filename)
if err != nil {
if !errors.Is(err, recorder.NotAPlaybackFile) {
return fmt.Errorf("debugger: %w", err)
}
+ var cartload cartridgeloader.Loader
+
+ if filename == "" {
+ cartload = cartridgeloader.Loader{}
+ } else {
+ cartload, err = cartridgeloader.NewLoaderFromFilename(filename, dbg.opts.Mapping)
+ if err != nil {
+ return fmt.Errorf("debugger: %w", err)
+ }
+ }
+
+ // cartload is should be passed to attachCartridge() almost immediately. the
+ // closure of cartload will then be handled for us
err = dbg.attachCartridge(cartload)
if err != nil {
return fmt.Errorf("debugger: %w", err)
@@ -940,8 +942,8 @@ func (dbg *Debugger) run() error {
// make sure any cartridge loader has been finished with
defer func() {
- if dbg.loader != nil {
- err := dbg.loader.Close()
+ if dbg.cartload != nil {
+ err := dbg.cartload.Close()
if err != nil {
logger.Logf("debugger", err.Error())
}
@@ -1141,9 +1143,12 @@ func (dbg *Debugger) Notify(notice notifications.Notice) error {
//
// if the new cartridge loader has the same filename as the previous loader
// then reset() is called with a newCartridge argument of false.
+//
+// VERY IMPORTANT that the supplied cartload is assigned to dbg.cartload before
+// returning from the function
func (dbg *Debugger) attachCartridge(cartload cartridgeloader.Loader) (e error) {
// is this a new cartridge we're loading. value is used for dbg.reset()
- newCartridge := dbg.loader == nil || cartload.Filename != dbg.loader.Filename
+ newCartridge := dbg.cartload == nil || cartload.Filename != dbg.cartload.Filename
// stop optional sub-systems that shouldn't survive a new cartridge insertion
dbg.endPlayback()
@@ -1169,13 +1174,13 @@ func (dbg *Debugger) attachCartridge(cartload cartridgeloader.Loader) (e error)
}()
// close any existing loader before continuing
- if dbg.loader != nil {
- err := dbg.loader.Close()
+ if dbg.cartload != nil {
+ err := dbg.cartload.Close()
if err != nil {
- return err
+ logger.Logf("debuger", err.Error())
}
}
- dbg.loader = &cartload
+ dbg.cartload = &cartload
// reset of vcs is implied with attach cartridge
err := setup.AttachCartridge(dbg.vcs, cartload, false)
@@ -1332,11 +1337,14 @@ func (dbg *Debugger) startComparison(comparisonROM string, comparisonPrefs strin
return err
}
+ // cartload is passed to comparision.CreateFromLoader(). closure will be
+ // handled from there
cartload, err := cartridgeloader.NewLoaderFromFilename(comparisonROM, "AUTO")
if err != nil {
return err
}
+ // comparision emulation handles closure of cartridgeloader
dbg.comparison.CreateFromLoader(cartload)
// check use of comparison prefs
@@ -1361,49 +1369,6 @@ func (dbg *Debugger) endComparison() {
}
}
-func (dbg *Debugger) hotload() (e error) {
- // tell GUI that we're in the initialistion phase
- dbg.setState(govern.Initialising, govern.Normal)
- defer func() {
- if dbg.runUntilHalt && e == nil {
- dbg.setState(govern.Running, govern.Normal)
- } else {
- dbg.setState(govern.Paused, govern.Normal)
- }
- }()
-
- // close any existing loader before continuing
- if dbg.loader != nil {
- err := dbg.loader.Close()
- if err != nil {
- return err
- }
- }
-
- cartload, err := cartridgeloader.NewLoaderFromFilename(dbg.vcs.Mem.Cart.Filename, dbg.vcs.Mem.Cart.ID())
- if err != nil {
- return err
- }
-
- err = dbg.vcs.Mem.Cart.HotLoad(cartload)
- if err != nil {
- return err
- }
-
- dbg.loader = &cartload
-
- // disassemble newly attached cartridge
- err = dbg.Disasm.FromMemory()
- if err != nil {
- return err
- }
-
- dbg.CoProcDisasm.AttachCartridge(dbg)
- dbg.CoProcDev.AttachCartridge(dbg, cartload.Filename, dbg.opts.ELF)
-
- return nil
-}
-
// parseInput splits the input into individual commands. each command is then
// passed to parseCommand for processing
//
@@ -1453,7 +1418,7 @@ func (dbg *Debugger) Plugged(port plugging.PortID, peripheral plugging.Periphera
}
func (dbg *Debugger) reloadCartridge() error {
- if dbg.loader == nil {
+ if dbg.cartload == nil {
return nil
}
@@ -1462,7 +1427,7 @@ func (dbg *Debugger) reloadCartridge() error {
dbg.macro.Reset()
}
- return dbg.insertCartridge(dbg.loader.Filename)
+ return dbg.insertCartridge(dbg.cartload.Filename)
}
// ReloadCartridge inserts the current cartridge and states the emulation over.
@@ -1472,7 +1437,7 @@ func (dbg *Debugger) ReloadCartridge() {
func (dbg *Debugger) insertCartridge(filename string) error {
if filename == "" {
- filename = dbg.loader.Filename
+ filename = dbg.cartload.Filename
}
cartload, err := cartridgeloader.NewLoaderFromFilename(filename, "AUTO")
@@ -1480,6 +1445,8 @@ func (dbg *Debugger) insertCartridge(filename string) error {
return fmt.Errorf("debugger: %w", err)
}
+ // cartload is should be passed to attachCartridge() almost immediately. the
+ // closure of cartload will then be handled for us
err = dbg.attachCartridge(cartload)
if err != nil {
return fmt.Errorf("debugger: %w", err)
diff --git a/gui/sdlimgui/win_rom_select.go b/gui/sdlimgui/win_rom_select.go
index b8c1e117..b146262c 100644
--- a/gui/sdlimgui/win_rom_select.go
+++ b/gui/sdlimgui/win_rom_select.go
@@ -396,187 +396,172 @@ func (win *winSelectROM) draw() {
// control buttons. start controlHeight measurement
win.controlHeight = imguiMeasureHeight(func() {
- func() {
- if !win.thmb.IsEmulating() {
- imgui.PushItemFlag(imgui.ItemFlagsDisabled, true)
- imgui.PushStyleVarFloat(imgui.StyleVarAlpha, disabledAlpha)
- defer imgui.PopItemFlag()
- defer imgui.PopStyleVar()
- }
+ imgui.SetNextItemOpen(win.informationOpen, imgui.ConditionAlways)
+ if !imgui.CollapsingHeaderV(win.selectedName, imgui.TreeNodeFlagsNone) {
+ win.informationOpen = false
+ } else {
+ win.informationOpen = true
+ if imgui.BeginTable("#properties", 3) {
+ imgui.TableSetupColumnV("#information", imgui.TableColumnFlagsWidthStretch, -1, 0)
+ imgui.TableSetupColumnV("#spacingA", imgui.TableColumnFlagsWidthFixed, -1, 1)
+ imgui.TableSetupColumnV("#boxart", imgui.TableColumnFlagsWidthFixed, -1, 2)
- imgui.SetNextItemOpen(win.informationOpen, imgui.ConditionAlways)
- if !imgui.CollapsingHeaderV(win.selectedName, imgui.TreeNodeFlagsNone) {
- win.informationOpen = false
- } else {
- win.informationOpen = true
- if imgui.BeginTable("#properties", 3) {
- imgui.TableSetupColumnV("#information", imgui.TableColumnFlagsWidthStretch, -1, 0)
- imgui.TableSetupColumnV("#spacingA", imgui.TableColumnFlagsWidthFixed, -1, 1)
- imgui.TableSetupColumnV("#boxart", imgui.TableColumnFlagsWidthFixed, -1, 2)
+ // property table. we measure the height of this table to
+ // help centering the box art image in the next column
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ propertyTableTop := imgui.CursorPosY()
+ if imgui.BeginTable("#properties", 2) {
+ imgui.TableSetupColumnV("#category", imgui.TableColumnFlagsWidthFixed, -1, 0)
+ imgui.TableSetupColumnV("#detail", imgui.TableColumnFlagsWidthFixed, -1, 1)
+
+ // wrap text
+ imgui.PushTextWrapPosV(imgui.CursorPosX() + imgui.ContentRegionAvail().X)
+ defer imgui.PopTextWrapPos()
- // property table. we measure the height of this table to
- // help centering the box art image in the next column
imgui.TableNextRow()
imgui.TableNextColumn()
- propertyTableTop := imgui.CursorPosY()
- if imgui.BeginTable("#properties", 2) {
- imgui.TableSetupColumnV("#category", imgui.TableColumnFlagsWidthFixed, -1, 0)
- imgui.TableSetupColumnV("#detail", imgui.TableColumnFlagsWidthFixed, -1, 1)
-
- // wrap text
- imgui.PushTextWrapPosV(imgui.CursorPosX() + imgui.ContentRegionAvail().X)
- defer imgui.PopTextWrapPos()
-
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.Text("Name")
- imgui.TableNextColumn()
- if win.selectedProperties.IsValid() {
- imgui.Text(win.selectedProperties.Name)
- } else {
- imgui.Text(win.selectedName)
- }
-
- // results of preview emulation from the thumbnailer
- selectedFilePreview := win.thmb.PreviewResults()
-
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.AlignTextToFramePadding()
- imgui.Text("Mapper")
- imgui.TableNextColumn()
- if selectedFilePreview != nil {
- imgui.Text(selectedFilePreview.VCS.Mem.Cart.ID())
- }
-
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.PushItemFlag(imgui.ItemFlagsDisabled, true)
- imgui.PushStyleVarFloat(imgui.StyleVarAlpha, disabledAlpha)
- imgui.AlignTextToFramePadding()
- imgui.Text("Television")
- imgui.TableNextColumn()
- if selectedFilePreview != nil {
- imgui.SetNextItemWidth(80)
- if imgui.BeginCombo("##tvspec", selectedFilePreview.FrameInfo.Spec.ID) {
- for _, s := range specification.SpecList {
- if imgui.Selectable(s) {
- }
- }
- imgui.EndCombo()
- }
- }
- imgui.PopStyleVar()
- imgui.PopItemFlag()
-
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.PushItemFlag(imgui.ItemFlagsDisabled, true)
- imgui.PushStyleVarFloat(imgui.StyleVarAlpha, disabledAlpha)
- imgui.AlignTextToFramePadding()
- imgui.Text("Players")
- imgui.TableNextColumn()
- if selectedFilePreview != nil {
- imgui.SetNextItemWidth(100)
- if imgui.BeginCombo("##leftplayer", string(selectedFilePreview.VCS.RIOT.Ports.LeftPlayer.ID())) {
- for _, s := range peripherals.AvailableLeftPlayer {
- if imgui.Selectable(s) {
- }
- }
- imgui.EndCombo()
- }
- imgui.SameLineV(0, 15)
- imgui.Text("&")
- imgui.SameLineV(0, 15)
- imgui.SetNextItemWidth(100)
- if imgui.BeginCombo("##rightplayer", string(selectedFilePreview.VCS.RIOT.Ports.RightPlayer.ID())) {
- for _, s := range peripherals.AvailableRightPlayer {
- if imgui.Selectable(s) {
- }
- }
- imgui.EndCombo()
- }
- }
- imgui.PopStyleVar()
- imgui.PopItemFlag()
-
- if win.selectedProperties.Manufacturer != "" {
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.AlignTextToFramePadding()
- imgui.Text("Manufacturer")
- imgui.TableNextColumn()
- imgui.Text(win.selectedProperties.Manufacturer)
- }
- if win.selectedProperties.Rarity != "" {
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.AlignTextToFramePadding()
- imgui.Text("Rarity")
- imgui.TableNextColumn()
- imgui.Text(win.selectedProperties.Rarity)
- }
- if win.selectedProperties.Model != "" {
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.AlignTextToFramePadding()
- imgui.Text("Model")
- imgui.TableNextColumn()
- imgui.Text(win.selectedProperties.Model)
- }
-
- if win.selectedProperties.Note != "" {
- imgui.TableNextRow()
- imgui.TableNextColumn()
- imgui.AlignTextToFramePadding()
- imgui.Text("Note")
- imgui.TableNextColumn()
- imgui.Text(win.selectedProperties.Note)
- }
-
- imgui.EndTable()
- }
- propertyTableBottom := imgui.CursorPosY()
- propertyTableHeight := propertyTableBottom - propertyTableTop
-
- // spacing
+ imgui.Text("Name")
imgui.TableNextColumn()
+ if win.selectedProperties.IsValid() {
+ imgui.Text(win.selectedProperties.Name)
+ } else {
+ imgui.Text(win.selectedName)
+ }
- if win.boxartUse {
- imgui.TableNextColumn()
- sz := imgui.Vec2{float32(win.boxartDimensions.X), float32(win.boxartDimensions.Y)}
+ // results of preview emulation from the thumbnailer
+ selectedFilePreview := win.thmb.PreviewResults()
- // if thumbnail height is less than height of
- // property table then we position the image so that
- // it's centered in relation to the property table
- p := imgui.CursorPos()
- if sz.Y < propertyTableHeight {
- p.Y += (propertyTableHeight - sz.Y) / 2
- imgui.SetCursorPos(p)
- } else {
- // if height of thumbnail is greater than or
- // equal to height of property table then we add
- // a imgui.Spacing(). this may expand the height
- // of the property table but that's okay
- imgui.Spacing()
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Mapper")
+ imgui.TableNextColumn()
+ if selectedFilePreview != nil {
+ imgui.Text(selectedFilePreview.VCS.Mem.Cart.ID())
+ }
+
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.PushItemFlag(imgui.ItemFlagsDisabled, true)
+ imgui.PushStyleVarFloat(imgui.StyleVarAlpha, disabledAlpha)
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Television")
+ imgui.TableNextColumn()
+ if selectedFilePreview != nil {
+ imgui.SetNextItemWidth(80)
+ if imgui.BeginCombo("##tvspec", selectedFilePreview.FrameInfo.Spec.ID) {
+ for _, s := range specification.SpecList {
+ if imgui.Selectable(s) {
+ }
+ }
+ imgui.EndCombo()
}
+ }
+ imgui.PopStyleVar()
+ imgui.PopItemFlag()
- imgui.Image(imgui.TextureID(win.boxartTexture.getID()), sz)
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.PushItemFlag(imgui.ItemFlagsDisabled, true)
+ imgui.PushStyleVarFloat(imgui.StyleVarAlpha, disabledAlpha)
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Players")
+ imgui.TableNextColumn()
+ if selectedFilePreview != nil {
+ imgui.SetNextItemWidth(100)
+ if imgui.BeginCombo("##leftplayer", string(selectedFilePreview.VCS.RIOT.Ports.LeftPlayer.ID())) {
+ for _, s := range peripherals.AvailableLeftPlayer {
+ if imgui.Selectable(s) {
+ }
+ }
+ imgui.EndCombo()
+ }
+ imgui.SameLineV(0, 15)
+ imgui.Text("&")
+ imgui.SameLineV(0, 15)
+ imgui.SetNextItemWidth(100)
+ if imgui.BeginCombo("##rightplayer", string(selectedFilePreview.VCS.RIOT.Ports.RightPlayer.ID())) {
+ for _, s := range peripherals.AvailableRightPlayer {
+ if imgui.Selectable(s) {
+ }
+ }
+ imgui.EndCombo()
+ }
+ }
+ imgui.PopStyleVar()
+ imgui.PopItemFlag()
+
+ if win.selectedProperties.Manufacturer != "" {
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Manufacturer")
+ imgui.TableNextColumn()
+ imgui.Text(win.selectedProperties.Manufacturer)
+ }
+ if win.selectedProperties.Rarity != "" {
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Rarity")
+ imgui.TableNextColumn()
+ imgui.Text(win.selectedProperties.Rarity)
+ }
+ if win.selectedProperties.Model != "" {
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Model")
+ imgui.TableNextColumn()
+ imgui.Text(win.selectedProperties.Model)
+ }
+
+ if win.selectedProperties.Note != "" {
+ imgui.TableNextRow()
+ imgui.TableNextColumn()
+ imgui.AlignTextToFramePadding()
+ imgui.Text("Note")
+ imgui.TableNextColumn()
+ imgui.Text(win.selectedProperties.Note)
}
imgui.EndTable()
}
+ propertyTableBottom := imgui.CursorPosY()
+ propertyTableHeight := propertyTableBottom - propertyTableTop
+
+ // spacing
+ imgui.TableNextColumn()
+
+ if win.boxartUse {
+ imgui.TableNextColumn()
+ sz := imgui.Vec2{float32(win.boxartDimensions.X), float32(win.boxartDimensions.Y)}
+
+ // if thumbnail height is less than height of
+ // property table then we position the image so that
+ // it's centered in relation to the property table
+ p := imgui.CursorPos()
+ if sz.Y < propertyTableHeight {
+ p.Y += (propertyTableHeight - sz.Y) / 2
+ imgui.SetCursorPos(p)
+ } else {
+ // if height of thumbnail is greater than or
+ // equal to height of property table then we add
+ // a imgui.Spacing(). this may expand the height
+ // of the property table but that's okay
+ imgui.Spacing()
+ }
+
+ imgui.Image(imgui.TextureID(win.boxartTexture.getID()), sz)
+ }
+
+ imgui.EndTable()
}
- }()
+ }
imguiSeparator()
- // imgui.Checkbox("Show all files", &win.showAllFiles)
- // imgui.SameLine()
- // imgui.Checkbox("Show hidden files", &win.showHidden)
-
- // imgui.Spacing()
-
if imgui.Button("Cancel") {
// close rom selected in both the debugger and playmode
win.debuggerSetOpen(false)
@@ -646,7 +631,7 @@ func (win *winSelectROM) setSelectedFile(filename string) {
}
// create cartridge loader and start thumbnail emulation
- loader, err := cartridgeloader.NewLoaderFromFilename(filename, "AUTO")
+ cartload, err := cartridgeloader.NewLoaderFromFilename(filename, "AUTO")
if err != nil {
logger.Logf("ROM Select", err.Error())
return
@@ -654,10 +639,10 @@ func (win *winSelectROM) setSelectedFile(filename string) {
// push function to emulation goroutine. result will be checked for in
// draw() function
- win.img.dbg.PushPropertyLookup(loader.HashMD5, win.propertyResult)
+ win.img.dbg.PushPropertyLookup(cartload.HashMD5, win.propertyResult)
// create thumbnail animation
- win.thmb.Create(loader, thumbnailer.UndefinedNumFrames, true)
+ win.thmb.Create(cartload, thumbnailer.UndefinedNumFrames, true)
// defer boxart lookup to when we receive the property
}
diff --git a/hardware/memory/cartridge/cartridge.go b/hardware/memory/cartridge/cartridge.go
index 3b8292b1..3e0ad3c5 100644
--- a/hardware/memory/cartridge/cartridge.go
+++ b/hardware/memory/cartridge/cartridge.go
@@ -406,23 +406,6 @@ func (cart *Cartridge) Step(clock float32) {
cart.mapper.Step(clock)
}
-// Hotload cartridge ROM into emulation. Not changing any other state of the
-// emulation.
-func (cart *Cartridge) HotLoad(cartload cartridgeloader.Loader) error {
- if hl, ok := cart.mapper.(mapper.CartHotLoader); ok {
- cart.Hash = cartload.HashSHA1
-
- err := hl.HotLoad(cartload)
- if err != nil {
- return err
- }
-
- return nil
- }
-
- return fmt.Errorf("cartridge: %s does not support hotloading", cart.mapper.ID())
-}
-
// GetRegistersBus returns interface to the registers of the cartridge or nil
// if cartridge has no registers.
func (cart *Cartridge) GetRegistersBus() mapper.CartRegistersBus {
diff --git a/hardware/memory/cartridge/mapper/mapper.go b/hardware/memory/cartridge/mapper/mapper.go
index 8134a14f..d51c3c1d 100644
--- a/hardware/memory/cartridge/mapper/mapper.go
+++ b/hardware/memory/cartridge/mapper/mapper.go
@@ -16,7 +16,6 @@
package mapper
import (
- "github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/cpu"
"github.com/jetsetilly/gopher2600/hardware/memory/vcs"
@@ -341,12 +340,6 @@ type CartRewindBoundary interface {
RewindBoundary() bool
}
-// CartHotLoader is implemented by cartridge mappers that can be hot-loaded.
-// ie. ROM data updated but keeping RAM memory intact.
-type CartHotLoader interface {
- HotLoad(cartridgeloader.Loader) error
-}
-
// CartROMDump is implemented by cartridge mappers that can save themselves to disk.
type CartROMDump interface {
ROMDump(filename string) error