diff --git a/CartridgeMenu.cpp b/CartridgeMenu.cpp
deleted file mode 100644
index 8c8f718f..00000000
--- a/CartridgeMenu.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-
-// TODO: move this to libcommon
-
-#include "CartridgeMenu.h"
-#include
-#include "defines.h"
-
-CartridgeMenu::CartridgeMenu() {};
-
-// Init. Title is menu bar title. Position is where the menu is placed on title bar
-void CartridgeMenu::init(const char * title,int position) {
- MenuBarTitle_ = title;
- MenuPosition_ = position;
- reserve_ = 0;
-}
-
-// Menu add requests come from both the pakinterface and carts via config calls;
-// pakinterface entries should always be first, followed by carts in slot 4 to 1 in
-// that order. pakinterface can set the reserve to keep it's menu items from being
-// overwritten from the mpi scan of the slots.
-// Set the number of entries to reserve for cartridge menu
-void CartridgeMenu::reserve(const unsigned int count) {
- reserve_ = count;
-};
-
-// Add menu entry.
-void CartridgeMenu::add(const char * name, unsigned int menu_id, MenuItemType type) {
- switch (menu_id) {
- case MID_BEGIN:
- if (menu_.size() > reserve_) menu_.resize(reserve_);
- break;
- case MID_FINISH:
- draw();
- break;
- default:
- // Some older DLLs used message type MIT_Head with an empty name for a seperator.
- // To support those here is a check for MIT_Head with an empty name.
- if (type == MIT_Head && strcmp(name,"") == 0) type = MIT_Seperator;
- menu_.push_back({name,menu_id,type});
- break;
- }
-}
-
-// Draw the menu
-HMENU CartridgeMenu::draw() {
-
- // Fullscreen toggle changes the WindowHandle
- if (hMenuBar_ == nullptr || hMainWin_ != EmuState.WindowHandle) {
- hMainWin_ = EmuState.WindowHandle;
- hMenuBar_ = GetMenu(hMainWin_);
- }
-
- // Erase the Existing Cartridge Menu. Vcc.rc defines a dummy Cartridge menu to
- // preserve it's place.
- DeleteMenu(hMenuBar_,MenuPosition_,MF_BYPOSITION);
-
- // Create first sub menu item
- HMENU hMenu = CreatePopupMenu();
- HMENU hMenu0 = hMenu;
-
- MENUITEMINFO Mii{};
- memset(&Mii,0,sizeof(MENUITEMINFO));
-
- // Create title bar item
- Mii.cbSize= sizeof(MENUITEMINFO);
- Mii.fMask = MIIM_TYPE | MIIM_SUBMENU | MIIM_ID; // setting the submenu id
- Mii.fType = MFT_STRING; // Type is a string
- Mii.hSubMenu = hMenu;
- Mii.dwTypeData = const_cast(MenuBarTitle_.c_str());
- Mii.cch = MenuBarTitle_.size();
- InsertMenuItem(hMenuBar_,MenuPosition_,TRUE,&Mii);
-
- // Create sub menus in order
- unsigned int pos = 0u;
- for (CartMenuItem item : menu_) {
- DLOG_C("%4d %d '%s'\n",item.menu_id,item.type,item.name.c_str());
- switch (item.type) {
- case MIT_Head:
- hMenu = CreatePopupMenu();
- Mii.fMask = MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;
- Mii.fType = MFT_STRING;
- Mii.hSubMenu = hMenu;
- Mii.dwTypeData = const_cast(item.name.c_str());
- InsertMenuItem(hMenu0,pos,TRUE,&Mii);
- pos++;
- break;
- case MIT_Slave:
- Mii.fMask = MIIM_TYPE | MIIM_ID;
- Mii.fType = MFT_STRING;
- Mii.wID = item.menu_id;
- Mii.hSubMenu = hMenu;
- Mii.dwTypeData = const_cast(item.name.c_str());
- Mii.cch=item.name.size();
- InsertMenuItem(hMenu,0,FALSE,&Mii);
- break;
- case MIT_Seperator:
- Mii.fMask = MIIM_TYPE | MIIM_ID;
- Mii.hSubMenu = hMenuBar_;
- Mii.dwTypeData = "";
- Mii.cch=0;
- Mii.fType = MF_SEPARATOR;
- InsertMenuItem(hMenu0,pos,TRUE,&Mii);
- pos++;
- break;
- case MIT_StandAlone:
- Mii.fMask = MIIM_TYPE | MIIM_ID;
- Mii.wID = item.menu_id;
- Mii.hSubMenu = hMenuBar_;
- Mii.dwTypeData = const_cast(item.name.c_str());
- Mii.cch=item.name.size();
- Mii.fType = MFT_STRING;
- InsertMenuItem(hMenu0,pos,TRUE,&Mii);
- pos++;
- break;
- }
- }
- DrawMenuBar(hMainWin_);
- return hMenu0;
-}
-
diff --git a/CartridgeMenu.h b/CartridgeMenu.h
deleted file mode 100644
index 1111d9bd..00000000
--- a/CartridgeMenu.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- Copyright 2015 by Joseph Forgione
- This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-
-#pragma once
-
-#include
-#include
-#include
-
-// A menu ID is either a small unsigned integer less than or equal to 50 used
-// to identify cart menu functions with control id in the range 5000 - 5050.
-// Menu ID's map directly to control id's by adding 5000. The ControlId()
-// constexpr should be used to get the control id from a menu id. There are three
-// "special" message IDs as follows:
-
-constexpr auto MID_BEGIN = 0; // Clears the menu, optionally reserving some entries.
-constexpr auto MID_FINISH = 1; // Draws the menu
-constexpr auto MID_ENTRY = 2; // A menu item with no control
-
-// Menu IDs other than the above special ones must be converted to control IDs
-// using the ControlId() constexpr. These reference controls that are activated
-// when the menu item is selected.
-
-// The MPI adds 50 times the slot number (1-4) to the ID when a cartridge is loaded in
-// an mpi slot, then subtracts this value when the item is activated before using
-// it to call the control in the cartridge dll. This allows dynamic cartridge menus to
-// work properly regardless of which slot they are in.
-
-constexpr auto MID_CONTROL = 5000;
-
-// constexpr to convert menu id number to control id
-constexpr int ControlId(int id) { return MID_CONTROL + id; };
-
-// Menu item types, one of the following.
-enum MenuItemType
-{
- MIT_Head, // Menu header with no associated control, may have slave items
- MIT_Slave, // Slave items with associated control in header submenu.
- MIT_StandAlone, // Menu item with an associated control
- MIT_Seperator, // Draws a horizontal line to seperate groups of menu items
-};
-
-
-struct CartMenuItem {
- std::string name;
- unsigned int menu_id;
- MenuItemType type;
-};
-
-class CartridgeMenu {
-
-private:
- std::vector menu_ {};
- HWND hMainWin_;
- HMENU hMenuBar_;
- std::string MenuBarTitle_;
- int MenuPosition_;
- unsigned int reserve_;
-
-public:
- CartridgeMenu();
-
-// Title is menu bar title, position is location menu will be placed on the menu bar.
- void init(const char * title="Cartridge", int position=3);
-
-// Reserve cartmenu items. The reserve value allows the 'Cartridge' menu item and
-// it's submenu to remain intact when DLL's append items to the menu. The reserve
-// value is only used whwn MID_BEGIN items are encountered.
- void reserve(const unsigned int count);
-
-// Add menu entry. name is the item text, menu_id and type per above. Reserve is the
-// number of menu items to kept before MID_BEGIN.
- void add(const char * name, unsigned int menu_id, MenuItemType type);
-
-// Draw refreshes the menu
- HMENU draw();
-};
-
-// Make CartridgeMenu Object global;
-extern CartridgeMenu CartMenu;
diff --git a/FD502/fd502.cpp b/FD502/fd502.cpp
index 818dd195..9a5e7add 100644
--- a/FD502/fd502.cpp
+++ b/FD502/fd502.cpp
@@ -35,11 +35,14 @@
#include "wd1793.h"
#include "distortc.h"
#include "fd502.h"
-#include "../CartridgeMenu.h"
#include
#include
#include
#include
+// Three includes added for PakGetMenuItem
+#include
+#include
+#include
//include becker code if COMBINE_BECKER is defined in fd502.h
#ifdef COMBINE_BECKER
@@ -59,7 +62,6 @@ static char RomFileName[MAX_PATH]="";
static char TempRomFileName[MAX_PATH]="";
slot_id_type gSlotId {};
PakAssertInteruptHostCallback AssertInt = nullptr;
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
unsigned char PhysicalDriveA=0,PhysicalDriveB=0,OldPhysicalDriveA=0,OldPhysicalDriveB=0;
static unsigned char *RomPointer[3]={ExternalRom,DiskRom,RGBDiskRom};
static unsigned char SelectRom=0;
@@ -74,6 +76,7 @@ LRESULT CALLBACK NewDisk(HWND,UINT, WPARAM, LPARAM);
void LoadConfig();
void SaveConfig();
long CreateDiskHeader(const char *,unsigned char,unsigned char,unsigned char);
+void Unload_Disk(unsigned char);
void Load_Disk(unsigned char);
static HWND g_hConfDlg = nullptr;
@@ -83,10 +86,16 @@ long CreateDisk (unsigned char);
static char gSelectedDiskFile[MAX_PATH]="";
unsigned char LoadExtRom( unsigned char, const char *);
+// Added for PakGetMenuItem export
+bool get_menu_item(menu_item_entry*, size_t index);
+
int BeckerEnabled=0;
char BeckerAddr[MAX_PATH]="";
char BeckerPort[32]="";
+// Added for PakGetMenuItem export
+static HWND gVccWnd = nullptr;
+
//----------------------------------------------------------------------------
extern "C"
{
@@ -126,13 +135,13 @@ extern "C"
{
DLOG_C("FDC %p %p %p %p %p\n",*callbacks);
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
+ gVccWnd = hVccWnd;
AssertInt = callbacks->assert_interrupt;
strcpy(IniFile, configuration_path);
RealDisks = InitController();
LoadConfig();
- BuildCartridgeMenu();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
}
__declspec(dllexport) void PakReset()
@@ -152,6 +161,12 @@ extern "C"
}
}
+ //PakGetMenuItem export
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
+ }
+
__declspec(dllexport) void PakMenuItemClicked(unsigned char MenuID)
{
HWND h_own = GetActiveWindow();
@@ -161,37 +176,33 @@ extern "C"
Load_Disk(0);
break;
case 11:
- unmount_disk_image(0);
- SaveConfig();
+ Unload_Disk(0);
break;
case 12:
Load_Disk(1);
break;
case 13:
- unmount_disk_image(1);
- SaveConfig();
+ Unload_Disk(1);
break;
case 14:
Load_Disk(2);
break;
case 15:
- unmount_disk_image(2);
- SaveConfig();
- break;
- case 16:
- if (g_hConfDlg == nullptr)
- g_hConfDlg = CreateDialog(gModuleInstance,(LPCTSTR)IDD_CONFIG,h_own,(DLGPROC)Config);
- ShowWindow(g_hConfDlg,1);
+ Unload_Disk(2);
break;
case 17:
Load_Disk(3);
break;
case 18:
- unmount_disk_image(3);
- SaveConfig();
+ Unload_Disk(3);
+ break;
+ case 16:
+ if (g_hConfDlg == nullptr)
+ g_hConfDlg = CreateDialog(
+ gModuleInstance,(LPCTSTR)IDD_CONFIG,h_own,(DLGPROC)Config);
+ ShowWindow(g_hConfDlg,1);
break;
}
- BuildCartridgeMenu();
return;
}
@@ -400,6 +411,12 @@ LRESULT CALLBACK Config(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*
return FALSE;
}
+void Unload_Disk(unsigned char disk) {
+ unmount_disk_image(disk);
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
+ SaveConfig();
+}
+
void Load_Disk(unsigned char disk)
{
HWND h_own = GetActiveWindow();
@@ -430,6 +447,7 @@ void Load_Disk(unsigned char disk)
MessageBox(g_hConfDlg,"Can't open file","Error",0);
} else {
dlg.getdir(FloppyPath);
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
SaveConfig();
}
}
@@ -444,50 +462,37 @@ unsigned char SetChip(unsigned char Tmp)
return SelectRom;
}
-void BuildCartridgeMenu()
+// Added for PakGetMenuItem export
+// Return items for cartridge menu. Called for each item
+bool get_menu_item(menu_item_entry* item, size_t index)
{
- char TempMsg[MAX_PATH]="";
- char TempBuf[MAX_PATH]="";
- if (CartMenuCallback ==nullptr)
- MessageBox(g_hConfDlg,"No good","Ok",0);
-
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
-
- CartMenuCallback(gSlotId, "FD-502 Drive 0",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(10),MIT_Slave);
- strncpy(TempMsg,"Eject: ",MAX_PATH);
- strncpy(TempBuf,gVirtualDrive[0].ImageName,MAX_PATH);
- PathStripPath(TempBuf);
- strncat(TempMsg,TempBuf,MAX_PATH);
- CartMenuCallback(gSlotId, TempMsg,ControlId(11),MIT_Slave);
-
- CartMenuCallback(gSlotId, "FD-502 Drive 1",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(12),MIT_Slave);
- strncpy(TempMsg,"Eject: ",MAX_PATH);
- strncpy(TempBuf,gVirtualDrive[1].ImageName,MAX_PATH);
- PathStripPath(TempBuf);
- strncat(TempMsg,TempBuf,MAX_PATH);
- CartMenuCallback(gSlotId, TempMsg,ControlId(13),MIT_Slave);
-
- CartMenuCallback(gSlotId, "FD-502 Drive 2",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(14),MIT_Slave);
- strncpy(TempMsg,"Eject: ",MAX_PATH);
- strncpy(TempBuf,gVirtualDrive[2].ImageName,MAX_PATH);
- PathStripPath(TempBuf);
- strncat(TempMsg,TempBuf,MAX_PATH);
- CartMenuCallback(gSlotId, TempMsg,ControlId(15),MIT_Slave);
-
- CartMenuCallback(gSlotId, "FD-502 Drive 3",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(17),MIT_Slave);
- strncpy(TempMsg,"Eject: ",MAX_PATH);
- strncpy(TempBuf,gVirtualDrive[3].ImageName,MAX_PATH);
- PathStripPath(TempBuf);
- strncat(TempMsg,TempBuf,MAX_PATH);
- CartMenuCallback(gSlotId, TempMsg,ControlId(18),MIT_Slave);
-
- CartMenuCallback(gSlotId, "FD-502 Config",ControlId(16),MIT_StandAlone);
- CartMenuCallback(gSlotId,"", MID_FINISH, MIT_Head);
+ using VCC::Bus::gDllCartMenu;
+ std::string disk;
+ if (!item) return false;
+ // request zero rebuilds the menu list
+ if (index == 0) {
+ gDllCartMenu.clear();
+ gDllCartMenu.add("", 0, MIT_Seperator);
+ gDllCartMenu.add("FD-502 Drive 0",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(10),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(gVirtualDrive[0].ImageName);
+ gDllCartMenu.add("Eject: "+disk,ControlId(11),MIT_Slave);
+ gDllCartMenu.add("FD-502 Drive 1",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(12),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(gVirtualDrive[1].ImageName);
+ gDllCartMenu.add("Eject: "+disk,ControlId(13),MIT_Slave);
+ gDllCartMenu.add("FD-502 Drive 2",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(14),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(gVirtualDrive[2].ImageName);
+ gDllCartMenu.add("Eject: "+disk,ControlId(15),MIT_Slave);
+ gDllCartMenu.add("FD-502 Drive 3",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(17),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(gVirtualDrive[3].ImageName);
+ gDllCartMenu.add("Eject: "+disk,ControlId(18),MIT_Slave);
+ gDllCartMenu.add("FD-502 Config",ControlId(16),MIT_StandAlone);
+ }
+ // return requested list item or false
+ return gDllCartMenu.copy_item(*item, index);
}
long CreateDisk (unsigned char Disk)
@@ -712,8 +717,7 @@ void LoadConfig() // Called on SetIniPath
}
ClockEnabled=GetPrivateProfileInt(ModName,"ClkEnable",1,IniFile);
SetTurboDisk(GetPrivateProfileInt(ModName, "TurboDisk", 1, IniFile));
-
- BuildCartridgeMenu();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return;
}
diff --git a/FD502/fd502.h b/FD502/fd502.h
index 17cd9b61..5d5f5cdc 100644
--- a/FD502/fd502.h
+++ b/FD502/fd502.h
@@ -21,7 +21,6 @@ This file is part of VCC (Virtual Color Computer).
extern slot_id_type gSlotId;
extern PakAssertInteruptHostCallback AssertInt;
-void BuildCartridgeMenu();
// DO NOT REMOVE until becker.dll is retired. Then FD502 becker becomes permanant.
#define COMBINE_BECKER
diff --git a/FD502/wd1793.cpp b/FD502/wd1793.cpp
index 506e6c05..08481076 100644
--- a/FD502/wd1793.cpp
+++ b/FD502/wd1793.cpp
@@ -248,7 +248,6 @@ int mount_disk_image(const char *filename,unsigned char drive)
{
unsigned int Temp=0;
Temp=MountDisk(filename,drive);
- BuildCartridgeMenu();
return(!Temp);
}
diff --git a/GMC/Cartridge.cpp b/GMC/Cartridge.cpp
index f92d73b3..28801003 100644
--- a/GMC/Cartridge.cpp
+++ b/GMC/Cartridge.cpp
@@ -22,7 +22,6 @@
namespace detail
{
void NullAssetCartridgeLine(slot_id_type, bool) {}
- void NullAddMenuItem(slot_id_type, const char *, int, MenuItemType) {}
}
@@ -76,41 +75,28 @@ void Cartridge::SetConfigurationPath(std::string path)
LoadMenuItems();
}
-
-void Cartridge::SetMenuBuilderCallback(PakAppendCartridgeMenuHostCallback callback)
-{
- AddMenuItemPtr = callback;
-}
-
-
-
std::string Cartridge::GetStatusMessage() const
{
return std::string();
}
-
void Cartridge::OnMenuItemSelected(unsigned char /*menuId*/)
{
}
-
-
-
void Cartridge::OnReset()
{}
-
-
-
unsigned short Cartridge::UpdateAudio()
{
return 0;
}
-
-
+bool Cartridge::GetMenuItem(menu_item_entry* /*item*/, size_t /*index*/)
+{
+ return false;
+}
unsigned char Cartridge::OnReadMemory(unsigned short /*address*/) const
{
diff --git a/GMC/Cartridge.h b/GMC/Cartridge.h
index 1bab6b66..c59626f1 100644
--- a/GMC/Cartridge.h
+++ b/GMC/Cartridge.h
@@ -5,7 +5,6 @@
namespace detail
{
void NullAssetCartridgeLine(slot_id_type, bool);
- void NullAddMenuItem(slot_id_type, const char*, int, MenuItemType);
}
class Cartridge
@@ -22,7 +21,6 @@ class Cartridge
virtual void SetSlotId(slot_id_type SlotId);
virtual void SetCartLineAssertCallback(PakAssertCartridgeLineHostCallback callback);
- virtual void SetMenuBuilderCallback(PakAppendCartridgeMenuHostCallback addMenuCallback);
virtual void SetConfigurationPath(std::string path);
virtual std::string GetStatusMessage() const;
@@ -33,7 +31,7 @@ class Cartridge
virtual unsigned char OnReadMemory(unsigned short address) const;
virtual void OnWritePort(unsigned char port, unsigned char data);
virtual unsigned char OnReadPort(unsigned char port) const;
-
+ virtual bool GetMenuItem(menu_item_entry* item, size_t index);
protected:
@@ -42,11 +40,6 @@ class Cartridge
AssetCartridgeLinePtr(m_SlotId, state);
}
- void AddMenuItem(const char * name, int id, MenuItemType type)
- {
- AddMenuItemPtr(m_SlotId, name, id, type);
- }
-
virtual void LoadConfiguration(const std::string& filename);
virtual void LoadMenuItems();
@@ -66,6 +59,7 @@ class Cartridge
friend void PakWritePort(unsigned char port, unsigned char data);
friend unsigned char PakReadPort(unsigned char port);
friend unsigned short PakSampleAudio();
+ friend bool PakGetMenuItem(menu_item_entry* item, size_t index);
private:
@@ -76,6 +70,5 @@ class Cartridge
std::string m_CatalogId;
std::string m_ConfigurationPath;
PakAssertCartridgeLineHostCallback AssetCartridgeLinePtr = detail::NullAssetCartridgeLine;
- PakAppendCartridgeMenuHostCallback AddMenuItemPtr = detail::NullAddMenuItem;
};
diff --git a/GMC/CartridgeTrampolines.cpp b/GMC/CartridgeTrampolines.cpp
index 7dceab99..58b7dba9 100644
--- a/GMC/CartridgeTrampolines.cpp
+++ b/GMC/CartridgeTrampolines.cpp
@@ -40,15 +40,13 @@ GMC_EXPORT void PakInitialize(
HWND hVccWnd,
const cpak_callbacks* const callbacks)
{
- DLOG_C("GMC %p %p %p %p %p\n",
+ DLOG_C("GMC %p %p %p %p\n",
callbacks->assert_interrupt,
callbacks->assert_cartridge_line,
callbacks->write_memory_byte,
- callbacks->read_memory_byte,
- callbacks->add_menu_item);
+ callbacks->read_memory_byte);
Cartridge::m_Singleton->SetSlotId(SlotId);
- Cartridge::m_Singleton->SetMenuBuilderCallback(callbacks->add_menu_item);
Cartridge::m_Singleton->SetCartLineAssertCallback(callbacks->assert_cartridge_line);
Cartridge::m_Singleton->SetConfigurationPath(configuration_path);
}
@@ -83,9 +81,6 @@ GMC_EXPORT unsigned char PakReadMemoryByte(unsigned short address)
return Cartridge::m_Singleton->OnReadMemory(address);
}
-
-
-
GMC_EXPORT void PakWritePort(unsigned char port, unsigned char data)
{
Cartridge::m_Singleton->OnWritePort(port, data);
@@ -104,3 +99,9 @@ GMC_EXPORT unsigned short PakSampleAudio()
return Cartridge::m_Singleton->UpdateAudio();
}
+// Return menu
+GMC_EXPORT bool PakGetMenuItem(menu_item_entry* item, size_t index)
+{
+ return Cartridge::m_Singleton->GetMenuItem(item, index);
+}
+
diff --git a/GMC/CartridgeTrampolines.h b/GMC/CartridgeTrampolines.h
index 4fdb5961..2ec64889 100644
--- a/GMC/CartridgeTrampolines.h
+++ b/GMC/CartridgeTrampolines.h
@@ -16,3 +16,4 @@ GMC_EXPORT unsigned char PakReadMemoryByte(unsigned short address);
GMC_EXPORT void PakWritePort(unsigned char port, unsigned char data);
GMC_EXPORT unsigned char PakReadPort(unsigned char port);
GMC_EXPORT unsigned short PakSampleAudio();
+GMC_EXPORT bool PakGetMenuItem(menu_item_entry* item, size_t index);
diff --git a/GMC/GMC.h b/GMC/GMC.h
index 09fdd0bd..44c6e5a8 100644
--- a/GMC/GMC.h
+++ b/GMC/GMC.h
@@ -1,7 +1,7 @@
#pragma once
#include
-#include "../CartridgeMenu.h"
#include
+#include
#ifdef GMC_EXPORTS
#define GMC_EXPORT extern "C" __declspec(dllexport)
diff --git a/GMC/GMCCartridge.cpp b/GMC/GMCCartridge.cpp
index bdf52d31..86468ddc 100644
--- a/GMC/GMCCartridge.cpp
+++ b/GMC/GMCCartridge.cpp
@@ -1,6 +1,9 @@
#include "GMCCartridge.h"
#include
+#include
+#include
+static VCC::Bus::cartridge_menu GMCMenu {};
void GMCCartridge::LoadConfiguration(const std::string& filename)
{
@@ -8,12 +11,18 @@ void GMCCartridge::LoadConfiguration(const std::string& filename)
m_Configuration = Configuration(filename);
}
-void GMCCartridge::LoadMenuItems()
+bool GMCCartridge::GetMenuItem(menu_item_entry* item, size_t index)
{
- AddMenuItem("",MID_BEGIN,MIT_Head);
- AddMenuItem("",MID_ENTRY, MIT_Seperator);
- AddMenuItem("Select GMC ROM", ControlId(MenuItems::SelectRom), MIT_StandAlone);
- AddMenuItem("",MID_FINISH,MIT_Head);
+ if (!item) return false;
+ // request zero rebuilds the menu list but does it ever change?
+ // leave it incase we want to show the loaded rom in the menu
+ if (index == 0) {
+ GMCMenu.clear();
+ GMCMenu.add("", 0, MIT_Seperator);
+ GMCMenu.add("Select GMC ROM", ControlId(MenuItems::SelectRom), MIT_StandAlone);
+ }
+ // return requested list item or false
+ return GMCMenu.copy_item(*item, index);
}
std::string GMCCartridge::GetStatusMessage() const
diff --git a/GMC/GMCCartridge.h b/GMC/GMCCartridge.h
index 6fa2bc96..a5b80833 100644
--- a/GMC/GMCCartridge.h
+++ b/GMC/GMCCartridge.h
@@ -18,12 +18,7 @@ class GMCCartridge : public Cartridge
unsigned char OnReadMemory(unsigned short address) const override;
void OnWritePort(unsigned char port, unsigned char data) override;
unsigned char OnReadPort(unsigned char port) const override;
-
-
-protected:
-
- void LoadMenuItems() override;
-
+ bool GetMenuItem(menu_item_entry* item, size_t index) override;
private:
diff --git a/HardDisk/harddisk.cpp b/HardDisk/harddisk.cpp
index 511dcd64..d93cddac 100644
--- a/HardDisk/harddisk.cpp
+++ b/HardDisk/harddisk.cpp
@@ -1,22 +1,23 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-
-// hardisk.cpp : Defines the entry point for the DLL application.
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//
+//======================================================================
#include
#include
@@ -26,9 +27,12 @@ This file is part of VCC (Virtual Color Computer).
#include
#include
#include
-#include "../CartridgeMenu.h"
#include
#include
+// Three includes added for PakGetMenuItem
+#include
+#include
+#include
#include
constexpr auto DEF_HD_SIZE = 132480u;
@@ -44,7 +48,6 @@ static ::VCC::Device::rtc::cloud9 cloud9_rtc;
static slot_id_type gSlotId {};
static PakReadMemoryByteHostCallback MemRead8 = nullptr;
static PakWriteMemoryByteHostCallback MemWrite8 = nullptr;
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
static bool ClockEnabled = true;
static bool ClockReadOnly = true;
LRESULT CALLBACK NewDisk(HWND,UINT, WPARAM, LPARAM);
@@ -53,13 +56,20 @@ LRESULT CALLBACK NewDisk(HWND,UINT, WPARAM, LPARAM);
void LoadHardDisk(int drive);
void LoadConfig();
void SaveConfig();
-void BuildCartridgeMenu();
int CreateDisk(HWND,int);
static HINSTANCE gModuleInstance;
static HWND hConfDlg = nullptr;
LRESULT CALLBACK Config(HWND, UINT, WPARAM, LPARAM );
+// Added for PakGetMenuItem export
+bool get_menu_item(menu_item_entry* item, size_t index);
+
+// Added for PakGetMenuItem export
+static HWND gVccWnd = nullptr;
+
+//=================================================================================
+
using namespace std;
void MemWrite(unsigned char Data, unsigned short Address)
@@ -110,7 +120,7 @@ extern "C"
const cpak_callbacks* const callbacks)
{
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
+ gVccWnd = hVccWnd;
MemRead8 = callbacks->read_memory_byte;
MemWrite8 = callbacks->write_memory_byte;
strcpy(IniFile, configuration_path);
@@ -118,7 +128,13 @@ extern "C"
LoadConfig();
cloud9_rtc.set_read_only(ClockReadOnly);
VhdReset(); // Selects drive zero
- BuildCartridgeMenu();
+ // Request menu rebuild
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
+ }
+
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
}
__declspec(dllexport) void PakTerminate()
@@ -127,10 +143,8 @@ extern "C"
UnmountHD(0);
UnmountHD(1);
}
-
}
-
// Configure the hard drive(s). Called from menu
// Mount or dismount a hard drive and save config
// MountHD and UnmountHD are defined in cc3vhd
@@ -166,7 +180,8 @@ extern "C"
return;
}
SaveConfig();
- BuildCartridgeMenu();
+ // FIXME should only rebuild menus if drive is changed
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return;
}
}
@@ -349,7 +364,7 @@ void LoadConfig()
ClockReadOnly = GetPrivateProfileInt(ModName, "ClkRdOnly", 1, IniFile) != 0;
// Create config menu
- BuildCartridgeMenu();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return;
}
@@ -372,33 +387,29 @@ void SaveConfig()
return;
}
-// Generate menu for mounting the drives
-void BuildCartridgeMenu()
+// Added for PakGetMenuItem export
+// Return items for cartridge menu. Called for each item
+bool get_menu_item(menu_item_entry* item, size_t index)
{
- char TempMsg[512] = "";
- char TempBuf[MAX_PATH] = "";
-
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
-
- CartMenuCallback(gSlotId, "HD Drive 0", MID_ENTRY, MIT_Head);
- CartMenuCallback(gSlotId, "Insert", ControlId(10), MIT_Slave);
- strcpy(TempMsg, "Eject: ");
- strcpy(TempBuf, VHDfile0);
- PathStripPath(TempBuf);
- strcat(TempMsg, TempBuf);
- CartMenuCallback(gSlotId, TempMsg, ControlId(11), MIT_Slave);
-
- CartMenuCallback(gSlotId, "HD Drive 1", MID_ENTRY, MIT_Head);
- CartMenuCallback(gSlotId, "Insert", ControlId(12), MIT_Slave);
- strcpy(TempMsg, "Eject: ");
- strcpy(TempBuf, VHDfile1);
- PathStripPath(TempBuf);
- strcat(TempMsg, TempBuf);
- CartMenuCallback(gSlotId, TempMsg, ControlId(13), MIT_Slave);
-
- CartMenuCallback(gSlotId, "HD Config", ControlId(14), MIT_StandAlone);
- CartMenuCallback(gSlotId, "", MID_FINISH, MIT_Head);
+ using VCC::Bus::gDllCartMenu;
+ std::string disk;
+ if (!item) return false;
+ // request zero rebuilds the menu list
+ if (index == 0) {
+ gDllCartMenu.clear();
+ gDllCartMenu.add("", 0, MIT_Seperator);
+ gDllCartMenu.add("HD Drive 0",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(10),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(VHDfile0);
+ gDllCartMenu.add("Eject: "+disk,ControlId(11),MIT_Slave);
+ gDllCartMenu.add("HD Drive 1",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(12),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(VHDfile1);
+ gDllCartMenu.add("Eject: "+disk,ControlId(13),MIT_Slave);
+ gDllCartMenu.add("HD Config",ControlId(14),MIT_StandAlone);
+ }
+ // return requested list item or false
+ return gDllCartMenu.copy_item(*item, index);
}
// Dialog for creating a new hard disk
diff --git a/SuperIDE/IdeBus.cpp b/SuperIDE/IdeBus.cpp
index a35c0320..23dadb6f 100644
--- a/SuperIDE/IdeBus.cpp
+++ b/SuperIDE/IdeBus.cpp
@@ -1,28 +1,31 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//
+//======================================================================
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-
-#include "logger.h"
+#include
#include "IdeBus.h"
#include
#include
+#include
static unsigned int Lba=0,LastLba;
-char Message[256]=""; //DEBUG
static unsigned char XferBuffer[512]="";
static unsigned int BufferIndex=0;
@@ -31,7 +34,7 @@ static unsigned char CurrentCommand=0;
void ExecuteCommand();
void ByteSwap (char *);
static IDEINTERFACE Registers;
-static HANDLE hDiskFile[2];
+static HANDLE hDiskFile[2] {};
static unsigned char DiskSelect=0,LbaEnabled=0;
unsigned long BytesMoved=0;
unsigned char BusyCounter=BUSYWAIT;
@@ -40,11 +43,9 @@ static unsigned short IDBlock[2][256];
static unsigned char Mounted=0,ScanCount=0;
static char CurrStatus[32]="IDE:Idle ";
static char FileNames[2][MAX_PATH]={"",""};
+
void IdeInit()
{
-
- hDiskFile[MASTER]=INVALID_HANDLE_VALUE;
- hDiskFile[SLAVE]=INVALID_HANDLE_VALUE;
Registers.Command=0;
Registers.Cylinderlsb=0;
Registers.Cylindermsb=0;
@@ -342,11 +343,13 @@ unsigned char MountDisk(const char *FileName,unsigned char DiskNumber)
return FALSE;
strcpy(FileNames[DiskNumber],FileName);
Mounted=1;
+ DLOG_C(">>>MountDisk %d %d<<<\n",DiskNumber,hDiskFile[DiskNumber]);
return TRUE;
}
unsigned char DropDisk(unsigned char DiskNumber)
{
+ DLOG_C(">>>DropDisk %d %d<<<\n",DiskNumber,hDiskFile[DiskNumber]);
CloseHandle(hDiskFile[DiskNumber]);
hDiskFile[DiskNumber]=INVALID_HANDLE_VALUE;
strcpy(FileNames[DiskNumber],"");
@@ -358,4 +361,11 @@ void QueryDisk(unsigned char DiskNumber,char *Name)
{
strcpy(Name,FileNames[DiskNumber]);
return;
-}
\ No newline at end of file
+}
+
+std::string QueryDisk(unsigned char DiskNumber)
+{
+ return FileNames[DiskNumber];
+}
+
+
diff --git a/SuperIDE/IdeBus.h b/SuperIDE/IdeBus.h
index 56fbde3e..ef52a23a 100644
--- a/SuperIDE/IdeBus.h
+++ b/SuperIDE/IdeBus.h
@@ -17,6 +17,8 @@ This file is part of VCC (Virtual Color Computer).
You should have received a copy of the GNU General Public License
along with VCC (Virtual Color Computer). If not, see .
*/
+#include
+
struct IDEINTERFACE {
unsigned short Data;
unsigned char Error[2];
@@ -36,6 +38,8 @@ void DiskStatus(char* text_buffer, size_t buffer_size);
unsigned char MountDisk(const char *,unsigned char );
unsigned char DropDisk(unsigned char);
void QueryDisk(unsigned char,char *);
+std::string QueryDisk(unsigned char);
+
//Status
#define ERR 1 //Previous command ended in an error
#define IDX 2 //Unused
diff --git a/SuperIDE/SuperIDE.cpp b/SuperIDE/SuperIDE.cpp
index 9341479f..69913dc2 100644
--- a/SuperIDE/SuperIDE.cpp
+++ b/SuperIDE/SuperIDE.cpp
@@ -1,21 +1,23 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//
+//======================================================================
#include
#include "stdio.h"
@@ -23,26 +25,26 @@ This file is part of VCC (Virtual Color Computer).
#include "resource.h"
#include "IdeBus.h"
#include
-#include "logger.h"
#include
-#include "../CartridgeMenu.h"
#include
#include
#include
#include
+#include
+#include
+#include
static char FileName[MAX_PATH] { 0 };
static char IniFile[MAX_PATH] { 0 };
static char SuperIDEPath[MAX_PATH];
static ::VCC::Device::rtc::cloud9 cloud9_rtc;
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
static unsigned char BaseAddress=0x50;
-void BuildCartridgeMenu();
LRESULT CALLBACK IDE_Config(HWND, UINT, WPARAM, LPARAM );
void Select_Disk(unsigned char);
void SaveConfig();
void LoadConfig();
unsigned char BaseTable[4]={0x40,0x50,0x60,0x70};
+bool get_menu_item(menu_item_entry*, size_t index);
static unsigned char BaseAddr=1;
static bool ClockEnabled = true;
@@ -52,9 +54,12 @@ static HINSTANCE gModuleInstance;
static HWND hConfDlg = nullptr;
static slot_id_type gSlotId {};
+static HWND gVccWnd = nullptr;
+
using namespace std;
+//----------------------------------------------------------------------------
extern "C"
{
@@ -92,13 +97,12 @@ extern "C"
const cpak_callbacks* const callbacks)
{
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
+ gVccWnd = hVccWnd;
strcpy(IniFile, configuration_path);
LoadConfig();
IdeInit();
-
- BuildCartridgeMenu();
+ //SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
}
__declspec(dllexport) void PakTerminate()
@@ -161,33 +165,39 @@ extern "C"
DiskStatus(text_buffer, buffer_size);
}
-
+
+ //PakGetMenuItem export
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
+ }
+
__declspec(dllexport) void PakMenuItemClicked(unsigned char MenuID)
{
switch (MenuID)
{
case 10:
Select_Disk(MASTER);
- BuildCartridgeMenu();
SaveConfig();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
break;
case 11:
DropDisk(MASTER);
- BuildCartridgeMenu();
SaveConfig();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
break;
case 12:
Select_Disk(SLAVE);
- BuildCartridgeMenu();
SaveConfig();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
break;
case 13:
DropDisk(SLAVE);
- BuildCartridgeMenu();
SaveConfig();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
break;
case 14:
@@ -216,28 +226,29 @@ BOOL WINAPI DllMain(
return TRUE;
}
-void BuildCartridgeMenu()
+// Added for PakGetMenuItem export
+// Return items for cartridge menu. Called for each item
+bool get_menu_item(menu_item_entry* item, size_t index)
{
- char TempMsg[512]="";
- char TempBuf[MAX_PATH]="";
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
- CartMenuCallback(gSlotId, "IDE Master",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(10),MIT_Slave);
- QueryDisk(MASTER,TempBuf);
- strcpy(TempMsg,"Eject: ");
- PathStripPath (TempBuf);
- strcat(TempMsg,TempBuf);
- CartMenuCallback(gSlotId, TempMsg,ControlId(11),MIT_Slave);
- CartMenuCallback(gSlotId, "IDE Slave",MID_ENTRY,MIT_Head);
- CartMenuCallback(gSlotId, "Insert",ControlId(12),MIT_Slave);
- QueryDisk(SLAVE,TempBuf);
- strcpy(TempMsg,"Eject: ");
- PathStripPath (TempBuf);
- strcat(TempMsg,TempBuf);
- CartMenuCallback(gSlotId, TempMsg,ControlId(13),MIT_Slave);
- CartMenuCallback(gSlotId, "IDE Config",ControlId(14),MIT_StandAlone);
- CartMenuCallback(gSlotId, "", MID_FINISH, MIT_Head);
+ using VCC::Bus::gDllCartMenu;
+ std::string disk;
+ if (!item) return false;
+ // request zero rebuilds the menu list
+ if (index == 0) {
+ gDllCartMenu.clear();
+ gDllCartMenu.add("", 0, MIT_Seperator);
+ gDllCartMenu.add("IDE Master",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(10),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(QueryDisk(MASTER));
+ gDllCartMenu.add("Eject: "+disk,ControlId(11),MIT_Slave);
+ gDllCartMenu.add("IDE Slave",0,MIT_Head);
+ gDllCartMenu.add("Insert",ControlId(12),MIT_Slave);
+ disk = VCC::Util::GetFileNamePart(QueryDisk(SLAVE));
+ gDllCartMenu.add("Eject: "+disk,ControlId(13),MIT_Slave);
+ gDllCartMenu.add("IDE Config",ControlId(14),MIT_StandAlone);
+ }
+ // return requested list item or false
+ return gDllCartMenu.copy_item(*item, index);
}
LRESULT CALLBACK IDE_Config(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
@@ -362,6 +373,6 @@ void LoadConfig()
BaseAddress=BaseTable[BaseAddr];
cloud9_rtc.set_read_only(ClockReadOnly);
MountDisk(FileName ,SLAVE);
- BuildCartridgeMenu();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return;
}
diff --git a/SuperIDE/logger.cpp b/SuperIDE/logger.cpp
deleted file mode 100644
index ea738f17..00000000
--- a/SuperIDE/logger.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-#include
-#include
-
-#include "logger.h"
-
-void WriteLog(char *Message,unsigned char Type)
-{
- static unsigned int Counter=1;
- static HANDLE hout=nullptr;
- static FILE *disk_handle=nullptr;
- unsigned long dummy;
- char cTemp[512]="";
- switch (Type)
- {
- case TOCONS:
- if (hout==nullptr)
- {
- AllocConsole();
- hout=GetStdHandle(STD_OUTPUT_HANDLE);
- SetConsoleTitle("Logging Window");
- }
- sprintf(cTemp,"%s",Message);
- WriteConsole(hout,cTemp,strlen(cTemp),&dummy,nullptr);
- Counter++;
- break;
-
- case TOFILE:
- if (disk_handle ==nullptr)
- disk_handle=fopen("c:\\VccLog.txt","w");
-
- fprintf(disk_handle,"%s\r\n",Message);
- fflush(disk_handle);
- break;
- }
-
-}
-
-
-
-
diff --git a/SuperIDE/logger.h b/SuperIDE/logger.h
deleted file mode 100644
index 2591c483..00000000
--- a/SuperIDE/logger.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __LOGGER_H__
-#define __LOGGER_H__
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
-
-void WriteLog(char *,unsigned char);
-
-// FIXME: These should be a scoped enum
-#define TOCONS 0
-#define TOFILE 1
-
-#endif
diff --git a/Vcc.cpp b/Vcc.cpp
index 1585e005..58df4ffa 100644
--- a/Vcc.cpp
+++ b/Vcc.cpp
@@ -56,7 +56,6 @@
#include "mc6821.h"
#include "keyboard.h"
#include "coco3.h"
-#include "CartridgeMenu.h"
#include "pakinterface.h"
#include "audio.h"
#include "config.h"
@@ -78,6 +77,9 @@
#include "MMUMonitor.h"
#include "ExecutionTrace.h"
+#include
+#include
+
#if USE_DEBUG_MOUSE
#include "IDisplayDebug.h"
#endif
@@ -119,6 +121,7 @@ void raise_saved_keys();
void FunctionHelpBox(HWND);
void SetupClock();
HMENU GetConfMenu();
+HMENU DrawCartMenu(HWND hWnd);
// Globals
static HANDLE hEMUThread ;
@@ -133,17 +136,21 @@ static unsigned char FlagEmuStop=TH_RUNNING;
bool IsShiftKeyDown();
-CartridgeMenu CartMenu;
+using VCC::Bus::gVccCartMenu;
static bool gHasFocus {};
//static CRITICAL_SECTION FrameRender;
-/*--------------------------------------------------------------------------*/
+
+//--------------------------------------------------------------------------//
+// Main entry
+//--------------------------------------------------------------------------//
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow)
{
+
MSG Msg;
EmuState.WindowInstance = hInstance;
@@ -164,6 +171,7 @@ int APIENTRY WinMain(_In_ HINSTANCE hInstance,
LoadConfig(&EmuState);
EmuState.ResetPending=2; // after LoadConfig pls
InitInstance(hInstance, nCmdShow);
+
if ((CmdArg.NoOutput && !CreateNullWindow(&EmuState)) ||
(!CmdArg.NoOutput && !CreateDDWindow(&EmuState)))
{
@@ -171,10 +179,6 @@ int APIENTRY WinMain(_In_ HINSTANCE hInstance,
exit(0);
}
- // Set up the cartridge menu. This gets drawn after modules are loaded
- CartMenu.init();
- BeginCartMenu();
-
InitSound();
LoadModule();
SetClockSpeed(1); //Default clock speed .89 MHZ
@@ -270,8 +274,10 @@ void CloseApp()
UnloadDll();
}
-/*--------------------------------------------------------------------------*/
-// The Window Procedure
+//--------------------------------------------------------------------------//
+// VCC Main Window messaging loop
+//--------------------------------------------------------------------------//
+
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
@@ -302,7 +308,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
// Parse the menu selections:
- // Check if ID is in cartridge menu range
+ // Check if ID is in cartridge menu range. Control ID's are
+ // biased by SlotNum, there are five slots each gets 50
if ( (wmId >= MID_CONTROL) & (wmId < MID_CONTROL + 250) )
{
CartMenuActivated(wmId-MID_CONTROL);
@@ -352,6 +359,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
case ID_FILE_RESET:
+ case IDC_MSG_CPU_RESET:
if (EmuState.EmulationRunning)
EmuState.ResetPending=2;
break;
@@ -364,6 +372,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case ID_FILE_RESET_SFT:
if (EmuState.EmulationRunning)
EmuState.ResetPending=1;
+
+ case IDC_MSG_UPD_MENU:
+ BuildCartMenu();
+ DrawCartMenu(hWnd);
break;
case ID_FILE_LOAD:
@@ -432,13 +444,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
-#ifdef _LEGACY_VCC
case WM_CREATE:
+ // Create initial cartridge menu. If no carts are loaded at startup
+ // build and draw here are needed to bootstrap the cartridge menu
+ BuildCartMenu();
+ DrawCartMenu(hWnd);
+#ifdef _LEGACY_VCC
{ char title[80] = "Legacy ";
strncat(title,g_szAppName,80);
SetWindowTextA(hWnd,title); }
- break;
#endif
+ break;
case WM_SETCURSOR:
// Hide mouse cursor
@@ -568,7 +584,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if ( IsShiftKeyDown() ) {
hMenu = GetConfMenu();
} else {
- hMenu = CartMenu.draw();
+ hMenu = DrawCartMenu(hWnd);
}
if (hMenu && EmuState.FullScreen) {
RECT r;
@@ -687,6 +703,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hWnd, message, wParam, lParam);
}
+//--------------------------------------------------------------------------
+// Refresh the cartridge menu from the menu item list
+//--------------------------------------------------------------------------
+HMENU DrawCartMenu (HWND hWnd)
+{
+ gVccCartMenu.log();
+
+ // window handle, zero based position on menu bar, name on bar.
+ return gVccCartMenu.draw( hWnd, 3, "Cartridge");
+}
+
//--------------------------------------------------------------------------
// When the main window is about to lose keyboard focus there are one
// or two keys down in the emulation that must be raised. These routines
@@ -1091,7 +1118,7 @@ void FullScreenToggle()
exit(0);
}
InvalidateBoarder();
- CartMenu.draw();
+// CartMenu.draw();
EmuState.ConfigDialog=nullptr;
PauseAudio(false);
diff --git a/Vcc.vcxproj b/Vcc.vcxproj
index 4c55ce8b..117321db 100644
--- a/Vcc.vcxproj
+++ b/Vcc.vcxproj
@@ -150,14 +150,6 @@
-
- Level4
- true
- Level4
- Level4
- true
- true
-
Level4
true
@@ -303,4 +295,4 @@
-
\ No newline at end of file
+
diff --git a/acia/acia.cpp b/acia/acia.cpp
index 28ab5a22..79354fe6 100644
--- a/acia/acia.cpp
+++ b/acia/acia.cpp
@@ -1,3 +1,4 @@
+//#define USE_LOGGING
//------------------------------------------------------------------
// Copyright E J Jaquay 2022
//
@@ -22,17 +23,15 @@
//------------------------------------------------------------------
#include "acia.h"
-#include "../CartridgeMenu.h"
#include
#include
#include
+#include
//------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------
-void BuildCartridgeMenu();
-
LRESULT CALLBACK Config(HWND, UINT, WPARAM, LPARAM);
void LoadConfig();
void SaveConfig();
@@ -42,7 +41,6 @@ void SaveConfig();
//------------------------------------------------------------------------
slot_id_type gSlotId;
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
PakAssertInteruptHostCallback AssertInt = nullptr;
//------------------------------------------------------------------------
@@ -74,6 +72,9 @@ char AciaFileWrPath[MAX_PATH]; // Path for file writes
static unsigned char Rom[8192];
unsigned char LoadExtRom(const char *);
+static VCC::Bus::cartridge_menu AciaMenu {};
+bool get_menu_item(menu_item_entry* item, size_t index);
+
//------------------------------------------------------------------------
// DLL Entry point
//------------------------------------------------------------------------
@@ -125,12 +126,10 @@ extern "C"
const cpak_callbacks* const callbacks)
{
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
AssertInt = callbacks->assert_interrupt;
strcpy(IniFile, configuration_path);
LoadConfig();
- BuildCartridgeMenu();
LoadExtRom("RS232.ROM");
sc6551_init();
}
@@ -141,6 +140,11 @@ extern "C"
AciaStat[0]='\0';
}
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
+ }
+
}
//-----------------------------------------------------------------------
@@ -236,16 +240,17 @@ __declspec(dllexport) void PakMenuItemClicked(unsigned char /*MenuID*/)
return;
}
-
//-----------------------------------------------------------------------
-// Add config option to Cartridge menu
-//----------------------------------------------------------------------
-void BuildCartridgeMenu()
-{
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
- CartMenuCallback(gSlotId, "ACIA Config", ControlId(16), MIT_StandAlone);
- CartMenuCallback(gSlotId, "", MID_FINISH, MIT_Head);
+// Return acia menu items
+//-----------------------------------------------------------------------
+bool get_menu_item(menu_item_entry* item, size_t index) {
+ if (!item) return false;
+ if (index == 0) {
+ AciaMenu.clear();
+ AciaMenu.add("", 0, MIT_Seperator);
+ AciaMenu.add("ACIA Config", ControlId(16), MIT_StandAlone);
+ }
+ return AciaMenu.copy_item(*item, index);
}
//-----------------------------------------------------------------------
diff --git a/becker/becker.cpp b/becker/becker.cpp
index 25dbb4fb..ba1ad7ad 100644
--- a/becker/becker.cpp
+++ b/becker/becker.cpp
@@ -1,3 +1,24 @@
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//
+//======================================================================
+
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
@@ -6,12 +27,12 @@
#include
#include "becker.h"
#include "resource.h"
-#include "../CartridgeMenu.h"
#include
#include
#include
#include
#include
+#include
// socket
static SOCKET dwSocket = 0;
@@ -19,7 +40,6 @@ static SOCKET dwSocket = 0;
// vcc stuff
static HINSTANCE gModuleInstance;
slot_id_type gSlotId {};
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
static PakAssertCartridgeLineHostCallback PakSetCart = nullptr;
LRESULT CALLBACK Config(HWND, UINT, WPARAM, LPARAM);
static char IniFile[MAX_PATH]="";
@@ -63,10 +83,12 @@ unsigned char LoadExtRom(const char *);
void SetDWTCPConnectionEnable(unsigned int enable);
int dw_setaddr(const char *bufdwaddr);
int dw_setport(const char *bufdwport);
-void BuildCartridgeMenu();
void LoadConfig();
void SaveConfig();
+static VCC::Bus::cartridge_menu BeckerMenu {};
+bool get_menu_item(menu_item_entry* item, size_t index);
+
// dll entry hook
BOOL APIENTRY DllMain( HINSTANCE hinstDLL,
@@ -95,11 +117,6 @@ BOOL APIENTRY DllMain( HINSTANCE hinstDLL,
return TRUE;
}
-
-
-
-
-
// coco checks for data
unsigned char dw_status( void )
{
@@ -421,15 +438,19 @@ extern "C"
const cpak_callbacks* const callbacks)
{
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
PakSetCart = callbacks->assert_cartridge_line;
strcpy(IniFile, configuration_path);
LastStats = GetTickCount();
LoadConfig();
SetDWTCPConnectionEnable(1);
- BuildCartridgeMenu();
}
+
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
+ }
+
}
@@ -533,13 +554,14 @@ extern "C" __declspec(dllexport) void PakGetStatus(char* text_buffer, size_t buf
return;
}
-
-void BuildCartridgeMenu()
-{
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
- CartMenuCallback(gSlotId, "DriveWire Server..", ControlId(16), MIT_StandAlone);
- CartMenuCallback(gSlotId, "", MID_FINISH, MIT_Head);
+bool get_menu_item(menu_item_entry* item, size_t index) {
+ if (!item) return false;
+ if (index == 0) {
+ BeckerMenu.clear();
+ BeckerMenu.add("", 0, MIT_Seperator);
+ BeckerMenu.add("DriveWire Server..", ControlId(16), MIT_StandAlone);
+ }
+ return BeckerMenu.copy_item(*item, index);
}
extern "C" __declspec(dllexport) void PakMenuItemClicked(unsigned char MenuID)
@@ -547,7 +569,6 @@ extern "C" __declspec(dllexport) void PakMenuItemClicked(unsigned char MenuID)
HWND h_own = GetActiveWindow();
CreateDialog(gModuleInstance,(LPCTSTR)IDD_PROPPAGE,h_own,(DLGPROC)Config);
ShowWindow(g_hConfigDlg,1);
- BuildCartridgeMenu();
return;
}
@@ -647,7 +668,6 @@ void LoadConfig()
dw_setport("65504");
- BuildCartridgeMenu();
GetModuleFileName(NULL, DiskRomPath, MAX_PATH);
PathRemoveFileSpec(DiskRomPath);
strcat( DiskRomPath, "hdbdwbck.rom");
diff --git a/becker/becker.h b/becker/becker.h
index 51d38c7e..e2f5a786 100644
--- a/becker/becker.h
+++ b/becker/becker.h
@@ -10,7 +10,6 @@
// functions
void MemWrite(unsigned char,unsigned short );
unsigned char MemRead(unsigned short );
-void BuildCartridgeMenu();
extern const unsigned char Rom[8192];
diff --git a/libcommon/include/vcc/bus/basic_cartridge.h b/libcommon/include/vcc/bus/basic_cartridge.h
index e6d90932..ec390938 100644
--- a/libcommon/include/vcc/bus/basic_cartridge.h
+++ b/libcommon/include/vcc/bus/basic_cartridge.h
@@ -48,12 +48,11 @@ namespace VCC::Core
void status(char* text_buffer, size_t buffer_size) override;
unsigned short sample_audio() override;
void menu_item_clicked(unsigned char menu_item_id) override;
-
+ bool get_menu_item(menu_item_entry* item, size_t index) override;
protected:
virtual void initialize_pak();
virtual void initialize_bus();
};
-
}
diff --git a/libcommon/include/vcc/bus/cartridge.h b/libcommon/include/vcc/bus/cartridge.h
index da92f934..422b99de 100644
--- a/libcommon/include/vcc/bus/cartridge.h
+++ b/libcommon/include/vcc/bus/cartridge.h
@@ -17,15 +17,14 @@
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include // defines LIBCOMMON_EXPORT if libcommon is a DLL
+#include
#include
namespace VCC::Core
{
-
struct LIBCOMMON_EXPORT cartridge
{
public:
- // In Chet's workd strings get a typedef because that keeps things opaque
using name_type = std::string;
using catalog_id_type = std::string;
using description_type = std::string;
@@ -52,6 +51,7 @@ namespace VCC::Core
virtual void status(char* text_buffer, size_t buffer_size) = 0;
virtual unsigned short sample_audio() = 0;
virtual void menu_item_clicked(unsigned char menu_item_id) = 0;
+ virtual bool get_menu_item(menu_item_entry* item, size_t index) = 0;
};
}
diff --git a/libcommon/include/vcc/bus/cartridge_callbacks.h b/libcommon/include/vcc/bus/cartridge_callbacks.h
index 56a12a5b..d6d86501 100644
--- a/libcommon/include/vcc/bus/cartridge_callbacks.h
+++ b/libcommon/include/vcc/bus/cartridge_callbacks.h
@@ -22,29 +22,19 @@
enum MenuItemType;
-// TODO: Where cartridge_context is used make it explicit; It should not be passed as void *;
-// Defines the callbacks a cartridge can make
namespace VCC::Core
{
-
struct LIBCOMMON_EXPORT cartridge_context
{
using path_type = std::string;
-
virtual ~cartridge_context() = default;
-
virtual path_type configuration_path() const = 0;
- virtual void reset() = 0;
-
virtual void assert_cartridge_line(bool line_state) = 0;
virtual void assert_interrupt(Interrupt interrupt, InterruptSource interrupt_source) = 0;
-
virtual void write_memory_byte(unsigned char value, unsigned short address) = 0;
virtual unsigned char read_memory_byte(unsigned short address) = 0;
-
- virtual void add_menu_item(const char* menu_name, int menu_id, MenuItemType menu_type) = 0;
};
-
}
+
diff --git a/libcommon/include/vcc/bus/cartridge_loader.h b/libcommon/include/vcc/bus/cartridge_loader.h
index e5d61729..1325bad4 100644
--- a/libcommon/include/vcc/bus/cartridge_loader.h
+++ b/libcommon/include/vcc/bus/cartridge_loader.h
@@ -68,7 +68,6 @@ namespace VCC::Core
LIBCOMMON_EXPORT cartridge_loader_result load_cpak_cartridge(
const std::string& filename,
std::unique_ptr cartridge_context,
-// void* const pakContainer,
slot_id_type SlotId,
const std::string& iniPath,
HWND hVccWnd,
@@ -77,7 +76,6 @@ namespace VCC::Core
LIBCOMMON_EXPORT cartridge_loader_result load_cartridge(
const std::string& filename, // Cartridge filename
std::unique_ptr cartridge_context, // Loader context
-// void* const pakContainer, // Pak container object
slot_id_type SlotId,
const std::string& iniPath, // Path of ini file
HWND hVccWnd, // handle to main window
diff --git a/libcommon/include/vcc/bus/cartridge_menu.h b/libcommon/include/vcc/bus/cartridge_menu.h
new file mode 100644
index 00000000..9b4172e5
--- /dev/null
+++ b/libcommon/include/vcc/bus/cartridge_menu.h
@@ -0,0 +1,109 @@
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//======================================================================
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+//-----------------------------------------------------------------------
+// cartridge_menu objects hold cartridge menu lists.
+//
+// Every cartridge DLL that uses menu items holds a cartridge_menu
+// list for it's items. When it modifies what is in it's list it posts
+// a menu changed message to Vcc main.
+//
+// Menu building and drawing is controlled by the PakInterface and
+// is initiated by VCC startup or by a menu changed message from
+// one of the catridge DLL's.
+//
+// PakInterface builds the master cartridge_menu starting with it's
+// own items. It then calls PakGetMenuItems to get and append items
+// from the DLL in slot 0 (AKA the boot or side slot).
+//
+// If the MPI is in slot 0 it responds with it's own list plus the
+// lists from each cartridge it has loaded, each via PakGetMenuItems
+// calls to them.
+//-----------------------------------------------------------------------
+
+namespace VCC::Bus {
+
+// A single menu entry
+struct CartMenuItem {
+ std::string name;
+ size_t menu_id;
+ MenuItemType type;
+};
+
+class cartridge_menu {
+
+private:
+ std::vector menu_;
+
+public:
+
+ // Constructor
+ cartridge_menu() {}
+
+ // Clear all items
+ void clear() { menu_.clear(); }
+
+ // Add a single item
+ void add(const std::string& name, unsigned int menu_id, MenuItemType type)
+ {
+ menu_.push_back({ name, menu_id, type });
+ }
+
+ // fetch an item
+ CartMenuItem& operator[](size_t i)
+ {
+ return menu_[i];
+ }
+
+ // Number of items in list
+ size_t size() const { return menu_.size(); }
+
+ // copy an item to API structure
+ bool copy_item(menu_item_entry& out, size_t index) const;
+
+ // debug logging
+ void log()
+ {
+ for (size_t i = 0; i < menu_.size(); ++i) {
+ DLOG_C("%s %d %d\n", menu_[i].name.c_str(),menu_[i].menu_id,menu_[i].type);
+ }
+ }
+
+ // Draw the menu (implemented in catridge_menu.cpp)
+ HMENU draw(HWND hWnd,
+ int position=3,
+ const std::string& title="Cartridge");
+};
+
+// instance for Vcc.cpp and pakinterface to use. Host only!
+extern cartridge_menu gVccCartMenu;
+
+// instance for dll's to use. DLL's only!
+extern cartridge_menu gDllCartMenu;
+
+} // namespace VCC::Bus
diff --git a/libcommon/include/vcc/bus/cartridge_menuitem.h b/libcommon/include/vcc/bus/cartridge_menuitem.h
new file mode 100644
index 00000000..ece4548d
--- /dev/null
+++ b/libcommon/include/vcc/bus/cartridge_menuitem.h
@@ -0,0 +1,45 @@
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//======================================================================
+
+#pragma once
+
+enum MenuItemType
+{
+ MIT_Head, // Menu header, should have slave items
+ MIT_Slave, // Slave items with associated control in header submenu.
+ MIT_StandAlone, // Menu item with an associated control
+ MIT_Seperator, // Draws a horizontal line to seperate groups of menu items
+};
+
+// Define a C API safe struct for DLL ItemList export
+// PakGetMenuItem(menu_item_entry* items, size_t* count)
+struct menu_item_entry
+{
+ char name[256];
+ size_t menu_id;
+ MenuItemType type;
+};
+
+// Sanity check maximum menu items
+constexpr auto MAX_MENU_ITEMS = 200u;
+
+// MenuItem ID <-> Command ID mapping
+constexpr auto MID_CONTROL = 5000;
+constexpr int ControlId(int id) { return MID_CONTROL + id; }
+
diff --git a/libcommon/include/vcc/bus/cartridge_messages.h b/libcommon/include/vcc/bus/cartridge_messages.h
new file mode 100644
index 00000000..4912b660
--- /dev/null
+++ b/libcommon/include/vcc/bus/cartridge_messages.h
@@ -0,0 +1,9 @@
+// Messages sent to VCC main message loop
+
+//-----------------------------------------------------
+// ID 5000 - 5249 are reserved for cartridge menus
+// ID 5250 - 5299 are reseverd for cartridge messaging
+//-----------------------------------------------------
+
+#define IDC_MSG_CPU_RESET 5260
+#define IDC_MSG_UPD_MENU 5261
diff --git a/libcommon/include/vcc/bus/cpak_cartridge.h b/libcommon/include/vcc/bus/cpak_cartridge.h
index 666fe870..a342fcda 100644
--- a/libcommon/include/vcc/bus/cpak_cartridge.h
+++ b/libcommon/include/vcc/bus/cpak_cartridge.h
@@ -18,10 +18,10 @@
#pragma once
#include
#include
+#include
#include
#include
-
namespace VCC::Core
{
@@ -55,7 +55,7 @@ namespace VCC::Core
LIBCOMMON_EXPORT unsigned char read_memory_byte(unsigned short memory_address) override;
LIBCOMMON_EXPORT unsigned short sample_audio() override;
LIBCOMMON_EXPORT void menu_item_clicked(unsigned char menu_item_id) override;
-
+ LIBCOMMON_EXPORT bool get_menu_item(menu_item_entry* item, size_t index) override;
private:
@@ -79,6 +79,7 @@ namespace VCC::Core
const PakReadMemoryByteModuleFunction read_memory_byte_;
const PakSampleAudioModuleFunction sample_audio_;
const PakMenuItemClickedModuleFunction menu_item_clicked_;
+ const PakGetMenuItemFunction get_menu_item_;
};
}
diff --git a/libcommon/include/vcc/bus/cpak_cartridge_definitions.h b/libcommon/include/vcc/bus/cpak_cartridge_definitions.h
index ead0739a..9bd033ba 100644
--- a/libcommon/include/vcc/bus/cpak_cartridge_definitions.h
+++ b/libcommon/include/vcc/bus/cpak_cartridge_definitions.h
@@ -22,6 +22,7 @@
#pragma once
#include
+#include // for MenuItemType
#include // for std::size_t
#include
@@ -42,8 +43,6 @@ extern "C"
(slot_id_type SlotId, bool lineState);
using PakAssertInteruptHostCallback = void (*)
(slot_id_type SlotId, Interrupt interrupt, InterruptSource interrupt_source);
- using PakAppendCartridgeMenuHostCallback = void (*)
- (slot_id_type SlotId, const char* menu_name, int menu_id, MenuItemType menu_type);
// Cartridge Callbacks
struct cpak_callbacks
@@ -52,7 +51,6 @@ extern "C"
const PakAssertCartridgeLineHostCallback assert_cartridge_line;
const PakWriteMemoryByteHostCallback write_memory_byte;
const PakReadMemoryByteHostCallback read_memory_byte;
- const PakAppendCartridgeMenuHostCallback add_menu_item;
};
// Cartridge exports. At least PakInitilizeModuleFunction must be implimented
@@ -74,5 +72,5 @@ extern "C"
using PakReadPortModuleFunction = unsigned char (*)(unsigned char port);
using PakSampleAudioModuleFunction = unsigned short (*)();
using PakMenuItemClickedModuleFunction = void (*)(unsigned char itemId);
-
+ using PakGetMenuItemFunction = bool (*)(menu_item_entry* item, size_t index);
}
diff --git a/libcommon/libcommon.vcxproj b/libcommon/libcommon.vcxproj
index 70dae6ae..bcf3d6f2 100644
--- a/libcommon/libcommon.vcxproj
+++ b/libcommon/libcommon.vcxproj
@@ -111,6 +111,7 @@
+
@@ -127,6 +128,7 @@
+
diff --git a/libcommon/src/bus/CartridgeInterface.txt b/libcommon/src/bus/CartridgeInterface.txt
index c8a265dc..eb95ea93 100644
--- a/libcommon/src/bus/CartridgeInterface.txt
+++ b/libcommon/src/bus/CartridgeInterface.txt
@@ -103,8 +103,8 @@ DLL's can export any of the following calls
Initiate pack (REQUIRED)
PakInitialize (SLotId, settings_path, hVccWnd, &callbacks);
- Retrieve cart menu (NEW)
- PakGetMenuItems(menu_items, count);
+ Retrieve cart menu item
+ PakGetMenuItem(item, index);
Get cart capabilities (PROPOSED)
PakGetCapabilities (void);
@@ -149,41 +149,31 @@ DLL's can export any of the following calls
#Callbacks
-Callbacks are used by cartridge DLL's to initiate host (or MPI) actions. The
-following callbacks currently exist:
+There are two ways a cartridge can initiate host actions:
- assert_cartridge_line (SlotId, line_state)
-
- assert_interrupt (SlotId, interrupt, interrupt_source)
-
- write_memory_byte (SlotId, value, address)
-
- read_memory_byte (SlotId, unsigned short address)
-
- add_menu_item (SlotId, menu_name, menu_id, menu_type) **depreciated**
-
-SlotId is used by the MPI to filter assert_cartridge_line and to bias menu items.
-
-There are two type of callbacks:
+1) Notifications initiated by cartridge UI events like adding menu items or inserting
+cartridges in slots. These are asyncronous and can rely on DLL exports for details.
+The mechanism for these is Vcc's main window message loop. The window handle (hVccWnd)
+has been added to PakInitialize() for this purpose. Two notification messages are
+defined, one to initiate a VCC reset and another to initiate cartridge menu rebuilds.
-- Fast callbacks initiated by 6x09 code running inside the CPU loop such as asserting
+2) Callbacks initiated by 6x09 code running inside the CPU loop such as asserting
interrupts, cart lines, or reading and writing memory to handle DMA requests. These
-are syncronous and must return quickly to not affect emulator timing. Fast callbacks
-are determined by Coco3's physical bus and are not likely to change.
+are syncronous and must return quickly to not affect emulator timing. Callbacks are
+determined by Coco3's physical bus and are not likely to change. There are four
+callbacks:
-- Notifications initiated by cartridge UI events like adding menu items or inserting
-cartridges in slots. These are asyncronous and can rely on DLL exports for details.
-A good mechanism for these is Vcc's main window message loop. The main window handle
-(hVccWnd) has been added to PakInitialize() and a message to it is used by the MPI to
-initiate a VCC reset.
+ void assert_cartridge_line (SlotId, line_state)
+ void assert_interrupt (SlotId, interrupt, interrupt_source)
+ void write_memory_byte (SlotId, value, address)
+ unsigned char read_memory_byte (SlotId, unsigned short address)
-The add_menu_item callback is not tied to the CPU loop and qualifies as a slow callback.
-This callback is being replaced by windows menu item change message and a new export.
-See **CartridgeMenuSystem.txt** for a description of this change.
+SlotId is used by the MPI to filter assert_cartridge_line. DLL's are passed their slot
+location in PakInitialize().
---
-#A New Design Philosophy For The MPI (In progress)
+#Proposed New Design Philosophy For The MPI (under consideration)
VCC and forks of VCC use run-time loading and unloading of dynamic libraries to simulate
the inserting and removing of Cartridges.
@@ -204,53 +194,18 @@ The pakinterface slot management concept:
- The pakinterface maintains a list indexed by slot number of loaded cartridges.
-- Slots are numbered 0-4. Slot 0 is the Boot slot. Slots 1-4 only loaded if MPI is in the Boot slot.
-
-- The pakinterface maintains the cartridge menu and dynamic menu items
+- Slots are numbered 0-4. Slot 0 is the Boot slot. Slots 1-4 loaded if MPI is in the Boot slot.
- The pakInterface routes I/O to slots per CTS/SCS using existing capability / callcacks
- The pakinterface saves slot content to settings.
- Any change to current CTS triggers a reset. This is detected and effected by the pakinterface
-
-- Reset stops the CPU, unloads all cartridges, reloads the basic rom, reloads cartridges
+ Reset stops the CPU, unloads all cartridges, reloads the basic rom, reloads cartridges
per settings, and then restarts the CPU.
-- pakInterface sends MPI changes to CTS/SCS via a new MPI export
-
-- The opaque slot_context is renamed to SlotId (0-4) and is made transparent. Some carts
- don't work right if they are not a specific slot. They can use SlotId to verify the slot
- they are in is right for them. (This has been completed)
-
-- On request pakInterface sends MPI active cart description via a new MPI export
-
-- On request pakInterface sends MPI slot contents
-
-- Then MPI should never call a cartridge DLL directly. It should always request actions through
- messages to the pakInterface using the WinMain message loop.
-
-- The MPI saves the startup slot setting. Changing this causes no changes to running CPU
+- MPI sends changes to startup CTS/SCS via a notification message. Startup CTS/SCS does not
+ affect the running CPU, a reset is required for them to take effect.
- The MPI requests cartridge loads / unloads by sending messages to WinMain.
-- The MPI requests slot and cartridge information by sending messages to WinMain.
-
-- The MPI has new exports to recieve results from slot changes and cartridge information requests.
-
-- The MPI "Reset VCC" button sends a reset message to VCC main.
-
-- With the exception of add_menu_item() all other exports and callbacks remain the same.
-
----
-
-Implementation Plan
-
-1. Replace opaque slot_context pointer in init export with transparent SlotId. Cartridges can
- use SlotId or simply return it in callbacks. (This is complete)
-
-2. Replace the AddCartMenu callback with a message and modify pakinterface to maintain the
- cartridge dynamic menus. See **CartridgeMenuSystem.txt** for more description.
-
-3. Move slot maintenance, cartridge loading, and cartidge calls from MPI to pakinterface.
-
diff --git a/libcommon/src/bus/CartridgeMenuSystem.txt b/libcommon/src/bus/CartridgeMenuSystem.txt
index c2fa2326..0269f5b6 100644
--- a/libcommon/src/bus/CartridgeMenuSystem.txt
+++ b/libcommon/src/bus/CartridgeMenuSystem.txt
@@ -1,80 +1,73 @@
-# **VCC Cartridge Export Based Menu System**
+# VCC Export Based Cartridge Menu System
-This replaces per‑item callbacks with a single export‑based model for exchanging menu
+This replaces per‑item callbacks with a export‑based model for exchanging menu
items between cartridge DLLs, Multipak (MPI), and the PakInterface host.
Concept:
-- Each cartridge DLL maintains its own internal list of menu items.
-- Each DLL exposes **one export** that returns its entire menu list on demand.
+- Each cartridge DLL creates an internal list of it's menu items as needed.
+- DLL's expose an export that returns menu items from the list on demand.
- MPI aggregates child cartridge menus, applies slot‑based ID biasing, and returns a
- unified list to the host.
-- The host rebuilds the UI menu from the aggregated list.
+ unified list to the host.
+- The host pakinterface rebuilds the UI menu from the aggregated list.
- DLLs notify the host of menu changes using a single Windows message.
-
-Benefits:
-
-- Menu state is always derived from a **single export call**, not a sequence of callbacks.
-- DLLs do not depend on host internals, callback tables, or routing logic.
- Clear separation of responsibilities:
- - DLLs own their menu state.
- - MPI aggregates and biases.
- - Host renders.
-- The export signature and struct layout remain stable even if internal implementations change.
+ - DLLs own their menu state.
+ - MPI aggregates and biases.
+ - Host renders.
+- The export signature remains stable even if internal implementations change.
---
-## **Component Details**
-
-### **Cartridge DLL**
+## Cartridge DLL
-A cartridge DLL:
+- Sends IDC_MSG_UPD_MENU to the host on internal state changes that affect its menu.
+- Keeps a static list of menu items that represents it's internal state.
+- Implements a GetMenuItemList(item,index) export that:
+ - Updates the list as required (see note)
+ - Accepts a index that indicate which entry is desired.
+ - Returns the entry at that index in the item buffer.
+ - Returns false if the entry does not exist.
-- Maintains a **static internal list** of its menu items.
-- Updates this list whenever its internal state changes.
-- Sends **WM_VCC_MENU_CHANGED** to the host after updating its list.
-- Implements a single GetMenuItemList export that:
- - Accepts a pointer to a buffer of menu items (or `nullptr` for size query).
- - Accepts a pointer to a count value.
- - Interprets the count as:
- - **Input:** maximum number of items the host can accept.
- - **Output:** total number of items the DLL has (or number copied).
-- Never copies more items than the host indicates.
-- Returns failure if not all items could be copied.
-- Protects the list from export access while it is being updated.
+Notes:
-If the buffer pointer is `nullptr`, the DLL sets count to the number of items it has.
-If the buffer pointer is not `nullptr`, the DLL copies up to the specified count.
+If the item buffer is a nullptr the DLL returns false.
+If the index is above MAX_MENU_ITEMS DLL returns false.
+An index of zero indicates the DLL's internal list should be refreshed.
+ - DLL updates / recreates it's internal list as required.
+ - DLL returns the first item if it exists, otherwise false.
+For indexes above zero the DLL simply returns the item or false.
+Cartridge plumbing guarantees that DLL's who don't expose the actual
+export will return false when call is attempted.
---
-### **Multipak (MPI)**
+## Multipak (MPI)
-MPI acts as an **aggregator** and applies deterministic slot‑based menu ID biasing.
+MPI acts as an aggregator and applies deterministic slot‑based menu ID biasing.
The MPI is only permitted to be installed in the boot slot. (Coco side slot)
MPI:
-- Maintains references to each child cartridge’s menu export.
+- Maintains references to each child cartridge’s menu export.
- When its export is called:
- - Generates MPI’s own menu items.
- - Calls each child cartridge’s export to retrieve their items.
- - Applies **slot‑based menu ID biasing**:
- - Each slot receives a unique bias range.
- - Biasing is applied only by MPI.
- - DLLs remain unaware of slot numbers or bias rules.
- - Merges all items into a single unified list.
-- Returns the unified list to the host using the same export pattern as cartridges.
+ - If index is zero it refreshes it's own menu items.
+ - Calls each child cartridge’s export to retrieve their items.
+ - Applies slot‑based menu ID biasing:
+ - Merges all items into a single unified list.
+- Returns item from the list indicated by the index.
---
-### **PakInterface Host**
+## PakInterface (Host)
The host:
-- Listens for **WM_VCC_MENU_CHANGED** from any DLL including the MPI.
-- On receiving the message, calls the boot slot's export and rebuilds the menu.
+- Creates the master menu item list from which the cartridge menu is drawn
+- Listens for IDC_MSG_UPD_MENU from any DLL including the MPI.
+- On receiving the message, updates it's list using calls to the boot slot's
+ (slot 0) export and rebuilds the menu.
The host only sees a flat, final list of menu items.
diff --git a/libcommon/src/bus/basic_cartridge.cpp b/libcommon/src/bus/basic_cartridge.cpp
index c00ff288..9143b48f 100644
--- a/libcommon/src/bus/basic_cartridge.cpp
+++ b/libcommon/src/bus/basic_cartridge.cpp
@@ -84,4 +84,8 @@ namespace VCC::Core
void basic_cartridge::initialize_bus()
{}
+ bool basic_cartridge::get_menu_item( menu_item_entry* item, size_t index)
+ {
+ return false;
+ }
}
diff --git a/libcommon/src/bus/cartridge_menu.cpp b/libcommon/src/bus/cartridge_menu.cpp
new file mode 100644
index 00000000..76e0b351
--- /dev/null
+++ b/libcommon/src/bus/cartridge_menu.cpp
@@ -0,0 +1,135 @@
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//======================================================================
+
+#include
+#include
+#include
+
+namespace VCC::Bus {
+
+// Global cart menu for vcc.exe
+// DLL's should never use this
+cartridge_menu gVccCartMenu;
+
+// Cart menu for DLL use
+// Vcc or pakinterface should not use this
+cartridge_menu gDllCartMenu;
+
+// ------------------------------------------------------------
+// Copy a menu item to the API safe structure
+// ------------------------------------------------------------
+bool cartridge_menu::copy_item(menu_item_entry& out, size_t index) const
+{
+ if (index >= menu_.size() || index >= MAX_MENU_ITEMS)
+ return false;
+
+ const auto& src = menu_[index];
+
+ size_t n = std::min(src.name.size(), sizeof(out.name) - 1);
+ memcpy(out.name, src.name.data(), n);
+ out.name[n] = '\0';
+
+ out.menu_id = src.menu_id;
+ out.type = src.type;
+
+ return true;
+}
+
+// ------------------------------------------------------------
+// Draw the menu. DLL's should not call this
+// ------------------------------------------------------------
+HMENU cartridge_menu::draw(HWND hWnd, int position, const std::string& title)
+{
+ auto hMenuBar = GetMenu(hWnd);
+
+ // Erase the Existing Cartridge Menu. Vcc.rc defines
+ // a dummy Cartridge menu to preserve it's place.
+ DeleteMenu(hMenuBar,position,MF_BYPOSITION);
+
+ // Create first sub menu item
+ HMENU hMenu = CreatePopupMenu();
+ HMENU hMenu0 = hMenu;
+
+ MENUITEMINFO Mii{};
+ memset(&Mii,0,sizeof(MENUITEMINFO));
+ Mii.cbSize= sizeof(MENUITEMINFO);
+
+ // Create title bar item
+ Mii.fMask = MIIM_TYPE | MIIM_SUBMENU | MIIM_ID; // setting the submenu id
+ Mii.fType = MFT_STRING; // Type is a string
+ Mii.hSubMenu = hMenu;
+ Mii.dwTypeData = const_cast(title.c_str());
+ Mii.cch = title.size();
+ InsertMenuItem(hMenuBar,position,TRUE,&Mii);
+
+ // Create sub menus in order
+ unsigned int pos = 0u;
+ for (CartMenuItem item : menu_) {
+ DLOG_C("%4d %d '%s'\n",item.menu_id,item.type,item.name.c_str());
+// should this also be done inside the loop?
+// memset(&Mii,0,sizeof(MENUITEMINFO));
+// Mii.cbSize= sizeof(MENUITEMINFO);
+ switch (item.type) {
+ case MIT_Head:
+ hMenu = CreatePopupMenu();
+ Mii.fMask = MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;
+ Mii.fType = MFT_STRING;
+ Mii.hSubMenu = hMenu;
+ Mii.dwTypeData = const_cast(item.name.c_str());
+ Mii.cch = item.name.size();
+ InsertMenuItem(hMenu0,pos,TRUE,&Mii);
+ pos++;
+ break;
+ case MIT_Slave:
+ Mii.fMask = MIIM_TYPE | MIIM_ID;
+ Mii.fType = MFT_STRING;
+ Mii.wID = item.menu_id;
+ Mii.hSubMenu = hMenu;
+ Mii.dwTypeData = const_cast(item.name.c_str());
+ Mii.cch=item.name.size();
+ InsertMenuItem(hMenu,0,FALSE,&Mii);
+ break;
+ case MIT_Seperator:
+ Mii.fMask = MIIM_TYPE;
+ Mii.hSubMenu = hMenuBar;
+ Mii.dwTypeData = "";
+ Mii.cch=0;
+ Mii.fType = MF_SEPARATOR;
+ InsertMenuItem(hMenu0,pos,TRUE,&Mii);
+ pos++;
+ break;
+ case MIT_StandAlone:
+ Mii.fMask = MIIM_TYPE | MIIM_ID;
+ Mii.wID = item.menu_id;
+ Mii.hSubMenu = hMenuBar;
+ Mii.dwTypeData = const_cast(item.name.c_str());
+ Mii.cch=item.name.size();
+ Mii.fType = MFT_STRING;
+ InsertMenuItem(hMenu0,pos,TRUE,&Mii);
+ pos++;
+ break;
+ }
+ }
+ DrawMenuBar(hWnd);
+ return hMenu0;
+}
+
+} // namespace VCC::Bus
+
diff --git a/libcommon/src/bus/cpak_cartridge.cpp b/libcommon/src/bus/cpak_cartridge.cpp
index 4c590f3c..105f3306 100644
--- a/libcommon/src/bus/cpak_cartridge.cpp
+++ b/libcommon/src/bus/cpak_cartridge.cpp
@@ -19,6 +19,7 @@
// TODO: Rename this to hardware_cartridge (cpak_cartridge?)
#include
+#include
#include
namespace VCC::Core
@@ -75,6 +76,11 @@ namespace VCC::Core
return "";
}
+ bool default_get_menu_item(menu_item_entry*, size_t)
+ {
+ return false;
+ }
+
}
@@ -90,19 +96,34 @@ namespace VCC::Core
configuration_path_(move(configuration_path)),
hVccWnd_(hVccWnd),
cpak_callbacks_(cpak_callbacks),
- initialize_(GetImportedProcAddress(module_handle, "PakInitialize", nullptr)),
- terminate_(GetImportedProcAddress(module_handle, "PakTerminate", default_stop)),
- get_name_(GetImportedProcAddress(module_handle, "PakGetName", default_get_empty_string)),
- get_catalog_id_(GetImportedProcAddress(module_handle, "PakGetCatalogId", default_get_empty_string)),
- get_description_(GetImportedProcAddress(module_handle, "PakGetDescription", default_get_empty_string)),
- reset_(GetImportedProcAddress(module_handle, "PakReset", default_reset)),
- heartbeat_(GetImportedProcAddress(module_handle, "PakProcessHorizontalSync", default_heartbeat)),
- status_(GetImportedProcAddress(module_handle, "PakGetStatus", default_status)),
- write_port_(GetImportedProcAddress(module_handle, "PakWritePort", default_write_port)),
- read_port_(GetImportedProcAddress(module_handle, "PakReadPort", default_read_port)),
- read_memory_byte_(GetImportedProcAddress(module_handle, "PakReadMemoryByte", default_read_memory_byte)),
- sample_audio_(GetImportedProcAddress(module_handle, "PakSampleAudio", default_sample_audio)),
- menu_item_clicked_(GetImportedProcAddress(module_handle, "PakMenuItemClicked", default_menu_item_clicked))
+ initialize_(GetImportedProcAddress(
+ module_handle, "PakInitialize", nullptr)),
+ terminate_(GetImportedProcAddress(
+ module_handle, "PakTerminate", default_stop)),
+ get_name_(GetImportedProcAddress(
+ module_handle, "PakGetName", default_get_empty_string)),
+ get_catalog_id_(GetImportedProcAddress(
+ module_handle, "PakGetCatalogId", default_get_empty_string)),
+ get_description_(GetImportedProcAddress(
+ module_handle, "PakGetDescription", default_get_empty_string)),
+ reset_(GetImportedProcAddress(
+ module_handle, "PakReset", default_reset)),
+ heartbeat_(GetImportedProcAddress(
+ module_handle, "PakProcessHorizontalSync", default_heartbeat)),
+ status_(GetImportedProcAddress(
+ module_handle, "PakGetStatus", default_status)),
+ write_port_(GetImportedProcAddress(
+ module_handle, "PakWritePort", default_write_port)),
+ read_port_(GetImportedProcAddress(
+ module_handle, "PakReadPort", default_read_port)),
+ read_memory_byte_(GetImportedProcAddress(
+ module_handle, "PakReadMemoryByte", default_read_memory_byte)),
+ sample_audio_(GetImportedProcAddress(
+ module_handle, "PakSampleAudio", default_sample_audio)),
+ menu_item_clicked_(GetImportedProcAddress(
+ module_handle, "PakMenuItemClicked", default_menu_item_clicked)),
+ get_menu_item_(GetImportedProcAddress(
+ module_handle, "PakGetMenuItem", default_get_menu_item))
{
if (initialize_ == nullptr)
{
@@ -175,4 +196,9 @@ namespace VCC::Core
menu_item_clicked_(menu_item_id);
}
+ bool cpak_cartridge::get_menu_item(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item_(item, index);
+ }
+
}
diff --git a/mpi/cartridge_slot.cpp b/mpi/cartridge_slot.cpp
index 7fc65b96..d0dc2598 100644
--- a/mpi/cartridge_slot.cpp
+++ b/mpi/cartridge_slot.cpp
@@ -45,7 +45,6 @@ namespace VCC::Core
path_ = move(other.path_);
handle_ = move(other.handle_);
cartridge_ = move(other.cartridge_);
- menu_items_ = move(other.menu_items_);
line_state_ = other.line_state_;
other.line_state_ = false;
diff --git a/mpi/cartridge_slot.h b/mpi/cartridge_slot.h
index 42d00d9b..0347cd4a 100644
--- a/mpi/cartridge_slot.h
+++ b/mpi/cartridge_slot.h
@@ -18,8 +18,8 @@
#pragma once
#include
#include
-#include "../CartridgeMenu.h"
-
+#include
+//#include "../CartridgeMenu.h"
namespace VCC::Core
{
@@ -35,11 +35,8 @@ namespace VCC::Core
using label_type = std::string;
using handle_type = ::VCC::Core::cartridge_loader_result::handle_type;
using cartridge_ptr_type = std::unique_ptr<::VCC::Core::cartridge>;
- using menu_item_type = CartMenuItem;
- using menu_item_collection_type = std::vector;
using context_type = ::VCC::Core::cartridge_context;
-
public:
cartridge_slot();
@@ -137,31 +134,16 @@ namespace VCC::Core
return line_state_;
}
- void reset_menu()
- {
- menu_items_.clear();
- }
-
- void append_menu_item(const menu_item_type& item)
+ bool get_menu_item(menu_item_entry* item, size_t index)
{
- menu_items_.push_back(item);
+ return cartridge_->get_menu_item(item, index);
}
- void enumerate_menu_items(context_type& context) const
- {
- for (const auto& item : menu_items_)
- {
- context.add_menu_item(item.name.c_str(), item.menu_id, item.type);
- }
- }
-
-
private:
path_type path_;
handle_type handle_;
cartridge_ptr_type cartridge_;
- menu_item_collection_type menu_items_;
bool line_state_ = false;
};
diff --git a/mpi/configuration_dialog.cpp b/mpi/configuration_dialog.cpp
index 44ff0d74..72f6bcd5 100644
--- a/mpi/configuration_dialog.cpp
+++ b/mpi/configuration_dialog.cpp
@@ -116,7 +116,7 @@ void configuration_dialog::select_new_cartridge(unsigned int item)
}
update_slot_details(slot);
- mpi_.build_menu();
+// mpi_.build_menu();
}
void configuration_dialog::set_selected_slot(size_t slot)
@@ -217,7 +217,6 @@ void configuration_dialog::eject_or_select_new_cartridge(unsigned int Button)
mpi_.eject_cartridge(slot);
configuration_.slot_cartridge_path(slot, {});
update_slot_details(slot);
- mpi_.build_menu();
}
else
{
diff --git a/mpi/configuration_dialog.h b/mpi/configuration_dialog.h
index 9c6756a9..7535bfdc 100644
--- a/mpi/configuration_dialog.h
+++ b/mpi/configuration_dialog.h
@@ -20,7 +20,6 @@
#include "multipak_configuration.h"
#include
-//TODO: ELiminate this useless class BS. It gains nothing but obscurity
class configuration_dialog
{
public:
diff --git a/mpi/host_cartridge_context.h b/mpi/host_cartridge_context.h
index 9f831214..8ade2f21 100644
--- a/mpi/host_cartridge_context.h
+++ b/mpi/host_cartridge_context.h
@@ -31,10 +31,8 @@ class host_cartridge_context : public ::VCC::Core::cartridge_context
{
public:
- // FIXME: Remove this when we derive from cartridge_context
using path_type = std::string;
-
public:
explicit host_cartridge_context(slot_id_type SlotId, const path_type& configuration_filename)
@@ -48,11 +46,6 @@ class host_cartridge_context : public ::VCC::Core::cartridge_context
return configuration_filename_;
}
- void reset() override
- {
- // FIXME-CHET: this needs to do something
- }
-
void write_memory_byte(unsigned char value, unsigned short address) override
{
write_memory_byte_(SlotId_, value, address);
@@ -73,11 +66,6 @@ class host_cartridge_context : public ::VCC::Core::cartridge_context
assert_interrupt_(SlotId_, interrupt, interrupt_source);
}
- void add_menu_item(const char* menu_name, int menu_id, MenuItemType menu_type) override
- {
- add_menu_item_(SlotId_, menu_name, menu_id, menu_type);
- }
-
private:
friend void PakInitialize(
@@ -90,11 +78,15 @@ class host_cartridge_context : public ::VCC::Core::cartridge_context
private:
- slot_id_type SlotId_;
- const path_type& configuration_filename_;
- PakWriteMemoryByteHostCallback write_memory_byte_ = [](slot_id_type, unsigned char, unsigned short) {};
- PakReadMemoryByteHostCallback read_memory_byte_ = [](slot_id_type, unsigned short) -> unsigned char { return 0; };
- PakAssertCartridgeLineHostCallback assert_cartridge_line_ = [](slot_id_type, bool) {};
- PakAssertInteruptHostCallback assert_interrupt_ = [](slot_id_type, Interrupt, InterruptSource) {};
- PakAppendCartridgeMenuHostCallback add_menu_item_ = [](slot_id_type, const char*, int, MenuItemType) {};
+ slot_id_type SlotId_;
+ const path_type& configuration_filename_;
+ PakWriteMemoryByteHostCallback write_memory_byte_ = []
+ (slot_id_type, unsigned char, unsigned short) {};
+ PakReadMemoryByteHostCallback read_memory_byte_ = []
+ (slot_id_type, unsigned short) -> unsigned char { return 0; };
+ PakAssertCartridgeLineHostCallback assert_cartridge_line_ = []
+ (slot_id_type, bool) {};
+ PakAssertInteruptHostCallback assert_interrupt_ = []
+ (slot_id_type, Interrupt, InterruptSource) {};
};
+
diff --git a/mpi/mpi.cpp b/mpi/mpi.cpp
index 9389ae6d..65fe3f8b 100644
--- a/mpi/mpi.cpp
+++ b/mpi/mpi.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include // for MenuItemType
HINSTANCE gModuleInstance = nullptr;
static std::string gConfigurationFilename;
@@ -68,7 +69,6 @@ extern "C"
gMultiPakConfiguration.configuration_path(configuration_path);
gConfigurationFilename = configuration_path;
gVccWnd = hVccWnd;
- gHostCallbacks->add_menu_item_ = callbacks->add_menu_item;
gHostCallbacks->read_memory_byte_ = callbacks->read_memory_byte;
gHostCallbacks->write_memory_byte_ = callbacks->write_memory_byte;
gHostCallbacks->assert_interrupt_ = callbacks->assert_interrupt;
@@ -87,6 +87,12 @@ extern "C"
gMultiPakInterface.menu_item_clicked(menu_item_id);
}
+ // Fetch menu item list for MPI and carts it has loaded
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return gMultiPakInterface.get_menu_item(item, index);
+ }
+
// Write to port
__declspec(dllexport) void PakWritePort(unsigned char port_id,unsigned char value)
{
diff --git a/mpi/multipak_cartridge.cpp b/mpi/multipak_cartridge.cpp
index 301df45a..7cb23ab0 100644
--- a/mpi/multipak_cartridge.cpp
+++ b/mpi/multipak_cartridge.cpp
@@ -23,7 +23,9 @@
#include
#include
#include
-
+#include
+#include
+#include
namespace
{
@@ -85,9 +87,6 @@ void multipak_cartridge::start()
}
}
}
-
- // Build the dynamic menu
- build_menu();
}
@@ -231,33 +230,68 @@ unsigned short multipak_cartridge::sample_audio()
void multipak_cartridge::menu_item_clicked(unsigned char menu_item_id)
{
+
if (menu_item_id == 19) //MPI Config
{
gConfigurationDialog.open();
}
+ // Each slot is allocated 50 menu items and items were
+ // biased by SlotId * 50 so MPI knows which slot the item is for
+ if (menu_item_id < 50) return; // Nothing more for SlotId 0
+
VCC::Util::section_locker lock(mutex_);
- // Menu items for loaded carts. Each slot is allocated 50.
- if (menu_item_id >= 50 && menu_item_id <= 100)
- {
+ if (menu_item_id < 100) {
slots_[0].menu_item_clicked(menu_item_id - 50);
+ return;
}
- if (menu_item_id > 100 && menu_item_id <= 150)
- {
+ if (menu_item_id < 150) {
slots_[1].menu_item_clicked(menu_item_id - 100);
+ return;
}
- if (menu_item_id > 150 && menu_item_id <= 200)
- {
+ if (menu_item_id < 200) {
slots_[2].menu_item_clicked(menu_item_id - 150);
+ return;
}
- if (menu_item_id > 200 && menu_item_id <= 250)
- {
+ if (menu_item_id < 250) {
slots_[3].menu_item_clicked(menu_item_id - 200);
+ return;
+ }
+}
+
+// returns menu item from DLL item list
+bool multipak_cartridge::get_menu_item(menu_item_entry* item, size_t index)
+{
+ using VCC::Bus::gDllCartMenu;
+
+ if (!item) return false;
+
+ // index 0 is special, it indicates DLL should refresh it's menus
+ if (index == 0) {
+ // Rebuild MPI menu
+ gDllCartMenu.clear();
+ gDllCartMenu.add("", 0, MIT_Seperator);
+ gDllCartMenu.add("MPI Config", ControlId(19), MIT_StandAlone);
+ // Append child menus
+ for (int SlotId = 4; SlotId > 0; SlotId--) {
+ menu_item_entry pakitm;
+ for (int ndx = 0; ndx < MAX_MENU_ITEMS; ndx++) {
+ if (slots_[SlotId-1].get_menu_item(&pakitm,ndx)) {
+ // bias control_ids per slot
+ if (pakitm.menu_id >= MID_CONTROL)
+ pakitm.menu_id += (SlotId * 50);
+ gDllCartMenu.add(pakitm.name,pakitm.menu_id,pakitm.type);
+ } else {
+ break;
+ }
+ }
+ }
}
+ return gDllCartMenu.copy_item( *item, index);
}
@@ -290,6 +324,7 @@ void multipak_cartridge::eject_cartridge(slot_id_type mpi_slot)
slots_[mpi_slot] = {};
if (mpi_slot == cached_cts_slot_ || mpi_slot == switch_slot_)
SendMessage(gVccWnd,WM_COMMAND,(WPARAM) ID_FILE_RESET,(LPARAM) 0);
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
}
// create cartridge object and load cart DLL
@@ -308,23 +343,12 @@ multipak_cartridge::mount_status_type multipak_cartridge::mount_cartridge(
self->assert_cartridge_line(SlotId, line_state);
};
- static auto append_menu_item_thunk =
- +[](slot_id_type SlotId,
- const char* menu_name,
- int menu_id,
- MenuItemType menu_type)
- {
- menu_item_type item {menu_name, (unsigned int)menu_id, menu_type};
- self->append_menu_item(SlotId, item);
- };
-
// Build callback table for carts loaded on MPI
cpak_callbacks callbacks {
gHostCallbacks->assert_interrupt_,
assert_cartridge_line_thunk,
gHostCallbacks->write_memory_byte_,
- gHostCallbacks->read_memory_byte_,
- append_menu_item_thunk
+ gHostCallbacks->read_memory_byte_//,
};
DLOG_C("%3d %p %p %p %p %p\n",mpi_slot,callbacks);
@@ -376,6 +400,7 @@ multipak_cartridge::mount_status_type multipak_cartridge::mount_cartridge(
slots_[mpi_slot].start();
slots_[mpi_slot].reset();
+ SendMessage(gVccWnd,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return loadedCartridge.load_result;
}
@@ -395,53 +420,6 @@ multipak_cartridge::slot_id_type multipak_cartridge::selected_scs_slot() const
return cached_scs_slot_;
}
-// Save cart Menu items into containers per slot
-void multipak_cartridge::append_menu_item(slot_id_type SlotId, menu_item_type item)
-{
- DLOG_C("menu_item %d %d \n",SlotId,item.menu_id);
-
- auto mpi_slot = SlotId - 1;
-
- switch (item.menu_id) {
- case MID_BEGIN:
- {
- VCC::Util::section_locker lock(mutex_);
- slots_[mpi_slot].reset_menu();
- break;
- }
- case MID_FINISH:
- build_menu();
- break;
- default:
- {
- // Add 50 times the slot_id to menu_ids so WinMain knows who is calling
- if (item.menu_id >= MID_CONTROL) {
- item.menu_id += SlotId * 50;
- }
- VCC::Util::section_locker lock(mutex_);
- slots_[mpi_slot].append_menu_item(item);
- break;
- }
- }
-}
-
-// This gets called any time a cartridge menu is changed. It draws the entire menu.
-void multipak_cartridge::build_menu()
-{
- // do we really need this here? menu draw should be async
- VCC::Util::section_locker lock(mutex_);
-
- // Init the menu, establish MPI config control, build slot menus, then draw it.
- context_->add_menu_item("", MID_BEGIN, MIT_Head);
- context_->add_menu_item("", MID_ENTRY, MIT_Seperator);
- context_->add_menu_item("MPI Config", ControlId(19), MIT_StandAlone);
- for (int mpi_slot = 3; mpi_slot >= 0; mpi_slot--)
- {
- slots_[mpi_slot].enumerate_menu_items(*context_);
- }
- context_->add_menu_item("", MID_FINISH, MIT_Head); // Finish draws the entire menu
-}
-
void multipak_cartridge::assert_cartridge_line(slot_id_type SlotId, bool line_state)
{
DLOG_C("cart line %d %d \n",SlotId,line_state);
diff --git a/mpi/multipak_cartridge.h b/mpi/multipak_cartridge.h
index 874e2f5d..860cb561 100644
--- a/mpi/multipak_cartridge.h
+++ b/mpi/multipak_cartridge.h
@@ -20,11 +20,10 @@
#include "multipak_configuration.h"
#include
#include
+#include
#include
-#include "../CartridgeMenu.h"
#include
-
constexpr size_t NUMSLOTS = 4u;
class multipak_cartridge : public ::VCC::Core::cartridge
@@ -37,8 +36,6 @@ class multipak_cartridge : public ::VCC::Core::cartridge
using path_type = std::string;
using label_type = std::string;
using description_type = std::string;
- using menu_item_type = CartMenuItem;
-
public:
@@ -67,6 +64,7 @@ class multipak_cartridge : public ::VCC::Core::cartridge
void status(char* text_buffer, size_t buffer_size) override;
unsigned short sample_audio() override;
void menu_item_clicked(unsigned char menu_item_id) override;
+ bool get_menu_item(menu_item_entry* item, size_t index) override;
// Multi-pak implementation
label_type slot_label(slot_id_type slot) const;
@@ -81,12 +79,8 @@ class multipak_cartridge : public ::VCC::Core::cartridge
slot_id_type selected_switch_slot() const;
slot_id_type selected_scs_slot() const;
- void build_menu();
-
// Make automatic when mounting, ejecting, selecting slot, etc.
void assert_cartridge_line(slot_id_type slot, bool line_state);
- void append_menu_item(slot_id_type slot, menu_item_type item);
-
private:
diff --git a/mpi/multipak_cartridge_context.h b/mpi/multipak_cartridge_context.h
index 34fdf247..c89f1511 100644
--- a/mpi/multipak_cartridge_context.h
+++ b/mpi/multipak_cartridge_context.h
@@ -36,16 +36,6 @@ class multipak_cartridge_context : public ::VCC::Core::cartridge_context
return parent_context_.configuration_path();
}
- void reset() override
- {
- parent_context_.reset();
- }
-
- void add_menu_item(const char* menu_name, int menu_id, MenuItemType menu_type) override
- {
- multipak_.append_menu_item(slot_id_, { menu_name, static_cast(menu_id), menu_type });
- }
-
void write_memory_byte(unsigned char value, unsigned short address) override
{
parent_context_.write_memory_byte(value, address);
diff --git a/mpi/multipak_configuration.cpp b/mpi/multipak_configuration.cpp
index 1e1415f7..26918e3a 100644
--- a/mpi/multipak_configuration.cpp
+++ b/mpi/multipak_configuration.cpp
@@ -60,7 +60,6 @@ multipak_configuration::path_type multipak_configuration::last_accessed_dll_path
return settings(configuration_path()).read("DefaultPaths", "MPIPath");
}
-// selected slot FIXME:: it is not clear that slot is an int
void multipak_configuration::selected_slot(slot_id_type slot) const
{
settings(configuration_path()).write(section_, "SWPOSITION", slot);
diff --git a/mpi/multipak_configuration.h b/mpi/multipak_configuration.h
index 37b3be7e..039ade09 100644
--- a/mpi/multipak_configuration.h
+++ b/mpi/multipak_configuration.h
@@ -37,7 +37,6 @@ class multipak_configuration
void configuration_path(path_type path);
path_type configuration_path() const;
- //void last_accessed_module_type(const path_type& path) const;
path_type last_accessed_module_type() const;
void last_accessed_rom_path(const path_type& path) const;
@@ -57,7 +56,6 @@ class multipak_configuration
string_type get_slot_path_key(slot_id_type slot) const;
-
private:
const string_type section_;
diff --git a/pakinterface.cpp b/pakinterface.cpp
index 0509a8be..fa6c7112 100644
--- a/pakinterface.cpp
+++ b/pakinterface.cpp
@@ -1,31 +1,34 @@
-/*
- Copyright 2015 by Joseph Forgione
- This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
+//#define USE_LOGGING
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//======================================================================
#include "defines.h"
#include "tcc1014mmu.h"
#include "tcc1014registers.h"
-#include "CartridgeMenu.h"
#include "pakinterface.h"
#include "config.h"
#include "Vcc.h"
#include "mc6821.h"
#include "resource.h"
#include
+#include
+#include
#include
#include
#include
@@ -36,11 +39,9 @@
#include
#include
-
using cartridge_loader_status = VCC::Core::cartridge_loader_status;
using cartridge_loader_result = VCC::Core::cartridge_loader_result;
-
// Storage for Pak ROMs
extern SystemState EmuState;
@@ -67,12 +68,6 @@ struct vcc_cartridge_context : public ::VCC::Core::cartridge_context
return path_buffer;
}
- void reset() override
- {
- //SendMessage(EmuState.WindowHandle,WM_COMMAND,(WPARAM) ID_FILE_RESET,(LPARAM) 0);
- EmuState.ResetPending = 2;
- }
-
void write_memory_byte(unsigned char value, unsigned short address) override
{
MemWrite8(value, address);
@@ -93,10 +88,6 @@ struct vcc_cartridge_context : public ::VCC::Core::cartridge_context
PakAssertInterupt(interrupt, interrupt_source);
}
- void add_menu_item(const char* menu_name, int menu_id, MenuItemType menu_type) override
- {
- CartMenuCallBack(menu_name, menu_id, menu_type);
- }
};
static void PakAssertCartrigeLine(slot_id_type /*SlotId*/, bool line_state)
@@ -119,11 +110,6 @@ static void PakAssertInterupt(slot_id_type /*SlotId*/, Interrupt interrupt, Inte
PakAssertInterupt(interrupt, source);
}
-static void PakAddMenuItem(slot_id_type /*SlotId*/, const char* name, int menu_id, MenuItemType type)
-{
- CartMenuCallBack(name, menu_id, type);
-}
-
void PakTimer()
{
VCC::Util::section_locker lock(gPakMutex);
@@ -188,38 +174,32 @@ unsigned short PackAudioSample()
return gActiveCartrige->sample_audio();
}
-// Create entries for cartridge menu. The rest will be for MPI
-// ControlId(MenuId) set what control does
-void BeginCartMenu()
+// Build entries for cartridge menu.
+void BuildCartMenu()
{
- VCC::Util::section_locker lock(gPakMutex);
-
- CartMenu.reserve(0);
- CartMenu.add("", MID_BEGIN, MIT_Head);
- CartMenu.add("Cartridge", MID_ENTRY, MIT_Head);
- if (!gActiveCartrige->name().empty())
- {
- char tmp[64] = {};
- snprintf(tmp, 64, "Eject %s", gActiveCartrige->name().c_str());
- CartMenu.add(tmp, ControlId(2), MIT_Slave);
- CartMenu.add("", MID_FINISH, MIT_Head);
- CartMenu.reserve(2);
+ //VCC::Util::section_locker lock(gPakMutex);
+ using VCC::Bus::gVccCartMenu;
+ gVccCartMenu.clear();
+ gVccCartMenu.add("Cartridge", 0, MIT_Head);
+ if (!gActiveCartrige->name().empty()) {
+ std::string tmp = "Eject " + gActiveCartrige->name();
+ gVccCartMenu.add(tmp, ControlId(2), MIT_Slave);
+ // Add items from loaded pak
+ menu_item_entry item;
+ for (size_t index=0;indexget_menu_item(&item,index)) {
+ gVccCartMenu.add(item.name,item.menu_id,item.type);
+ } else {
+ break;
+ }
+ }
} else {
- CartMenu.add("Load MPI", ControlId(3), MIT_Slave);
- CartMenu.add("Load DLL", ControlId(1), MIT_Slave);
- CartMenu.add("Load ROM", ControlId(4), MIT_Slave);
- CartMenu.add("", MID_FINISH, MIT_Head);
- CartMenu.reserve(3);
+ gVccCartMenu.add("Load MPI", ControlId(3), MIT_Slave);
+ gVccCartMenu.add("Load DLL", ControlId(1), MIT_Slave);
+ gVccCartMenu.add("Load ROM", ControlId(4), MIT_Slave);
}
}
-// Callback for loaded cart DLLs.
-void CartMenuCallBack(const char *name, int menu_id, MenuItemType type)
-{
- CartMenu.add(name, menu_id, type);
-}
-
-
void PakLoadCartridgeUI(int type)
{
char inifile[MAX_PATH];
@@ -230,11 +210,13 @@ static char cartDir[MAX_PATH] = "";
FileDialog dlg;
if (type == 0) {
dlg.setTitle(TEXT("Load Program Pack"));
- dlg.setFilter("Hardware Packs\0*.dll\0All Supported Formats (*.dll;*.ccc;*.rom)\0*.dll;*.ccc;*.rom\0\0");
+ dlg.setFilter("Hardware Packs\0*.dll\0"
+ "All Supported Formats (*.dll;*.ccc;*.rom)\0*.dll;*.ccc;*.rom\0\0");
Setting().read("DefaultPaths", "MPIPath", "", cartDir, MAX_PATH);
} else {
dlg.setTitle(TEXT("Load ROM"));
- dlg.setFilter("Rom Packs(*.ccc;*.rom)\0*.ccc;*.rom\0All Supported Formats (*.dll;*.ccc;*.rom)\0*.dll;*.ccc;*.rom\0\0");
+ dlg.setFilter("Rom Packs(*.ccc;*.rom)\0*.ccc;*.rom\0"
+ "All Supported Formats (*.dll;*.ccc;*.rom)\0*.dll;*.ccc;*.rom\0\0");
Setting().read("DefaultPaths", "PakPath", "", cartDir, MAX_PATH);
}
dlg.setInitialDir(cartDir);
@@ -294,8 +276,7 @@ static cartridge_loader_status load_any_cartridge(const char *filename, const ch
PakAssertInterupt,
PakAssertCartrigeLine,
PakWriteMemoryByte,
- PakReadMemoryByte,
- PakAddMenuItem
+ PakReadMemoryByte
};
slot_id_type SlotId = 0;
@@ -321,12 +302,10 @@ static cartridge_loader_status load_any_cartridge(const char *filename, const ch
strcpy(DllPath, filename);
gActiveCartrige = move(loadedCartridge.cartridge);
gActiveModule = move(loadedCartridge.handle);
- BeginCartMenu();
+ SendMessage(EmuState.WindowHandle,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
- // initialize the cartridge
+ // initialize the cartridge and reset the CPU
gActiveCartrige->start();
-
- // Reset if enabled. TODO: Send DoHardReset message instead
EmuState.ResetPending = 2;
return loadedCartridge.load_result;
@@ -342,7 +321,7 @@ void UnloadDll()
gActiveCartrige = std::make_unique();
gActiveModule.reset();
- BeginCartMenu();
+ SendMessage(EmuState.WindowHandle,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
gActiveCartrige->start();
}
@@ -354,7 +333,7 @@ void GetCurrentModule(char *DefaultModule)
void UpdateBusPointer()
{
- // Do nothing for now. No clue given what the plan for this was.
+ // Do nothing for now. What the plan was for this is unknown.
}
void UnloadPack()
diff --git a/pakinterface.h b/pakinterface.h
index d82fc7cd..acf05118 100644
--- a/pakinterface.h
+++ b/pakinterface.h
@@ -1,20 +1,21 @@
-/*
-Copyright 2015 by Joseph Forgione
-This file is part of VCC (Virtual Color Computer).
-
- VCC (Virtual Color Computer) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- VCC (Virtual Color Computer) is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VCC (Virtual Color Computer). If not, see .
-*/
+//======================================================================
+// This file is part of VCC (Virtual Color Computer).
+// Vcc is Copyright 2015 by Joseph Forgione
+//
+// VCC (Virtual Color Computer) is free software, you can redistribute
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// VCC (Virtual Color Computer) is distributed in the hope that it will
+// be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with VCC (Virtual Color Computer). If not, see
+// .
+//======================================================================
#pragma once
#include
@@ -32,6 +33,6 @@ void GetCurrentModule(char *);
void UpdateBusPointer();
void UnloadDll();
void UnloadPack();
-void BeginCartMenu();
+void BuildCartMenu();
void CartMenuActivated(unsigned int);
diff --git a/resource.h b/resource.h
index a01e7243..96e640ea 100644
--- a/resource.h
+++ b/resource.h
@@ -412,6 +412,12 @@
#define IDC_EDIT_RANGE_BEG 2152
#define IDC_EDIT_RANGE_END 2153
#define IDC_EDIT_RANGE_SEP 2154
+
+//-----------------------------------------------------
+// ID 5000 - 5250 are reserved for cartridge menus
+// ID 5251 - 5299 are reseverd for cartridge messaging
+//-----------------------------------------------------
+
#define IDM_USER_WIKI 40001
#define ID_FILE_EXIT 40002
#define IDM_HELP_ABOUT 40003
@@ -464,6 +470,7 @@
#define ID_BITBANGER_CONFIG 40057
#define ID_SWAP_JOYSTICKS 40058
#define IDM_HELP_FUNKEY 40059
+
#define ID_CONFIGURE_OPTIONS 65535
diff --git a/sdc/sdc.cpp b/sdc/sdc.cpp
index 33e0f7c2..1f273adf 100644
--- a/sdc/sdc.cpp
+++ b/sdc/sdc.cpp
@@ -137,12 +137,13 @@
#include
#include
#include
-#include "../CartridgeMenu.h"
#include
#include
#include
#include
+#include
+#include
#include "sdc.h"
@@ -168,7 +169,6 @@ static slot_id_type gSlotId {};
// Callback pointers
static PakAssertInteruptHostCallback AssertIntCallback = nullptr;
-static PakAppendCartridgeMenuHostCallback CartMenuCallback = nullptr;
// Settings
static char IniFile[MAX_PATH] = {};
@@ -227,6 +227,9 @@ static int UPDBTNS[8] = {ID_UPDATE0,ID_UPDATE1,ID_UPDATE2,ID_UPDATE3,
static std::string gRomPath {};
+static VCC::Bus::cartridge_menu SdcMenu {};
+bool get_menu_item(menu_item_entry* item, size_t index);
+
//======================================================================
// Functions
//======================================================================
@@ -234,7 +237,6 @@ static std::string gRomPath {};
LRESULT CALLBACK SDC_Configure(HWND, UINT, WPARAM, LPARAM);
void LoadConfig();
bool SaveConfig(HWND);
-void BuildCartridgeMenu();
void SelectCardBox();
void UpdateFlashItem(int);
void InitCardBox();
@@ -310,11 +312,9 @@ extern "C"
gVccWindow = hVccWnd;
DLOG_C("SDC %p %p %p %p %p\n",*callbacks);
gSlotId = SlotId;
- CartMenuCallback = callbacks->add_menu_item;
AssertIntCallback = callbacks->assert_interrupt;
strcpy(IniFile, configuration_path);
LoadConfig();
- BuildCartridgeMenu();
}
__declspec(dllexport) const char* PakGetName()
@@ -386,9 +386,9 @@ extern "C"
break;
case 11:
SDCMountNext (0);
+ SendMessage(gVccWindow,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
break;
}
- BuildCartridgeMenu();
return;
}
@@ -415,6 +415,13 @@ extern "C"
return(PakRom[adr]);
}
}
+
+ // Return SDC menu
+ __declspec(dllexport) bool PakGetMenuItem(menu_item_entry* item, size_t index)
+ {
+ return get_menu_item(item, index);
+ }
+
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID rsvd)
@@ -432,27 +439,27 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID rsvd)
//======================================================================
//-------------------------------------------------------------
-// Generate menu for configuring the SDC
+// Return items for cartridge menu. Called for each item
//-------------------------------------------------------------
-void BuildCartridgeMenu()
-{
- CartMenuCallback(gSlotId, "", MID_BEGIN, MIT_Head);
- CartMenuCallback(gSlotId, "", MID_ENTRY, MIT_Seperator);
- CartMenuCallback(gSlotId, "SDC Drive 0",MID_ENTRY,MIT_Head);
- char tmp[64]={};
- if (strcmp(gCocoDisk[0].name,"") == 0) {
- strcpy(tmp,"empty");
- } else {
- strcpy(tmp,gCocoDisk[0].name);
- if (gFileList.nextload_flag) {
- strcat(tmp," (load next)");
+bool get_menu_item(menu_item_entry* item, size_t index)
+{
+ if (!item) return false;
+ if (index == 0) {
+ std::string tmp = gCocoDisk[0].name;
+ if (tmp.empty()) {
+ tmp = "empty";
+ } else if (gFileList.nextload_flag) {
+ tmp = tmp + " (load next)";
} else {
- strcat(tmp," (no next)");
+ tmp = tmp + " (no next)";
}
+ SdcMenu.clear();
+ SdcMenu.add("", 0, MIT_Seperator);
+ SdcMenu.add("SDC Drive 0",0,MIT_Head);
+ SdcMenu.add(tmp, ControlId(11),MIT_Slave);
+ SdcMenu.add("SDC Config", ControlId(10), MIT_StandAlone);
}
- CartMenuCallback(gSlotId, tmp, ControlId(11),MIT_Slave);
- CartMenuCallback(gSlotId, "SDC Config", ControlId(10), MIT_StandAlone);
- CartMenuCallback(gSlotId, "", MID_FINISH, MIT_Head);
+ return SdcMenu.copy_item(*item, index);
}
//------------------------------------------------------------
@@ -1878,7 +1885,8 @@ void SDCMountDisk (int drive, const char * path, int raw)
if (*path == '\0') {
DLOG_C("SDCMountDisk unload %d %s\n",drive,path);
IFace.status = STA_NORMAL;
- if (drive == 0) BuildCartridgeMenu();
+ if (drive == 0)
+ SendMessage(gVccWindow,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
return;
}
@@ -2064,7 +2072,8 @@ void SDCOpenFound (int drive,int raw)
DLOG_C("SDCOpenFound %s directory initiate\n",pattern.c_str());
if (SDCInitiateDir(pattern.c_str())) {
SDCOpenFound(drive, 0);
- if (drive == 0) BuildCartridgeMenu();
+ if (drive == 0)
+ SendMessage(gVccWindow,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
}
return;
}
@@ -2195,7 +2204,8 @@ void SDCOpenFound (int drive,int raw)
}
}
- if (drive == 0) BuildCartridgeMenu();
+ if (drive == 0)
+ SendMessage(gVccWindow,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
IFace.status = STA_NORMAL;
return;
@@ -2521,7 +2531,7 @@ bool SearchFile(const std::string& pat)
// Fill gFileList with files found.
GetFileList(pat);
// Update menu to show next disk status
- BuildCartridgeMenu();
+ SendMessage(gVccWindow,WM_COMMAND,(WPARAM) IDC_MSG_UPD_MENU,(LPARAM) 0);
// Return true if something found
return (gFileList.files.size() > 0);
}