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); }