├── .gitmodules ├── Externals ├── capsimg │ ├── CAPSImg.lib │ ├── CapsAPI.h │ ├── CapsFDC.h │ ├── CapsForm.h │ ├── CapsLib.h │ ├── CapsLibAll.h │ ├── CapsLibVersion.h │ ├── ComLib.h │ └── CommonTypes.h ├── crtnew │ └── crtnew.h ├── fdrawcmd │ └── fdrawcmd.h └── winusb │ ├── usb.h │ ├── usb100.h │ ├── usb200.h │ ├── winusb.h │ ├── winusb.lib │ └── winusbio.h ├── Main ├── Main.vcxproj ├── Main.vcxproj.filters ├── Main.vcxproj.user ├── res │ ├── appicon.ico │ ├── fileManager.bmp │ ├── hexaEditor.bmp │ ├── image.bmp │ ├── logo2.psd │ ├── mainFrame.bmp │ ├── misc.bmp │ ├── resource.h │ ├── resource.rc │ ├── spectrumTape.bmp │ ├── trackMap.bmp │ └── webPage.bmp └── src │ ├── BSDOS.cpp │ ├── BSDOS.h │ ├── BSDOS_Boot.cpp │ ├── BSDOS_FAT.cpp │ ├── BSDOS_FileManager.cpp │ ├── BackgroundAction.cpp │ ├── BackgroundAction.h │ ├── CapsBase.cpp │ ├── CapsBase.h │ ├── CapsBase_Mining.cpp │ ├── CapsBase_Precomp.cpp │ ├── Charting.cpp │ ├── Charting.h │ ├── CtRaw.cpp │ ├── CtRaw.h │ ├── Debug.cpp │ ├── Debug.h │ ├── DialogEmptySpaceFilling.cpp │ ├── DialogEmptySpaceFilling.h │ ├── DialogFormatting.cpp │ ├── DialogFormatting.h │ ├── DialogNewImage.cpp │ ├── DialogNewImage.h │ ├── DialogRealDeviceSelection.cpp │ ├── DialogRealDeviceSelection.h │ ├── DialogUnformatting.cpp │ ├── DialogUnformatting.h │ ├── DialogVerification.cpp │ ├── DialogVerification.h │ ├── Diff.cpp │ ├── Diff.h │ ├── Dos.cpp │ ├── Dos.h │ ├── DosUnknown.cpp │ ├── DosUnknown.h │ ├── Dos_FatPath.cpp │ ├── Dos_FilePreview.cpp │ ├── Dos_FileReaderWriter.cpp │ ├── Dos_HexaPreview.cpp │ ├── Dos_PathString.cpp │ ├── Dos_Recognition.cpp │ ├── Dsk5.cpp │ ├── Dsk5.h │ ├── FDD.cpp │ ├── FDD.h │ ├── GDOS.cpp │ ├── GDOS.h │ ├── GDOS_Boot.cpp │ ├── GDOS_FileManager.cpp │ ├── Greaseweazle.cpp │ ├── Greaseweazle.h │ ├── HFE.cpp │ ├── HFE.h │ ├── HexaEditor.cpp │ ├── HexaEditor.h │ ├── IPF.cpp │ ├── IPF.h │ ├── Image.cpp │ ├── Image.h │ ├── ImageFloppy.cpp │ ├── ImageFloppy.h │ ├── ImageRaw.cpp │ ├── ImageRaw.h │ ├── Image_Dump.cpp │ ├── Image_SectorDataSerializer.cpp │ ├── Image_TrackEditor.cpp │ ├── Image_TrackRW.cpp │ ├── KryoFluxBase.cpp │ ├── KryoFluxBase.h │ ├── KryoFluxDevice.cpp │ ├── KryoFluxDevice.h │ ├── KryoFluxStreams.cpp │ ├── KryoFluxStreams.h │ ├── MDOS2.cpp │ ├── MDOS2.h │ ├── MDOS2_Boot.cpp │ ├── MDOS2_FileManager.cpp │ ├── MDOS2_GKFM.cpp │ ├── MSDOS7.cpp │ ├── MSDOS7.h │ ├── MSDOS7_Boot.cpp │ ├── MSDOS7_FAT.cpp │ ├── MSDOS7_FSInfo.cpp │ ├── MSDOS7_FileManager.cpp │ ├── MainWindow.cpp │ ├── MainWindow.h │ ├── OptionalLibAPIs.cpp │ ├── OptionalLibAPIs.h │ ├── SCL.cpp │ ├── SCL.h │ ├── SCP.cpp │ ├── SCP.h │ ├── SpectrumBase.cpp │ ├── SpectrumDos.cpp │ ├── SpectrumDos.h │ ├── SpectrumDos_AssemblerPreview.cpp │ ├── SpectrumDos_BasicPreview.cpp │ ├── SpectrumDos_FileManagerBase.cpp │ ├── SpectrumDos_ScreenPreview.cpp │ ├── SpectrumDos_Tape.cpp │ ├── SpectrumDos_ZXRom.cpp │ ├── SuperCardProBase.cpp │ ├── SuperCardProBase.h │ ├── TRDOS.h │ ├── TRDOS503.cpp │ ├── TRDOS503_Boot.cpp │ ├── TRDOS503_FileManager.cpp │ ├── TRDOS504.cpp │ ├── TRDOS505.cpp │ ├── TdiTemplate.cpp │ ├── TdiView.cpp │ ├── Utils.cpp │ ├── Utils.h │ ├── ViewBoot.cpp │ ├── ViewBoot.h │ ├── ViewCriticalSector.cpp │ ├── ViewCriticalSector.h │ ├── ViewDirectoryEntries.cpp │ ├── ViewDirectoryEntries.h │ ├── ViewDiskBrowser.cpp │ ├── ViewDiskBrowser.h │ ├── ViewFatHexa.cpp │ ├── ViewFatHexa.h │ ├── ViewFileManager.cpp │ ├── ViewFileManager.h │ ├── ViewFileManager_compare.cpp │ ├── ViewFileManager_editor.cpp │ ├── ViewFileManager_exportImport.cpp │ ├── ViewTrackMap.cpp │ ├── ViewTrackMap.h │ ├── ViewWebPage.cpp │ ├── ViewWebPage.h │ ├── XmlDocs.cpp │ ├── XmlDocs.h │ ├── editor.cpp │ ├── editor.h │ └── stdafx.h ├── PropGrid ├── PropGrid.vcxproj ├── PropGrid.vcxproj.filters ├── PropGrid.vcxproj.user └── src │ ├── Editor.cpp │ ├── Editor_Boolean.cpp │ ├── Editor_Custom.cpp │ ├── Editor_Enum.cpp │ ├── Editor_Hyperlink.cpp │ ├── Editor_Integer.cpp │ ├── Editor_String.cpp │ ├── Editors.h │ ├── PropGrid.cpp │ ├── PropGrid.h │ ├── PropGrid_Items.cpp │ ├── PropGrid_ListBox.cpp │ ├── api.cpp │ ├── api.h │ └── stdafx.h ├── README.md ├── Ride.sln ├── Tdi ├── Tdi.vcxproj ├── Tdi.vcxproj.filters ├── Tdi.vcxproj.user └── src │ ├── Tdi.cpp │ ├── Tdi.h │ ├── api.cpp │ ├── api.h │ └── stdafx.h └── _cleanup.bat /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "YAHEL"] 2 | path = YAHEL 3 | url = https://github.com/tomas-nestorovic/YAHEL 4 | -------------------------------------------------------------------------------- /Externals/capsimg/CAPSImg.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Externals/capsimg/CAPSImg.lib -------------------------------------------------------------------------------- /Externals/capsimg/CapsForm.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPSFORM_H 2 | #define CAPSFORM_H 3 | 4 | #pragma pack(push, 1) 5 | 6 | // block data descriptor for converter 7 | struct CapsFormatBlock { 8 | UDWORD gapacnt; // gap before first am count 9 | UDWORD gapavalue; // gap before first am value 10 | UDWORD gapbcnt; // gap after first am count 11 | UDWORD gapbvalue; // gap after first am value 12 | UDWORD gapccnt; // gap before second am count 13 | UDWORD gapcvalue; // gap before second am value 14 | UDWORD gapdcnt; // gap after second am count 15 | UDWORD gapdvalue; // gap after second am value 16 | UDWORD blocktype; // type of block 17 | UDWORD track; // track# 18 | UDWORD side; // side# 19 | UDWORD sector; // sector# 20 | SDWORD sectorlen; // sector length in bytes 21 | PUBYTE databuf; // source data buffer 22 | UDWORD datavalue; // source data value if buffer is NULL 23 | }; 24 | 25 | typedef struct CapsFormatBlock *PCAPSFORMATBLOCK; 26 | 27 | // track data descriptor for converter 28 | struct CapsFormatTrack { 29 | UDWORD type; // structure type 30 | UDWORD gapacnt; // gap after index count 31 | UDWORD gapavalue; // gap after index value 32 | UDWORD gapbvalue; // gap before index value 33 | PUBYTE trackbuf; // track buffer memory 34 | UDWORD tracklen; // track buffer memory length 35 | UDWORD buflen; // track buffer allocation size 36 | UDWORD bufreq; // track buffer requested size 37 | UDWORD startpos; // start position in buffer 38 | SDWORD blockcnt; // number of blocks 39 | PCAPSFORMATBLOCK block; // block data 40 | UDWORD size; // internal counter 41 | }; 42 | 43 | typedef struct CapsFormatTrack *PCAPSFORMATTRACK; 44 | 45 | #pragma pack(pop) 46 | 47 | // block types 48 | enum { 49 | cfrmbtNA=0, // invalid type 50 | cfrmbtIndex, // index 51 | cfrmbtData // data 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Externals/capsimg/CapsLib.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPSLIB_H 2 | #define CAPSLIB_H 3 | 4 | #undef LIB_USER 5 | #ifdef CAPS_USER 6 | #define LIB_USER 7 | #endif 8 | #include "ComLib.h" 9 | 10 | ExtSub SDWORD __cdecl CAPSInit(); 11 | ExtSub SDWORD __cdecl CAPSExit(); 12 | ExtSub SDWORD __cdecl CAPSAddImage(); 13 | ExtSub SDWORD __cdecl CAPSRemImage(SDWORD id); 14 | ExtSub SDWORD __cdecl CAPSLockImage(SDWORD id, PCHAR name); 15 | ExtSub SDWORD __cdecl CAPSLockImageMemory(SDWORD id, PUBYTE buffer, UDWORD length, UDWORD flag); 16 | ExtSub SDWORD __cdecl CAPSUnlockImage(SDWORD id); 17 | ExtSub SDWORD __cdecl CAPSLoadImage(SDWORD id, UDWORD flag); 18 | ExtSub SDWORD __cdecl CAPSGetImageInfo(PCAPSIMAGEINFO pi, SDWORD id); 19 | ExtSub SDWORD __cdecl CAPSLockTrack(PVOID ptrackinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD flag); 20 | ExtSub SDWORD __cdecl CAPSUnlockTrack(SDWORD id, UDWORD cylinder, UDWORD head); 21 | ExtSub SDWORD __cdecl CAPSUnlockAllTracks(SDWORD id); 22 | ExtSub PCHAR __cdecl CAPSGetPlatformName(UDWORD pid); 23 | ExtSub SDWORD __cdecl CAPSGetVersionInfo(PVOID pversioninfo, UDWORD flag); 24 | ExtSub UDWORD __cdecl CAPSFdcGetInfo(SDWORD iid, PCAPSFDC pc, SDWORD ext); 25 | ExtSub SDWORD __cdecl CAPSFdcInit(PCAPSFDC pc); 26 | ExtSub void __cdecl CAPSFdcReset(PCAPSFDC pc); 27 | ExtSub void __cdecl CAPSFdcEmulate(PCAPSFDC pc, UDWORD cyclecnt); 28 | ExtSub UDWORD __cdecl CAPSFdcRead(PCAPSFDC pc, UDWORD address); 29 | ExtSub void __cdecl CAPSFdcWrite(PCAPSFDC pc, UDWORD address, UDWORD data); 30 | ExtSub SDWORD __cdecl CAPSFdcInvalidateTrack(PCAPSFDC pc, SDWORD drive); 31 | ExtSub SDWORD __cdecl CAPSFormatDataToMFM(PVOID pformattrack, UDWORD flag); 32 | ExtSub SDWORD __cdecl CAPSGetInfo(PVOID pinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD inftype, UDWORD infid); 33 | ExtSub SDWORD __cdecl CAPSSetRevolution(SDWORD id, UDWORD value); 34 | ExtSub SDWORD __cdecl CAPSGetImageType(PCHAR name); 35 | ExtSub SDWORD __cdecl CAPSGetImageTypeMemory(PUBYTE buffer, UDWORD length); 36 | ExtSub SDWORD __cdecl CAPSGetDebugRequest(); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Externals/capsimg/CapsLibAll.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPSLIBALL_H 2 | #define CAPSLIBALL_H 3 | 4 | #include "CapsLibVersion.h" 5 | #include "CommonTypes.h" 6 | #include "CapsAPI.h" 7 | #include "CapsFDC.h" 8 | #include "CapsForm.h" 9 | #include "CapsLib.h" 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Externals/capsimg/CapsLibVersion.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPSLIBVERSION_H 2 | #define CAPSLIBVERSION_H 3 | 4 | #define CAPS_LIB_RELEASE 5 5 | #define CAPS_LIB_REVISION 1 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Externals/capsimg/ComLib.h: -------------------------------------------------------------------------------- 1 | #undef DllSub 2 | #undef DllVar 3 | #undef ExtSub 4 | #undef ExtVar 5 | 6 | #ifdef LIB_USER 7 | 8 | #define DllSub DllImport 9 | #define DllVar DllImport 10 | 11 | #else 12 | 13 | #define DllSub DllExport 14 | #define DllVar extern DllExport 15 | 16 | #endif 17 | 18 | #define ExtSub extern "C" DllSub 19 | #define ExtVar extern "C" DllVar 20 | 21 | -------------------------------------------------------------------------------- /Externals/capsimg/CommonTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMONTYPES_H 2 | #define COMMONTYPES_H 3 | 4 | typedef void *PVOID; 5 | typedef char *PCHAR; 6 | 7 | typedef BYTE UBYTE; 8 | typedef WORD UWORD; 9 | typedef DWORD UDWORD; 10 | typedef unsigned __int64 UQUAD; 11 | //typedef char SBYTE; 12 | typedef short SWORD; 13 | typedef int SDWORD; 14 | typedef __int64 SQUAD; 15 | 16 | typedef UBYTE *PUBYTE; 17 | typedef UWORD *PUWORD; 18 | typedef UDWORD *PUDWORD; 19 | typedef UQUAD *PUQUAD; 20 | typedef CHAR *PSBYTE; 21 | typedef SWORD *PSWORD; 22 | typedef SDWORD *PSDWORD; 23 | typedef SQUAD *PSQUAD; 24 | 25 | enum { 26 | DB_0 = 0, 27 | DB_1, 28 | DB_2, 29 | DB_3, 30 | DB_4, 31 | DB_5, 32 | DB_6, 33 | DB_7, 34 | DB_8, 35 | DB_9, 36 | DB_10, 37 | DB_11, 38 | DB_12, 39 | DB_13, 40 | DB_14, 41 | DB_15, 42 | DB_16, 43 | DB_17, 44 | DB_18, 45 | DB_19, 46 | DB_20, 47 | DB_21, 48 | DB_22, 49 | DB_23, 50 | DB_24, 51 | DB_25, 52 | DB_26, 53 | DB_27, 54 | DB_28, 55 | DB_29, 56 | DB_30, 57 | DB_31 58 | }; 59 | 60 | #define DF_0 (1UL< 8 | 9 | 10 | #if _MSC_VER >= 1200 11 | #pragma warning(push) 12 | #endif 13 | #pragma warning (disable:4201) 14 | #pragma warning(disable:4214) // named type definition in parentheses 15 | 16 | typedef enum _USB_DEVICE_SPEED { 17 | UsbLowSpeed = 0, 18 | UsbFullSpeed, 19 | UsbHighSpeed 20 | } USB_DEVICE_SPEED; 21 | 22 | typedef enum _USB_DEVICE_TYPE { 23 | Usb11Device = 0, 24 | Usb20Device 25 | } USB_DEVICE_TYPE; 26 | 27 | 28 | // standard definitions for the port status 29 | // word of the HUB port register 30 | 31 | #define USB_PORT_STATUS_CONNECT 0x0001 32 | #define USB_PORT_STATUS_ENABLE 0x0002 33 | #define USB_PORT_STATUS_SUSPEND 0x0004 34 | #define USB_PORT_STATUS_OVER_CURRENT 0x0008 35 | #define USB_PORT_STATUS_RESET 0x0010 36 | #define USB_PORT_STATUS_POWER 0x0100 37 | #define USB_PORT_STATUS_LOW_SPEED 0x0200 38 | #define USB_PORT_STATUS_HIGH_SPEED 0x0400 39 | 40 | typedef union _BM_REQUEST_TYPE { 41 | struct _BM { 42 | UCHAR Recipient:2; 43 | UCHAR Reserved:3; 44 | UCHAR Type:2; 45 | UCHAR Dir:1; 46 | }; 47 | UCHAR B; 48 | } BM_REQUEST_TYPE, *PBM_REQUEST_TYPE; 49 | 50 | typedef struct _USB_DEFAULT_PIPE_SETUP_PACKET { 51 | BM_REQUEST_TYPE bmRequestType; 52 | UCHAR bRequest; 53 | 54 | union _wValue { 55 | struct { 56 | UCHAR LowByte; 57 | UCHAR HiByte; 58 | }; 59 | USHORT W; 60 | } wValue; 61 | 62 | union _wIndex { 63 | struct { 64 | UCHAR LowByte; 65 | UCHAR HiByte; 66 | }; 67 | USHORT W; 68 | } wIndex; 69 | USHORT wLength; 70 | } USB_DEFAULT_PIPE_SETUP_PACKET, *PUSB_DEFAULT_PIPE_SETUP_PACKET; 71 | 72 | // setup packet is eight bytes -- defined by spec 73 | C_ASSERT(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) == 8); 74 | 75 | 76 | #define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 0x06 77 | #define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE 0x07 78 | 79 | typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR { 80 | UCHAR bLength; 81 | UCHAR bDescriptorType; 82 | USHORT bcdUSB; 83 | UCHAR bDeviceClass; 84 | UCHAR bDeviceSubClass; 85 | UCHAR bDeviceProtocol; 86 | UCHAR bMaxPacketSize0; 87 | UCHAR bNumConfigurations; 88 | UCHAR bReserved; 89 | } USB_DEVICE_QUALIFIER_DESCRIPTOR, *PUSB_DEVICE_QUALIFIER_DESCRIPTOR; 90 | 91 | 92 | typedef union _USB_HIGH_SPEED_MAXPACKET { 93 | struct _MP { 94 | USHORT MaxPacket:11; /* 0..10 */ 95 | USHORT HSmux:2; /* 11..12 */ 96 | USHORT Reserved:3; /* 13..15 */ 97 | }; 98 | USHORT us; 99 | } USB_HIGH_SPEED_MAXPACKET, *PUSB_HIGH_SPEED_MAXPACKET; 100 | 101 | #define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 0x0B 102 | 103 | typedef struct _USB_INTERFACE_ASSOCIATION_DESCRIPTOR { 104 | 105 | UCHAR bLength; 106 | UCHAR bDescriptorType; 107 | UCHAR bFirstInterface; 108 | UCHAR bInterfaceCount; 109 | UCHAR bFunctionClass; 110 | UCHAR bFunctionSubClass; 111 | UCHAR bFunctionProtocol; 112 | UCHAR iFunction; 113 | 114 | } USB_INTERFACE_ASSOCIATION_DESCRIPTOR, *PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR; 115 | 116 | 117 | #if _MSC_VER >= 1200 118 | #pragma warning(pop) 119 | #endif 120 | 121 | 122 | 123 | #include 124 | 125 | #endif // __USB200_H__ 126 | 127 | -------------------------------------------------------------------------------- /Externals/winusb/winusb.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2002 Microsoft Corporation 4 | 5 | Module Name: 6 | 7 | wusb.h 8 | 9 | Abstract: 10 | 11 | Public interface to winusb.dll 12 | 13 | Environment: 14 | 15 | Kernel Mode Only 16 | 17 | Notes: 18 | 19 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 20 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 22 | PURPOSE. 23 | 24 | Copyright (c) 2001 Microsoft Corporation. All Rights Reserved. 25 | 26 | 27 | Revision History: 28 | 29 | 11/19/2002 : created 30 | 31 | Authors: 32 | 33 | --*/ 34 | 35 | #ifndef __WUSB_H__ 36 | #define __WUSB_H__ 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | #if(NTDDI_VERSION >= NTDDI_WINXP) 43 | 44 | #include 45 | 46 | 47 | typedef PVOID WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; 48 | 49 | 50 | #pragma pack(1) 51 | 52 | typedef struct _WINUSB_SETUP_PACKET { 53 | UCHAR RequestType; 54 | UCHAR Request; 55 | USHORT Value; 56 | USHORT Index; 57 | USHORT Length; 58 | } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; 59 | 60 | #pragma pack() 61 | 62 | 63 | 64 | BOOL __stdcall 65 | WinUsb_Initialize( 66 | __in HANDLE DeviceHandle, 67 | __out PWINUSB_INTERFACE_HANDLE InterfaceHandle 68 | ); 69 | 70 | 71 | BOOL __stdcall 72 | WinUsb_Free( 73 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle 74 | ); 75 | 76 | 77 | BOOL __stdcall 78 | WinUsb_GetAssociatedInterface( 79 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 80 | __in UCHAR AssociatedInterfaceIndex, 81 | __out PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle 82 | ); 83 | 84 | 85 | 86 | BOOL __stdcall 87 | WinUsb_GetDescriptor( 88 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 89 | __in UCHAR DescriptorType, 90 | __in UCHAR Index, 91 | __in USHORT LanguageID, 92 | __out_bcount_part_opt(BufferLength, *LengthTransferred) PUCHAR Buffer, 93 | __in ULONG BufferLength, 94 | __out PULONG LengthTransferred 95 | ); 96 | 97 | BOOL __stdcall 98 | WinUsb_QueryInterfaceSettings( 99 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 100 | __in UCHAR AlternateInterfaceNumber, 101 | __out PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor 102 | ); 103 | 104 | BOOL __stdcall 105 | WinUsb_QueryDeviceInformation( 106 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 107 | __in ULONG InformationType, 108 | __inout PULONG BufferLength, 109 | __out_bcount(*BufferLength) PVOID Buffer 110 | ); 111 | 112 | BOOL __stdcall 113 | WinUsb_SetCurrentAlternateSetting( 114 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 115 | __in UCHAR SettingNumber 116 | ); 117 | 118 | BOOL __stdcall 119 | WinUsb_GetCurrentAlternateSetting( 120 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 121 | __out PUCHAR SettingNumber 122 | ); 123 | 124 | 125 | BOOL __stdcall 126 | WinUsb_QueryPipe( 127 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 128 | __in UCHAR AlternateInterfaceNumber, 129 | __in UCHAR PipeIndex, 130 | __out PWINUSB_PIPE_INFORMATION PipeInformation 131 | ); 132 | 133 | 134 | BOOL __stdcall 135 | WinUsb_SetPipePolicy( 136 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 137 | __in UCHAR PipeID, 138 | __in ULONG PolicyType, 139 | __in ULONG ValueLength, 140 | __in_bcount(ValueLength) PVOID Value 141 | ); 142 | 143 | BOOL __stdcall 144 | WinUsb_GetPipePolicy( 145 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 146 | __in UCHAR PipeID, 147 | __in ULONG PolicyType, 148 | __inout PULONG ValueLength, 149 | __out_bcount(*ValueLength) PVOID Value 150 | ); 151 | 152 | BOOL __stdcall 153 | WinUsb_ReadPipe( 154 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 155 | __in UCHAR PipeID, 156 | __out_bcount_part_opt(BufferLength,*LengthTransferred) PUCHAR Buffer, 157 | __in ULONG BufferLength, 158 | __out_opt PULONG LengthTransferred, 159 | __in_opt LPOVERLAPPED Overlapped 160 | ); 161 | 162 | BOOL __stdcall 163 | WinUsb_WritePipe( 164 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 165 | __in UCHAR PipeID, 166 | __in_bcount(BufferLength) PUCHAR Buffer, 167 | __in ULONG BufferLength, 168 | __out_opt PULONG LengthTransferred, 169 | __in_opt LPOVERLAPPED Overlapped 170 | ); 171 | 172 | BOOL __stdcall 173 | WinUsb_ControlTransfer( 174 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 175 | __in WINUSB_SETUP_PACKET SetupPacket, 176 | __out_bcount_part_opt(BufferLength, *LengthTransferred) PUCHAR Buffer, 177 | __in ULONG BufferLength, 178 | __out_opt PULONG LengthTransferred, 179 | __in_opt LPOVERLAPPED Overlapped 180 | ); 181 | 182 | BOOL __stdcall 183 | WinUsb_ResetPipe( 184 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 185 | __in UCHAR PipeID 186 | ); 187 | 188 | BOOL __stdcall 189 | WinUsb_AbortPipe( 190 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 191 | __in UCHAR PipeID 192 | ); 193 | 194 | BOOL __stdcall 195 | WinUsb_FlushPipe( 196 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 197 | __in UCHAR PipeID 198 | ); 199 | 200 | BOOL __stdcall 201 | WinUsb_SetPowerPolicy( 202 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 203 | __in ULONG PolicyType, 204 | __in ULONG ValueLength, 205 | __in_bcount(ValueLength) PVOID Value 206 | ); 207 | 208 | BOOL __stdcall 209 | WinUsb_GetPowerPolicy( 210 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 211 | __in ULONG PolicyType, 212 | __inout PULONG ValueLength, 213 | __out_bcount(*ValueLength) PVOID Value 214 | ); 215 | 216 | BOOL __stdcall 217 | WinUsb_GetOverlappedResult( 218 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 219 | __in LPOVERLAPPED lpOverlapped, 220 | __out LPDWORD lpNumberOfBytesTransferred, 221 | __in BOOL bWait 222 | ); 223 | 224 | 225 | PUSB_INTERFACE_DESCRIPTOR __stdcall 226 | WinUsb_ParseConfigurationDescriptor( 227 | __in PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, 228 | __in PVOID StartPosition, 229 | __in LONG InterfaceNumber, 230 | __in LONG AlternateSetting, 231 | __in LONG InterfaceClass, 232 | __in LONG InterfaceSubClass, 233 | __in LONG InterfaceProtocol 234 | ); 235 | 236 | PUSB_COMMON_DESCRIPTOR __stdcall 237 | WinUsb_ParseDescriptors( 238 | __in_bcount(TotalLength) PVOID DescriptorBuffer, 239 | __in ULONG TotalLength, 240 | __in PVOID StartPosition, 241 | __in LONG DescriptorType 242 | ); 243 | 244 | 245 | #endif // (NTDDI_VERSION >= NTDDI_WINXP) 246 | 247 | #ifdef __cplusplus 248 | } 249 | #endif 250 | 251 | 252 | #endif //__WUSB_H__ 253 | 254 | -------------------------------------------------------------------------------- /Externals/winusb/winusb.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Externals/winusb/winusb.lib -------------------------------------------------------------------------------- /Externals/winusb/winusbio.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | 3 | Copyright (c) 2002 Microsoft Corporation 4 | 5 | Module Name: 6 | 7 | wusbio.h 8 | 9 | Abstract: 10 | 11 | Public header for WINUSB 12 | 13 | Environment: 14 | 15 | User and Kernel Mode 16 | 17 | Notes: 18 | 19 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 20 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 22 | PURPOSE. 23 | 24 | Copyright (c) 2001 Microsoft Corporation. All Rights Reserved. 25 | 26 | 27 | Revision History: 28 | 29 | 11/12/2002 : created 30 | 31 | 32 | ****************************************************************************/ 33 | 34 | #ifndef __WUSBIO_H__ 35 | #define __WUSBIO_H__ 36 | 37 | #if(NTDDI_VERSION >= NTDDI_WINXP) 38 | 39 | #include 40 | 41 | // Pipe policy types 42 | #define SHORT_PACKET_TERMINATE 0x01 43 | #define AUTO_CLEAR_STALL 0x02 44 | #define PIPE_TRANSFER_TIMEOUT 0x03 45 | #define IGNORE_SHORT_PACKETS 0x04 46 | #define ALLOW_PARTIAL_READS 0x05 47 | #define AUTO_FLUSH 0x06 48 | #define RAW_IO 0x07 49 | #define MAXIMUM_TRANSFER_SIZE 0x08 50 | #define RESET_PIPE_ON_RESUME 0x09 51 | 52 | // Power policy types 53 | // 54 | // Add 0x80 for Power policy types in order to prevent overlap with 55 | // Pipe policy types to prevent "accidentally" setting the wrong value for the 56 | // wrong type. 57 | // 58 | #define AUTO_SUSPEND 0x81 59 | #define SUSPEND_DELAY 0x83 60 | 61 | // Device Information types 62 | #define DEVICE_SPEED 0x01 63 | 64 | // Device Speeds 65 | #define LowSpeed 0x01 66 | #define FullSpeed 0x02 67 | #define HighSpeed 0x03 68 | 69 | // {DA812BFF-12C3-46a2-8E2B-DBD3B7834C43} 70 | #include 71 | DEFINE_GUID(WinUSB_TestGuid, 0xda812bff, 0x12c3, 0x46a2, 0x8e, 0x2b, 0xdb, 0xd3, 0xb7, 0x83, 0x4c, 0x43); 72 | 73 | 74 | typedef struct _WINUSB_PIPE_INFORMATION { 75 | USBD_PIPE_TYPE PipeType; 76 | UCHAR PipeId; 77 | USHORT MaximumPacketSize; 78 | UCHAR Interval; 79 | } WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION; 80 | 81 | #endif // (NTDDI_VERSION >= NTDDI_WINXP) 82 | 83 | #endif // __WUSBIO_H__ 84 | 85 | 86 | -------------------------------------------------------------------------------- /Main/Main.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | --godmode 6 | WindowsLocalDebugger 7 | --godmode 8 | WindowsLocalDebugger 9 | --godmode 10 | WindowsLocalDebugger 11 | 12 | -------------------------------------------------------------------------------- /Main/res/appicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/appicon.ico -------------------------------------------------------------------------------- /Main/res/fileManager.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/fileManager.bmp -------------------------------------------------------------------------------- /Main/res/hexaEditor.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/hexaEditor.bmp -------------------------------------------------------------------------------- /Main/res/image.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/image.bmp -------------------------------------------------------------------------------- /Main/res/logo2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/logo2.psd -------------------------------------------------------------------------------- /Main/res/mainFrame.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/mainFrame.bmp -------------------------------------------------------------------------------- /Main/res/misc.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/misc.bmp -------------------------------------------------------------------------------- /Main/res/resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/resource.rc -------------------------------------------------------------------------------- /Main/res/spectrumTape.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/spectrumTape.bmp -------------------------------------------------------------------------------- /Main/res/trackMap.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/trackMap.bmp -------------------------------------------------------------------------------- /Main/res/webPage.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/res/webPage.bmp -------------------------------------------------------------------------------- /Main/src/BSDOS.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/BSDOS.h -------------------------------------------------------------------------------- /Main/src/BackgroundAction.h: -------------------------------------------------------------------------------- 1 | #ifndef BACKGROUNDACTION_H 2 | #define BACKGROUNDACTION_H 3 | 4 | typedef const class CBackgroundAction{ 5 | protected: 6 | std::unique_ptr pWorker; 7 | LPCVOID fnParams; // Parameters which the Worker was launched with 8 | public: 9 | CBackgroundAction(); 10 | CBackgroundAction(AFX_THREADPROC fnAction,LPCVOID actionParams,int actionThreadPriority); 11 | virtual ~CBackgroundAction(); // virtual in order for the keyword "this" to work in AfxBeginThread when constructing a descendant 12 | 13 | inline LPCVOID GetParams() const{ return fnParams; } 14 | void Resume() const; 15 | void Suspend() const; 16 | void BeginAnother(AFX_THREADPROC fnAction,LPCVOID actionParams,int actionThreadPriority); 17 | operator HANDLE() const; 18 | } *PCBackgroundAction; 19 | 20 | 21 | 22 | typedef class CActionProgress{ 23 | protected: 24 | const CActionProgress *parent; 25 | const int parentProgressBegin, parentProgressInc; // the beginning and increment in total progress (see BeginSubtask method) 26 | int targetProgress; // call SetProgressTarget or ctor 27 | mutable int currProgress; 28 | 29 | CActionProgress(const CActionProgress *parent,const volatile bool &cancelled,int parentProgressBegin,int parentProgressInc); 30 | CActionProgress(const CActionProgress &r); // can't copy! 31 | public: 32 | static CActionProgress None; 33 | 34 | const volatile bool &Cancelled; 35 | 36 | CActionProgress(const volatile bool &cancelled); 37 | CActionProgress(CActionProgress &&r); 38 | ~CActionProgress(); 39 | 40 | virtual void SetProgressTarget(int targetProgress); 41 | virtual void UpdateProgress(int newProgress,TBPFLAG status=TBPFLAG::TBPF_NORMAL) const; 42 | void IncrementProgress(int increment=1) const; 43 | CActionProgress CreateSubactionProgress(int thisProgressIncrement,int subactionProgressTarget=INT_MAX) const; 44 | } *PActionProgress; // call UpdateProgress method with progress from <0;ProgressTarget) 45 | 46 | 47 | 48 | class CActionProgressBar:public CActionProgress{ 49 | protected: 50 | bool IsVisibleProgress(int newProgress) const; 51 | public: 52 | HWND hProgressBar; 53 | 54 | CActionProgressBar(const volatile bool &cancelled); 55 | 56 | void SetProgressTarget(int targetProgress) override; 57 | void SetProgressTargetInfinity(); 58 | void UpdateProgress(int newProgress,TBPFLAG status=TBPFLAG::TBPF_NORMAL) const override; 59 | }; 60 | 61 | 62 | 63 | typedef class CBackgroundActionCancelable:public CBackgroundAction,public CActionProgressBar,public Utils::CRideDialog{ 64 | protected: 65 | const int callerThreadPriorityOrg; 66 | volatile bool bCancelled; 67 | mutable volatile bool bTargetStateReached; 68 | CComPtr pActionTaskbarList; 69 | Utils::CRideTime startTime; 70 | Utils::CRideTime duration; 71 | 72 | CBackgroundActionCancelable(UINT dlgResId); 73 | 74 | void ChangeWorkerPriority(int newPriority); 75 | BOOL OnInitDialog() override; 76 | LRESULT WindowProc(UINT msg,WPARAM wParam,LPARAM lParam) override; 77 | public: 78 | static const CBackgroundActionCancelable *pSingleInstance; 79 | 80 | static void SignalPausedProgress(HWND hFromChild); 81 | 82 | CBackgroundActionCancelable(AFX_THREADPROC fnAction,LPCVOID actionParams,int actionThreadPriority); 83 | ~CBackgroundActionCancelable(); 84 | 85 | TStdWinError Perform(bool suspendAllViews=false); 86 | void SetProgressTarget(int targetProgress) override; 87 | void UpdateProgress(int newProgress,TBPFLAG status=TBPFLAG::TBPF_NORMAL) const override; 88 | void UpdateProgressFinished() const; 89 | TStdWinError TerminateWithSuccess(); 90 | TStdWinError TerminateWithError(TStdWinError error); 91 | TStdWinError TerminateWithLastError(); 92 | inline const Utils::CRideTime &GetDurationTime() const{ return duration; } 93 | } *PBackgroundActionCancelable; 94 | 95 | 96 | class CBackgroundMultiActionCancelable sealed:public CBackgroundActionCancelable{ 97 | int actionThreadPriority; 98 | char nActions,iCurrAction; 99 | struct{ 100 | AFX_THREADPROC fnAction; 101 | LPCVOID fnParams; 102 | LPCTSTR fnName; 103 | } actions[16]; 104 | CComPtr pMultiActionTaskbarList; 105 | struct{ 106 | int glyphX; 107 | int charHeight; 108 | int progressHeight; 109 | CRect rcActions; 110 | } painting; 111 | 112 | void __drawAction__(HDC dc,WCHAR wingdingsGlyph,LPCTSTR name,RECT &inOutRc) const; 113 | BOOL OnInitDialog() override; 114 | LRESULT WindowProc(UINT msg,WPARAM wParam,LPARAM lParam) override; 115 | public: 116 | CBackgroundMultiActionCancelable(int actionThreadPriority); 117 | ~CBackgroundMultiActionCancelable(); 118 | 119 | void AddAction(AFX_THREADPROC fnAction,LPCVOID actionParams,LPCTSTR name); 120 | void UpdateProgress(int newProgress,TBPFLAG status) const override; 121 | inline char GetCurrentAction() const{ return iCurrAction; } 122 | inline AFX_THREADPROC GetCurrentFunction() const{ return actions[iCurrAction].fnAction; } 123 | }; 124 | 125 | #endif // BACKGROUNDACTION_H -------------------------------------------------------------------------------- /Main/src/CapsBase_Mining.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/CapsBase_Mining.cpp -------------------------------------------------------------------------------- /Main/src/CtRaw.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CapsBase.h" 3 | #include "CtRaw.h" 4 | 5 | static LPCTSTR Recognize(PTCHAR){ 6 | static constexpr TCHAR SingleDeviceName[]=_T("CT Raw\0"); 7 | return SingleDeviceName; 8 | } 9 | static PImage Instantiate(LPCTSTR){ 10 | return new CCtRaw; 11 | } 12 | const CImage::TProperties CCtRaw::Properties={ 13 | MAKE_IMAGE_ID('C','A','P','S','_','R','A','W'), // a unique identifier 14 | Recognize, // list of recognized device names 15 | Instantiate, // instantiation function 16 | _T("*.raw"), // filter 17 | Medium::FLOPPY_ANY, // supported Media 18 | Codec::FLOPPY_ANY, // supported Codecs 19 | 1,2*6144, // Sector supported min and max length 20 | true // is read-only; modifications not possible at the moment 21 | }; 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | #define INI_CTRAW _T("CtRaw") 30 | 31 | CCtRaw::CCtRaw() 32 | // ctor 33 | // - base 34 | : CCapsBase( &Properties, '\0', true, INI_CTRAW ) { // '\0' = not a real drive 35 | } 36 | -------------------------------------------------------------------------------- /Main/src/CtRaw.h: -------------------------------------------------------------------------------- 1 | #ifndef CTRAW_H 2 | #define CTRAW_H 3 | 4 | class CCtRaw sealed:public CCapsBase{ 5 | public: 6 | static const TProperties Properties; 7 | 8 | CCtRaw(); 9 | }; 10 | 11 | #endif // CTRAW_H 12 | -------------------------------------------------------------------------------- /Main/src/Debug.h: -------------------------------------------------------------------------------- 1 | #ifndef RIDEDEBUG_H 2 | #define RIDEDEBUG_H 3 | 4 | //#define LOGGING_ENABLED // uncomment to enable logging, otherwise logging and its classes unavailable 5 | 6 | namespace Debug{ 7 | 8 | #ifdef LOGGING_ENABLED 9 | 10 | class CLogFile sealed:public CFile{ 11 | const bool permanentlyOpen; 12 | TCHAR filename[MAX_PATH]; 13 | BYTE nIndent; 14 | public: 15 | static CLogFile Default; 16 | 17 | CMapStringToPtr actionMinTimes,actionMaxTimes; // minimum and maximum times that each of Actions took (in milliseconds) 18 | 19 | class CAction sealed{ 20 | CLogFile &logFile; 21 | const LPCTSTR name; 22 | const Utils::CLocalTime start; 23 | public: 24 | CAction(LPCTSTR name,CLogFile &rLogFile=Default); 25 | ~CAction(); 26 | }; 27 | 28 | CLogFile(LPCTSTR logDescription,bool permanentlyOpen); 29 | ~CLogFile(); 30 | 31 | CLogFile &operator<<(TCHAR c); 32 | CLogFile &operator<<(LPCTSTR text); 33 | CLogFile &operator<<(DWORD dw); 34 | CLogFile &operator<<(const Utils::CLocalTime &rlt); 35 | CLogFile &operator<<(const TSectorId &rsi); 36 | CLogFile &operator<<(const TPhysicalAddress &rchs); 37 | 38 | LPCTSTR LogMessage(LPCTSTR text); 39 | TStdWinError LogError(TStdWinError err); 40 | bool LogBool(bool b); 41 | PSectorData LogSectorDataPointer(PSectorData pSectorData); 42 | DWORD LogDialogResult(DWORD result); 43 | }; 44 | 45 | #define LOG_ACTION(name)\ 46 | const Debug::CLogFile::CAction a(name) 47 | 48 | #define LOG_MESSAGE(text)\ 49 | Debug::CLogFile::Default.LogMessage(text) 50 | 51 | #define LOG_ERROR(error)\ 52 | Debug::CLogFile::Default.LogError(error) 53 | 54 | #define LOG_BOOL(boolValue)\ 55 | Debug::CLogFile::Default.LogBool(boolValue) 56 | 57 | #define LOG_PSECTORDATA(pSectorData)\ 58 | Debug::CLogFile::Default.LogSectorDataPointer(pSectorData) 59 | 60 | #define LOG_CYLINDER_ACTION(cyl,name)\ 61 | TCHAR __cylinderActionName[200];\ 62 | ::wsprintf(__cylinderActionName,_T("Cyl %d %s"),cyl,name);\ 63 | LOG_ACTION(__cylinderActionName) 64 | 65 | #define LOG_TRACK_ACTION(cyl,head,name)\ 66 | TCHAR __trackActionName[200];\ 67 | ::wsprintf(__trackActionName,_T("Track [Cyl=%d,Head=%d] %s"),cyl,head,name);\ 68 | LOG_ACTION(__trackActionName) 69 | 70 | #define LOG_SECTOR_ACTION(pSectorId,name)\ 71 | TCHAR __sectorActionName[200];\ 72 | ::wsprintf(__sectorActionName,_T("Sector %s %s"),(LPCTSTR)(pSectorId)->ToString(),name);\ 73 | LOG_ACTION(__sectorActionName) 74 | 75 | #define LOG_DIALOG_DISPLAY(name)\ 76 | LOG_ACTION(name) 77 | 78 | #define LOG_DIALOG_RESULT(result)\ 79 | Debug::CLogFile::Default.LogDialogResult(result) 80 | 81 | #define LOG_FILE_ACTION(dos,file,name)\ 82 | TCHAR __fileActionName[MAX_PATH+200];\ 83 | ::wsprintf(__fileActionName,_T("File \"%s\" %s"),(LPCTSTR)dos->GetFilePresentationNameAndExt(file),name);\ 84 | LOG_ACTION(__fileActionName) 85 | 86 | #else 87 | #define LOG_ACTION(name) 88 | 89 | #define LOG_MESSAGE(text)\ 90 | text 91 | 92 | #define LOG_ERROR(error)\ 93 | error 94 | 95 | #define LOG_BOOL(boolValue)\ 96 | boolValue 97 | 98 | #define LOG_PSECTORDATA(pSectorData)\ 99 | pSectorData 100 | 101 | #define LOG_CYLINDER_ACTION(cyl,name) 102 | 103 | #define LOG_TRACK_ACTION(cyl,head,name) 104 | 105 | #define LOG_SECTOR_ACTION(pSectorId,name) 106 | 107 | #define LOG_DIALOG_DISPLAY(name) 108 | 109 | #define LOG_DIALOG_RESULT(result)\ 110 | result 111 | 112 | #define LOG_FILE_ACTION(dos,file,name) 113 | 114 | #endif 115 | 116 | } 117 | 118 | #endif // RIDEDEBUG_H -------------------------------------------------------------------------------- /Main/src/DialogEmptySpaceFilling.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | CFillEmptySpaceDialog::CFillEmptySpaceDialog(const CDos *dos) 4 | // ctor 5 | // - base 6 | : Utils::CRideDialog(IDR_DOS_FILL_EMPTY_SPACE) 7 | // - initialization 8 | , dos(dos) 9 | , dosProps(dos->properties) 10 | , sectorFillerByte(dosProps->sectorFillerByte) , directoryFillerByte(dosProps->directoryFillerByte) 11 | , nOptionsChecked(0) 12 | , fillEmptySectors(false) 13 | , fillFileEndings(false) , fillSubdirectoryFileEndings(false) 14 | , fillEmptyDirectoryEntries(false) , fillEmptySubdirectoryEntries(false) { 15 | } 16 | 17 | BEGIN_MESSAGE_MAP(CFillEmptySpaceDialog,CDialog) 18 | ON_COMMAND_RANGE(ID_FILE,ID_DIRECTORY,__enableOkButton__) 19 | ON_BN_CLICKED(ID_DEFAULT1,__setDefaultFillerByteForGeneralSectors__) 20 | ON_BN_CLICKED(ID_DEFAULT2,__setDefaultFillerByteForDirectorySectors__) 21 | END_MESSAGE_MAP() 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | void CFillEmptySpaceDialog::DoDataExchange(CDataExchange *pDX){ 33 | // exchange of data from and to controls 34 | DDX_Check( pDX, ID_SECTOR, fillEmptySectors ); 35 | DDX_Check( pDX, ID_FILE, fillFileEndings ); 36 | DDX_Check( pDX, ID_RECURRENCY, fillSubdirectoryFileEndings ); 37 | DDX_Check( pDX, ID_DIRECTORY, fillEmptyDirectoryEntries ); 38 | DDX_Check( pDX, ID_SUBDIRECTORY,fillEmptySubdirectoryEntries ); 39 | DDX_Text( pDX, ID_NUMBER, sectorFillerByte ); 40 | DDX_Text( pDX, ID_NUMBER2, directoryFillerByte ); 41 | } 42 | 43 | afx_msg void CFillEmptySpaceDialog::__enableOkButton__(UINT id){ 44 | // projecting feasibility into UI 45 | nOptionsChecked+=-1+2*IsDlgItemChecked(id); 46 | EnableDlgItem( ID_RECURRENCY, IsDlgItemChecked(ID_FILE) && dos->pFileManager->pDirectoryStructureManagement!=nullptr ); 47 | EnableDlgItem( ID_SUBDIRECTORY, IsDlgItemChecked(ID_DIRECTORY) && dos->pFileManager->pDirectoryStructureManagement!=nullptr ); 48 | EnableDlgItem( IDOK, nOptionsChecked>0 ); 49 | } 50 | 51 | afx_msg void CFillEmptySpaceDialog::__setDefaultFillerByteForGeneralSectors__(){ 52 | // adopts default SectorFillerByte from DOS properties 53 | SetDlgItemInt( ID_NUMBER, dosProps->sectorFillerByte, FALSE ); 54 | } 55 | afx_msg void CFillEmptySpaceDialog::__setDefaultFillerByteForDirectorySectors__(){ 56 | // adopts default DirectoryFillerByte from DOS properties 57 | SetDlgItemInt( ID_NUMBER2, dosProps->directoryFillerByte, FALSE ); 58 | } 59 | -------------------------------------------------------------------------------- /Main/src/DialogEmptySpaceFilling.h: -------------------------------------------------------------------------------- 1 | #ifndef FILLEMPTYSPACEDIALOG_H 2 | #define FILLEMPTYSPACEDIALOG_H 3 | 4 | class CFillEmptySpaceDialog sealed:public Utils::CRideDialog{ 5 | DECLARE_MESSAGE_MAP() 6 | private: 7 | const CDos *const dos; 8 | const CDos::PCProperties dosProps; 9 | BYTE nOptionsChecked; 10 | 11 | void DoDataExchange(CDataExchange *pDX) override; 12 | afx_msg void __enableOkButton__(UINT id); 13 | afx_msg void __setDefaultFillerByteForGeneralSectors__(); 14 | afx_msg void __setDefaultFillerByteForDirectorySectors__(); 15 | public: 16 | BYTE sectorFillerByte,directoryFillerByte; 17 | bool fillEmptySectors; 18 | bool fillFileEndings, fillSubdirectoryFileEndings; 19 | bool fillEmptyDirectoryEntries, fillEmptySubdirectoryEntries; 20 | 21 | CFillEmptySpaceDialog(const CDos *dos); 22 | }; 23 | 24 | #endif // FILLEMPTYSPACEDIALOG_H 25 | -------------------------------------------------------------------------------- /Main/src/DialogFormatting.h: -------------------------------------------------------------------------------- 1 | #ifndef FORMATDIALOG_H 2 | #define FORMATDIALOG_H 3 | 4 | #define WARNING_MSG_CONSISTENCY_AT_STAKE _T("Consistency at stake!") 5 | 6 | class CFormatDialog sealed:public Utils::CRideDialog{ 7 | DECLARE_MESSAGE_MAP() 8 | public: 9 | #pragma pack(1) 10 | typedef const struct TParameters sealed{ 11 | TCylinder cylinder0; 12 | TFormat format; 13 | BYTE interleaving; 14 | BYTE skew; 15 | BYTE gap3; 16 | BYTE nAllocationTables; 17 | WORD nRootDirectoryEntries; 18 | } *PCParameters; 19 | #pragma pack(1) 20 | typedef const struct TStdFormat sealed{ 21 | LPCTSTR name; 22 | TParameters params; 23 | } *PCStdFormat; 24 | private: 25 | void PreInitDialog() override; 26 | void DoDataExchange(CDataExchange *pDX) override; 27 | BOOL OnNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult) override; 28 | afx_msg void OnPaint(); 29 | afx_msg void __onMediumOrEncodingChanged__(); 30 | afx_msg void __onFormatChanged__(); 31 | afx_msg void __recognizeStandardFormat__(); 32 | afx_msg void __recognizeStandardFormatAndRepaint__(); 33 | afx_msg void __toggleReportingOnFormatting__(); 34 | public: 35 | const PDos dos; 36 | const PCStdFormat additionalFormats; 37 | const BYTE nAdditionalFormats; 38 | TParameters params; 39 | bool updateBoot, addTracksToFat, showReportOnFormatting; 40 | 41 | CFormatDialog(PDos _dos,PCStdFormat _additionalFormats,BYTE _nAdditionalFormats); 42 | }; 43 | 44 | #endif // FORMATDIALOG_H 45 | -------------------------------------------------------------------------------- /Main/src/DialogNewImage.h: -------------------------------------------------------------------------------- 1 | #ifndef NEWIMAGEDIALOG_H 2 | #define NEWIMAGEDIALOG_H 3 | 4 | class CNewImageDialog sealed:public Utils::CRideDialog{ 5 | void __refreshListOfContainers__(); 6 | BOOL OnInitDialog() override; 7 | BOOL OnCommand(WPARAM wParam,LPARAM lParam) override; 8 | BOOL OnNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult) override; 9 | void OnOK() override; 10 | public: 11 | CImage::TFnInstantiate fnImage; 12 | TCHAR deviceName[DEVICE_NAME_CHARS_MAX]; 13 | CDos::PCProperties dosProps; 14 | 15 | CNewImageDialog(); 16 | }; 17 | 18 | #endif // NEWIMAGEDIALOG_H 19 | 20 | -------------------------------------------------------------------------------- /Main/src/DialogRealDeviceSelection.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #define INI_SECTION _T("RealDevsDlg") 4 | 5 | CRealDeviceSelectionDialog::CRealDeviceSelectionDialog(CDos::PCProperties dosProps) 6 | // ctor 7 | : Utils::CRideDialog(IDR_DRIVE_ACCESS) 8 | , mru( CRecentFileList(1,INI_SECTION,_T("MruDev%d"),1) ) 9 | , deviceProps(nullptr) , dosProps(dosProps) { 10 | } 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | BOOL CRealDeviceSelectionDialog::OnInitDialog(){ 20 | // dialog initialization 21 | // - base 22 | __super::OnInitDialog(); 23 | // - positioning and scaling the Error box to match the Image list-box 24 | SetDlgItemPos( ID_ERROR, MapDlgItemClientRect(ID_IMAGE) ); 25 | // - populating the list with devices compatible with specified DOS 26 | refreshListOfDevices(); 27 | mru.ReadList(); 28 | if (const CImage::PCProperties mruDevProps=mru.GetMruDevice(0)){ 29 | // preselection of most recently used Device 30 | CListBox lb; 31 | lb.Attach( GetDlgItemHwnd(ID_IMAGE) ); 32 | for( TCHAR i=1,buf[DEVICE_NAME_CHARS_MAX]; im_hWnd); 68 | lb.ResetContent(); 69 | lb.ShowWindow(SW_SHOW), ShowDlgItem(ID_ERROR,false); 70 | lb.SetItemDataPtr( lb.AddString(_T("-- Select --")), (PVOID)&CUnknownDos::Properties ); 71 | lb.SetCurSel(0); 72 | const WORD dosStdSectorLength=dosProps->stdFormats->params.format.sectorLength; 73 | for( POSITION pos=CImage::Devices.GetHeadPosition(); pos; ){ 74 | const CImage::PCProperties devProps=CImage::Devices.GetNext(pos); 75 | if (!dosProps->IsKnown() // no preconditions on a Device 76 | || 77 | devProps->supportedMedia&dosProps->supportedMedia // DOS and Image support common Media 78 | && 79 | devProps->supportedCodecs&dosProps->supportedCodecs // DOS and Image support common Codecs 80 | && 81 | devProps->sectorLengthMin<=dosStdSectorLength && dosStdSectorLength<=devProps->sectorLengthMax 82 | ){ 83 | TCHAR deviceNames[4*DEVICE_NAME_CHARS_MAX+1]; // up to 4 Devices, "+1" = terminating null-character 84 | for( LPCTSTR p=devProps->fnRecognize(deviceNames); p&&*p; p+=::lstrlen(p)+1 ) 85 | lb.SetItemDataPtr( lb.AddString(p), (PVOID)devProps ); 86 | } 87 | } 88 | const int nCompatibleDevices=lb.GetCount(); 89 | lb.Detach(); 90 | // - if some Devices compatible with specified DOS found, focusing on the list 91 | if (nCompatibleDevices>1) // 1 = the "-- Select--" item 92 | pDeviceListBox->SetFocus(); 93 | // - otherwise, displaying an error message 94 | else{ 95 | ShowDlgItem(ID_ERROR), pDeviceListBox->ShowWindow(SW_HIDE); 96 | TCHAR quotedDosName[50]; 97 | ::wsprintf( quotedDosName, _T("\"%s\""), dosProps->name ); 98 | SetDlgItemFormattedText( ID_ERROR, _T("No local physical device compatible with %s found. Maybe they are all being already used?"), dosProps->IsKnown()?quotedDosName:_T("any DOS") ); 99 | } 100 | } 101 | 102 | BOOL CRealDeviceSelectionDialog::OnCommand(WPARAM wParam,LPARAM lParam){ 103 | // command processing 104 | switch (wParam){ 105 | case MAKELONG(ID_IMAGE,LBN_DBLCLK): 106 | // Device selected by double-clicking on it 107 | if (IsDlgItemEnabled(IDOK)) 108 | SendMessage( WM_COMMAND, IDOK ); 109 | break; 110 | case MAKELONG(ID_IMAGE,LBN_SELCHANGE): 111 | // Device selection changed 112 | EnableDlgItem( IDOK, GetDlgListBoxSelectedIndex(ID_IMAGE)>0 ); 113 | return TRUE; 114 | } 115 | return __super::OnCommand(wParam,lParam); 116 | } 117 | 118 | BOOL CRealDeviceSelectionDialog::OnNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult){ 119 | // processes notification 120 | if (GetClickedHyperlinkId(lParam)){ 121 | refreshListOfDevices(); 122 | *pResult=0; 123 | return TRUE; 124 | } 125 | return __super::OnNotify(wParam,lParam,pResult); 126 | } 127 | -------------------------------------------------------------------------------- /Main/src/DialogRealDeviceSelection.h: -------------------------------------------------------------------------------- 1 | #ifndef REALDEVICESELECTIONDIALOG_H 2 | #define REALDEVICESELECTIONDIALOG_H 3 | 4 | class CRealDeviceSelectionDialog sealed:public Utils::CRideDialog{ 5 | const CDos::PCProperties dosProps; 6 | CRideApp::CRecentFileListEx mru; 7 | 8 | void refreshListOfDevices(); 9 | BOOL OnInitDialog() override; 10 | void OnOK() override; 11 | BOOL OnCommand(WPARAM wParam,LPARAM lParam) override; 12 | BOOL OnNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult) override; 13 | public: 14 | CImage::PCProperties deviceProps; 15 | TCHAR deviceName[DEVICE_NAME_CHARS_MAX]; 16 | 17 | CRealDeviceSelectionDialog(CDos::PCProperties dosProps); 18 | }; 19 | 20 | #endif // REALDEVICESELECTIONDIALOG_H 21 | -------------------------------------------------------------------------------- /Main/src/DialogUnformatting.h: -------------------------------------------------------------------------------- 1 | #ifndef UNFORMATDIALOG_H 2 | #define UNFORMATDIALOG_H 3 | 4 | #define STR_TRIM_TO_MIN_NUMBER_OF_CYLINDERS _T("Trim to minimum # of cylinders") 5 | 6 | class CUnformatDialog sealed:protected Utils::CRideDialog{ 7 | DECLARE_MESSAGE_MAP() 8 | public: 9 | typedef const struct TStdUnformat sealed{ 10 | LPCTSTR name; 11 | TCylinder cylA,cylZ; 12 | } *PCStdUnformat; 13 | private: 14 | const PCStdUnformat stdUnformats; 15 | const BYTE nStdUnformats; 16 | bool updateBoot, removeTracksFromFat; 17 | 18 | static UINT AFX_CDECL UnformatTracks_thread(PVOID pCancelableAction); 19 | static UINT AFX_CDECL UnregisterStdCylinders_thread(PVOID pCancelableAction); 20 | protected: 21 | void PreInitDialog() override; 22 | void DoDataExchange(CDataExchange *pDX) override; 23 | afx_msg void OnPaint(); 24 | afx_msg void __onUnformatChanged__(); 25 | afx_msg void __recognizeStandardUnformat__(); 26 | afx_msg void __recognizeStandardUnformatAndRepaint__(); 27 | afx_msg void __warnOnPossibleInconsistency__(); 28 | public: 29 | struct TParams{ 30 | const PDos dos; 31 | const PCHead specificHeadOnly; 32 | TCylinder cylA,cylZInclusive; 33 | 34 | TParams(PDos dos,PCHead specificHeadOnly); 35 | } params; 36 | 37 | CUnformatDialog(PDos dos,PCStdUnformat stdUnformats,BYTE nStdUnformats); 38 | 39 | TStdWinError ShowModalAndUnformatStdCylinders(); 40 | }; 41 | 42 | #endif // UNFORMATDIALOG_H 43 | -------------------------------------------------------------------------------- /Main/src/Diff.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | void CDiffBase::TScriptItem::ConvertToDual(){ 4 | // transforms in-place the Item to its dual counterpart 5 | std::swap( iPosA, op.iPosB ); 6 | switch (operation){ 7 | case INSERTION: 8 | operation=DELETION; 9 | break; 10 | default: 11 | ASSERT(FALSE); 12 | //fallthrough 13 | case DELETION: 14 | operation=INSERTION; 15 | break; 16 | } 17 | } 18 | 19 | 20 | 21 | 22 | int CDiffBase::MergeScriptItems(TScriptItem *buffer) const{ 23 | // merges script Operations which the descendant has split into multiple consecutive ScriptItems; returns the number of merged ScriptItems 24 | if (buffer==pEmptyScriptItem) 25 | return 0; 26 | TScriptItem *psiLast=buffer; 27 | for( PCScriptItem psiNext=buffer+1; psiNextoperation==psiLast->operation) 29 | switch (psiNext->operation){ 30 | case TScriptItem::INSERTION: 31 | // "theirs" contains some extra bits that "this" misses - must "insert" into "this" 32 | if (psiNext->iPosA==psiLast->iPosA && psiNext->ins.iPosB==psiLast->ins.iPosB+psiLast->ins.nItemsB){ 33 | psiLast->ins.nItemsB+=psiNext->ins.nItemsB; // merge 34 | continue; 35 | }else 36 | break; 37 | default: 38 | ASSERT(FALSE); 39 | //fallthrough 40 | case TScriptItem::DELETION: 41 | // "theirs" misses some bits that "this" contains - must "delete" from "this" 42 | if (psiNext->iPosA==psiLast->iPosA+psiLast->del.nItemsA){ 43 | psiLast->del.nItemsA+=psiNext->del.nItemsA; // merge 44 | continue; 45 | }else 46 | break; 47 | } 48 | *++psiLast=*psiNext; // can't be merged 49 | } 50 | return psiLast+1-buffer; 51 | } 52 | -------------------------------------------------------------------------------- /Main/src/DosUnknown.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MDOS2.h" // included to refer to one of its StandardFormats 3 | 4 | static PDos __instantiate__(PImage image,PCFormat pFormatBoot){ 5 | return new CUnknownDos(image,pFormatBoot); 6 | } 7 | static TStdWinError __recognize__(PImage image,PFormat pFormatBoot){ 8 | // returns the result of attempting to recognize Image by this DOS as follows: ERROR_SUCCESS = recognized, ERROR_CANCELLED = user cancelled the recognition sequence, any other error = not recognized 9 | *pFormatBoot=TFormat::Unknown; 10 | return ERROR_SUCCESS; 11 | } 12 | const CDos::TProperties CUnknownDos::Properties={ 13 | _T("Unknown"), // name 14 | MAKE_DOS_ID('U','n','k','n','o','w','n','!'), // unique identifier 15 | 0, // recognition priority 16 | 0, // the Cylinder where usually the Boot Sector (or its backup) is found 17 | __recognize__, // recognition function 18 | __instantiate__, // instantiation function 19 | Medium::UNKNOWN, // Unknown Medium 20 | nullptr, // the most common Image to contain data for this DOS (e.g. *.D80 Image for MDOS) 21 | 1, // number of std Formats 22 | CMDOS2::Properties.stdFormats, // std Formats ("some" Format in case of UnknownDos) 23 | Codec::ANY, // a set of Codecs this DOS supports 24 | 0,0, // range of supported number of Sectors 25 | 0, // minimal total number of Sectors required 26 | 0, // maximum number of Sector in one Cluster (must be power of 2) 27 | 0, // maximum size of a Cluster (in Bytes) 28 | 0,0, // range of supported number of allocation tables (FATs) 29 | 0,0, // range of supported number of root Directory entries 30 | 1, // lowest Sector number on each Track 31 | 0xe5,0, // regular Sector and Directory Sector filler Byte 32 | 0,0 // number of reserved Bytes at the beginning and end of each Sector 33 | }; 34 | 35 | CUnknownDos::CUnknownDos(PImage image,PCFormat pFormatBoot) 36 | // ctor 37 | // - base 38 | : CDos( image, pFormatBoot, TTrackScheme::BY_CYLINDERS, &Properties, nullptr, image->GetSideMap()?image->GetSideMap():StdSidesMap, IDR_DOS_UNKNOWN, nullptr, TGetFileSizeOptions::OfficialDataLength, TSectorStatus::UNKNOWN ) { 39 | } 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | void CUnknownDos::FlushToBootSector() const{ 51 | // flushes internal Format information to the actual Boot Sector's data 52 | //nop 53 | } 54 | 55 | 56 | 57 | 58 | 59 | bool CUnknownDos::GetSectorStatuses(TCylinder,THead,TSector nSectors,PCSectorId,PSectorStatus buffer) const{ 60 | // True <=> Statuses of all Sectors in the Track successfully retrieved and populated the Buffer, otherwise False 61 | while (nSectors--) *buffer++=TSectorStatus::UNKNOWN; // all Sector are Unknown by design 62 | return true; 63 | } 64 | bool CUnknownDos::ModifyStdSectorStatus(RCPhysicalAddress,TSectorStatus) const{ 65 | // True <=> the Status of the specified DOS-standard Sector successfully changed, otherwise False 66 | return false; //nop (doesn't have an allocation table) 67 | } 68 | bool CUnknownDos::GetFileFatPath(PCFile,CFatPath &) const{ 69 | // True <=> FatPath of given File (even an erroneous FatPath) successfully retrieved, otherwise False 70 | return false; //nop (doesn't have an allocation table) 71 | } 72 | bool CUnknownDos::ModifyFileFatPath(PFile,const CFatPath &) const{ 73 | // True <=> a error-free FatPath of given File successfully written, otherwise False 74 | return false; //nop (doesn't have an allocation table) 75 | } 76 | DWORD CUnknownDos::GetFreeSpaceInBytes(TStdWinError &rError) const{ 77 | // computes and returns the empty space on disk 78 | rError=ERROR_SUCCESS; 79 | return 0; 80 | } 81 | 82 | 83 | 84 | 85 | 86 | bool CUnknownDos::GetFileNameOrExt(PCFile,PPathString,PPathString) const{ 87 | // populates the Buffers with File's name and extension; caller guarantees that the Buffer sizes are at least MAX_PATH characters each 88 | return false; // name irrelevant 89 | } 90 | TStdWinError CUnknownDos::ChangeFileNameAndExt(PFile,RCPathString,RCPathString,PFile &){ 91 | // tries to change given File's name and extension; returns Windows standard i/o error 92 | return ERROR_FILE_INVALID; 93 | } 94 | DWORD CUnknownDos::GetFileSize(PCFile,PBYTE,PBYTE,TGetFileSizeOptions) const{ 95 | // determines and returns the size of specified File 96 | return 0; 97 | } 98 | DWORD CUnknownDos::GetAttributes(PCFile) const{ 99 | // maps File's attributes to Windows attributes and returns the result 100 | return 0; // none but standard attributes 101 | } 102 | TStdWinError CUnknownDos::DeleteFile(PFile){ 103 | // deletes specified File; returns Windows standard i/o error 104 | return ERROR_NOT_SUPPORTED; 105 | } 106 | 107 | std::unique_ptr CUnknownDos::BeginDirectoryTraversal(PCFile) const{ 108 | // initiates exploration of specified Directory through a DOS-specific DirectoryTraversal 109 | return nullptr; 110 | } 111 | CDos::CPathString CUnknownDos::GetFileExportNameAndExt(PCFile,bool) const{ 112 | // returns File name concatenated with File extension for export of the File to another Windows application (e.g. Explorer) 113 | return CPathString::Empty; 114 | } 115 | TStdWinError CUnknownDos::ImportFile(CFile *fIn,DWORD fileSize,RCPathString nameAndExtension,DWORD winAttr,PFile &rFile){ 116 | // imports specified File (physical or virtual) into the Image; returns Windows standard i/o error 117 | return ERROR_NOT_SUPPORTED; 118 | } 119 | 120 | 121 | 122 | 123 | 124 | 125 | TStdWinError CUnknownDos::CreateUserInterface(HWND hTdi){ 126 | // creates DOS-specific Tabs in TDI; returns Windows standard i/o error 127 | if (const TStdWinError err=__super::CreateUserInterface(hTdi)) 128 | return err; 129 | CTdiCtrl::SwitchToTab( hTdi, &image->trackMap.tab ); 130 | return ERROR_SUCCESS; 131 | } 132 | CDos::TCmdResult CUnknownDos::ProcessCommand(WORD cmd){ 133 | // returns the Result of processing a DOS-related command 134 | if (cmd==ID_DOS){ 135 | Utils::Information(_T("You see this because:\n(a) the boot sector was not found on the disk, or\n(b) the boot sector was found but not recognized.\n\nIf you know for sure that the disk relates to one of implemented DOSes, you can try to open it using the \"Open as\" menu command.\n\nIf you ended up here after formatting a new disk, there have been problems formatting it - irregularities in the \"") TRACK_MAP_TAB_LABEL _T("\" tab help to reveal them.")); 136 | return TCmdResult::DONE; 137 | }else 138 | return TCmdResult::REFUSED; 139 | } 140 | 141 | void CUnknownDos::InitializeEmptyMedium(CFormatDialog::PCParameters,CActionProgress &){ 142 | // initializes a fresh formatted Medium (Boot, FAT, root dir, etc.) 143 | } 144 | -------------------------------------------------------------------------------- /Main/src/DosUnknown.h: -------------------------------------------------------------------------------- 1 | #ifndef DOS_UNKNOWN_H 2 | #define DOS_UNKNOWN_H 3 | 4 | class CUnknownDos sealed:public CDos{ 5 | public: 6 | static const TProperties Properties; 7 | 8 | CUnknownDos(PImage image,PCFormat pFormatBoot); 9 | 10 | // boot 11 | void FlushToBootSector() const override; // projects information stored in internal FormatBoot back to the Boot Sector (e.g. called automatically by BootView) 12 | // FAT 13 | bool GetSectorStatuses(TCylinder,THead,TSector nSectors,PCSectorId,PSectorStatus buffer) const override; 14 | bool ModifyStdSectorStatus(RCPhysicalAddress,TSectorStatus) const override; 15 | bool GetFileFatPath(PCFile,CFatPath &) const override; 16 | bool ModifyFileFatPath(PFile,const CFatPath &) const override; 17 | DWORD GetFreeSpaceInBytes(TStdWinError &rError) const override; 18 | // file system 19 | bool GetFileNameOrExt(PCFile file,PPathString,PPathString) const override; 20 | TStdWinError ChangeFileNameAndExt(PFile,RCPathString,RCPathString,PFile &) override; 21 | DWORD GetFileSize(PCFile,PBYTE,PBYTE,TGetFileSizeOptions) const override; 22 | DWORD GetAttributes(PCFile file) const override; 23 | TStdWinError DeleteFile(PFile) override; 24 | std::unique_ptr BeginDirectoryTraversal(PCFile directory) const override; 25 | CPathString GetFileExportNameAndExt(PCFile,bool) const override; 26 | TStdWinError ImportFile(CFile *fIn,DWORD fileSize,RCPathString nameAndExtension,DWORD winAttr,PFile &rFile) override; 27 | // other 28 | TStdWinError CreateUserInterface(HWND hTdi) override; 29 | TCmdResult ProcessCommand(WORD cmd) override; 30 | void InitializeEmptyMedium(CFormatDialog::PCParameters,CActionProgress &) override; 31 | }; 32 | 33 | #endif // DOS_UNKNOWN_H -------------------------------------------------------------------------------- /Main/src/Dos_FatPath.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | LPCTSTR CDos::CFatPath::GetErrorDesc(TError error){ 4 | // returns textual description of Error 5 | switch (error){ 6 | case OK : break; 7 | case SECTOR : return _T("Invalid or unreadable FAT sector."); 8 | case VALUE_CYCLE : return _T("Cyclic path in the FAT."); 9 | case VALUE_INVALID : return _T("Invalid value in the FAT."); 10 | case VALUE_BAD_SECTOR: return _T("Data sector marked as bad."); 11 | case LENGTH : return _T("Incorrect FAT path length."); 12 | case FILE : return _T("Invalid file descriptor."); 13 | default: 14 | ASSERT(FALSE); // unknown Error 15 | } 16 | return nullptr; 17 | } 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | CDos::CFatPath::CFatPath(DWORD nItemsMax) 27 | // ctor for Dummy object which has no Buffer and just counts the Items (allocation units) 28 | : buffer(0) 29 | , nItems(0) , pLastItem(nullptr) , error(TError::OK) { 30 | buffer.length=nItemsMax; 31 | } 32 | 33 | CDos::CFatPath::CFatPath(const CDos *dos,PCFile file) 34 | // ctor for exporting a File in Image 35 | : buffer( dos->formatBoot.clusterSize // "clusterSize+" = to round up to whole multiples of ClusterSize 36 | + 37 | dos->GetFileSizeOnDisk(file)/dos->formatBoot.sectorLength 38 | + 39 | 1 ) // "1" = for the case that caller wanted to extend the File content (e.g. before calling CDos::ShiftFileContent) 40 | , nItems(0) , pLastItem(buffer) , error(TError::OK) { 41 | if (!dos->GetFileFatPath(file,*this)) 42 | error=TError::FILE; 43 | } 44 | CDos::CFatPath::CFatPath(const CDos *dos,DWORD fileSize) 45 | // ctor for importing a File to Image 46 | : buffer( dos->formatBoot.clusterSize // "clusterSize+" = to round up to whole multiples of ClusterSize 47 | + 48 | fileSize/(dos->formatBoot.sectorLength-dos->properties->dataBeginOffsetInSector-dos->properties->dataEndOffsetInSector) ) 49 | , nItems(0) , pLastItem(buffer) , error(TError::OK) { 50 | } 51 | CDos::CFatPath::CFatPath(const CDos *dos,RCPhysicalAddress chs) 52 | // ctor for editing a Sector (e.g. Boot Sector) 53 | : buffer(1) 54 | , nItems(0) , pLastItem(buffer) , error(TError::OK) { 55 | const TItem p={ 0, chs }; 56 | AddItem(&p); 57 | } 58 | CDos::CFatPath::CFatPath(CFatPath &&r) 59 | // move ctor 60 | : nItems(r.nItems) , pLastItem(r.pLastItem) , error(r.error) { 61 | buffer.reset( r.buffer.release() ); 62 | buffer.length=r.buffer.length; 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | bool CDos::CFatPath::AddItem(PCItem pItem){ 75 | // True <=> FatPath extended with given Item is valid, otherwise False 76 | // - VALIDATION: FatPath must be acyclic (detected by wanting to exceed the expected number of Items) 77 | if (nItems==buffer.length){ error=VALUE_CYCLE; return false; } 78 | // - extending FatPath 79 | if (pLastItem!=nullptr) 80 | *pLastItem++=*pItem; 81 | nItems++; 82 | return true; // CDos-derivate performs additional validation 83 | } 84 | 85 | CDos::CFatPath::PCItem CDos::CFatPath::PopItem(){ 86 | // removes and returns the last Item; returns Null if no Items in the FatPath 87 | if (nItems>0){ 88 | nItems--; 89 | return --pLastItem; 90 | }else 91 | return nullptr; 92 | } 93 | 94 | LPCTSTR CDos::CFatPath::GetItems(PCItem &rBuffer,DWORD &rnItems) const{ 95 | // retrieves pointer to the first Item in the Buffer and their number; returns textual description of this FatPath's error (or Null if error-less) 96 | rBuffer=buffer, rnItems=GetNumberOfItems(); 97 | return GetErrorDesc(); 98 | } 99 | 100 | LPCTSTR CDos::CFatPath::GetItems(PItem &rBuffer,DWORD &rnItems) const{ 101 | // retrieves pointer to the first Item in the Buffer and their number; returns textual description of this FatPath's error (or Null if error-less) 102 | rBuffer=buffer, rnItems=GetNumberOfItems(); 103 | return GetErrorDesc(); 104 | } 105 | 106 | CDos::CFatPath::PItem CDos::CFatPath::GetItem(DWORD i) const{ 107 | // returns I-th Item or Null 108 | if (i>=nItems) // request out of bounds 109 | return nullptr; 110 | return buffer+i; 111 | } 112 | 113 | CDos::CFatPath::PItem CDos::CFatPath::GetHealthyItem(DWORD i) const{ 114 | // returns I-th Item or Null 115 | if (error) // FatPath erroneous 116 | return nullptr; 117 | return GetItem(i); 118 | } 119 | 120 | bool CDos::CFatPath::ContainsSector(RCPhysicalAddress chs) const{ 121 | // True <=> the FatPath has the specified Sector linked in, otherwise False 122 | for( PCItem p=buffer; pchs==chs) 124 | return true; 125 | if (!buffer) 126 | ASSERT(FALSE); // it's senseless to call this method for a dummy object! 127 | return false; 128 | } 129 | 130 | bool CDos::CFatPath::AreAllSectorsReadable(const CDos *dos) const{ 131 | // True <=> all Sectors refered in the FatPath are healthy, otherwise False 132 | PCItem p; DWORD n; 133 | if (GetItems(p,n)) // error 134 | return false; 135 | while (n--) 136 | if (!dos->image->GetHealthySectorData(p++->chs)) 137 | return false; 138 | return true; 139 | } 140 | 141 | bool CDos::CFatPath::MarkAllSectorsModified(PImage image) const{ 142 | // True <=> all Sectors refered in the FatPath are healthy, otherwise False 143 | PCItem p; DWORD n; 144 | if (GetItems(p,n)) // error 145 | return false; 146 | while (n--) 147 | image->MarkSectorAsDirty(p++->chs); 148 | return true; 149 | } 150 | 151 | DWORD CDos::CFatPath::GetPhysicalAddresses(TPhysicalAddress *pOutChs) const{ 152 | // returns the NumberOfItems of Items written to the output buffer; returns zero if the FatPath is erroneous 153 | if (error) 154 | return 0; 155 | for( DWORD i=0; idos 12 | 13 | CDos::CFilePreview *CDos::CHexaPreview::pSingleInstance; 14 | 15 | CDos::CHexaPreview::CHexaPreview(const CFileManagerView &fileManager) 16 | // ctor 17 | // - base 18 | : CFilePreview( &hexaEditor, LABEL, INI_PREVIEW, fileManager, HEXA_WIDTH, HEXA_HEIGHT, false, 0, &pSingleInstance ) 19 | // - initialization 20 | , hexaEditor(DOS,this) { 21 | pSingleInstance=this; 22 | // - creating the HexaEditor view 23 | hexaEditor.Create( nullptr, nullptr, AFX_WS_DEFAULT_VIEW&~WS_BORDER|WS_CLIPSIBLINGS, rectDefault, this, AFX_IDW_PANE_FIRST ); 24 | hexaEditor.SetEditable(!IMAGE->IsWriteProtected()); 25 | // - showing the first File 26 | __showNextFile__(); 27 | } 28 | 29 | CDos::CHexaPreview::~CHexaPreview(){ 30 | // dtor 31 | // - destroying the HexaEditor window 32 | hexaEditor.DestroyWindow(); 33 | pSingleInstance=nullptr; 34 | } 35 | 36 | 37 | 38 | void CDos::CHexaPreview::RefreshPreview(){ 39 | // refreshes the Preview (e.g. when switched to another File) 40 | if (const PCFile file=pdt->entry){ 41 | // . resetting the content of the HexaPreview 42 | CFileReaderWriter *const frw=new CFileReaderWriter(DOS,file); 43 | hexaEditor.Reset( frw, frw, DOS->GetFileOccupiedSize(file) ); 44 | frw->Release(); 45 | } 46 | //SetWindowPos( nullptr, 0,0, 0,0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_NOSENDCHANGING ); 47 | hexaEditor.SetFocus(); 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | CDos::CHexaPreview::CHexaEditorView::CHexaEditorView(PCDos dos,CHexaPreview *pHexaPreview) 57 | // ctor 58 | : CFileReaderWriter::CHexaEditor(pHexaPreview) { 59 | } 60 | 61 | LRESULT CDos::CHexaPreview::CHexaEditorView::WindowProc(UINT msg,WPARAM wParam,LPARAM lParam){ 62 | // window procedure 63 | switch (msg){ 64 | case WM_KEYDOWN: 65 | // char 66 | switch (wParam){ 67 | case 'W': 68 | // toggling the WriteProtection of Image 69 | if (::GetAsyncKeyState(VK_CONTROL)<0){ // if Ctrl+W pressed 70 | app.m_pMainWnd->SendMessage( WM_COMMAND, ID_IMAGE_PROTECT ); // toggling the WriteProtection 71 | SetEditable(!pSingleInstance->IMAGE->IsWriteProtected()); // setting the possibility edit in HexaEditor 72 | SetFocus(); // focusing the HexaEditor 73 | } 74 | break; 75 | case VK_ESCAPE: 76 | // closing the Preview's window 77 | pSingleInstance->DestroyWindow(); 78 | return 0; 79 | } 80 | break; 81 | } 82 | return __super::WindowProc(msg,wParam,lParam); 83 | } 84 | -------------------------------------------------------------------------------- /Main/src/Dsk5.h: -------------------------------------------------------------------------------- 1 | #ifndef DSK_H 2 | #define DSK_H 3 | 4 | #define DSK_REV5_TRACKS_MAX 204 5 | #define DSK_TRACKINFO_SECTORS_MAX 29 6 | 7 | class CDsk5 sealed:public CFloppyImage{ 8 | #pragma pack(1) 9 | typedef struct TSectorInfo sealed{ 10 | BYTE cylinderNumber; 11 | BYTE sideNumber; 12 | BYTE sectorNumber; 13 | BYTE sectorLengthCode; 14 | TFdcStatus fdcStatus; 15 | WORD rev5_sectorLength; 16 | 17 | bool operator==(const TSectorId &rSectorId) const; 18 | bool __hasValidSectorLengthCode__() const; 19 | inline bool HasGoodDataReady() const{ return fdcStatus.IsWithoutError(); } 20 | } *PSectorInfo; 21 | 22 | #pragma pack(1) 23 | typedef struct TTrackInfo sealed{ 24 | char header[12]; 25 | DWORD reserved1; 26 | BYTE cylinderNumber; 27 | BYTE headNumber; 28 | WORD reserved2; 29 | BYTE std_sectorMaxLengthCode; 30 | BYTE nSectors; 31 | BYTE gap3; 32 | BYTE fillerByte; 33 | TSectorInfo sectorInfo[DSK_TRACKINFO_SECTORS_MAX]; 34 | 35 | bool ReadAndValidate(CFile &f); 36 | } *PTrackInfo; 37 | 38 | struct TParams sealed{ 39 | bool rev5; 40 | bool preserveEmptyTracks; 41 | 42 | TParams(); 43 | } params; 44 | #pragma pack(1) 45 | struct TDiskInfo sealed{ 46 | char header[34]; 47 | char creator[14]; 48 | BYTE nCylinders; 49 | BYTE nHeads; 50 | WORD std_trackLength; 51 | BYTE rev5_trackOffsets256[DSK_REV5_TRACKS_MAX]; 52 | 53 | TDiskInfo(const TParams &rParams); 54 | } diskInfo; 55 | PTrackInfo tracks[DSK_REV5_TRACKS_MAX]; // each TrackInfo followed by data of its Sectors 56 | #ifdef _DEBUG 57 | struct TSectorDebug sealed{ 58 | bool modified; 59 | TCrc16 crc16; 60 | } *tracksDebug[DSK_REV5_TRACKS_MAX]; // debug information on Sectors as they appear on the Track 61 | #endif 62 | 63 | static PImage Instantiate(LPCTSTR); 64 | 65 | CDsk5(PCProperties properties); 66 | 67 | PTrackInfo __findTrack__(TCylinder cyl,THead head) const; 68 | WORD __getSectorLength__(const TSectorInfo *si) const; 69 | WORD __getTrackLength256__(const TTrackInfo *ti) const; 70 | void __freeAllTracks__(); 71 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 72 | public: 73 | static const TProperties Properties; 74 | 75 | ~CDsk5(); 76 | 77 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 78 | TCylinder GetCylinderCount() const override; 79 | THead GetHeadCount() const override; 80 | TSector ScanTrack(TCylinder cyl,THead head,Codec::PType pCodec=nullptr,PSectorId bufferId=nullptr,PWORD bufferLength=nullptr,PLogTime startTimesNanoseconds=nullptr,PBYTE pAvgGap3=nullptr) const override; 81 | bool IsTrackScanned(TCylinder cyl,THead head) const override; 82 | TStdWinError UnscanTrack(TCylinder cyl,THead head) override; 83 | void GetTrackData(TCylinder cyl,THead head,Revolution::TType rev,PCSectorId bufferId,PCBYTE bufferNumbersOfSectorsToSkip,TSector nSectors,PSectorData *outBufferData,PWORD outBufferLengths,TFdcStatus *outFdcStatuses,TLogTime *outDataStarts) override; 84 | TDataStatus IsSectorDataReady(TCylinder cyl,THead head,RCSectorId id,BYTE nSectorsToSkip,Revolution::TType rev) const override; 85 | TStdWinError MarkSectorAsDirty(RCPhysicalAddress chs,BYTE nSectorsToSkip,PCFdcStatus pFdcStatus) override; 86 | TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 87 | bool EditSettings(bool initialEditing) override; 88 | void EnumSettings(CSettings &rOut) const override; 89 | TStdWinError Reset() override; 90 | TStdWinError FormatTrack(TCylinder cyl,THead head,Codec::TType codec,TSector nSectors,PCSectorId bufferId,PCWORD bufferLength,PCFdcStatus bufferFdcStatus,BYTE gap3,BYTE fillerByte,const volatile bool &cancelled) override; 91 | TStdWinError UnformatTrack(TCylinder cyl,THead head) override; 92 | }; 93 | 94 | #endif // DSK_H 95 | -------------------------------------------------------------------------------- /Main/src/GDOS_Boot.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "GDOS.h" 3 | 4 | static PDos __instantiate__(PImage image,PCFormat pFormatBoot){ 5 | return new CGDOS(image,pFormatBoot); 6 | } 7 | static constexpr CFormatDialog::TStdFormat StdFormats[]={ 8 | { _T("DS 80x10"), 0, {Medium::FLOPPY_DD,Codec::MFM,GDOS_CYLINDERS_COUNT-1,2,GDOS_TRACK_SECTORS_COUNT,GDOS_SECTOR_LENGTH_STD_CODE,GDOS_SECTOR_LENGTH_STD,1}, 1, 0, FDD_350_SECTOR_GAP3, 1, GDOS_DIR_FILES_COUNT_MAX } 9 | }; 10 | 11 | TStdWinError CGDOS::__recognizeDisk__(PImage image,PFormat pFormatBoot){ 12 | // returns the result of attempting to recognize Image by this DOS as follows: ERROR_SUCCESS = recognized, ERROR_CANCELLED = user cancelled the recognition sequence, any other error = not recognized 13 | // - setting up the biggest possible geometry 14 | //static const TFormat Fmt={ Medium::FLOPPY_DD, 1,1,10, GDOS_SECTOR_LENGTH_STD_CODE,GDOS_SECTOR_LENGTH_STD, 1 }; 15 | //if (image->SetMediumTypeAndGeometry( &fmt, StdSidesMap, 1 )!=ERROR_SUCCESS) return false; 16 | ( *pFormatBoot=StdFormats[0].params.format ).nCylinders++; 17 | if (const TStdWinError err=image->SetMediumTypeAndGeometry( pFormatBoot, StdSidesMap, Properties.firstSectorNumber )) 18 | return err; 19 | if (image->GetCylinderCount()fileType!=TDirectoryEntry::EMPTY_ENTRY){ 30 | // . checking NumberOfSectors 31 | if (de->nSectors>GDOS_CYLINDERS_COUNT*2*GDOS_TRACK_SECTORS_COUNT-GDOS_DIR_FILES_COUNT_MAX*sizeof(TDirectoryEntry)/GDOS_SECTOR_LENGTH_STD) 32 | return ERROR_UNRECOGNIZED_VOLUME; 33 | // . checking position of the FirstSector 34 | if (!de->firstSector.__isValid__()) 35 | return ERROR_UNRECOGNIZED_VOLUME; 36 | // . checking SectorAllocationBitmap 37 | if (!de->sectorAllocationBitmap.IsDisjunctiveWith(allocatedSectorsOnDisk)) 38 | return ERROR_UNRECOGNIZED_VOLUME; 39 | allocatedSectorsOnDisk.MergeWith(de->sectorAllocationBitmap); 40 | } 41 | }else 42 | // root Directory Sector not found - if "too many" Sectors not found, it's not a GDOS disk 43 | if (++nDirectorySectorsBad>3) 44 | return ERROR_UNRECOGNIZED_VOLUME; 45 | // - GDOS successfully recognizes the disk 46 | return ERROR_SUCCESS; 47 | } 48 | 49 | 50 | const CDos::TProperties CGDOS::Properties={ 51 | _T("GDOS (experimental)"), // name 52 | MAKE_DOS_ID('G','D','O','S','_','_','_','_'), // unique identifier 53 | 20, // recognition priority (the bigger the number the earlier the DOS gets crack on the image) 54 | 0, // the Cylinder where usually the Boot Sector (or its backup) is found 55 | __recognizeDisk__, // recognition function 56 | __instantiate__, // instantiation function 57 | Medium::FLOPPY_DD_ANY, 58 | &MGT::Properties, // the most common Image to contain data for this DOS (e.g. *.D80 Image for MDOS) 59 | 1, // number of std Formats 60 | StdFormats, // std Formats 61 | Codec::MFM, // a set of Codecs this DOS supports 62 | GDOS_TRACK_SECTORS_COUNT,GDOS_TRACK_SECTORS_COUNT, // range of supported number of Sectors 63 | GDOS_DIR_FILES_COUNT_MAX/2, // minimal total number of Sectors required 64 | 1, // maximum number of Sector in one Cluster (must be power of 2) 65 | -1, // maximum size of a Cluster (in Bytes) 66 | 1,1, // range of supported number of allocation tables (FATs) 67 | GDOS_DIR_FILES_COUNT_MAX,GDOS_DIR_FILES_COUNT_MAX, // range of supported number of root Directory entries 68 | 1, // lowest Sector number on each Track 69 | 0,0, // regular Sector and Directory Sector filler Byte 70 | 0,2 // number of reserved Bytes at the beginning and end of each Sector 71 | }; 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | void CGDOS::FlushToBootSector() const{ 83 | // flushes internal Format information to the actual Boot Sector's data 84 | //nop (doesn't have a Boot Sector) 85 | } 86 | 87 | void CGDOS::InitializeEmptyMedium(CFormatDialog::PCParameters params,CActionProgress &ap){ 88 | // initializes a fresh formatted Medium (Boot, FAT, root dir, etc.) 89 | // - creating the Boot Sector 90 | //nop (doesn't have a Boot Sector) 91 | // - initializing FAT 92 | //nop (doesn't have a FAT) 93 | // - empty Directory 94 | //nop (DirectoryEntry set as Empty during formatting - FillerByte happens to have the same value) 95 | } 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | namespace MGT{ 106 | static const CImage::TProperties Properties={ 107 | MAKE_IMAGE_ID('G','D','O','S','_','M','G','T'), // a unique identifier 108 | Recognize, // list of recognized device names 109 | Instantiate,// instantiation function 110 | _T("*.mgt"), // filter 111 | Medium::FLOPPY_DD_ANY, // supported Media 112 | Codec::MFM, // supported Codecs 113 | GDOS_SECTOR_LENGTH_STD, GDOS_SECTOR_LENGTH_STD // Sector supported min and max length 114 | }; 115 | 116 | LPCTSTR Recognize(PTCHAR){ 117 | static constexpr TCHAR SingleDeviceName[]=_T("MGT image\0"); 118 | return SingleDeviceName; 119 | } 120 | PImage Instantiate(LPCTSTR){ 121 | return new CImageRaw( &Properties, false ); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Main/src/Greaseweazle.h: -------------------------------------------------------------------------------- 1 | #ifndef GREASEWEAZLE_H 2 | #define GREASEWEAZLE_H 3 | 4 | class CGreaseweazleV4 sealed:public CCapsBase{ 5 | enum TRequest:BYTE{ 6 | GET_INFO =0, 7 | UPDATE =1, 8 | SEEK_ABS =2, 9 | HEAD =3, 10 | SET_PARAMS =4, 11 | GET_PARAMS =5, 12 | MOTOR =6, 13 | READ_FLUX =7, 14 | WRITE_FLUX =8, 15 | GET_FLUX_STATUS =9, 16 | GET_INDEX_TIMES =10, 17 | SWITCH_FW_MODE =11, 18 | SELECT_DRIVE =12, 19 | DESELECT_DRIVE =13, 20 | SET_BUS_TYPE =14, 21 | SET_PIN =15, 22 | SOFT_RESET =16, 23 | ERASE_FLUX =17, 24 | SOURCE_BYTES =18, 25 | SINK_BYTES =19, 26 | GET_PIN =20, 27 | TEST_MODE =21, 28 | NO_CLICK_STEP =22 29 | }; 30 | 31 | enum TResponse:BYTE{ 32 | OKAY =0, 33 | BAD_COMMAND =1, 34 | NO_INDEX =2, 35 | NO_TRK0 =3, 36 | FLUX_OVERFLOW =4, 37 | FLUX_UNDERFLOW =5, 38 | WRPROT =6, 39 | NO_UNIT =7, 40 | NO_BUS =8, 41 | BAD_UNIT =9, 42 | BAD_PIN =10, 43 | BAD_CYLINDER =11, 44 | OUT_OF_SRAM =12, 45 | OUT_OF_FLASH =13 46 | }; 47 | 48 | struct TDriveInfo sealed{ 49 | DWORD cylSeekedValid:1; 50 | DWORD motorOn:1; 51 | DWORD isFlippy:1; 52 | union{ 53 | TCylinder cylSeeked; 54 | int reserved1; 55 | }; 56 | BYTE reserved2[24]; 57 | }; 58 | 59 | const enum TDriver{ 60 | UNSUPPORTED, 61 | USBSER 62 | } driver; 63 | enum TBusType:BYTE{ 64 | BUS_UNKNOWN, 65 | BUS_IBM, 66 | BUS_SHUGART, 67 | BUS_LAST 68 | }; 69 | const BYTE fddId; 70 | const Utils::CCallocPtr dataBuffer; 71 | #pragma pack(1) 72 | struct{ 73 | BYTE major, minor, isMainFirmware, maxCmd; 74 | DWORD sampleFrequency; 75 | BYTE hardwareModel, hardwareSubmodel, usbSpeed, mcuId; 76 | short mcuMhz, mcuRamKb; 77 | BYTE reserved[16]; 78 | } firmwareInfo; 79 | struct{ 80 | mutable CMutex locker; 81 | HANDLE handle; 82 | union{ 83 | // Driver-related params here 84 | }; 85 | } device; 86 | Utils::TRationalNumber sampleClock; 87 | 88 | static LPCTSTR Recognize(PTCHAR deviceNameList); 89 | static PImage Instantiate(LPCTSTR deviceName); 90 | 91 | CGreaseweazleV4(TDriver driver,BYTE fddId); 92 | 93 | operator bool() const; 94 | 95 | TStdWinError Connect(); 96 | void Disconnect(); 97 | DWORD Read(PVOID buffer,DWORD nBytesFree) const; 98 | TStdWinError ReadFull(PVOID buffer,DWORD nBytes) const; 99 | DWORD Write(LPCVOID buffer,DWORD nBytes) const; 100 | TStdWinError WriteFull(LPCVOID buffer,DWORD nBytes) const; 101 | TStdWinError SendRequest(TRequest req,LPCVOID params,BYTE paramsLength) const; 102 | CTrackReaderWriter GwV4StreamToTrack(PCBYTE p,DWORD length) const; 103 | DWORD TrackToGwV4Stream(CTrackReader tr,PBYTE pOutStream) const; 104 | TStdWinError UploadTrack(TCylinder cyl,THead head,CTrackReader tr) const override; 105 | inline TStdWinError GetLastFluxOperationError() const{ return SendRequest( TRequest::GET_FLUX_STATUS, nullptr, 0 ); } 106 | inline TStdWinError SelectDrive() const{ return SendRequest( TRequest::SELECT_DRIVE, &fddId, sizeof(BYTE) ); } 107 | TStdWinError GetDriveInfo(TDriveInfo &rOutDi) const; 108 | TStdWinError GetPin(BYTE pin,bool &outValue) const; 109 | TStdWinError SetMotorOn(bool on=true) const; 110 | TStdWinError SeekTo(TCylinder cyl) const; 111 | TStdWinError SelectHead(THead head) const; 112 | public: 113 | static const TProperties Properties; 114 | 115 | ~CGreaseweazleV4(); 116 | 117 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 118 | TStdWinError SeekHeadsHome() const override; 119 | bool EditSettings(bool initialEditing) override; 120 | void EnumSettings(CSettings &rOut) const override; 121 | TStdWinError Reset() override; 122 | CTrackReader ReadTrack(TCylinder cyl,THead head) const override; 123 | void SetPathName(LPCTSTR lpszPathName,BOOL bAddToMRU=TRUE) override; 124 | }; 125 | 126 | #endif // GREASEWEAZLE_H 127 | -------------------------------------------------------------------------------- /Main/src/HFE.h: -------------------------------------------------------------------------------- 1 | #ifndef HFE_H 2 | #define HFE_H 3 | 4 | class CHFE sealed:public CCapsBase{ 5 | enum TFloppyInterface:BYTE{ 6 | IBM_PC_DD, 7 | IBM_PC_HD, 8 | ATARI_ST_DD, 9 | ATARI_ST_HD, 10 | AMIGA_DD, 11 | AMIGA_HD, 12 | CPC_DD, 13 | GENERIC_SHUGART, 14 | IBM_PC_ED, 15 | MSX2_DD, 16 | C64_DD, 17 | EMU_SHUGART, 18 | S950_DD, 19 | S950_HD, 20 | LAST_KNOWN, 21 | DISABLED =0xfe 22 | }; 23 | 24 | enum TTrackEncoding:BYTE{ 25 | IBM_MFM, 26 | AMIGA_MFM, 27 | IBM_FM, 28 | EMU_FM, 29 | UNKNOWN =0xff 30 | }; 31 | 32 | enum TStep:BYTE{ 33 | DOUBLE =0, 34 | SINGLE =255 35 | }; 36 | 37 | struct TBlock{ 38 | BYTE bytes[512]; 39 | }; 40 | 41 | #pragma pack(1) 42 | union UHeader{ 43 | struct{ 44 | char signature[8]; 45 | BYTE formatRevision; // Revision 0 46 | BYTE nCylinders; 47 | BYTE nHeads; 48 | TTrackEncoding trackEncoding; 49 | WORD dataBitRate; // data kBit/s; e.g. 250 = 250,000 bit/s; multiply by 2 to get total bitrate (data and clock bits) 50 | WORD driveRpm; 51 | TFloppyInterface floppyInterface; 52 | BYTE reserved; // don't use 53 | WORD cylInfosBegin; // offset (in multiples of 512 Bytes) of the TTrackInfo structures in the image; e.g. 1 = 0x200 54 | BYTE writeable; // NOT write-protected ? 55 | TStep step; 56 | struct{ 57 | BYTE disabled; 58 | TTrackEncoding track0Encoding; // Track 0 encoding 59 | } alternative[2]; // Alternative encoding for Track 0 under either Head 60 | }; 61 | TBlock block; 62 | 63 | UHeader(LPCSTR signature); 64 | 65 | bool IsValid() const; 66 | bool IsVersion3() const; 67 | CString ListUnsupportedFeatures() const; 68 | TLogTime GetCellTime() const; 69 | } header; 70 | 71 | #pragma pack(1) 72 | struct TTrackData sealed{ 73 | BYTE bytes[256]; // 256*8 bits 74 | }; 75 | 76 | #pragma pack(1) 77 | struct TCylinderBlock sealed{ 78 | TTrackData head[2]; // 2 Heads 79 | }; 80 | 81 | #pragma pack(1) 82 | struct TCylinderInfo sealed{ 83 | WORD nBlocksOffset; 84 | WORD nBytesLength; 85 | 86 | inline bool IsValid() const{ return nBlocksOffset>=2 && nBytesLength!=0; } 87 | } cylInfos[84]; 88 | 89 | class CTrackBytes sealed:public Utils::CCallocPtr{ 90 | WORD count; 91 | public: 92 | CTrackBytes(WORD count); 93 | CTrackBytes(CTrackBytes &&r); 94 | 95 | inline operator PBYTE() const{ return get(); } 96 | inline WORD GetCount() const{ return count; } 97 | inline PBYTE end() const{ return get()+count; } 98 | inline void TrimTo(WORD newCount){ count=newCount; } 99 | void Invalidate(); 100 | void ReverseBitsInEachByte() const; 101 | }; 102 | 103 | enum TOpCode:BYTE{ 104 | NOP =0xf0, 105 | SETINDEX, 106 | SETBITRATE, 107 | SKIPBITS, 108 | RANDOM, 109 | LAST 110 | }; 111 | 112 | mutable CFile f; 113 | 114 | CTrackBytes ReadTrackBytes(TCylinder cyl,THead head) const; 115 | CTrackBytes TrackToBytes(CInternalTrack &rit) const; 116 | PInternalTrack BytesToTrack(const CTrackBytes &bytes) const; 117 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 118 | public: 119 | static const TProperties Properties; 120 | 121 | CHFE(); 122 | 123 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 124 | TStdWinError SaveTrack(TCylinder cyl,THead head,const volatile bool &cancelled) const; 125 | CTrackReader ReadTrack(TCylinder cyl,THead head) const override; 126 | TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 127 | bool EditSettings(bool initialEditing) override; 128 | //void EnumSettings(CSettings &rOut) const override; 129 | TStdWinError Reset() override; 130 | TStdWinError FormatTrack(TCylinder cyl,THead head,Codec::TType codec,TSector nSectors,PCSectorId bufferId,PCWORD bufferLength,PCFdcStatus bufferFdcStatus,BYTE gap3,BYTE fillerByte,const volatile bool &cancelled) override; 131 | CString ListUnsupportedFeatures() const override; 132 | }; 133 | 134 | #endif // HFE_H 135 | -------------------------------------------------------------------------------- /Main/src/IPF.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CapsBase.h" 3 | #include "IPF.h" 4 | 5 | static LPCTSTR Recognize(PTCHAR){ 6 | static constexpr TCHAR SingleDeviceName[]=_T("Interchangeable Preservation Format\0"); 7 | return SingleDeviceName; 8 | } 9 | static PImage Instantiate(LPCTSTR){ 10 | return new CIpf; 11 | } 12 | const CImage::TProperties CIpf::Properties={ 13 | MAKE_IMAGE_ID('C','A','P','S','_','I','P','F'), // a unique identifier 14 | Recognize, // list of recognized device names 15 | Instantiate, // instantiation function 16 | _T("*.") _T(CAPS_FILEEXT), // filter 17 | Medium::FLOPPY_ANY, // supported Media 18 | Codec::FLOPPY_ANY, // supported Codecs 19 | 1,2*6144, // Sector supported min and max length 20 | true // is read-only; by design, the IPF serves for PRESERVATION and modifications thus should be NOT allowed 21 | }; 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | #define INI_IPF _T("Ipf") 30 | 31 | CIpf::CIpf() 32 | // ctor 33 | // - base 34 | : CCapsBase( &Properties, '\0', true, INI_IPF ) { // '\0' = not a real drive 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | BOOL CIpf::OnOpenDocument(LPCTSTR lpszPathName){ 43 | // True <=> Image opened successfully, otherwise False 44 | // - base 45 | if (!__super::OnOpenDocument(lpszPathName)) 46 | return FALSE; 47 | // - warn about a draft version 48 | if (!capsImageInfo.release || !capsImageInfo.revision) 49 | draftVersionMessageBar.Show(); 50 | // - successfully mounted 51 | return TRUE; 52 | } 53 | -------------------------------------------------------------------------------- /Main/src/IPF.h: -------------------------------------------------------------------------------- 1 | #ifndef IPF_H 2 | #define IPF_H 3 | 4 | class CIpf sealed:public CCapsBase{ 5 | public: 6 | static const TProperties Properties; 7 | 8 | CIpf(); 9 | 10 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 11 | }; 12 | 13 | #endif // IPF_H 14 | -------------------------------------------------------------------------------- /Main/src/Image.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/Image.cpp -------------------------------------------------------------------------------- /Main/src/ImageFloppy.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEFLOPPY_H 2 | #define IMAGEFLOPPY_H 3 | 4 | class CFloppyImage:public CImage{ 5 | struct TScannerState{ 6 | static const TScannerState Initial; 7 | 8 | CSectorDataSerializer::TScannerStatus scannerStatus; 9 | BYTE n; 10 | bool allScanned; 11 | #if _MFC_VER>=0x0A00 12 | LONGLONG dataTotalLength; 13 | #else 14 | LONG dataTotalLength; 15 | #endif 16 | BYTE nDiscoveredRevolutions; 17 | }; 18 | 19 | struct TScannedTracks sealed:public TScannerState{ 20 | CCriticalSection locker; 21 | 22 | TScannedTracks(); 23 | } scannedTracks; 24 | public: 25 | typedef WORD TCrc16; 26 | 27 | static TCrc16 GetCrc16Ccitt(TCrc16 seed,LPCVOID bytes,WORD nBytes); 28 | static TCrc16 GetCrc16Ccitt(LPCVOID bytes,WORD nBytes); 29 | static bool IsValidSectorLengthCode(BYTE lengthCode); 30 | protected: 31 | Medium::TType floppyType; // DD/HD 32 | 33 | CFloppyImage(PCProperties properties,bool hasEditableSettings); 34 | public: 35 | WORD GetUsableSectorLength(BYTE sectorLengthCode) const; 36 | TFormat::TLengthCode GetMaximumSectorLengthCode() const; 37 | TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 38 | TStdWinError UnscanTrack(TCylinder cyl,THead head) override; 39 | CSectorDataSerializer *CreateSectorDataSerializer(CHexaEditor *pParentHexaEditor) override sealed; 40 | TLogTime EstimateNanosecondsPerOneByte() const override; 41 | virtual void EstimateTrackTiming(TCylinder cyl,THead head,TSector nSectors,PCSectorId bufferId,PCWORD bufferLength,BYTE gap3,PLogTime startTimesNanoseconds) const; 42 | }; 43 | 44 | #endif // IMAGEFLOPPY_H 45 | -------------------------------------------------------------------------------- /Main/src/ImageRaw.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGERAW_H 2 | #define IMAGERAW_H 3 | 4 | class CImageRaw:public CImage{ 5 | TCylinder nCylinders; 6 | Utils::CCallocPtr bufferOfCylinders; 7 | THead nHeads; 8 | TSector nSectors,firstSectorNumber; 9 | BYTE sectorLengthCode; WORD sectorLength; 10 | 11 | bool IsKnownSector(TCylinder cyl,THead head,RCSectorId id) const; 12 | PSectorData __getBufferedSectorData__(TCylinder cyl,THead head,PCSectorId sectorId) const; 13 | TStdWinError SaveTrackToCurrentPositionInFile(CFile *pfOtherThanCurrentFile,TPhysicalAddress chs); 14 | protected: 15 | TTrackScheme trackAccessScheme; 16 | Utils::CCallocPtr explicitSides; // non-Null = Side numbers explicitly provided by user 17 | DWORD sizeWithoutGeometry; 18 | CFile f; 19 | 20 | TStdWinError __setMediumTypeAndGeometry__(PCFormat pFormat,PCSide _sideMap,TSector _firstSectorNumber); 21 | TStdWinError ExtendToNumberOfCylinders(TCylinder nCyl,BYTE fillerByte,const volatile bool &cancelled); 22 | void __freeCylinder__(TCylinder cyl); 23 | void __freeBufferOfCylinders__(); 24 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 25 | public: 26 | static const TProperties Properties; 27 | 28 | CImageRaw(PCProperties properties,bool hasEditableSettings); 29 | ~CImageRaw(); 30 | 31 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 32 | TCylinder GetCylinderCount() const override sealed; 33 | THead GetHeadCount() const override sealed; 34 | TSector ScanTrack(TCylinder cyl,THead head,Codec::PType pCodec=nullptr,PSectorId bufferId=nullptr,PWORD bufferLength=nullptr,PLogTime startTimesNanoseconds=nullptr,PBYTE pAvgGap3=nullptr) const override; 35 | bool IsTrackScanned(TCylinder cyl,THead head) const override sealed; 36 | void GetTrackData(TCylinder cyl,THead head,Revolution::TType rev,PCSectorId bufferId,PCBYTE bufferNumbersOfSectorsToSkip,TSector nSectors,PSectorData *outBufferData,PWORD outBufferLengths,TFdcStatus *outFdcStatuses,TLogTime *outDataStarts) override; 37 | TDataStatus IsSectorDataReady(TCylinder cyl,THead head,RCSectorId id,BYTE nSectorsToSkip,Revolution::TType rev) const override; 38 | TStdWinError MarkSectorAsDirty(RCPhysicalAddress chs,BYTE,PCFdcStatus pFdcStatus) override; 39 | TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 40 | bool EditSettings(bool initialEditing) override; 41 | void EnumSettings(CSettings &rOut) const override; 42 | TStdWinError Reset() override; 43 | TStdWinError FormatTrack(TCylinder cyl,THead head,Codec::TType codec,TSector _nSectors,PCSectorId bufferId,PCWORD bufferLength,PCFdcStatus bufferFdcStatus,BYTE gap3,BYTE fillerByte,const volatile bool &cancelled) override; 44 | TStdWinError UnformatTrack(TCylinder cyl,THead head) override; 45 | CSectorDataSerializer *CreateSectorDataSerializer(CHexaEditor *pParentHexaEditor) override; 46 | }; 47 | 48 | #endif // IMAGERAW_H 49 | -------------------------------------------------------------------------------- /Main/src/Image_SectorDataSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | CImage::CSectorDataSerializer::CSectorDataSerializer(CHexaEditor *pParentHexaEditor,PImage image,LONG dataTotalLength,const BYTE &nDiscoveredRevolutions) 4 | // ctor 5 | : pParentHexaEditor(pParentHexaEditor) , image(image) , currTrack(0) 6 | , nDiscoveredRevolutions(nDiscoveredRevolutions) 7 | , revolution(Revolution::ANY_GOOD) { 8 | this->dataTotalLength=dataTotalLength; 9 | sector.indexOnTrack=0, sector.offset=0; 10 | } 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | UINT CImage::CSectorDataSerializer::Read(LPVOID lpBuf,UINT nCount){ 21 | // tries to read given NumberOfBytes into the Buffer, starting with current Position; returns the number of Bytes actually read (increments the Position by this actually read number of Bytes) 22 | nCount=std::min( nCount, dataTotalLength-position ); 23 | const UINT nBytesToRead=nCount; 24 | for( WORD w; true; ) 25 | if (revolution==Revolution::ALL_INTERSECTED){ 26 | const TPhysicalAddress chs=GetCurrentPhysicalAddress(); 27 | const BYTE nAvailableRevolutions=GetAvailableRevolutionCount(chs.cylinder,chs.head); 28 | PCSectorData data[Revolution::MAX]; 29 | bool allRevolutionsIdentical=true; // assumption 30 | for( BYTE rev=0; revGetSectorData( chs, sector.indexOnTrack, (Revolution::TType)rev, &w ); 32 | allRevolutionsIdentical&=data[rev]!=nullptr; 33 | } 34 | if (!w) // e.g. reading Sector with LengthCode 231 - such Sector has by default no data (a pointer to zero-length data has been returned by GetSectorData) 35 | break; 36 | if (!allRevolutionsIdentical) // at least one Revolution didn't return any data for the Sector 37 | if (nCount(w,nCount); i=Revolution::MAX) 65 | revolution=Revolution::ANY_GOOD; 66 | TFdcStatus sr; // in/out 67 | const PCSectorData sectorData=image->GetSectorData( chs, sector.indexOnTrack, revolution, &w, &sr ); 68 | if (!sectorData) 69 | break; 70 | if (!w) // e.g. reading Sector with LengthCode 231 - such Sector has by default no data (a pointer to zero-length data has been returned by GetSectorData) 71 | break; 72 | w-=sector.offset; 73 | if (sr.IsWithoutError()){ 74 | if (w( nCount, w ); 90 | ::memcpy( lpBuf, sectorData+sector.offset, len ); 91 | Seek( len, SeekPosition::current ); 92 | ::SetLastError( ERROR_CRC ); 93 | return len; // bad data are to be retrieved in individual chunks 94 | } 95 | } 96 | ::SetLastError(ERROR_READ_FAULT); 97 | return nBytesToRead-nCount; 98 | } 99 | 100 | void CImage::CSectorDataSerializer::Write(LPCVOID lpBuf,UINT nCount){ 101 | // tries to write given NumberOfBytes from the Buffer to the current Position (increments the Position by the number of Bytes actually written) 102 | nCount=std::min( nCount, dataTotalLength-position ); 103 | bool writtenWithoutCrcError=true; // assumption 104 | for( WORD w; true; ){ 105 | const TPhysicalAddress chs=GetCurrentPhysicalAddress(); 106 | TFdcStatus sr; // in/out 107 | if (const PSectorData sectorData=image->GetSectorData(chs,sector.indexOnTrack,Revolution::CURRENT,&w,&sr)){ // Revolution.Current = freezing the state of data (eventually erroneous) 108 | if (!w) // e.g. reading Sector with LengthCode 231 - such Sector has by default no data (a pointer to zero-length data has been returned by GetSectorData) 109 | break; 110 | writtenWithoutCrcError&=sr.IsWithoutError(); 111 | image->MarkSectorAsDirty(chs,sector.indexOnTrack,&sr); 112 | w-=sector.offset; 113 | if (wCreateSectorDataSerializer(pParentHexaEditor); 132 | return S_OK; 133 | }else 134 | return E_INVALIDARG; 135 | } 136 | 137 | BYTE CImage::CSectorDataSerializer::GetAvailableRevolutionCount(TCylinder cyl,THead head) const{ 138 | // wrapper around CImage::GetAvailableRevolutionCount 139 | return std::min( (BYTE)Revolution::MAX, image->GetAvailableRevolutionCount(cyl,head) ); 140 | } 141 | -------------------------------------------------------------------------------- /Main/src/Image_TrackEditor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/Image_TrackEditor.cpp -------------------------------------------------------------------------------- /Main/src/Image_TrackRW.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/Image_TrackRW.cpp -------------------------------------------------------------------------------- /Main/src/KryoFluxBase.h: -------------------------------------------------------------------------------- 1 | #ifndef KRYOFLUXBASE_H 2 | #define KRYOFLUXBASE_H 3 | 4 | #define KF_BUFFER_CAPACITY 2000000 5 | 6 | #define KF_STREAM_ID MAKE_IMAGE_ID('K','r','y','o','F','l','u','x') 7 | 8 | class CKryoFluxBase abstract:public CCapsBase{ 9 | protected: 10 | static int WriteCreatorOob(PBYTE streamBuffer); 11 | 12 | struct TParamsEtc{ 13 | // persistent (saved and loaded) 14 | CString firmwareFileName; 15 | // volatile (current session only) 16 | //none 17 | 18 | TParamsEtc(); 19 | ~TParamsEtc(); 20 | } paramsEtc; 21 | 22 | const LPCTSTR firmware; 23 | 24 | CKryoFluxBase(PCProperties properties,char realDriveLetter,LPCTSTR firmware); 25 | 26 | CTrackReaderWriter StreamToTrack(LPBYTE inStreamBytes,DWORD nStreamBytes) const; 27 | DWORD TrackToStream(CTrackReader tr,LPBYTE outBuffer) const; 28 | public: 29 | static DWORD TimeToStdSampleCounter(TLogTime t); 30 | 31 | //BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 32 | //BOOL OnSaveDocument(LPCTSTR lpszPathName) override; 33 | //TCylinder GetCylinderCount() const override; 34 | //THead GetNumberOfFormattedSides(TCylinder cyl) const override; 35 | //BYTE GetAvailableRevolutionCount(TCylinder cyl,THead head) const override; 36 | //TSector ScanTrack(TCylinder cyl,THead head,PSectorId bufferId=nullptr,PWORD bufferLength=nullptr,PLogTime startTimesNanoseconds=nullptr,PBYTE pAvgGap3=nullptr) const override; 37 | //void GetTrackData(TCylinder cyl,THead head,PCSectorId bufferId,PCBYTE bufferNumbersOfSectorsToSkip,TSector nSectors,PSectorData *outBufferData,PWORD outBufferLengths,TFdcStatus *outFdcStatuses) override; 38 | //TStdWinError MarkSectorAsDirty(RCPhysicalAddress chs,BYTE nSectorsToSkip,PCFdcStatus pFdcStatus) override; 39 | //TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 40 | bool EditSettings(bool initialEditing) override; 41 | void EnumSettings(CSettings &rOut) const override; 42 | }; 43 | 44 | #endif // KRYOFLUXBASE_H 45 | -------------------------------------------------------------------------------- /Main/src/KryoFluxDevice.h: -------------------------------------------------------------------------------- 1 | #ifndef KRYOFLUXDEVICE_H 2 | #define KRYOFLUXDEVICE_H 3 | 4 | /* 5 | The KryoFlux support is heavily inspired, or after rewriting fully adopted, 6 | from Simon Owen's SamDisk 7 | 8 | Copyright (c) 2002-2020 Simon Owen, https://simonowen.com 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | */ 20 | 21 | 22 | class CKryoFluxDevice sealed:public CKryoFluxBase{ 23 | enum TRequest{ 24 | STATUS = 0x00, // status 25 | INFO = 0x01, // info (index 1 or 2) 26 | RESULT = 0x02, 27 | DATA = 0x03, 28 | INDEX = 0x04, // index positions from last read? 29 | RESET = 0x05, // soft reset 30 | DEVICE = 0x06, // select device 31 | MOTOR = 0x07, // motor state 32 | DENSITY = 0x08, // select density; indication that 5.25" DD floppy inserted in 360 RPM HD drive; don't set - the app handles this case its way! 33 | SIDE = 0x09, // select side 34 | TRACK = 0x0a, // seek 35 | STREAM = 0x0b, // stream on/off, MSB=revs 36 | MIN_TRACK = 0x0c, // set min track (default=0) 37 | MAX_TRACK = 0x0d, // set max track (default=81) 38 | RESULT_WRITE = 0x82, 39 | INDEX_WRITE = 0x84, 40 | 41 | T_SET_LINE = 0x0e, // (default=4) 42 | T_DENSITY_SELECT = 0x0f, // (default=500000) 43 | T_DRIVE_SELECT = 0x10, // (default=60000) 44 | T_SIDE_SELECT = 0x11, // (default=1000) 45 | T_DIRECTION_SELECT = 0x12, // (default=12) 46 | T_SPIN_UP = 0x13, // (default=800000) 47 | T_STEP_AFTER_MOTOR = 0x14, // (default=200000) 48 | T_STEP_SIGNAL = 0x15, // (default=4) 49 | T_STEP = 0x16, // (default=8000) 50 | T_TRACK0_SIGNAL = 0x17, // (default=1000) 51 | T_DIRECTION_CHANGE = 0x18, // (default=38000) 52 | T_HEAD_SETTLING = 0x19, // (default=40000) 53 | T_WRITE_GATE_OFF = 0x20, // (default=1200) 54 | T_WRITE_GATE_ON = 0x21, // (default=8) 55 | T_BYPASS_OFF = 0x22, // (default=8) 56 | T_BYPASS_ON = 0x23 // (default=8) 57 | }; 58 | 59 | const enum TDriver{ 60 | UNSUPPORTED, 61 | WINUSB 62 | } driver; 63 | const BYTE fddId; 64 | const Utils::CCallocPtr dataBuffer; 65 | struct{ 66 | mutable CMutex locker; 67 | HANDLE handle; 68 | union{ 69 | WinUsb::TDevInterfaceHandle winusb; 70 | }; 71 | mutable char lastRequestResultMsg[240]; 72 | TCHAR firmwareVersion[100]; 73 | } device; 74 | 75 | static LPCTSTR Recognize(PTCHAR deviceNameList); 76 | static PImage Instantiate(LPCTSTR deviceName); 77 | 78 | CKryoFluxDevice(TDriver driver,BYTE fddId); 79 | 80 | operator bool() const; 81 | 82 | TStdWinError Connect(); 83 | void Disconnect(); 84 | LPCSTR GetProductName() const; 85 | TStdWinError SamBaCommand(LPCSTR cmd,LPCSTR end) const; 86 | TStdWinError UploadFirmware() override; 87 | TStdWinError UploadTrack(TCylinder cyl,THead head,CTrackReader tr) const override; 88 | DWORD TrackToKfw1(CTrackReader tr) const; 89 | TStdWinError SendRequest(TRequest req,WORD index=0,WORD value=0) const; 90 | int GetLastRequestResult() const; 91 | DWORD Read(PVOID buffer,DWORD nBytesFree) const; 92 | TStdWinError ReadFull(PVOID buffer,DWORD nBytes) const; 93 | DWORD Write(LPCVOID buffer,DWORD nBytes) const; 94 | TStdWinError WriteFull(LPCVOID buffer,DWORD nBytes) const; 95 | TStdWinError SetMotorOn(bool on=true) const; 96 | TStdWinError SeekTo(TCylinder cyl) const; 97 | TStdWinError SelectHead(THead head) const; 98 | public: 99 | static const TProperties Properties; 100 | 101 | ~CKryoFluxDevice(); 102 | 103 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 104 | //BOOL OnSaveDocument(LPCTSTR lpszPathName) override; 105 | //TCylinder GetCylinderCount() const override; 106 | //THead GetNumberOfFormattedSides(TCylinder cyl) const override; 107 | TStdWinError SeekHeadsHome() const override; 108 | //TSector ScanTrack(TCylinder cyl,THead head,Codec::PType pCodec=nullptr,PSectorId bufferId=nullptr,PWORD bufferLength=nullptr,PLogTime startTimesNanoseconds=nullptr,PBYTE pAvgGap3=nullptr) const override; 109 | //void GetTrackData(TCylinder cyl,THead head,PCSectorId bufferId,PCBYTE bufferNumbersOfSectorsToSkip,TSector nSectors,PSectorData *outBufferData,PWORD outBufferLengths,TFdcStatus *outFdcStatuses) override; 110 | //TStdWinError MarkSectorAsDirty(RCPhysicalAddress chs,BYTE nSectorsToSkip,PCFdcStatus pFdcStatus) override; 111 | //TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 112 | bool EditSettings(bool initialEditing) override; 113 | TStdWinError Reset() override; 114 | CTrackReader ReadTrack(TCylinder cyl,THead head) const override; 115 | void SetPathName(LPCTSTR lpszPathName,BOOL bAddToMRU=TRUE) override; 116 | }; 117 | 118 | #endif // KRYOFLUXDEVICE_H 119 | -------------------------------------------------------------------------------- /Main/src/KryoFluxStreams.h: -------------------------------------------------------------------------------- 1 | #ifndef KRYOFLUXSTREAMS_H 2 | #define KRYOFLUXSTREAMS_H 3 | 4 | class CKryoFluxStreams sealed:public CKryoFluxBase{ 5 | CString nameBase; 6 | 7 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 8 | CString GetStreamFileName(LPCTSTR nameBase,TCylinder cyl,THead head) const; 9 | inline CString GetStreamFileName(TCylinder cyl,THead head) const{ return GetStreamFileName(nameBase,cyl,head); } 10 | bool SetNameBase(LPCTSTR fullName); 11 | public: 12 | static const TProperties Properties; 13 | 14 | CKryoFluxStreams(); 15 | 16 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 17 | //TCylinder GetCylinderCount() const override; 18 | //THead GetNumberOfFormattedSides(TCylinder cyl) const override; 19 | //TSector ScanTrack(TCylinder cyl,THead head,Codec::PType pCodec=nullptr,PSectorId bufferId=nullptr,PWORD bufferLength=nullptr,PLogTime startTimesNanoseconds=nullptr,PBYTE pAvgGap3=nullptr) const override; 20 | //void GetTrackData(TCylinder cyl,THead head,PCSectorId bufferId,PCBYTE bufferNumbersOfSectorsToSkip,TSector nSectors,PSectorData *outBufferData,PWORD outBufferLengths,TFdcStatus *outFdcStatuses) override; 21 | //TStdWinError MarkSectorAsDirty(RCPhysicalAddress chs,BYTE nSectorsToSkip,PCFdcStatus pFdcStatus) override; 22 | //TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 23 | ///void EditSettings() override; 24 | //TStdWinError Reset() override; 25 | CTrackReader ReadTrack(TCylinder cyl,THead head) const override; 26 | TStdWinError SaveTrack(TCylinder cyl,THead head,const volatile bool &cancelled) const override; 27 | //TStdWinError FormatTrack(TCylinder cyl,THead head,TSector nSectors,PCSectorId bufferId,PCWORD bufferLength,PCFdcStatus bufferFdcStatus,BYTE gap3,BYTE fillerByte) override; 28 | //TStdWinError UnformatTrack(TCylinder cyl,THead head) override; 29 | void SetPathName(LPCTSTR lpszPathName,BOOL bAddToMRU=TRUE) override; 30 | }; 31 | 32 | #endif // KRYOFLUXSTREAMS_H 33 | -------------------------------------------------------------------------------- /Main/src/MSDOS7_FAT.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MSDOS7.h" 3 | 4 | const CMSDOS7::CFat::TType CMSDOS7::CFat::Types[]={ FAT12, FAT16, FAT32, UNDETERMINED }; 5 | 6 | CMSDOS7::CFat::CFat(const CMSDOS7 &msdos) 7 | // ctor 8 | : msdos(msdos) , type(UNDETERMINED) 9 | , firstFreeClusterTemp(-1) , nFreeClustersTemp(-1) { 10 | } 11 | 12 | #define FAT12_CLUSTERS_COUNT_MAX 4085 13 | #define FAT16_CLUSTERS_COUNT_MAX 65525 14 | #define FAT32_CLUSTERS_COUNT_MAX 0x03ffffff 15 | 16 | CMSDOS7::CFat::TType CMSDOS7::CFat::GetFatType(TCluster32 nClusters){ 17 | // determines and returns the FAT Type 18 | if (nClustersnFatCopies; nFatCopies--; ){ 56 | const TLogSector32 ls= bootSector->nReservedSectors // BootSector, etc. 57 | + 58 | d.quot+nFatCopies*bootSector->__getCountOfSectorsInOneFatCopy__(); // FAT 59 | if (const PCSectorData fatData=msdos.__getHealthyLogicalSectorData__(ls)){ 60 | *v++=fatData[d.rem]; 61 | goto nextByte; 62 | } 63 | } 64 | return MSDOS7_FAT_ERROR; 65 | nextByte: ; 66 | } 67 | switch (type){ 68 | case FAT12: 69 | value= cluster&1 70 | ? value>>4 // FAT12 value at odd address 71 | : value&0xfff;// FAT12 value at even address 72 | return value>=0xff0 73 | ? 0x0ffff000|value 74 | : value; 75 | case FAT16: 76 | return value>=0xfff0 77 | ? 0x0fff0000|value 78 | : value; 79 | case FAT32: 80 | return value&0x0fffffff; 81 | default: 82 | ASSERT(FALSE); 83 | } 84 | } 85 | return MSDOS7_FAT_ERROR; 86 | } 87 | 88 | bool CMSDOS7::CFat::SetClusterValue(TCluster32 cluster,DWORD newValue) const{ 89 | // True <=> NewValue of given Cluster successfully written into at least one copy of FAT, otherwise False 90 | if (const PCBootSector bootSector=msdos.boot.GetSectorData()){ 91 | // . modifying the information on first free Cluster 92 | const PFsInfoSector fsInfoSector=msdos.fsInfo.GetSectorData(); 93 | TCluster32 &rFirstFreeCluster= fsInfoSector!=nullptr ? fsInfoSector->firstFreeCluster : firstFreeClusterTemp; // take referential value either from FS-Info Sector, or this session only 94 | if (newValue==MSDOS7_FAT_CLUSTER_EMPTY && clusternFatCopies; nFatCopies--; ){ 124 | const TLogSector32 ls= bootSector->nReservedSectors // BootSector etc. 125 | + 126 | d.quot+nFatCopies*bootSector->__getCountOfSectorsInOneFatCopy__(); // FAT 127 | if (const PSectorData fatData=msdos.__getHealthyLogicalSectorData__(ls)){ 128 | fatData[d.rem] = fatData[d.rem]&*m | *v; 129 | byteWritten=true; 130 | msdos.__markLogicalSectorAsDirty__(ls); 131 | } 132 | } 133 | if (!byteWritten) 134 | return false; 135 | } 136 | return true; // NewValue written into available copies of FAT 137 | }else 138 | return false; 139 | } 140 | 141 | bool CMSDOS7::CFat::FreeChainOfClusters(TCluster32 cluster) const{ 142 | // True <=> the whole chain of Clusters until the EOF mark has been recorded as Free, beginning with the specified Cluster, otherwise False 143 | for( TCluster32 next; cluster!=MSDOS7_FAT_CLUSTER_EOF; cluster=next ){ 144 | next=GetClusterValue(cluster); 145 | if (next==MSDOS7_FAT_ERROR) // if Next Cluster cannot be read ... 146 | return false; // ... the chain is broken 147 | if (!SetClusterValue( cluster, MSDOS7_FAT_CLUSTER_EMPTY )) // if Cluster cannot be recorded as Free in any of FAT copies ... 148 | return false; // ... the chain is broken 149 | } 150 | return true; 151 | } 152 | -------------------------------------------------------------------------------- /Main/src/MSDOS7_FSInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MSDOS7.h" 3 | 4 | bool CMSDOS7::TFsInfoSector::__recognize__(WORD sectorLength) const{ 5 | // True <=> FS Info Sector recognized, otherwise False 6 | return sectorLength>=MSDOS7_SECTOR_LENGTH_STD 7 | && 8 | mark41615252==0x41615252 9 | && 10 | mark61417272==0x61417272 11 | && 12 | markAA550000==0xAA550000; 13 | } 14 | 15 | void CMSDOS7::TFsInfoSector::__init__(){ 16 | // initializes the FS Info Sector 17 | ::ZeroMemory( this, MSDOS7_SECTOR_LENGTH_STD ); 18 | mark41615252=0x41615252; 19 | mark61417272=0x61417272; 20 | nFreeClusters = firstFreeCluster = -1; // "-1" = information not available (will be set, for instance, in GetFirstFreeHealthyDataCluster) 21 | markAA550000=0xAA550000; 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | CMSDOS7::CFsInfoView::CFsInfoView(CMSDOS7 *msdos) 34 | // ctor 35 | : CCriticalSectorView( msdos, TPhysicalAddress::Invalid ) { 36 | } 37 | 38 | #define IMAGE tab.image 39 | #define MSDOS ((CMSDOS7 *)IMAGE->dos) 40 | 41 | CMSDOS7::PFsInfoSector CMSDOS7::CFsInfoView::GetSectorData() const{ 42 | // returns the data of FS Info Sector; returns Null if Sector doesn't exist or isn't readable 43 | // - if FS Info Sector doesn't exist, we are done 44 | if (MSDOS->fat.type!=CFat::FAT32) 45 | return nullptr; 46 | // - reading and recognizing the FS Info Sector 47 | if (const PCBootSector bootSector=MSDOS->boot.GetSectorData()) 48 | if (const PFsInfoSector fsInfo=(PFsInfoSector)MSDOS->__getHealthyLogicalSectorData__(bootSector->fat32.fsInfo)) 49 | if (fsInfo->__recognize__(MSDOS->formatBoot.sectorLength)) 50 | return fsInfo; 51 | else 52 | ::SetLastError( Utils::ErrorByOs(ERROR_VOLMGR_DISK_INVALID,ERROR_INVALID_DATA) ); 53 | // - FS Info Sector isn't readable or isn't recognized 54 | return nullptr; 55 | } 56 | 57 | void CMSDOS7::CFsInfoView::MarkSectorAsDirty() const{ 58 | // marks the FS Info Sector as dirty 59 | if (const PCBootSector bootSector=MSDOS->boot.GetSectorData()) 60 | if (MSDOS->fat.type==CFat::FAT32) 61 | MSDOS->__markLogicalSectorAsDirty__( bootSector->fat32.fsInfo ); 62 | } 63 | 64 | bool WINAPI CMSDOS7::CFsInfoView::__sectorModified__(PropGrid::PCustomParam,int){ 65 | // marking the Boot Sector as dirty 66 | const PMSDOS7 msdos=(PMSDOS7)CDos::GetFocused(); 67 | msdos->fsInfo.MarkSectorAsDirty(); 68 | msdos->image->UpdateAllViews(nullptr); 69 | return true; 70 | } 71 | 72 | void CMSDOS7::CFsInfoView::OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint){ 73 | // request to refresh the display of content 74 | // - changing to the FS-Info Sector (might have been switched elsewhere before, e.g. Boot error now recovered) 75 | if (const PCBootSector bootSector=MSDOS->boot.GetSectorData()) 76 | ChangeToSector( MSDOS->__logfyz__( bootSector->fat32.fsInfo ) ); 77 | else 78 | ChangeToSector( TPhysicalAddress::Invalid ); 79 | // - base 80 | __super::OnUpdate( pSender, lHint, pHint ); 81 | // - populating the PropertyGrid with values from the FS-Info Sector (if any found) 82 | const PFsInfoSector fsInfo=GetSectorData(); 83 | PropGrid::AddDisabledProperty( propGrid.m_hWnd, nullptr, _T("Status"), 84 | fsInfo?"Recognized":"Not recognized", 85 | PropGrid::String::DefineFixedLengthEditorA(0) 86 | ); 87 | if (fsInfo){ 88 | // FS-Info Sector found 89 | const HANDLE hClusters=PropGrid::AddCategory(propGrid.m_hWnd,nullptr,_T("Clusters")); 90 | static constexpr PropGrid::Integer::TUpDownLimits limits={ 2, INT_MAX }; 91 | PropGrid::AddProperty( propGrid.m_hWnd, hClusters, _T("First free"), 92 | &fsInfo->firstFreeCluster, 93 | PropGrid::Integer::DefineEditor( sizeof(TCluster32), limits, __sectorModified__ ) 94 | ); 95 | PropGrid::AddProperty( propGrid.m_hWnd, hClusters, _T("Count of free"), 96 | &fsInfo->nFreeClusters, 97 | PropGrid::Integer::DefineEditor( sizeof(TCluster32), PropGrid::Integer::TUpDownLimits::PositiveInteger, __sectorModified__ ) 98 | ); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Main/src/MainWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #define TDI_INSTANCE app.GetMainWindow()->pTdi 5 | #define TDI_HWND TDI_INSTANCE->m_hWnd 6 | 7 | 8 | class CMainWindow sealed:public CFrameWnd{ 9 | DECLARE_MESSAGE_MAP() 10 | private: 11 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 12 | BOOL PreTranslateMessage(PMSG pMsg) override; 13 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 14 | afx_msg void OnClose(); 15 | afx_msg void OnDropFiles(HDROP dropInfo); 16 | afx_msg void OnLButtonDblClk(UINT,CPoint); 17 | afx_msg void OnInitMenu(CMenu *menu); 18 | afx_msg void __imageOperation_updateUI__(CCmdUI *pCmdUI); 19 | afx_msg void __switchToNextTab__(); 20 | afx_msg void __switchToPrevTab__(); 21 | afx_msg void __closeCurrentTab__(); 22 | afx_msg void __closeCurrentTab_updateUI__(CCmdUI *pCmdUI); 23 | afx_msg void __openUrl_checkForUpdates__(); 24 | afx_msg void __openUrl_checkForUpdates_updateUI__(CCmdUI *pCmdUI); 25 | afx_msg void __openUrl_faq__(); 26 | afx_msg void OpenUrl_Donate(); 27 | afx_msg void __openUrl_reportBug__(); 28 | afx_msg void __openUrl_repository__(); 29 | afx_msg void __openUrl_tutorials__(); 30 | afx_msg void OpenYahelRepositoryUrl(); 31 | afx_msg void ShowYahelAbout(); 32 | afx_msg void __openUrl_credits__(); 33 | public: 34 | struct CDynMenu:public CMenu{ 35 | const HACCEL hAccel; 36 | 37 | CDynMenu(UINT nResId); 38 | ~CDynMenu(); 39 | public: 40 | void Show(UINT position) const; 41 | void Hide() const; 42 | }; 43 | 44 | class CDockableToolBar sealed:public CToolBar{ 45 | const UINT nResId,id; 46 | 47 | void OnUpdateCmdUI(CFrameWnd* pTarget,BOOL bDisableIfNoHndler) override; 48 | public: 49 | CDockableToolBar(UINT nResId,UINT id); 50 | 51 | void Show(const CToolBar &rDockNextTo); 52 | void Hide(); 53 | }; 54 | 55 | class CTdiTemplate sealed:public CSingleDocTemplate{ 56 | public: 57 | static CTdiTemplate *pSingleInstance; 58 | 59 | CTdiTemplate(); 60 | ~CTdiTemplate(); 61 | 62 | inline CDocument *GetDocument() const{ return m_pOnlyDoc; } // returns the main Image (usually a disk) 63 | bool __closeDocument__(); 64 | 65 | #if _MFC_VER>=0x0A00 66 | CDocument *OpenDocumentFile(LPCTSTR lpszPathName,BOOL bAddToMRU,BOOL bMakeVisible) override; 67 | #else 68 | CDocument *OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible=TRUE) override; 69 | #endif 70 | }; 71 | 72 | class CTdiView sealed:public CCtrlView{ 73 | friend class CMainWindow; 74 | public: 75 | typedef CView *PView; 76 | 77 | typedef struct TTab sealed{ 78 | static void WINAPI OnOptionalTabClosing(CTdiCtrl::TTab::PContent tab); 79 | 80 | const PImage image; // the Image that gets into focus when switched to this Tab (e.g. CSpectrumDos::CTape) 81 | const CDynMenu menu; 82 | const PView view; 83 | CDockableToolBar toolbar; 84 | 85 | TTab(UINT nMenuResId,UINT nToolbarResId,UINT nToolBarId,PImage image,PView _view); 86 | 87 | inline bool IsPartOfImage() const{ return image!=nullptr; } // True <=> the Tab is part of an Image (e.g. a WebPage usually isn't), otherwise False 88 | } *PTab; 89 | private: 90 | static void WINAPI __fnShowContent__(PVOID pTdi,LPCVOID pTab); 91 | static void WINAPI __fnHideContent__(PVOID pTdi,LPCVOID pTab); 92 | static void WINAPI __fnRepaintContent__(LPCVOID pTab); 93 | static HWND WINAPI __fnGetHwnd__(LPCVOID pTab); 94 | 95 | const CBackgroundAction recencyStatusThread; 96 | CDockableToolBar toolbarMisc; 97 | PTab pCurrentTab; 98 | 99 | LRESULT WindowProc(UINT msg,WPARAM wParam,LPARAM lParam) override; 100 | public: 101 | static UINT AFX_CDECL RecencyDetermination_thread(PVOID pCancelableAction); 102 | 103 | CTdiView(); 104 | 105 | void CloseAllTabsOfImage(PCImage image); 106 | inline PTab GetCurrentTab() const{ return pCurrentTab; } 107 | void RepopulateGuidePost() const; 108 | } *pTdi; 109 | 110 | class CMessageBar:protected CStatusBar{ 111 | HWND hGlyph,hSysLink,hCloseBtn; 112 | protected: 113 | static int D; // dimension 114 | const WCHAR glyph; 115 | CString msgHyperlink; 116 | 117 | virtual void HyperlinkClicked(LPCWSTR id) const; 118 | LRESULT WindowProc(UINT msg,WPARAM wParam,LPARAM lParam) override; 119 | public: 120 | CMessageBar(LPCTSTR msgHyperlink,WCHAR webdingsGlyph=L'\xf069'); 121 | ~CMessageBar(); 122 | 123 | void Show(); 124 | }; 125 | 126 | static void SetStatusBarTextReady(); 127 | static void __resetStatusBar__(); 128 | static void __setStatusBarText__(LPCTSTR text); 129 | 130 | CToolBar toolbar; 131 | CStatusBar statusBar; 132 | 133 | void OpenWebPage(LPCTSTR tabCaption,LPCTSTR url); 134 | void OpenRepositoryWebPage(LPCTSTR tabCaption,LPCTSTR documentName); 135 | void OpenApplicationPresentationWebPage(LPCTSTR tabCaption,LPCTSTR documentName); 136 | void OpenApplicationFaqWebPage(LPCTSTR documentName); 137 | afx_msg void EditAutomaticRecognitionSequence(); 138 | }; 139 | 140 | 141 | #endif // MAINWINDOW_H 142 | -------------------------------------------------------------------------------- /Main/src/OptionalLibAPIs.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTLIBAPIS_H 2 | #define OPTLIBAPIS_H 3 | 4 | namespace UxTheme 5 | { 6 | HTHEME OpenThemeData(HWND hwnd,LPCWSTR pszClassList); 7 | HRESULT DrawThemeBackground(HTHEME hTheme,HDC hdc,int iPartId,int iStateId,LPCRECT pRect,LPCRECT pClipRect); 8 | HRESULT CloseThemeData(HTHEME hTheme); 9 | } 10 | 11 | 12 | #include 13 | #include 14 | 15 | namespace SetupDi 16 | { 17 | extern const GUID GUID_DEVINTERFACE_USB_DEVICE; 18 | 19 | namespace Lib{ 20 | HDEVINFO GetClassDevs( 21 | __in_opt CONST GUID &ClassGuid, 22 | __in_opt PCTSTR Enumerator, 23 | __in_opt HWND hwndParent, 24 | __in DWORD Flags 25 | ); 26 | BOOL EnumDeviceInterfaces( 27 | __in HDEVINFO DeviceInfoSet, 28 | __in_opt PSP_DEVINFO_DATA DeviceInfoData, 29 | __in CONST GUID &InterfaceClassGuid, 30 | __in DWORD MemberIndex, 31 | __out PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData 32 | ); 33 | BOOL GetDeviceInterfaceDetail( 34 | __in HDEVINFO DeviceInfoSet, 35 | __in PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 36 | __out_bcount_opt(DeviceInterfaceDetailDataSize) PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, 37 | __in DWORD DeviceInterfaceDetailDataSize, 38 | __out_opt PDWORD RequiredSize, 39 | __out_opt PSP_DEVINFO_DATA DeviceInfoData 40 | ); 41 | BOOL GetDevicePropertyW( 42 | __in HDEVINFO DeviceInfoSet, 43 | __in PSP_DEVINFO_DATA DeviceInfoData, 44 | __in CONST DEVPROPKEY &PropertyKey, 45 | __out DEVPROPTYPE &PropertyType, 46 | __out_bcount_opt(PropertyBufferSize) PBYTE PropertyBuffer, 47 | __in DWORD PropertyBufferSize, 48 | __out_opt PDWORD RequiredSize, 49 | __in DWORD Flags 50 | ); 51 | BOOL GetDeviceRegistryProperty( 52 | __in HDEVINFO DeviceInfoSet, 53 | __in PSP_DEVINFO_DATA DeviceInfoData, 54 | __in DWORD Property, 55 | __out_opt PDWORD PropertyRegDataType, 56 | __out_bcount_opt(PropertyBufferSize) PBYTE PropertyBuffer, 57 | __in DWORD PropertyBufferSize, 58 | __out_opt PDWORD RequiredSize 59 | ); 60 | BOOL DestroyDeviceInfoList( 61 | __in HDEVINFO DeviceInfoSet 62 | ); 63 | } 64 | 65 | CString GetDevicePath(const GUID &interfaceGuid,LPCWSTR deviceNameSubstr=nullptr); 66 | } 67 | 68 | 69 | #undef _MP 70 | #include "winusb.h" 71 | 72 | namespace WinUsb 73 | { 74 | namespace Lib{ 75 | BOOL Initialize( 76 | __in HANDLE DeviceHandle, 77 | __out PWINUSB_INTERFACE_HANDLE InterfaceHandle 78 | ); 79 | BOOL GetAssociatedInterface( 80 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 81 | __in UCHAR AssociatedInterfaceIndex, 82 | __out PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle 83 | ); 84 | BOOL SetPipePolicy( 85 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 86 | __in UCHAR PipeID, 87 | __in ULONG PolicyType, 88 | __in ULONG ValueLength, 89 | __in_bcount(ValueLength) PVOID Value 90 | ); 91 | BOOL Free( 92 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle 93 | ); 94 | BOOL GetDescriptor( 95 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 96 | __in UCHAR DescriptorType, 97 | __in UCHAR Index, 98 | __in USHORT LanguageID, 99 | __out_bcount_part_opt(BufferLength, *LengthTransferred) PUCHAR Buffer, 100 | __in ULONG BufferLength, 101 | __out PULONG LengthTransferred 102 | ); 103 | BOOL ReadPipe( 104 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 105 | __in UCHAR PipeID, 106 | __out_bcount_part_opt(BufferLength,*LengthTransferred) PUCHAR Buffer, 107 | __in ULONG BufferLength, 108 | __out_opt PULONG LengthTransferred, 109 | __in_opt LPOVERLAPPED Overlapped 110 | ); 111 | BOOL WritePipe( 112 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 113 | __in UCHAR PipeID, 114 | __in_bcount(BufferLength) PUCHAR Buffer, 115 | __in ULONG BufferLength, 116 | __out_opt PULONG LengthTransferred, 117 | __in_opt LPOVERLAPPED Overlapped 118 | ); 119 | BOOL ControlTransfer( 120 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 121 | __in WINUSB_SETUP_PACKET SetupPacket, 122 | __out_bcount_part_opt(BufferLength, *LengthTransferred) PUCHAR Buffer, 123 | __in ULONG BufferLength, 124 | __out_opt PULONG LengthTransferred, 125 | __in_opt LPOVERLAPPED Overlapped 126 | ); 127 | BOOL ResetPipe( 128 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 129 | __in UCHAR PipeID 130 | ); 131 | BOOL AbortPipe( 132 | __in WINUSB_INTERFACE_HANDLE InterfaceHandle, 133 | __in UCHAR PipeID 134 | ); 135 | } 136 | 137 | 138 | struct TDevInterfaceHandle{ 139 | WINUSB_INTERFACE_HANDLE hLibrary; 140 | WINUSB_INTERFACE_HANDLE hDeviceInterface; 141 | 142 | void Clear(); 143 | bool ConnectToInterface(HANDLE hDevice,UCHAR interfaceIndex); 144 | void DisconnectFromInterface(); 145 | LPCSTR GetProductName(PCHAR productNameBuffer,BYTE productNameBufferLength) const; 146 | void SetPipePolicy(UCHAR bulkPipeId,BYTE enable,DWORD msTimeout) const; 147 | void ClearIoPipes(UCHAR bulkInPipeId,UCHAR bulkOutPipeId) const; 148 | }; 149 | } 150 | 151 | 152 | #include "CapsLibAll.h" 153 | 154 | namespace CAPS 155 | { 156 | SDWORD Init(); 157 | SDWORD Exit(); 158 | SDWORD AddImage(); 159 | SDWORD RemImage(SDWORD id); 160 | SDWORD LockImage(SDWORD id, LPCSTR name); 161 | SDWORD LockImageMemory(SDWORD id, PUBYTE buffer, UDWORD length, UDWORD flag); 162 | SDWORD UnlockImage(SDWORD id); 163 | SDWORD LoadImage(SDWORD id, UDWORD flag); 164 | SDWORD GetImageInfo(PCAPSIMAGEINFO pi, SDWORD id); 165 | SDWORD LockTrack(PVOID ptrackinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD flag); 166 | SDWORD UnlockTrack(SDWORD id, UDWORD cylinder, UDWORD head); 167 | SDWORD UnlockAllTracks(SDWORD id); 168 | PCHAR GetPlatformName(UDWORD pid); 169 | SDWORD GetVersionInfo(PVOID pversioninfo, UDWORD flag); 170 | UDWORD FdcGetInfo(SDWORD iid, PCAPSFDC pc, SDWORD ext); 171 | SDWORD FdcInit(PCAPSFDC pc); 172 | void FdcReset(PCAPSFDC pc); 173 | void FdcEmulate(PCAPSFDC pc, UDWORD cyclecnt); 174 | UDWORD FdcRead(PCAPSFDC pc, UDWORD address); 175 | void FdcWrite(PCAPSFDC pc, UDWORD address, UDWORD data); 176 | SDWORD FdcInvalidateTrack(PCAPSFDC pc, SDWORD drive); 177 | SDWORD FormatDataToMFM(PVOID pformattrack, UDWORD flag); 178 | SDWORD GetInfo(PVOID pinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD inftype, UDWORD infid); 179 | SDWORD SetRevolution(SDWORD id, UDWORD value); 180 | SDWORD GetImageType(PCHAR name); 181 | SDWORD GetImageTypeMemory(PUBYTE buffer, UDWORD length); 182 | SDWORD GetDebugRequest(); 183 | } 184 | 185 | #endif // OPTLIBAPIS_H 186 | -------------------------------------------------------------------------------- /Main/src/SCL.h: -------------------------------------------------------------------------------- 1 | #ifndef SCL_H 2 | #define SCL_H 3 | 4 | class CSCL sealed:public CImageRaw{ 5 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 6 | public: 7 | static const TProperties Properties; 8 | 9 | CSCL(); 10 | 11 | TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 12 | }; 13 | 14 | #endif // SCL_H 15 | -------------------------------------------------------------------------------- /Main/src/SCP.h: -------------------------------------------------------------------------------- 1 | #ifndef SCP_H 2 | #define SCP_H 3 | 4 | class CSCP sealed:public CSuperCardProBase{ 5 | mutable CFile f; 6 | 7 | DWORD tdhOffsets[84][2]; // Track Data Header offsets 8 | 9 | TStdWinError SaveAllModifiedTracks(LPCTSTR lpszPathName,CActionProgress &ap) override; 10 | public: 11 | static const TProperties Properties; 12 | 13 | CSCP(); 14 | 15 | BOOL OnOpenDocument(LPCTSTR lpszPathName) override; 16 | TStdWinError SaveTrack(TCylinder cyl,THead head,const volatile bool &cancelled) const; 17 | CTrackReader ReadTrack(TCylinder cyl,THead head) const override; 18 | TStdWinError Reset() override; 19 | }; 20 | 21 | #endif // SCP_H 22 | -------------------------------------------------------------------------------- /Main/src/SpectrumDos_ZXRom.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/SpectrumDos_ZXRom.cpp -------------------------------------------------------------------------------- /Main/src/SuperCardProBase.h: -------------------------------------------------------------------------------- 1 | #ifndef SUPERCARDPROBASE_H 2 | #define SUPERCARDPROBASE_H 3 | 4 | #define INI_SUPERCARDPRO _T("Scpflux") 5 | 6 | #define SCP_BUFFER_CAPACITY 2000000 7 | 8 | class CSuperCardProBase abstract:public CCapsBase{ 9 | protected: 10 | struct TParamsEtc{ 11 | const LPCTSTR iniSection; 12 | // persistent (saved and loaded) 13 | CString firmwareFileName; 14 | // volatile (current session only) 15 | //none 16 | 17 | TParamsEtc(LPCTSTR iniSection); 18 | ~TParamsEtc(); 19 | } paramsEtc; 20 | 21 | #pragma pack(1) 22 | struct THeader{ 23 | union{ 24 | struct{ 25 | char signature[3]; // "SCP" 26 | BYTE revision; // (version << 4) | revision, e.g. 0x24 = v2.4 27 | }; 28 | DWORD signatureAndRevision; 29 | }; 30 | enum:BYTE{ 31 | CBM_C64_FLOPPY =0x00, 32 | CBM_AMIGA_FLOPPY_DD =0x04, 33 | CBM_AMIGA_FLOPPY_HD =0x08, 34 | 35 | ATARI_FM_FLOPPY_SS =0x10, 36 | ATARI_FM_FLOPPY_DS =0x11, 37 | ATARI_FM_FLOPPY_EX =0x12, 38 | ATARI_ST_FLOPPY_SS =0x14, 39 | ATARI_ST_FLOPPY_DS =0x15, 40 | 41 | APPLE_II =0x20, 42 | APPLE_II_PRO =0x21, 43 | APPLE_FLOPPY_400K =0x24, 44 | APPLE_FLOPPY_800K =0x25, 45 | APPLE_FLOPPY_HD_350 =0x26, 46 | 47 | PC_FLOPPY_SD =0x30, 48 | PC_FLOPPY_DD =0x31, 49 | PC_FLOPPY_HD_525 =0x32, 50 | PC_FLOPPY_HD_350 =0x33, 51 | 52 | TANDY_TRS80_SS_SD =0x40, 53 | TANDY_TRS80_SS_DD =0x41, 54 | TANDY_TRS80_DS_SD =0x42, 55 | TANDY_TRS80_DS_DD =0x43, 56 | 57 | TI_994A =0x50, 58 | 59 | ROLAND_D20 =0x60, 60 | 61 | AMSTRAD_CPC =0x70, 62 | 63 | OTHER_FLOPPY_SD =0x80, 64 | OTHER_FLOPPY_HD_525 =0x81, 65 | OTHER_FLOPPY_DD =0x84, 66 | OTHER_FLOPPY_HD_350 =0x85, 67 | 68 | TAPE_GCR1 =0xE0, 69 | TAPE_GCR2 =0xE1, 70 | TAPE_MFM =0xE2, 71 | 72 | HDD_MFM =0xF0, 73 | HDD_RLL =0xF1 74 | } deviceDiskType; // device/disk 75 | BYTE nAvailableRevolutions; // number of stored (always FULL) Revolutions 76 | BYTE firstTrack; 77 | BYTE lastTrack; 78 | struct{ 79 | BYTE indexAligned:1; // True <=> index-synchronised, otherwise data start randomly in a Revolution and roll over indices in 200/166ms intervals (300/360rpm drives, respectively) 80 | BYTE tpi96:1; // True <=> 96 TPI drive, otherwise 48 TPI 81 | BYTE rpm360:1; // True <=> 360 RPM drive, otherwise 300 RPM 82 | BYTE normalized:1; // True <=> normalized fluxes, otherwise preservation quality 83 | BYTE modifiable:1; // True <=> read/write Image, otherwise read-only 84 | BYTE footerPresent:1; // True <=> Footer blocks present, otherwise no Footer 85 | BYTE extended:1; // True <=> this Image is NOT solely for floppy drives, otherwise this Image is intended ONLY for floppy drives 86 | BYTE createdUsingScp:1; // True <=> this Image has been created by official SuperCard Pro device/software, otherwise 3rd party device/software used 87 | } flags; 88 | BYTE nFluxCellBits; // 0 = 16 bits, non-zero = number of bits 89 | enum:BYTE{ 90 | BOTH_HEADS, 91 | HEAD_0_ONLY, 92 | HEAD_1_ONLY 93 | } heads; 94 | BYTE resolutionMul; // multiplier of the basic 25ns resolution 95 | DWORD checksum; // 32-bit checksum from after header to EOF (unless FLAG_MODE is set) 96 | 97 | THeader(); 98 | 99 | bool IsValid() const; 100 | bool IsSupported() const; 101 | inline TLogTime GetSampleClockTime() const{ return TIME_NANO(25)*std::max((BYTE)1,resolutionMul); } 102 | } header; 103 | 104 | struct TRevolution sealed{ 105 | DWORD durationCounter; // length of the Revolution (=N); total time in nanoseconds then obtained as N*25ns 106 | DWORD nFluxes; 107 | DWORD iFluxDataBegin; 108 | }; 109 | 110 | #pragma pack(1) 111 | struct TTrackDataHeader sealed{ 112 | char signature[3]; // "TRK" 113 | BYTE trackNumber; 114 | TRevolution revolutions[Revolution::MAX]; // only first N are valid, see the Header 115 | 116 | TTrackDataHeader(BYTE trackNumber); 117 | 118 | bool IsTrack(BYTE trackNumber) const; 119 | bool Read(CFile &fSeeked,TCylinder cyl,THead head,BYTE nAvailableRevolutions); 120 | void Write(CFile &fSeeked,BYTE nAvailableRevolutions) const; 121 | const TRevolution &GetLastRevolution(BYTE nAvailableRevolutions) const; 122 | BYTE GetDistinctRevolutionCount(BYTE nAvailableRevolutions,PBYTE pOutUniqueRevs=nullptr) const; 123 | DWORD GetFullTrackLengthInBytes(const THeader &header) const; 124 | DWORD GetFullTrackCapacityInBytes(Medium::PCProperties mp,const THeader &header) const; 125 | }; 126 | 127 | 128 | const LPCTSTR firmware; 129 | 130 | CSuperCardProBase(PCProperties properties,char realDriveLetter,LPCTSTR iniSection,LPCTSTR firmware); 131 | 132 | CTrackReaderWriter StreamToTrack(CFile &fTdhAndFluxes,TCylinder cyl,THead head) const; 133 | DWORD TrackToStream(CTrackReader tr,CFile &fTdhAndFluxes,TCylinder cyl,THead head,bool &rOutAdjusted) const; 134 | public: 135 | //static DWORD TimeToStdSampleCounter(TLogTime t); 136 | 137 | //TStdWinError SetMediumTypeAndGeometry(PCFormat pFormat,PCSide sideMap,TSector firstSectorNumber) override; 138 | bool EditSettings(bool initialEditing) override; 139 | void EnumSettings(CSettings &rOut) const override; 140 | //TStdWinError Reset() override; 141 | }; 142 | 143 | #endif // SUPERCARDPROBASE_H 144 | -------------------------------------------------------------------------------- /Main/src/TRDOS504.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TRDOS.h" 3 | 4 | static PDos __instantiate__(PImage image,PCFormat pFormatBoot){ 5 | return new CTRDOS504( image, pFormatBoot, &CTRDOS504::Properties ); 6 | } 7 | 8 | TStdWinError CTRDOS504::__recognizeDisk__(PImage image,PFormat pFormatBoot){ 9 | // returns the result of attempting to recognize Image by this DOS as follows: ERROR_SUCCESS = recognized, ERROR_CANCELLED = user cancelled the recognition sequence, any other error = not recognized 10 | if (const TStdWinError err=__super::__recognizeDisk__(image,pFormatBoot)) 11 | return err; 12 | else if (TBootSector::Get(image)->__getLabelLengthEstimation__()==TRDOS504_BOOT_LABEL_LENGTH_MAX) 13 | return ERROR_SUCCESS; 14 | else 15 | return ERROR_UNRECOGNIZED_VOLUME; 16 | } 17 | 18 | const CDos::TProperties CTRDOS504::Properties={ 19 | TRDOS_NAME_BASE _T(" 5.04"), // name 20 | MAKE_DOS_ID('T','R','D','O','S','5','0','4'), // unique identifier 21 | 42, // recognition priority (the bigger the number the earlier the DOS gets crack on the image) 22 | 0, // the Cylinder where usually the Boot Sector (or its backup) is found 23 | __recognizeDisk__, // recognition function 24 | __instantiate__, // instantiation function 25 | Medium::FLOPPY_DD_ANY, 26 | &TRD::Properties, // the most common Image to contain data for this DOS (e.g. *.D80 Image for MDOS) 27 | 4, // number of std Formats 28 | StdFormats, // std Formats 29 | Codec::MFM, // a set of Codecs this DOS supports 30 | TRDOS503_TRACK_SECTORS_COUNT,TRDOS503_TRACK_SECTORS_COUNT, // range of supported number of Sectors 31 | TRDOS503_SECTOR_RESERVED_COUNT, // minimal total number of Sectors required 32 | 1, // maximum number of Sector in one Cluster (must be power of 2) 33 | -1, // maximum size of a Cluster (in Bytes) 34 | 0,0, // range of supported number of allocation tables (FATs) 35 | 128,128, // range of supported number of root Directory entries 36 | TRDOS503_SECTOR_FIRST_NUMBER, // lowest Sector number on each Track 37 | 0,TDirectoryEntry::END_OF_DIR, // regular Sector and Directory Sector filler Byte 38 | 0,0 // number of reserved Bytes at the beginning and end of each Sector 39 | }; 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | CTRDOS504::CTRDOS504(PImage image,PCFormat pFormatBoot,PCProperties pTrdosProps) 49 | // ctor 50 | : CTRDOS503( image, pFormatBoot, pTrdosProps ) { 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Main/src/TRDOS505.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TRDOS.h" 3 | 4 | static PDos __instantiate__(PImage image,PCFormat pFormatBoot){ 5 | return new CTRDOS505(image,pFormatBoot); 6 | } 7 | 8 | TStdWinError CTRDOS505::__recognizeDisk__(PImage image,PFormat pFormatBoot){ 9 | // returns the result of attempting to recognize Image by this DOS as follows: ERROR_SUCCESS = recognized, ERROR_CANCELLED = user cancelled the recognition sequence, any other error = not recognized 10 | if (const TStdWinError err=CTRDOS503::__recognizeDisk__(image,pFormatBoot)) // explicitly calling TR-DOS 5.03 recognition routine, thus bypassing TR-DOS 5.04 recognition routine 11 | return err; 12 | else if (TBootSector::Get(image)->__getLabelLengthEstimation__()==TRDOS505_BOOT_LABEL_LENGTH_MAX) 13 | return ERROR_SUCCESS; 14 | else 15 | return ERROR_UNRECOGNIZED_VOLUME; 16 | } 17 | 18 | const CDos::TProperties CTRDOS505::Properties={ 19 | TRDOS_NAME_BASE _T(" 5.05"), // name 20 | MAKE_DOS_ID('T','R','D','O','S','5','0','5'), // unique identifier 21 | 44, // recognition priority (the bigger the number the earlier the DOS gets crack on the image) 22 | 0, // the Cylinder where usually the Boot Sector (or its backup) is found 23 | __recognizeDisk__, // recognition function 24 | __instantiate__, // instantiation function 25 | Medium::FLOPPY_DD_ANY, 26 | &TRD::Properties, // the most common Image to contain data for this DOS (e.g. *.D80 Image for MDOS) 27 | 4, // number of std Formats 28 | StdFormats, // std Formats 29 | Codec::MFM, // a set of Codecs this DOS supports 30 | TRDOS503_TRACK_SECTORS_COUNT,TRDOS503_TRACK_SECTORS_COUNT, // range of supported number of Sectors 31 | TRDOS503_SECTOR_RESERVED_COUNT, // minimal total number of Sectors required 32 | 1, // maximum number of Sector in one Cluster (must be power of 2) 33 | -1, // maximum size of a Cluster (in Bytes) 34 | 0,0, // range of supported number of allocation tables (FATs) 35 | 128,128, // range of supported number of root Directory entries 36 | TRDOS503_SECTOR_FIRST_NUMBER, // lowest Sector number on each Track 37 | 0,TDirectoryEntry::END_OF_DIR, // regular Sector and Directory Sector filler Byte 38 | 0,0 // number of reserved Bytes at the beginning and end of each Sector 39 | }; 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | CTRDOS505::CTRDOS505(PImage image,PCFormat pFormatBoot) 49 | // ctor 50 | : CTRDOS504( image, pFormatBoot, &Properties ) { 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Main/src/TdiTemplate.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | CMainWindow::CTdiTemplate *CMainWindow::CTdiTemplate::pSingleInstance; 4 | 5 | CMainWindow::CTdiTemplate::CTdiTemplate() 6 | // ctor 7 | // - base 8 | : CSingleDocTemplate( IDR_MAINFRAME, nullptr, nullptr, nullptr ){ 9 | m_bAutoDelete=FALSE; // for the Template to be not destroyed when it contains no open documents (no open Images) 10 | // - creating the MainWindow 11 | app.m_pMainWnd=new CMainWindow; 12 | app.GetMainWindow()->LoadFrame( m_nIDResource, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, nullptr, nullptr ); 13 | pSingleInstance=this; 14 | } 15 | 16 | CMainWindow::CTdiTemplate::~CTdiTemplate(){ 17 | // dtor 18 | if (m_pOnlyDoc){ 19 | m_pOnlyDoc->SetModifiedFlag(FALSE); // don't ask about saving modified Image 20 | __closeDocument__(); 21 | } 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | bool CMainWindow::CTdiTemplate::__closeDocument__(){ 34 | // closes the main Image (usually a disk) 35 | if (m_pOnlyDoc){ 36 | if (!m_pOnlyDoc->CanCloseFrame(app.GetMainWindow())) // if refused to close the document ... 37 | return false; // ... keeping it open 38 | if (app.m_pMainWnd){ // may not exist if the application is starting or closing 39 | ( (CFrameWnd *)app.m_pMainWnd )->OnUpdateFrameTitle(FALSE); // updating the MainWindow's title (now without document) 40 | } 41 | if (m_pOnlyDoc){ 42 | m_pOnlyDoc->OnCloseDocument(); 43 | m_pOnlyDoc=nullptr; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | typedef CDocument *PDocument; 50 | 51 | #if _MFC_VER>=0x0A00 52 | PDocument CMainWindow::CTdiTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bAddToMRU,BOOL bMakeVisible){ 53 | #else 54 | PDocument CMainWindow::CTdiTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible){ 55 | #endif 56 | // opens the document stored in specified file 57 | // - closing current document 58 | if (!__closeDocument__()) 59 | return nullptr; 60 | // - creating a new document doesn't require opening any existing document 61 | if (!lpszPathName) 62 | return nullptr; 63 | // - opening the requested document (caller is now to load the document, and then call AddDocument) 64 | if (const CImage::PCProperties p=CImage::DetermineType(lpszPathName)) 65 | return p->fnInstantiate(nullptr); // instantiating recognized file Image; Null as buffer = one Image represents only one "device" whose name is known at compile-time 66 | return nullptr; 67 | } 68 | -------------------------------------------------------------------------------- /Main/src/Utils.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/Utils.cpp -------------------------------------------------------------------------------- /Main/src/ViewBoot.h: -------------------------------------------------------------------------------- 1 | #ifndef BOOTVIEW_H 2 | #define BOOTVIEW_H 3 | 4 | #define BOOT_SECTOR_TAB_LABEL _T("Boot sector") 5 | #define BOOT_SECTOR_LOCATION_STRING _T("boot sector") 6 | #define BOOT_SECTOR_ADVANCED _T("Advanced") 7 | #define BOOT_SECTOR_UPDATE_ONLINE _T("Update on-line") 8 | #define BOOT_SECTOR_UPDATE_ONLINE_HYPERLINK _T("Update on-line") 9 | 10 | class CBootView:public CCriticalSectorView{ 11 | static void __informationWithCheckableShowNoMore__(LPCTSTR text,LPCTSTR messageId); 12 | static bool WINAPI __confirmCriticalValueInBoot__(PVOID criticalValueId,int newValue); 13 | static bool WINAPI __updateFatAfterChangingCylinderCount__(PVOID,int newValue); 14 | protected: 15 | typedef struct TCommonBootParameters sealed{ 16 | unsigned geometryCategory :1; 17 | unsigned chs:1; 18 | unsigned sectorLength:1; 19 | unsigned volumeCategory :1; 20 | struct{ 21 | BYTE length; // non-zero = this structure is valid and the Label will be added to PropertyGrid 22 | PCHAR bufferA; 23 | char fillerByte; 24 | PropGrid::String::TOnValueConfirmedA onLabelConfirmedA; 25 | } label; 26 | struct{ 27 | PVOID buffer; // non-Null = this structure is valid and ID will be added to PropertyGrid 28 | BYTE bufferCapacity; 29 | } id; 30 | unsigned clusterSize:1; 31 | } &RCommonBootParameters; 32 | 33 | CBootView(PDos dos,RCPhysicalAddress rChsBoot); 34 | 35 | void OnSectorChanging() const override; 36 | void OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint) override; 37 | virtual void GetCommonBootParameters(RCommonBootParameters rParam,PSectorData boot)=0; 38 | virtual void AddCustomBootParameters(HWND hPropGrid,HANDLE hGeometry,HANDLE hVolume,const TCommonBootParameters &rParam,PSectorData boot)=0; 39 | public: 40 | static void WINAPI __bootSectorModified__(PropGrid::PCustomParam); 41 | static bool WINAPI __bootSectorModified__(PropGrid::PCustomParam,int); 42 | static bool WINAPI __bootSectorModifiedA__(PropGrid::PCustomParam,LPCSTR,short); 43 | static bool WINAPI __bootSectorModified__(PropGrid::PCustomParam,bool); 44 | static bool WINAPI __bootSectorModified__(PropGrid::PCustomParam,PropGrid::Enum::UValue); 45 | }; 46 | 47 | #endif // BOOTVIEW_H 48 | -------------------------------------------------------------------------------- /Main/src/ViewCriticalSector.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | const CCriticalSectorView *CCriticalSectorView::pCurrentlyShown; 4 | 5 | #define IMAGE tab.image 6 | #define DOS IMAGE->dos 7 | 8 | void WINAPI CCriticalSectorView::__updateCriticalSectorView__(PropGrid::PCustomParam){ 9 | // refreshes any current View 10 | const short iCurSel=PropGrid::GetCurrentlySelectedProperty( pCurrentlyShown->propGrid.m_hWnd ); 11 | CDos::GetFocused()->image->UpdateAllViews(nullptr); 12 | PropGrid::SetCurrentlySelectedProperty( pCurrentlyShown->propGrid.m_hWnd, iCurSel ); 13 | } 14 | 15 | bool CCriticalSectorView::__isValueBeingEditedInPropertyGrid__(){ 16 | // True <=> some value is right now being edited in PropertyGrid, otherwise False 17 | return pCurrentlyShown!=nullptr && PropGrid::IsValueBeingEdited(); 18 | } 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | CCriticalSectorView::CSectorReaderWriter::CSectorReaderWriter(PCDos dos,RCPhysicalAddress chs) 29 | // ctor 30 | : CDos::CFileReaderWriter(dos,chs) { 31 | } 32 | 33 | void CCriticalSectorView::CSectorReaderWriter::Write(LPCVOID lpBuf,UINT nCount){ 34 | // tries to write given NumberOfBytes from the Buffer to the current Position (increments the Position by the number of Bytes actually written) 35 | __super::Write(lpBuf,nCount); 36 | pCurrentlyShown->OnSectorChanging(); 37 | } 38 | 39 | HRESULT CCriticalSectorView::CSectorReaderWriter::Clone(IStream **ppstm){ 40 | // creates an exact copy of this object 41 | if (ppstm){ 42 | *ppstm=new CSectorReaderWriter(*this); 43 | return S_OK; 44 | }else 45 | return E_INVALIDARG; 46 | } 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | #define PROPGRID_WIDTH_DEFAULT 250 58 | 59 | CCriticalSectorView::CCriticalSectorView(PDos dos,RCPhysicalAddress rChs) 60 | // ctor 61 | // - initialization 62 | : tab(0,0,0,dos->image,this) , splitX(PROPGRID_WIDTH_DEFAULT) 63 | , hexaEditor(*this) { 64 | // - reset of HexaEditor's content 65 | fSectorData.Attach( new CSectorReaderWriter(dos,rChs) ); 66 | const TPhysicalAddress &chs=GetPhysicalAddress(); 67 | WORD sectorDataRealLength=CImage::GetOfficialSectorLength( chs.sectorId.lengthCode ); // initializing just in case the Sector is not found 68 | IMAGE->GetHealthySectorData( chs, §orDataRealLength ); 69 | hexaEditor.Reset( fSectorData, fSectorData, sectorDataRealLength ); 70 | } 71 | 72 | BEGIN_MESSAGE_MAP(CCriticalSectorView,CView) 73 | ON_WM_CREATE() 74 | ON_WM_SIZE() 75 | ON_WM_KILLFOCUS() 76 | ON_COMMAND(ID_IMAGE_PROTECT,ToggleWriteProtection) 77 | ON_WM_DESTROY() 78 | END_MESSAGE_MAP() 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | afx_msg int CCriticalSectorView::OnCreate(LPCREATESTRUCT lpcs){ 88 | // window created 89 | // - base 90 | if (__super::OnCreate(lpcs)==-1) 91 | return -1; 92 | // - creating the Content 93 | //CCreateContext cc; 94 | //cc.m_pCurrentDoc=dos->image; 95 | content.reset( new CSplitterWnd ); 96 | content->CreateStatic(this,1,2,WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS);//WS_CLIPCHILDREN| 97 | //content->CreateView(0,0,RUNTIME_CLASS(CPropertyGridView),CSize(splitX,0),&cc); 98 | //const HWND hPropGrid=content->GetDlgItemHwnd( content->IdFromRowCol(0,0) ); 99 | propGrid.CreateEx( 0, app.GetPropGridWndClass(), nullptr, AFX_WS_DEFAULT_VIEW&~WS_BORDER, 0,0,PROPGRID_WIDTH_DEFAULT,300, content->m_hWnd, (HMENU)content->IdFromRowCol(0,0) ); 100 | content->SetColumnInfo(0,Utils::LogicalUnitScaleFactor*PROPGRID_WIDTH_DEFAULT,0); 101 | //content->CreateView(0,1,RUNTIME_CLASS(CHexaEditor),CSize(),&cc); // commented out as created manually below 102 | hexaEditor.Update( fSectorData, fSectorData ); 103 | hexaEditor.Create( nullptr, nullptr, AFX_WS_DEFAULT_VIEW&~WS_BORDER|WS_CLIPSIBLINGS, CFrameWnd::rectDefault, content.get(), content->IdFromRowCol(0,1) ); 104 | //hexaEditor.CreateEx( 0, HEXAEDITOR_BASE_CLASS, nullptr, AFX_WS_DEFAULT_VIEW&~WS_BORDER, RECT(), nullptr, content->IdFromRowCol(0,1), nullptr ); 105 | OnSize( SIZE_RESTORED, lpcs->cx, lpcs->cy ); 106 | // - populating the PropertyGrid with values from Boot Sector 107 | OnUpdate(nullptr,0,nullptr); 108 | // - manually setting that none of the Splitter cells is the actual View 109 | //nop (see OnKillFocus) 110 | // - currently it's this Boot that's displayed 111 | pCurrentlyShown=this; 112 | return 0; 113 | } 114 | 115 | void CCriticalSectorView::OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint){ 116 | // request to refresh the display of content 117 | // - clearing the PropertyGrid 118 | PropGrid::RemoveProperty( propGrid.m_hWnd, nullptr ); 119 | // - planning repainting of the HexaEditor 120 | hexaEditor.Invalidate(); 121 | // - reflecting write-protection into the look of controls 122 | __updateLookOfControls__(); 123 | } 124 | 125 | afx_msg void CCriticalSectorView::OnSize(UINT nType,int cx,int cy){ 126 | // window size changed 127 | content->SetWindowPos( nullptr, 0,0, cx,cy, SWP_NOZORDER|SWP_NOMOVE ); 128 | } 129 | 130 | afx_msg void CCriticalSectorView::OnKillFocus(CWnd *newFocus){ 131 | // window lost focus 132 | // - manually setting that this Boot is still the active View, regardless of the lost focus 133 | ((CFrameWnd *)app.m_pMainWnd)->SetActiveView(this); 134 | } 135 | 136 | afx_msg void CCriticalSectorView::OnDestroy(){ 137 | // window destroyed 138 | // - saving the Splitter's X position for later 139 | RECT r; 140 | content->GetDlgItem( content->IdFromRowCol(0,0) )->GetClientRect(&r); 141 | splitX=r.right; 142 | // - disposing the Content 143 | content.reset(); 144 | // - base 145 | __super::OnDestroy(); 146 | // - no Boot is currently being displayed 147 | pCurrentlyShown=nullptr; 148 | } 149 | 150 | afx_msg void CCriticalSectorView::ToggleWriteProtection(){ 151 | // toggles Image's WriteProtection flag 152 | IMAGE->ToggleWriteProtection(); // "base" 153 | __updateLookOfControls__(); 154 | } 155 | 156 | void CCriticalSectorView::__updateLookOfControls__(){ 157 | PropGrid::EnableProperty( propGrid.m_hWnd, nullptr, !IMAGE->IsWriteProtected() ); 158 | hexaEditor.SetEditable( !IMAGE->IsWriteProtected() ); 159 | } 160 | 161 | void CCriticalSectorView::OnSectorChanging() const{ 162 | // custom action performed whenever the Sector data have been modified 163 | //nop 164 | } 165 | 166 | void CCriticalSectorView::OnDraw(CDC *pDC){ 167 | // drawing 168 | } 169 | 170 | void CCriticalSectorView::PostNcDestroy(){ 171 | // self-destruction 172 | //nop (View destroyed by its owner) 173 | } 174 | 175 | RCPhysicalAddress CCriticalSectorView::GetPhysicalAddress() const{ 176 | return fSectorData->fatPath->GetHealthyItem(0)->chs; 177 | } 178 | 179 | void CCriticalSectorView::ChangeToSector(RCPhysicalAddress rChs){ 180 | // changes to a different Sector with the PhysicalAddress specified 181 | fSectorData->fatPath->GetHealthyItem(0)->chs=rChs; 182 | fSectorData->SeekToBegin(); 183 | } 184 | 185 | void CCriticalSectorView::MarkSectorAsDirty() const{ 186 | IMAGE->MarkSectorAsDirty(GetPhysicalAddress()); 187 | } 188 | -------------------------------------------------------------------------------- /Main/src/ViewCriticalSector.h: -------------------------------------------------------------------------------- 1 | #ifndef CRITICALSECTORVIEW_H 2 | #define CRITICALSECTORVIEW_H 3 | 4 | class CCriticalSectorView:public CView{ 5 | DECLARE_MESSAGE_MAP() 6 | private: 7 | std::unique_ptr content; // newly created for whenever Sector is switched to in TDI 8 | int splitX; 9 | 10 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 11 | afx_msg void OnSize(UINT nType,int cx,int cy); 12 | afx_msg void OnKillFocus(CWnd *newFocus); 13 | afx_msg void OnDestroy(); 14 | afx_msg void ToggleWriteProtection(); 15 | void __updateLookOfControls__(); 16 | protected: 17 | class CSectorReaderWriter:public CDos::CFileReaderWriter{ 18 | public: 19 | CSectorReaderWriter(PCDos dos,RCPhysicalAddress chs); 20 | 21 | // CFile methods 22 | void Write(LPCVOID lpBuf,UINT nCount) override; 23 | // IStream methods 24 | HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm) override; 25 | }; 26 | 27 | CComPtr fSectorData; 28 | CWnd propGrid; 29 | CDos::CFileReaderWriter::CHexaEditor hexaEditor; 30 | 31 | CCriticalSectorView(PDos dos,RCPhysicalAddress rChs); 32 | 33 | virtual void OnSectorChanging() const; 34 | void OnDraw(CDC *pDC) override sealed; 35 | void OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint) override; 36 | void PostNcDestroy() override; 37 | public: 38 | static const CCriticalSectorView *pCurrentlyShown; // Sector that is currently shown (a volume can have multiple critical Sectors) 39 | 40 | static void WINAPI __updateCriticalSectorView__(PropGrid::PCustomParam); 41 | static bool __isValueBeingEditedInPropertyGrid__(); 42 | 43 | const CMainWindow::CTdiView::TTab tab; 44 | 45 | RCPhysicalAddress GetPhysicalAddress() const; 46 | void ChangeToSector(RCPhysicalAddress rChs); 47 | void MarkSectorAsDirty() const; 48 | }; 49 | 50 | #endif // CRITICALSECTORVIEW_H 51 | -------------------------------------------------------------------------------- /Main/src/ViewDirectoryEntries.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRHEXAVIEW_H 2 | #define DIRHEXAVIEW_H 3 | 4 | class CDirEntriesView sealed:public CHexaEditor{ 5 | DECLARE_MESSAGE_MAP() 6 | private: 7 | CDos::PCFile fileToSeekTo; 8 | CComPtr f; 9 | 10 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 11 | afx_msg void ToggleWriteProtection(); 12 | afx_msg void __closeView__(); 13 | void OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint) override; 14 | int GetCustomCommandMenuFlags(WORD cmd) const override; 15 | bool ProcessCustomCommand(UINT cmd) override; 16 | public: 17 | const CMainWindow::CTdiView::TTab tab; 18 | const CDos::PFile directory; 19 | const WORD sectorLength; // e.g. for Spectrum Tape, the SectorLength may temporarily be faked to correctly segment a display Headers, and then reset to normal to correctly display Tape data; this is the backup of the eventually faked value 20 | 21 | CDirEntriesView(PDos dos,CDos::PFile directory,CDos::PCFile fileToSeekTo=nullptr); 22 | }; 23 | 24 | #endif // DIRHEXAVIEW_H -------------------------------------------------------------------------------- /Main/src/ViewDiskBrowser.h: -------------------------------------------------------------------------------- 1 | #ifndef DISKHEXAVIEW_H 2 | #define DISKHEXAVIEW_H 3 | 4 | class CDiskBrowserView sealed:public CHexaEditor{ 5 | DECLARE_MESSAGE_MAP() 6 | private: 7 | struct{ 8 | TPhysicalAddress chs; 9 | BYTE nSectorsToSkip; 10 | } seekTo; 11 | Yahel::TRow iScrollY; // ScrollBar position 12 | CComPtr f; 13 | Revolution::TType revolution; 14 | 15 | void UpdateStatusBar(); 16 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 17 | afx_msg void OnDestroy(); 18 | afx_msg void ToggleWriteProtection(); 19 | afx_msg LRESULT ReportScanningProgress(WPARAM,LPARAM); 20 | afx_msg void __closeView__(); 21 | void OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint) override; 22 | int GetCustomCommandMenuFlags(WORD cmd) const override; 23 | bool ProcessCustomCommand(UINT cmd) override; 24 | public: 25 | static CDiskBrowserView &CreateAndSwitchToTab(PImage image,RCPhysicalAddress chsToSeekTo,BYTE nSectorsToSkip); 26 | 27 | const CMainWindow::CTdiView::TTab tab; 28 | 29 | CDiskBrowserView(PImage image,RCPhysicalAddress chsToSeekTo,BYTE nSectorsToSkip); 30 | }; 31 | 32 | #endif // DISKHEXAVIEW_H -------------------------------------------------------------------------------- /Main/src/ViewFatHexa.h: -------------------------------------------------------------------------------- 1 | #ifndef FATHEXAVIEW_H 2 | #define FATHEXAVIEW_H 3 | 4 | class CFatHexaView:public CHexaEditor{ 5 | public: 6 | class CFatPathReaderWriter:public CYahelStreamFile,public Yahel::Stream::IAdvisor{ 7 | const PCDos dos; 8 | const CDos::PFile file; 9 | const std::shared_ptr fatPath; 10 | public: 11 | CFatPathReaderWriter(PCDos dos,CDos::PFile file); 12 | 13 | // IStream methods 14 | HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm) override; 15 | 16 | // CFile methods 17 | #if _MFC_VER>=0x0A00 18 | void SetLength(ULONGLONG dwNewLen) override; 19 | #else 20 | void SetLength(DWORD dwNewLen) override; 21 | #endif 22 | UINT Read(LPVOID lpBuf,UINT nCount) override; 23 | void Write(LPCVOID lpBuf,UINT nCount) override; 24 | 25 | // Yahel::Stream::IAdvisor methods 26 | void GetRecordInfo(Yahel::TPosition pos,Yahel::PPosition pOutRecordStartLogPos,Yahel::PPosition pOutRecordLength,bool *pOutDataReady) override; 27 | Yahel::TRow LogicalPositionToRow(Yahel::TPosition pos,WORD nStreamBytesInRow) override; 28 | Yahel::TPosition RowToLogicalPosition(Yahel::TRow row,WORD nStreamBytesInRow) override; 29 | LPCWSTR GetRecordLabelW(Yahel::TPosition pos,PWCHAR labelBuffer,BYTE labelBufferCharsMax,PVOID param) const override; 30 | }; 31 | protected: 32 | const CDos::PFile file; 33 | CComPtr pFatData; 34 | 35 | bool ProcessCustomCommand(UINT cmd) override; 36 | LRESULT WindowProc(UINT msg,WPARAM wParam,LPARAM lParam) override; 37 | public: 38 | const CMainWindow::CTdiView::TTab tab; 39 | 40 | CFatHexaView(PDos dos,CDos::PFile file,LPCWSTR itemDefinition); 41 | }; 42 | 43 | #endif // FATHEXAVIEW_H 44 | -------------------------------------------------------------------------------- /Main/src/ViewFileManager.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/ViewFileManager.cpp -------------------------------------------------------------------------------- /Main/src/ViewTrackMap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomas-nestorovic/RIDE/7398b6506c8712641aac3f19739f117880b0dec4/Main/src/ViewTrackMap.cpp -------------------------------------------------------------------------------- /Main/src/ViewTrackMap.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACKMAPVIEW_H 2 | #define TRACKMAPVIEW_H 3 | 4 | typedef enum TSectorStatus:BYTE{ 5 | SYSTEM, // e.g. reserved for root Directory 6 | UNAVAILABLE,// Sectors that are not included in FAT (e.g. beyond the FAT, or FAT Sector error) 7 | SKIPPED, // e.g. deleted Files in TR-DOS 8 | BAD, 9 | OCCUPIED, 10 | RESERVED, // e.g. zero-length File in MDOS, or File with error during importing 11 | EMPTY, // reported as unallocated 12 | UNKNOWN_STD,// officially "Unknown" (e.g. BSDOS 'TFatValue::SectorUnknown') 13 | UNKNOWN, // any Sector whose ID doesn't match any ID from the standard format, e.g. ID={2,1,0,3} for an MDOS Sector 14 | LAST 15 | } *PSectorStatus; 16 | 17 | #define TRACK_MAP_TAB_LABEL _T("Track map") 18 | 19 | #define TRACK_MAP_COLORS_COUNT 256 20 | 21 | class CTrackMapView sealed:public CScrollView{ 22 | DECLARE_MESSAGE_MAP() 23 | public: 24 | const CMainWindow::CTdiView::TTab tab; 25 | private: 26 | bool informOnCapabilities; // True <=> user will be informed on what the TrackMap tab can do, otherwise False 27 | int iScrollX, iScrollY; // ScrollBar position 28 | struct TTrackLength sealed{ 29 | static TTrackLength FromTime(TLogTime nNanosecondsTotal,TLogTime nNanosecondsPerByte); 30 | 31 | TSector nSectors; 32 | int nBytes; 33 | 34 | TTrackLength(TSector nSectors,int nBytes); // ctor 35 | 36 | int GetUnitCount(BYTE zoomFactor) const; 37 | BYTE GetZoomFactorToFitWidth(long pixelWidth) const; 38 | bool operator<(const TTrackLength &r) const; 39 | } longestTrack; // to infer maximum horizontal scroll position 40 | TLogTime longestTrackNanoseconds; 41 | enum TDisplayType:WORD{ 42 | STATUS =ID_TRACKMAP_STATUS, 43 | DATA_OK_ONLY=ID_TRACKMAP_DATA, 44 | DATA_ALL =ID_TRACKMAP_BAD_DATA 45 | } displayType; 46 | HBRUSH statusBrushes[TSectorStatus::LAST]; 47 | HBRUSH rainbowBrushes[TRACK_MAP_COLORS_COUNT]; 48 | struct TTrackScanner sealed{ 49 | static UINT AFX_CDECL Thread(PVOID _pBackgroundAction); 50 | const CBackgroundAction action; 51 | struct TParams sealed{ 52 | CCriticalSection locker; 53 | THead nHeads; // 0 = terminate the Scanner 54 | TTrack a,z,x; // first, last, and currect Track to scan; it holds: A <= X < Z 55 | bool skipUnscannedTracks; // True <=> display only Tracks scanned thus far, otherwise scan all Tracks 56 | } params; 57 | CEvent scanNextTrack; 58 | TTrackScanner(const CTrackMapView *pvtm); // ctor 59 | } scanner; 60 | bool showSectorNumbers,showTimed,fitLongestTrackInWindow,showSelectedFiles; 61 | BYTE zoomLengthFactor; 62 | COLORREF fileSelectionColor; 63 | 64 | void OnUpdate(CView *pSender,LPARAM lHint,CObject *pHint) override; 65 | BOOL OnScroll(UINT nScrollCode,UINT nPos,BOOL bDoScroll=TRUE) override; 66 | void OnPrepareDC(CDC *pDC,CPrintInfo *pInfo=nullptr) override; 67 | void OnDraw(CDC *pDC) override; 68 | void PostNcDestroy() override; 69 | void TimesToUnits(TSector nSectors,PLogTime pInOutBuffer,PCWORD pInSectorLengths) const; 70 | enum TCursorPos{ NONE, TRACK, SECTOR } GetPhysicalAddressAndNanosecondsFromPoint(POINT point,TPhysicalAddress &rOutChs,BYTE &rnOutSectorsToSkip,int &rOutNanoseconds); 71 | void ResetStatusBarMessage() const; 72 | void UpdateLogicalDimensions(); 73 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 74 | afx_msg void OnSize(UINT nType,int cx,int cy); 75 | afx_msg void OnMouseMove(UINT nFlags,CPoint point); 76 | afx_msg void OnLButtonUp(UINT nFlags,CPoint point); 77 | afx_msg void OnRButtonUp(UINT nFlags,CPoint point); 78 | afx_msg BOOL OnMouseWheel(UINT nFlags,short delta,CPoint point); 79 | afx_msg void OnDestroy(); 80 | afx_msg LRESULT DrawTrack(WPARAM wParam,LPARAM lParam); 81 | afx_msg void ChangeDisplayType(UINT id); 82 | afx_msg void __changeDisplayType_updateUI__(CCmdUI *pCmdUI); 83 | afx_msg void ToggleSectorNumbering(); 84 | afx_msg void __toggleSectorNumbering_updateUI__(CCmdUI *pCmdUI); 85 | afx_msg void ToggleTiming(); 86 | afx_msg void __toggleTiming_updateUI__(CCmdUI *pCmdUI); 87 | afx_msg void ZoomOut(); 88 | afx_msg void __zoomOut_updateUI__(CCmdUI *pCmdUI); 89 | afx_msg void ZoomIn(); 90 | afx_msg void __zoomIn_updateUI__(CCmdUI *pCmdUI); 91 | afx_msg void ZoomFitWidth(); 92 | afx_msg void __zoomFitWidth_updateUI__(CCmdUI *pCmdUI); 93 | afx_msg void ShowSelectedFiles(); 94 | afx_msg void __showSelectedFiles_updateUI__(CCmdUI *pCmdUI); 95 | afx_msg void TogglePaused(); 96 | afx_msg void TogglePaused_updateUI(CCmdUI *pCmdUI); 97 | afx_msg void ChangeFileSelectionColor(); 98 | afx_msg void ShowDiskStatistics(); 99 | public: 100 | CTrackMapView(PImage image); 101 | ~CTrackMapView(); 102 | 103 | BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,const RECT &rect,CWnd *pParentWnd,UINT nID,CCreateContext *pContext=nullptr) override; 104 | afx_msg void RefreshDisplay(); 105 | }; 106 | 107 | #endif // TRACKMAPVIEW_H 108 | -------------------------------------------------------------------------------- /Main/src/ViewWebPage.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBPAGEVIEW_H 2 | #define WEBPAGEVIEW_H 3 | 4 | class CWebPageView sealed:public CHtmlView{ 5 | DECLARE_MESSAGE_MAP() 6 | private: 7 | CBitmap defaultBrowserIcon; 8 | struct THistory sealed{ 9 | #pragma pack(1) 10 | struct TPage sealed{ 11 | const CString url; 12 | long iScrollY; // ScrollBar position 13 | TPage *older,*newer; 14 | TPage(LPCTSTR _url); // ctor 15 | } initialPage, *currentPage; 16 | 17 | THistory(LPCTSTR defaultUrl); 18 | ~THistory(); 19 | 20 | void DestroyNewerPages() const; 21 | } history; 22 | bool navigationToLabel; 23 | 24 | void OnBeforeNavigate2(LPCTSTR lpszURL,DWORD nFlags,LPCTSTR lpszTargetFrameName,CByteArray &baPostedData,LPCTSTR lpszHeaders,BOOL *pbCancel) override; 25 | void OnDocumentComplete(LPCTSTR strURL) override; 26 | void PostNcDestroy() override; 27 | afx_msg void OnDestroy(); 28 | void __saveCurrentPageScrollPosition__() const; 29 | afx_msg void __navigateBack__(); 30 | afx_msg void __navigateBack_updateUI__(CCmdUI *pCmdUI); 31 | afx_msg void __navigateForward__(); 32 | afx_msg void __navigateForward_updateUI__(CCmdUI *pCmdUI); 33 | afx_msg void __openCurrentPageInDefaultBrowser__(); 34 | public: 35 | const CMainWindow::CTdiView::TTab tab; 36 | 37 | CWebPageView(LPCTSTR url); 38 | 39 | BOOL Create(LPCTSTR,LPCTSTR,DWORD dwStyle,const RECT &rect,CWnd *pParentWnd,UINT nID,CCreateContext *) override; 40 | }; 41 | 42 | #endif // WEBPAGEVIEW_H -------------------------------------------------------------------------------- /Main/src/XmlDocs.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "XmlDocs.h" 3 | 4 | CXmlDocument::CXmlAttribute::CXmlAttribute(const CXmlDocument &doc,LPCSTR attrName){ 5 | // ctor 6 | doc->createAttribute( COleVariant(attrName).bstrVal, &p ); 7 | p->AddRef(); 8 | } 9 | 10 | CXmlDocument::CXmlDocument(const CXmlElement &element){ 11 | // ctor 12 | element->get_ownerDocument( (IXMLDOMDocument **)&p ); 13 | } 14 | 15 | CXmlDocument::CXmlAttribute CXmlDocument::CXmlAttribute::operator()(LPCSTR format,...) const{ 16 | // returns a clone without any modifications 17 | va_list argList; 18 | va_start( argList, format ); 19 | CString value; 20 | value.FormatV( format, argList ); 21 | va_end(argList); 22 | CXmlAttribute copy; 23 | p->cloneNode( VARIANT_TRUE, (IXMLDOMNode **)©.p ); 24 | copy.p->AddRef(); 25 | copy->put_text( COleVariant(value).bstrVal ); 26 | return copy; 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | CXmlDocument::CXmlElement::CXmlElement(const CXmlDocument &doc,LPCSTR elementName){ 39 | // ctor 40 | doc->createElement( COleVariant(elementName).bstrVal, &p ); 41 | } 42 | 43 | CXmlDocument::CXmlElement::CXmlElement(CXmlElement &&element){ 44 | // move ctor 45 | p=element.p; 46 | element.p=nullptr; 47 | } 48 | 49 | 50 | 51 | CXmlDocument::CXmlElement CXmlDocument::CXmlElement::AppendChildElement(const CXmlElement &element){ 52 | // 53 | CXmlElement result; 54 | CComPtr parent; 55 | if (FAILED(element->get_parentNode(&parent.p))) 56 | return result; 57 | if (parent) // already has a Parent? 58 | element->cloneNode( VARIANT_FALSE, (IXMLDOMNode **)&result.p ); // must create a copy 59 | else 60 | result=element; 61 | p->appendChild( result, (IXMLDOMNode **)&result.p ); 62 | return result; 63 | } 64 | 65 | 66 | 67 | CXmlDocument::CXmlElement &CXmlDocument::CXmlElement::operator()(LPCTSTR format,va_list args){ 68 | // appends formatted text 69 | CString tmp; 70 | tmp.FormatV( format, args ); 71 | AppendChildText(tmp); 72 | return *this; 73 | } 74 | 75 | CXmlDocument::CXmlElement &CXmlDocument::CXmlElement::operator()(LPCTSTR format,...){ 76 | // appends formatted text 77 | va_list argList; 78 | va_start( argList, format ); 79 | operator()( format, argList ); 80 | va_end(argList); 81 | return *this; 82 | } 83 | 84 | CXmlDocument::CXmlElement &CXmlDocument::CXmlElement::operator()(const CXmlElement &wrapper,LPCTSTR text1,...){ 85 | // appends Wrapper nodes, each containing Text{1...N} 86 | for( LPCTSTR *pText=&text1; *pText; pText++ ) 87 | AppendChildElement(wrapper)(*pText); 88 | return *this; 89 | } 90 | 91 | CXmlDocument::CXmlElement &CXmlDocument::CXmlElement::SetAttribute(const CXmlAttribute &attr){ 92 | // sets Attribute 93 | CComPtr tmp; 94 | p->setAttributeNode( attr, &tmp.p ); 95 | return *this; 96 | } 97 | 98 | CXmlDocument::CXmlElement &CXmlDocument::CXmlElement::SetAttribute(BSTR attrName,const VARIANT &attrValue){ 99 | // sets Attribute with explicit Name and Value 100 | p->setAttribute( attrName, attrValue ); 101 | return *this; 102 | } 103 | 104 | 105 | 106 | void CXmlDocument::CXmlElement::AppendChildText(BSTR text) const{ 107 | // 108 | CComPtr tmp; 109 | CXmlDocument(*this)->createTextNode( text, &tmp.p ); 110 | CComPtr node; 111 | p->appendChild( tmp, &node.p ); 112 | } 113 | 114 | void CXmlDocument::CXmlElement::AppendChildText(LPCSTR text) const{ 115 | // 116 | const int unicodeLength=::MultiByteToWideChar( CP_UTF8, 0, text,-1, nullptr,0 ); 117 | CString unicode; 118 | const PWCHAR pw=(PWCHAR)unicode.GetBufferSetLength( sizeof(WCHAR)*unicodeLength ); 119 | ::MultiByteToWideChar( CP_UTF8, 0, text,-1, pw,unicodeLength ); 120 | return AppendChildText(pw); 121 | } 122 | 123 | void CXmlDocument::CXmlElement::AppendChildTextDot(LPCTSTR text) const{ 124 | // 125 | AppendChildText( CString(text)+'.' ); 126 | } 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | static IXMLDOMDocument *CreateXmlDoc(){ 138 | ::OleInitialize(nullptr); // may want to create a XmlDoc from any thread 139 | CComPtr tmp; 140 | return SUCCEEDED(tmp.CoCreateInstance( CLSID_DOMDocument60 )) //CLSID_DOMDocument60 141 | ? tmp.Detach() 142 | : nullptr; 143 | } 144 | 145 | CXmlDocument::CXmlDocument(LPCSTR rootName) 146 | // ctor 147 | : CComPtr( CreateXmlDoc() ) 148 | , root( *this, rootName ) { 149 | p->Release(); // because of 'Detach()' in CreateXmlDoc above 150 | p->putref_documentElement(root); 151 | } 152 | 153 | TStdWinError CXmlDocument::Save(LPCTSTR filename) const{ 154 | return SUCCEEDED( p->save(COleVariant(filename)) ) 155 | ? ERROR_SUCCESS 156 | : ::GetLastError(); 157 | } 158 | 159 | std::unique_ptr CXmlDocument::Save() const{ 160 | std::unique_ptr result(new COleStreamFile()); 161 | if (!result->CreateMemoryStream()) 162 | return nullptr; 163 | COleVariant v; 164 | v.vt=VT_UNKNOWN; 165 | ( v.punkVal=result->m_lpStream )->AddRef(); 166 | if (FAILED(p->save(v))) 167 | return nullptr; 168 | return result; 169 | } 170 | 171 | CString CXmlDocument::EncodeXml(LPCTSTR text){ 172 | // returns the XML-compliant version of the Text 173 | static const CString Empty; 174 | struct TXmlDoc sealed:public CXmlDocument{ 175 | TXmlDoc(LPCTSTR text) 176 | : CXmlDocument("x") { 177 | root.AppendChildText( const_cast(text) ); 178 | } 179 | } doc(text); 180 | const auto stream=doc.Save(); 181 | const auto streamLength=stream->GetLength(); 182 | CString xml; 183 | stream->SeekToBegin(); 184 | stream->Read( xml.GetBufferSetLength(streamLength), streamLength ); 185 | const int iOpenPlusLength=xml.Find(_T(""))+3; 186 | if (iOpenPlusLength<3) 187 | return Empty; 188 | return CString( (LPCTSTR)xml+iOpenPlusLength, xml.Find(_T(""))-iOpenPlusLength ); 189 | } 190 | -------------------------------------------------------------------------------- /Main/src/XmlDocs.h: -------------------------------------------------------------------------------- 1 | #ifndef MARKUPDOCUMENTS_H 2 | #define MARKUPDOCUMENTS_H 3 | 4 | class CXmlDocument:public CComPtr{ 5 | protected: 6 | class CXmlAttribute:public CComPtr{ 7 | public: 8 | // ctors 9 | inline CXmlAttribute(){} 10 | CXmlAttribute(const CXmlDocument &doc,LPCSTR attrName); 11 | 12 | // cloning with value setting 13 | CXmlAttribute operator()(LPCSTR format,...) const; 14 | }; 15 | 16 | class CXmlElement:public CComPtr{ 17 | public: 18 | // ctors 19 | inline CXmlElement(){} 20 | CXmlElement(const CXmlDocument &doc,LPCSTR elementName); 21 | CXmlElement(CXmlElement &&element); 22 | 23 | inline void operator=(const CXmlElement &r){ __super::operator=(r); } 24 | 25 | // cloning 26 | inline CXmlElement operator/(const CXmlElement &element){ return AppendChildElement(element); } 27 | CXmlElement AppendChildElement(const CXmlElement &element); 28 | 29 | // node modifications 30 | CXmlElement &operator()(LPCTSTR format,va_list args); 31 | CXmlElement &operator()(LPCTSTR format,...); 32 | CXmlElement &operator()(const CXmlElement &wrapper,LPCTSTR text1,...); 33 | inline CXmlElement &operator()(const CXmlAttribute &attr){ return SetAttribute(attr); } 34 | CXmlElement &operator()(const CXmlAttribute &attr,LPCTSTR format,...); 35 | CXmlElement &SetAttribute(const CXmlAttribute &attr); 36 | CXmlElement &SetAttribute(BSTR attrName,const VARIANT &attrValue); 37 | 38 | // adding extra text subnodes 39 | inline void operator<<(BSTR text) const{ AppendChildText(text); } 40 | inline void operator<<(LPCTSTR text) const{ AppendChildText(text); } 41 | void AppendChildText(BSTR text) const; 42 | void AppendChildText(LPCSTR text) const; 43 | void AppendChildTextDot(LPCTSTR text) const; 44 | }; 45 | 46 | CXmlElement root; 47 | public: 48 | static CString EncodeXml(LPCTSTR text); 49 | 50 | CXmlDocument(LPCSTR rootName); 51 | CXmlDocument(const CXmlElement &element); 52 | 53 | TStdWinError Save(LPCTSTR filename) const; 54 | std::unique_ptr Save() const; 55 | }; 56 | 57 | #endif // MARKUPDOCUMENTS_H 58 | -------------------------------------------------------------------------------- /Main/src/editor.h: -------------------------------------------------------------------------------- 1 | #ifndef RIDEAPP_H 2 | #define RIDEAPP_H 3 | 4 | #define INI_GENERAL _T("General") 5 | 6 | #define INI_IS_UP_TO_DATE _T("iu2e") 7 | #define INI_LATEST_KNOWN_VERSION _T("lu2d") 8 | 9 | class CRideApp sealed:public CWinApp{ 10 | DECLARE_MESSAGE_MAP() 11 | private: 12 | bool godMode; // launched with "--godmode" param ? 13 | ATOM propGridWndClass; 14 | public: 15 | class CRecentFileListEx sealed:public CRecentFileList{ 16 | HACCEL hAccelTable; 17 | CDos::PCProperties openWith[ID_FILE_MRU_LAST+1-ID_FILE_MRU_FIRST]; 18 | CImage::PCProperties m_deviceProps[ID_FILE_MRU_LAST+1-ID_FILE_MRU_FIRST]; 19 | public: 20 | CRecentFileListEx(const CRecentFileList &rStdMru); 21 | ~CRecentFileListEx(); 22 | 23 | inline const CString &operator[](int nIndex) const{ return const_cast(this)->__super::operator[](nIndex); } 24 | inline bool PreTranslateMessage(HWND hWnd,PMSG pMsg) const{ return ::TranslateAccelerator( hWnd, hAccelTable, pMsg )!=0; } 25 | CDos::PCProperties GetDosMruFileOpenWith(int nIndex) const; 26 | CImage::PCProperties GetMruDevice(int nIndex) const; 27 | void Add(LPCTSTR lpszPathName,CDos::PCProperties dosProps,CImage::PCProperties deviceProps); 28 | void Remove(int nIndex) override; 29 | void ReadList() override; 30 | void WriteList() override; 31 | }; 32 | 33 | static CImage::PCProperties DoPromptFileName(PTCHAR fileName,bool deviceAccessAllowed,UINT stdStringId,DWORD flags,CImage::PCProperties singleAllowedImage); 34 | 35 | static CLIPFORMAT cfDescriptor,cfRideFileList,cfContent,cfPreferredDropEffect,cfPerformedDropEffect,cfPasteSucceeded; 36 | 37 | DWORD dateRecencyLastChecked; // 0 = recency not yet automatically checked online 38 | 39 | BOOL InitInstance() override; 40 | int ExitInstance() override; 41 | bool GetProfileBool(LPCTSTR sectionName,LPCTSTR keyName,bool bDefault=false); 42 | CDocument *OpenDocumentFile(LPCTSTR lpszFileName) override; 43 | void OnFileOpen(); // public wrapper 44 | inline CRecentFileListEx *GetRecentFileList() const{ return (CRecentFileListEx *)m_pRecentFileList; } 45 | HWND GetEnabledActiveWindow() const; 46 | inline bool IsInGodMode() const{ return godMode; } 47 | inline LPCTSTR GetPropGridWndClass() const{ return (LPCTSTR)propGridWndClass; } 48 | inline CMainWindow *GetMainWindow() const{ return (CMainWindow *)m_pMainWnd; } 49 | #if _MFC_VER>=0x0A00 50 | afx_msg void OnOpenRecentFile(UINT nID); 51 | #else 52 | afx_msg BOOL OnOpenRecentFile(UINT nID); 53 | #endif 54 | afx_msg void CreateNewImage(); 55 | afx_msg void OpenImage(); 56 | afx_msg void __openImageAs__(); 57 | afx_msg void OpenImageWithoutDos(); 58 | afx_msg void __openDevice__(); 59 | afx_msg void __showAbout__(); 60 | 61 | template 62 | T GetProfileEnum(LPCTSTR sectionName,LPCTSTR keyName,T nDefault){ 63 | return (T)GetProfileInt( sectionName, keyName, nDefault ); 64 | } 65 | }; 66 | 67 | #endif // RIDEAPP_H -------------------------------------------------------------------------------- /PropGrid/PropGrid.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | 49 | 50 | Header Files 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | -------------------------------------------------------------------------------- /PropGrid/PropGrid.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /PropGrid/src/Editor_Boolean.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | static bool WINAPI __alwaysAccept__(PropGrid::PCustomParam,bool){ 4 | return true; // new Value is by default always accepted 5 | } 6 | 7 | TBooleanEditor::TBooleanEditor( PropGrid::TSize nValueBytes, 8 | DWORD reservedValue, 9 | bool reservedForTrue, 10 | PropGrid::Boolean::TOnValueConfirmed onValueConfirmed, 11 | PropGrid::TOnValueChanged onValueChanged 12 | ) 13 | // ctor 14 | : TEditor( EDITOR_DEFAULT_HEIGHT, true, std::min(nValueBytes,sizeof(DWORD)), nullptr, onValueChanged ) 15 | , reservedValue(reservedValue) , reservedForTrue(reservedForTrue) 16 | , onValueConfirmed( onValueConfirmed ? onValueConfirmed : __alwaysAccept__ ) { 17 | } 18 | 19 | void TBooleanEditor::__drawValue__(const TPropGridInfo::TItem::TValue &value,PDRAWITEMSTRUCT pdis) const{ 20 | // draws the Value into the specified rectangle 21 | RECT r={ PROPGRID_CELL_MARGIN_LEFT+1, PROPGRID_CELL_MARGIN_TOP+1, PROPGRID_CELL_MARGIN_LEFT+16, PROPGRID_CELL_MARGIN_TOP+16 }; 22 | ::FrameRect(pdis->hDC, &r, 23 | pdis->CtlType==ODT_LISTBOX // drawing invoked by the ListBox? 24 | ? TPropGridInfo::BRUSH_GRAY 25 | : TPropGridInfo::BRUSH_BLACK 26 | ); 27 | DWORD tmp=0; 28 | ::memcpy( &tmp, value.buffer, valueSize ); 29 | if (reservedForTrue && tmp==reservedValue || !reservedForTrue && tmp!=reservedValue){ 30 | const HDC dcmem=::CreateCompatibleDC(pdis->hDC); 31 | const HGDIOBJ hBitmap0=::SelectObject( dcmem, TPropGridInfo::CHECKBOX_CHECKED ); 32 | ::BitBlt( pdis->hDC, 33 | PROPGRID_CELL_MARGIN_LEFT+2, PROPGRID_CELL_MARGIN_TOP+2, 13, 13, 34 | dcmem, 0, 0, 35 | SRCCOPY 36 | ); 37 | ::SelectObject(dcmem,hBitmap0); 38 | ::DeleteDC(dcmem); 39 | } 40 | } 41 | 42 | static bool checked; 43 | 44 | HWND TBooleanEditor::__createMainControl__(const TPropGridInfo::TItem::TValue &value,HWND hParent) const{ 45 | // creates, initializes with current Value, and returns Editor's MainControl 46 | DWORD tmp=0; 47 | ::memcpy( &tmp, value.buffer, valueSize ); 48 | checked=reservedForTrue && tmp==reservedValue || !reservedForTrue && tmp!=reservedValue; 49 | return ::CreateWindow( WC_BUTTON, 50 | nullptr, // no caption next to the check-box 51 | EDITOR_STYLE | BS_AUTOCHECKBOX | BS_OWNERDRAW, 52 | 0,0, 1,1, 53 | hParent, 0, GET_PROPGRID_HINSTANCE(hParent), nullptr 54 | ); 55 | } 56 | 57 | bool TBooleanEditor::__tryToAcceptMainCtrlValue__() const{ 58 | // True <=> Editor's current Value is acceptable, otherwise False 59 | ignoreRequestToDestroy=true; 60 | const TPropGridInfo::TItem::TValue &value=TEditor::pSingleShown->value; 61 | const bool accepted=onValueConfirmed( value.param, checked ); 62 | if (accepted){ 63 | const DWORD tmp=reservedForTrue && checked || !reservedForTrue && !checked 64 | ? reservedValue 65 | : ~reservedValue; 66 | ::memcpy( value.buffer, &tmp, valueSize ); 67 | } 68 | ignoreRequestToDestroy=false; 69 | return accepted; 70 | } 71 | 72 | LRESULT TBooleanEditor::__mainCtrl_wndProc__(HWND hCheckBox,UINT msg,WPARAM wParam,LPARAM lParam) const{ 73 | // window procedure 74 | switch (msg){ 75 | case WM_CAPTURECHANGED: 76 | // CheckBox clicked (either by left mouse button or using space-bar) 77 | checked=!checked; 78 | ::InvalidateRect(hCheckBox,nullptr,TRUE); 79 | break; 80 | case WM_ERASEBKGND:{ 81 | RECT rc; 82 | GetClientRect(hCheckBox,&rc); 83 | ::FillRect( (HDC)wParam, &rc, (HBRUSH)::GetStockObject(WHITE_BRUSH) ); 84 | return TRUE; 85 | } 86 | case WM_PAINT:{ 87 | // painting 88 | DRAWITEMSTRUCT dis; 89 | ::ZeroMemory(&dis,sizeof(dis)); 90 | dis.rcItem.right=1000; 91 | dis.rcItem.bottom=height; 92 | PAINTSTRUCT ps; 93 | dis.hDC=::BeginPaint(hCheckBox,&ps); 94 | DWORD tmp= reservedForTrue && checked || !reservedForTrue && !checked 95 | ? reservedValue 96 | : ~reservedValue; 97 | __drawValue__( TPropGridInfo::TItem::TValue( pSingleShown->value.editor, &tmp, pSingleShown->value.param ), 98 | &dis 99 | ); 100 | ::EndPaint(hCheckBox,&ps); 101 | return 1; 102 | } 103 | } 104 | return __super::__mainCtrl_wndProc__(hCheckBox,msg,wParam,lParam); 105 | } 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | PropGrid::PCEditor PropGrid::Boolean::DefineEditor(TSize nValueBytes,TOnValueConfirmed onValueConfirmed,TOnValueChanged onValueChanged,DWORD reservedValue,bool reservedForTrue){ 116 | // creates and returns an Editor with specified parameters 117 | return RegisteredEditors.__add__( 118 | new TBooleanEditor( nValueBytes, reservedValue, reservedForTrue, onValueConfirmed, onValueChanged ), 119 | sizeof(TBooleanEditor) 120 | ); 121 | } 122 | 123 | PropGrid::PCEditor PropGrid::Boolean::DefineByteEditor(TOnValueConfirmed onValueConfirmed,TOnValueChanged onValueChanged,BYTE reservedValue,bool reservedForTrue){ 124 | // creates and returns an Editor with specified parameters 125 | return DefineEditor( sizeof(BYTE), onValueConfirmed, onValueChanged, reservedValue, reservedForTrue ); 126 | } 127 | -------------------------------------------------------------------------------- /PropGrid/src/Editor_Custom.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | static bool WINAPI __alwaysAccept__(PropGrid::PCustomParam,HWND,PropGrid::PValue){ 4 | return true; // new Value is by default always accepted 5 | } 6 | 7 | TCustomEditor::TCustomEditor( WORD height, 8 | PropGrid::TSize nValueBytes, 9 | PropGrid::TDrawValueHandler drawValue, 10 | PropGrid::Custom::TCreateCustomMainEditor createCustomMainEditor, 11 | PropGrid::TOnEllipsisButtonClicked onEllipsisBtnClicked, 12 | PropGrid::Custom::TOnValueConfirmed onValueConfirmed, 13 | PropGrid::TOnValueChanged onValueChanged 14 | ) 15 | // ctor 16 | : TEditor( height, createCustomMainEditor!=nullptr, nValueBytes, onEllipsisBtnClicked, onValueChanged ) 17 | , drawValue(drawValue) 18 | , createCustomMainEditor(createCustomMainEditor) 19 | , onValueConfirmed( onValueConfirmed ? onValueConfirmed : __alwaysAccept__ ) { 20 | } 21 | 22 | void TCustomEditor::__drawValue__(const TPropGridInfo::TItem::TValue &value,PDRAWITEMSTRUCT pdis) const{ 23 | // draws the Value into the specified rectangle 24 | drawValue( value.param, value.buffer, value.editor->valueSize, pdis ); 25 | } 26 | 27 | HWND TCustomEditor::__createMainControl__(const TPropGridInfo::TItem::TValue &value,HWND hParent) const{ 28 | // creates, initializes with current Value, and returns Editor's MainControl 29 | // - creating the MainControl 30 | const HWND hMainCtrl=createCustomMainEditor( value.buffer, value.editor->valueSize, hParent ); 31 | // - adjusting the MainControl's style 32 | ::SetWindowLong(hMainCtrl, GWL_STYLE, 33 | ::GetWindowLong(hMainCtrl,GWL_STYLE) 34 | & ~(WS_CAPTION | WS_BORDER | WS_OVERLAPPED) 35 | | EDITOR_STYLE 36 | ); 37 | // - returning the MainControl 38 | return hMainCtrl; 39 | } 40 | 41 | bool TCustomEditor::__tryToAcceptMainCtrlValue__() const{ 42 | // True <=> Editor's current Value is acceptable, otherwise False 43 | ignoreRequestToDestroy=true; 44 | const TPropGridInfo::TItem::TValue &value=TEditor::pSingleShown->value; 45 | const bool accepted=onValueConfirmed( value.param, TEditor::pSingleShown->hMainCtrl, value.buffer ); 46 | ignoreRequestToDestroy=false; 47 | return accepted; 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | PropGrid::PCEditor PropGrid::Custom::DefineEditor(WORD height,TSize nValueBytes,TDrawValueHandler drawValue,TCreateCustomMainEditor createCustomMainEditor,TOnEllipsisButtonClicked onEllipsisBtnClicked,TOnValueConfirmed onValueConfirmed,TOnValueChanged onValueChanged){ 59 | // creates and returns an Editor with specified parameters 60 | return RegisteredEditors.__add__( 61 | new TCustomEditor( height ? height : EDITOR_DEFAULT_HEIGHT, 62 | nValueBytes, 63 | drawValue, 64 | createCustomMainEditor, onEllipsisBtnClicked, 65 | onValueConfirmed, 66 | onValueChanged 67 | ), 68 | sizeof(TCustomEditor) 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /PropGrid/src/Editor_Hyperlink.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | static bool WINAPI __doNothingAfterClick__(PropGrid::PCustomParam,int,LPCTSTR){ 4 | return true; // True = destroy the SysLink after clicking on a hyperlink, otherwise False 5 | } 6 | 7 | THyperlinkEditor::THyperlinkEditor( bool wideChar, 8 | PropGrid::Hyperlink::TOnHyperlinkClicked onHyperlinkClicked, 9 | PropGrid::TOnValueChanged onValueChanged 10 | ) 11 | // ctor 12 | // - base 13 | : TEditor( EDITOR_DEFAULT_HEIGHT, true, 0, nullptr, onValueChanged ) 14 | // - initialization 15 | , wideChar(wideChar) 16 | , onHyperlinkClicked( onHyperlinkClicked ? onHyperlinkClicked : __doNothingAfterClick__ ) { 17 | // - initializing OLE and Common Controls 18 | ::OleInitialize(nullptr); 19 | static constexpr INITCOMMONCONTROLSEX Icc={ sizeof(Icc), ICC_LINK_CLASS }; 20 | ::InitCommonControlsEx(&Icc); // silently assuming that running on Windows 2000 and newer (see handling failures to create a SysLink window below) 21 | } 22 | 23 | void THyperlinkEditor::__drawValue__(const TPropGridInfo::TItem::TValue &value,PDRAWITEMSTRUCT pdis) const{ 24 | // draws the Value into the specified rectangle 25 | const LONG w=pdis->rcItem.right-pdis->rcItem.left, h=pdis->rcItem.bottom-pdis->rcItem.top; 26 | const HDC dcTmpBmp=::CreateCompatibleDC(pdis->hDC); 27 | const HBITMAP hTmpBmp=::CreateCompatibleBitmap( pdis->hDC, w, h ); // TemporaryBitmap 28 | const HGDIOBJ hBmp0=::SelectObject(dcTmpBmp,hTmpBmp); 29 | const HWND hSysLink=__createMainControl__( value, pdis->hwndItem ); // creating the temporary SysLink control to adopt the appearance of 30 | ::SendMessageW( hSysLink, WM_SETFONT, (WPARAM)TPropGridInfo::FONT_DEFAULT, 0 ); // explicitly setting DPI-scaled font 31 | ::SetWindowPos( hSysLink, nullptr, 0,0, w,h, SWP_NOZORDER ); 32 | // . capturing the SysLink visuals to the TemporaryBitmap 33 | ::SendMessageW( hSysLink, WM_PRINTCLIENT, (WPARAM)dcTmpBmp, PRF_CHILDREN|PRF_CLIENT ); 34 | // . drawing the captured visuals at place of the SysLink control 35 | ::TransparentBlt( pdis->hDC, 0,0, w,h, dcTmpBmp, 0,0, w,h, ::GetSysColor(COLOR_BTNFACE) ); 36 | ::DestroyWindow(hSysLink); 37 | ::DeleteObject( ::SelectObject(dcTmpBmp,hBmp0) ); 38 | ::DeleteDC(dcTmpBmp); 39 | } 40 | 41 | HWND THyperlinkEditor::__createMainControl__(const TPropGridInfo::TItem::TValue &value,HWND hParent) const{ 42 | // creates, initializes with current Value, and returns Editor's MainControl 43 | WCHAR buf[STRING_LENGTH_MAX+1]; 44 | *buf=' '; // imitating the value cell padding by prepending an extra space to the text 45 | if (wideChar) 46 | ::lstrcpyW(buf+1,(LPCWSTR)value.buffer); 47 | else 48 | ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)value.buffer,-1, buf+1,ARRAYSIZE(buf)-1 ); 49 | return ::CreateWindowW( WC_LINK, 50 | buf, 51 | EDITOR_STYLE, 52 | 0,0, 1,1, 53 | hParent, 0, GET_PROPGRID_HINSTANCE(hParent), nullptr 54 | ); 55 | } 56 | 57 | bool THyperlinkEditor::__tryToAcceptMainCtrlValue__() const{ 58 | // True <=> Editor's current Value is acceptable, otherwise False 59 | return true; // Hyperlink doesn't have a Value, but returning True for the OnValueChanged event to fire 60 | } 61 | 62 | LRESULT THyperlinkEditor::__mainCtrl_wndProc__(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) const{ 63 | // window procedure 64 | switch (msg){ 65 | case WM_LBUTTONUP:{ 66 | // left mouse button released 67 | LHITTESTINFO info; 68 | info.pt.x=GET_X_LPARAM(lParam), info.pt.y=GET_Y_LPARAM(lParam); 69 | info.item.mask=LIF_ITEMINDEX|LIF_ITEMID; 70 | if (::SendMessageW( hWnd, LM_HITTEST, 0, (LPARAM)&info )){ 71 | ignoreRequestToDestroy=true; 72 | const TPropGridInfo::TItem::TValue &value=TEditor::pSingleShown->value; 73 | bool destroy; 74 | if (wideChar) 75 | destroy=((THyperlinkEditor *)value.editor)->onHyperlinkClicked( value.param, info.item.iLink, (LPCTSTR)info.item.szID ); 76 | else{ 77 | char buf[1024]; 78 | ::WideCharToMultiByte( CP_ACP, 0, info.item.szID,-1, buf,sizeof(buf), nullptr,nullptr ); 79 | destroy=((THyperlinkEditor *)value.editor)->onHyperlinkClicked( value.param, info.item.iLink, (LPCTSTR)buf ); 80 | } 81 | ::SetFocus(hWnd); // renewing the focus, should it be lost during the Action 82 | ignoreRequestToDestroy=false; 83 | if (destroy) 84 | PropGrid::TryToAcceptCurrentValueAndCloseEditor(); // on success also destroys the Editor 85 | return 0; 86 | }else 87 | break; 88 | } 89 | } 90 | return __super::__mainCtrl_wndProc__(hWnd,msg,wParam,lParam); 91 | } 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | PropGrid::PCEditor PropGrid::Hyperlink::DefineEditorA(TOnHyperlinkClickedA onHyperlinkClicked,TOnValueChanged onValueChanged){ 102 | // creates and returns an Editor with specified parameters 103 | return RegisteredEditors.__add__( 104 | new THyperlinkEditor( false, (TOnHyperlinkClicked)onHyperlinkClicked, onValueChanged ), 105 | sizeof(THyperlinkEditor) 106 | ); 107 | } 108 | 109 | PropGrid::PCEditor PropGrid::Hyperlink::DefineEditorW(TOnHyperlinkClickedW onHyperlinkClicked,TOnValueChanged onValueChanged){ 110 | // creates and returns an Editor with specified parameters 111 | return RegisteredEditors.__add__( 112 | new THyperlinkEditor( true, (TOnHyperlinkClicked)onHyperlinkClicked, onValueChanged ), 113 | sizeof(THyperlinkEditor) 114 | ); 115 | } 116 | -------------------------------------------------------------------------------- /PropGrid/src/PropGrid.h: -------------------------------------------------------------------------------- 1 | #ifndef PROPGRID_H 2 | #define PROPGRID_H 3 | 4 | #define GET_PROPGRID_INFO(hWnd) ((PPropGridInfo)::GetWindowLong((hWnd),GWL_USERDATA)) 5 | #define GET_PROPGRID_HINSTANCE(hWnd) ((HINSTANCE)::GetWindowLong((hWnd),GWL_HINSTANCE)) 6 | 7 | #define CATEGORY_HEIGHT 21 8 | 9 | typedef struct TPropGridInfo sealed{ 10 | struct TCategoryItem; // forward 11 | typedef TCategoryItem *PCategoryItem; 12 | 13 | typedef const struct TItem{ 14 | const PCategoryItem parentCategory; 15 | const LPCWSTR name; 16 | //TPropGridInfo *const pPropGridInfo; 17 | const struct TValue sealed{ 18 | const PCEditor editor; // either ==TEditor::Category (then this Item is a category), or !=TEditor::Category (then this Item is a property) 19 | const PropGrid::PValue buffer; 20 | const PropGrid::PCustomParam param; 21 | 22 | TValue(PCEditor editor,PropGrid::PValue buffer,PropGrid::PCustomParam param); 23 | } value; 24 | BYTE disabled; // >0 = this Item cannot be Edited 25 | TItem *nextInCategory; 26 | 27 | TItem(TPropGridInfo *pPropGridInfo,PCategoryItem parentCategory,LPCWSTR name,PCEditor editor,PropGrid::PValue buffer,PropGrid::PCustomParam param); 28 | virtual ~TItem(); 29 | 30 | virtual void __drawIndentedName__(HDC dc,RECT rc,HFONT hFont) const; 31 | virtual void __enable__(); 32 | virtual void __disable__(); 33 | BYTE __getLevel__() const; 34 | bool __isTopLevel__() const; 35 | bool __isCategory__() const; 36 | } *PCItem; 37 | 38 | struct TCategoryItem sealed:public TItem{ 39 | TItem *subitems; 40 | bool expanded; // use TListBox::__expand/collapseCategory__ to modify 41 | 42 | TCategoryItem(TPropGridInfo *pPropGridInfo,PCategoryItem parentCategory,LPCWSTR name,bool initiallyExpanded); 43 | ~TCategoryItem(); 44 | 45 | void __drawIndentedName__(HDC dc,RECT rc,HFONT hFont) const override; 46 | void __enable__() override; 47 | void __disable__() override; 48 | }; 49 | 50 | static HCURSOR CURSOR_SPLITTER; 51 | static HBRUSH BRUSH_BLACK; 52 | static HBRUSH BRUSH_GRAY_DARK; 53 | static HBRUSH BRUSH_GRAY; 54 | static HBRUSH BRUSH_GRAY_LIGHT; 55 | static HBRUSH BRUSH_WHITE; 56 | static HBRUSH BRUSH_SELECTION; 57 | static HPEN PEN_BLACK; 58 | static HPEN PEN_GRAY_DARK; 59 | static HPEN PEN_GRAY; 60 | static HPEN PEN_GRAY_LIGHT; 61 | static HFONT FONT_DEFAULT; 62 | static HFONT FONT_DEFAULT_BOLD; 63 | static HBITMAP CHECKBOX_STATES; 64 | static HBITMAP CHECKBOX_CHECKED; 65 | 66 | static void __init__(); 67 | static void __uninit__(); 68 | static void __scaleLogicalUnit__(HDC dc); 69 | static LRESULT CALLBACK __wndProc__(HWND hPropGrid,UINT msg,WPARAM wParam,LPARAM lParam); 70 | 71 | const HWND handle; 72 | struct TListBox sealed{ 73 | static LRESULT CALLBACK __wndProc__(HWND hListBox,UINT msg,WPARAM wParam,LPARAM lParam); 74 | 75 | struct TSplitter sealed{ 76 | static HWND hListBoxWithCurrentlyDraggedSplitter; // handle of the ListBox whose Splitter is being dragged 77 | 78 | int position; 79 | 80 | TSplitter(int position); 81 | 82 | bool __isCloseEnough__(int x) const; 83 | void __beginDrag__(const TPropGridInfo *pPropGridInfo,int fromPosition); 84 | void __drawInvertedLine__() const; 85 | void __endDrag__(int toPosition); 86 | } splitter; 87 | 88 | const HWND handle; 89 | 90 | TListBox(TPropGridInfo *pPropGridInfo,LONG propGridWidth,LONG propGridHeight); 91 | 92 | void __addItem__(PCItem item) const; 93 | void __removeItem__(PCItem item) const; 94 | void __addCategorySubitems__(PCategoryItem category) const; 95 | void __removeCategorySubitems__(PCategoryItem category) const; 96 | } listBox; 97 | TCategoryItem root; 98 | 99 | TPropGridInfo(HWND hPropGrid,LONG propGridWidth,LONG propGridHeight); 100 | } *PPropGridInfo; 101 | 102 | typedef const TPropGridInfo *PCPropGridInfo; 103 | 104 | 105 | 106 | extern const struct TRationalNumber:public div_t{ 107 | TRationalNumber(); 108 | 109 | int operator*(short i) const; 110 | bool operator!=(int i) const; 111 | } LogicalUnitScaleFactor; 112 | 113 | #endif // PROPGRID_H 114 | -------------------------------------------------------------------------------- /PropGrid/src/PropGrid_Items.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #define ITEM_LEVEL_TOP 1 4 | 5 | TPropGridInfo::TItem::TValue::TValue(PCEditor editor,PropGrid::PValue buffer,PropGrid::PCustomParam param) 6 | // ctor 7 | : editor(editor) , buffer(buffer) , param(param) { 8 | } 9 | 10 | 11 | 12 | TPropGridInfo::TItem::TItem(TPropGridInfo *pPropGridInfo,PCategoryItem parentCategory,LPCWSTR name,PCEditor editor,PropGrid::PValue buffer,PropGrid::PCustomParam param) 13 | // ctor 14 | // - initialization 15 | : parentCategory(parentCategory) 16 | , name(::lstrcpyW((PWCHAR)::malloc((1+::lstrlenW(name))*sizeof(WCHAR)),name)) 17 | , value(editor,buffer,param) 18 | , disabled( parentCategory ? parentCategory->disabled : 0 ) 19 | , nextInCategory(nullptr) { 20 | // - adding this Item to the end of the ParentCategory 21 | if (parentCategory){ // NOT PropertyGrid's Root Category 22 | TItem **a=&parentCategory->subitems; 23 | while (TItem *const p=*a) a=&p->nextInCategory; 24 | *a=this; 25 | //} 26 | // - redrawing the ListBox if all ParentCategories are Expanded 27 | //if (parentCategory){ // NOT PropertyGrid's Root Category 28 | const TCategoryItem *c=parentCategory; 29 | while (c) 30 | if (c->expanded) c=c->parentCategory; else break; 31 | if (!c) 32 | pPropGridInfo->listBox.__addItem__(this); 33 | } 34 | } 35 | 36 | TPropGridInfo::TItem::~TItem(){ 37 | // dtor 38 | // - removing this Item from the ParentCategory 39 | if (parentCategory){ // NOT PropertyGrid's Root Category 40 | TItem **a=&parentCategory->subitems; 41 | while (*a!=this) a=&(*a)->nextInCategory; 42 | *a=nextInCategory; 43 | } 44 | // - uninitialization 45 | ::free((PVOID)name); 46 | } 47 | 48 | void TPropGridInfo::TItem::__drawIndentedName__(HDC dc,RECT rc,HFONT hFont) const{ 49 | // draws indented Item's Name into the Rectangle using specified Font 50 | const HGDIOBJ hFont0=::SelectObject(dc,hFont); 51 | rc.left=LogicalUnitScaleFactor 52 | * 53 | ( CATEGORY_HEIGHT + (__getLevel__()-ITEM_LEVEL_TOP)*EDITOR_DEFAULT_HEIGHT + PROPGRID_CELL_MARGIN_LEFT ); 54 | ::DrawTextW(dc, 55 | name, -1, &rc, 56 | DT_SINGLELINE | DT_LEFT | DT_VCENTER 57 | ); 58 | ::SelectObject(dc,hFont0); 59 | } 60 | 61 | void TPropGridInfo::TItem::__enable__(){ 62 | // enables this Item (i.e. "unlocks" this Item, making it eventually editable) 63 | if (disabled>0) 64 | disabled--; 65 | } 66 | 67 | void TPropGridInfo::TItem::__disable__(){ 68 | // disables this Item (i.e. "locks" this Item, making it not editable) 69 | if (++disabled) 70 | TEditor::__cancelEditing__(); 71 | } 72 | 73 | BYTE TPropGridInfo::TItem::__getLevel__() const{ 74 | // determines and returns the "sub-level" of this Item 75 | BYTE result=ITEM_LEVEL_TOP; 76 | for( const TCategoryItem *c=parentCategory; c=c->parentCategory; result++ ); 77 | return result; 78 | } 79 | 80 | bool TPropGridInfo::TItem::__isTopLevel__() const{ 81 | // True <=> this Item is in the top level (e.g. a top-level Category) 82 | return __getLevel__()==ITEM_LEVEL_TOP; 83 | } 84 | 85 | bool TPropGridInfo::TItem::__isCategory__() const{ 86 | // True <=> this Item is actually a Category, otherwise False 87 | return value.editor==nullptr; 88 | } 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | TPropGridInfo::TCategoryItem::TCategoryItem(TPropGridInfo *pPropGridInfo,PCategoryItem parentCategory,LPCWSTR name,bool initiallyExpanded) 102 | // ctor 103 | // - base 104 | : TItem( pPropGridInfo, parentCategory, name, nullptr, nullptr, nullptr ) 105 | // - initialization 106 | , subitems(nullptr) 107 | , expanded(initiallyExpanded) { 108 | } 109 | 110 | TPropGridInfo::TCategoryItem::~TCategoryItem(){ 111 | // dtor 112 | while (subitems) 113 | delete subitems; // also removes the Subitem from the list 114 | } 115 | 116 | #define CATEGORY_SYMBOL_SIZE 11 117 | 118 | void TPropGridInfo::TCategoryItem::__drawIndentedName__(HDC dc,RECT rc,HFONT hFont) const{ 119 | // draws indented Category's Name and icon on Expansion ("[+/-]") into the Rectangle using specified Font 120 | // - name 121 | TItem::__drawIndentedName__(dc,rc,hFont); 122 | // - icon on Expansion ("[+/-]") 123 | const int iDc0=::SaveDC(dc); 124 | ::SetViewportOrgEx( dc, 125 | LogicalUnitScaleFactor*(CATEGORY_HEIGHT+(__getLevel__()-2*ITEM_LEVEL_TOP)*EDITOR_DEFAULT_HEIGHT), 126 | rc.top, 127 | nullptr 128 | ); 129 | __scaleLogicalUnit__(dc); 130 | // . drawing the "[-]" icon 131 | ::Rectangle(dc, 132 | (CATEGORY_HEIGHT-CATEGORY_SYMBOL_SIZE)/2, (CATEGORY_HEIGHT-CATEGORY_SYMBOL_SIZE)/2, 133 | (CATEGORY_HEIGHT+CATEGORY_SYMBOL_SIZE)/2, (CATEGORY_HEIGHT+CATEGORY_SYMBOL_SIZE)/2 134 | ); 135 | ::MoveToEx( dc, CATEGORY_HEIGHT/2-2, CATEGORY_HEIGHT/2, nullptr ); 136 | ::LineTo( dc, CATEGORY_HEIGHT/2+2+1, CATEGORY_HEIGHT/2 ); // "+1" because the last point of a line isn't drawn 137 | // . if the Category is collapsed, changing the above "[-]" icon to "[+]" 138 | if (!expanded){ // is collapsed 139 | ::MoveToEx( dc, CATEGORY_HEIGHT/2, CATEGORY_HEIGHT/2-2, nullptr ); 140 | ::LineTo( dc, CATEGORY_HEIGHT/2, CATEGORY_HEIGHT/2+2+1 ); // "+1" because the last point of a line isn't drawn 141 | } 142 | ::RestoreDC(dc,iDc0); 143 | } 144 | 145 | void TPropGridInfo::TCategoryItem::__enable__(){ 146 | // enables this Item (i.e. "unlocks" this Item, making it eventually editable) 147 | // - base 148 | __super::__enable__(); 149 | // - enabling all Subitems in this Category 150 | for( TItem *p=subitems; p!=nullptr; p=p->nextInCategory ) 151 | p->__enable__(); 152 | } 153 | 154 | void TPropGridInfo::TCategoryItem::__disable__(){ 155 | // disables this Item (i.e. "locks" this Item, making it not editable) 156 | // - base 157 | __super::__disable__(); 158 | // - disabling all Subitems in this Category 159 | for( TItem *p=subitems; p!=nullptr; p=p->nextInCategory ) 160 | p->__disable__(); 161 | } 162 | -------------------------------------------------------------------------------- /PropGrid/src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | // use Common-Controls library version 6 5 | #pragma comment(linker,"\"/manifestdependency:type='win32' \ 6 | name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ 7 | processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 8 | 9 | #define OEMRESOURCE /* to enable using of predefined OBM_* resources */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | //#include 19 | 20 | #if _MSC_VER<=1600 21 | #define constexpr const 22 | #endif 23 | 24 | typedef const struct TEditor *PCEditor; // forward 25 | 26 | #include "api.h" 27 | #include "PropGrid.h" 28 | #include "Editors.h" 29 | 30 | #undef min 31 | #undef max 32 | 33 | #ifdef RELEASE_MFC42 34 | #if _MSC_VER<=1600 35 | #define noexcept 36 | #endif 37 | 38 | void __cdecl operator delete(PVOID ptr, UINT sz) noexcept; 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Ride.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual C++ Express 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Main", "Main\Main.vcxproj", "{4942F917-831D-40A3-BE9F-EA565D721A34}" 4 | EndProject 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropGrid", "PropGrid\PropGrid.vcxproj", "{3364C212-E5CB-4027-B58D-0DD1D5271ABC}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tdi", "Tdi\Tdi.vcxproj", "{A9001EA5-CA73-483D-B494-AFE3B98D7E1D}" 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Yahel", "YAHEL\Yahel\Yahel.vcxproj", "{7D9A9C78-93DB-426C-9082-B466ED09BFEA}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug in RAMdisk|Win32 = Debug in RAMdisk|Win32 14 | Debug|Win32 = Debug|Win32 15 | Release MFC 4.2|Win32 = Release MFC 4.2|Win32 16 | Release|Win32 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Debug in RAMdisk|Win32.ActiveCfg = Debug in RAMdisk|Win32 20 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Debug in RAMdisk|Win32.Build.0 = Debug in RAMdisk|Win32 21 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Debug|Win32.Build.0 = Debug|Win32 23 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Release MFC 4.2|Win32.ActiveCfg = Release MFC 4.2|Win32 24 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Release MFC 4.2|Win32.Build.0 = Release MFC 4.2|Win32 25 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Release|Win32.ActiveCfg = Release|Win32 26 | {A9001EA5-CA73-483D-B494-AFE3B98D7E1D}.Release|Win32.Build.0 = Release|Win32 27 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Debug in RAMdisk|Win32.ActiveCfg = Debug in RAMdisk|Win32 28 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Debug in RAMdisk|Win32.Build.0 = Debug in RAMdisk|Win32 29 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Debug|Win32.ActiveCfg = Debug|Win32 30 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Debug|Win32.Build.0 = Debug|Win32 31 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Release MFC 4.2|Win32.ActiveCfg = Release MFC 4.2|Win32 32 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Release MFC 4.2|Win32.Build.0 = Release MFC 4.2|Win32 33 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Release|Win32.ActiveCfg = Release|Win32 34 | {3364C212-E5CB-4027-B58D-0DD1D5271ABC}.Release|Win32.Build.0 = Release|Win32 35 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Debug in RAMdisk|Win32.ActiveCfg = Debug in RAMdisk|Win32 36 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Debug in RAMdisk|Win32.Build.0 = Debug in RAMdisk|Win32 37 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Debug|Win32.ActiveCfg = Debug|Win32 38 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Debug|Win32.Build.0 = Debug|Win32 39 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Release MFC 4.2|Win32.ActiveCfg = Release MFC 4.2|Win32 40 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Release MFC 4.2|Win32.Build.0 = Release MFC 4.2|Win32 41 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Release|Win32.ActiveCfg = Release|Win32 42 | {4942F917-831D-40A3-BE9F-EA565D721A34}.Release|Win32.Build.0 = Release|Win32 43 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Debug in RAMdisk|Win32.ActiveCfg = Debug|Win32 44 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Debug in RAMdisk|Win32.Build.0 = Debug|Win32 45 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Debug|Win32.ActiveCfg = Debug|Win32 46 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Debug|Win32.Build.0 = Debug|Win32 47 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Release MFC 4.2|Win32.ActiveCfg = Release MFC 4.2|Win32 48 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Release MFC 4.2|Win32.Build.0 = Release MFC 4.2|Win32 49 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Release|Win32.ActiveCfg = Release|Win32 50 | {7D9A9C78-93DB-426C-9082-B466ED09BFEA}.Release|Win32.Build.0 = Release|Win32 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /Tdi/Tdi.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | -------------------------------------------------------------------------------- /Tdi/Tdi.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Tdi/src/Tdi.h: -------------------------------------------------------------------------------- 1 | #ifndef TDI_H 2 | #define TDI_H 3 | 4 | #pragma pack(1) 5 | typedef const struct TTabInfo sealed{ 6 | const CTdiCtrl::TTab::TCanBeClosed fnCanBeClosed; 7 | const CTdiCtrl::TTab::TOnClosing fnOnTabClosing; // can be Null 8 | const CTdiCtrl::TTab::PContent content; 9 | 10 | TTabInfo(CTdiCtrl::TTab::TCanBeClosed fnCanBeClosed,CTdiCtrl::TTab::TOnClosing fnOnTabClosing,CTdiCtrl::TTab::PContent content); 11 | } *PCTabInfo; 12 | 13 | 14 | 15 | typedef struct TDraggedTabInfo sealed{ 16 | int tabId; 17 | TCHAR caption[50]; 18 | TCITEM data; 19 | RECT targetArea; 20 | 21 | TDraggedTabInfo(HWND hTdi,int _tabId); 22 | } *PDraggedTabInfo; 23 | 24 | 25 | 26 | #define GET_TDI_INFO(hTdi) ( (PTdiInfo)::GetWindowLong(hTdi,GWL_USERDATA) ) 27 | 28 | typedef struct TTdiInfo sealed{ 29 | static unsigned int nInstances; 30 | static HFONT fontWebdings; 31 | 32 | static LRESULT CALLBACK __wndProc__(HWND hTdi,UINT msg,WPARAM wParam,LPARAM lParam); 33 | 34 | const HWND handle; // handle of this TDI 35 | const HWND hBtnCloseCurrentTab; 36 | const CTdiCtrl::TParams params; 37 | const WNDPROC wndProc0; // original procedure of the control from which the TDI is subclassed 38 | CTdiCtrl::TTab::PContent currentTabContent; 39 | 40 | TTdiInfo(HINSTANCE hInstance,HWND hTdi,CTdiCtrl::PCParams params); 41 | ~TTdiInfo(); 42 | 43 | void __hideCurrentContent__(); 44 | void __switchToTab__(int i); 45 | void __fitContentToTdiCanvas__() const; 46 | } *PTdiInfo; 47 | 48 | 49 | 50 | PCTabInfo GetTabInfo(HWND hTdi,int tabId); 51 | 52 | 53 | #endif // TDI_H 54 | -------------------------------------------------------------------------------- /Tdi/src/api.h: -------------------------------------------------------------------------------- 1 | #ifndef TDI_API_H 2 | #define TDI_API_H 3 | 4 | #ifdef _DEBUG 5 | #define TDI_DECLSPEC 6 | #elif TDI_EXPORT 7 | #define TDI_DECLSPEC __declspec(dllexport) 8 | #else 9 | #define TDI_DECLSPEC __declspec(dllimport) 10 | #endif 11 | 12 | 13 | #define TDI_TAB_CANCLOSE_ALWAYS (CTdiCtrl::TTab::TCanBeClosed)TRUE 14 | #define TDI_TAB_CANCLOSE_NEVER nullptr 15 | 16 | 17 | class TDI_DECLSPEC CTdiCtrl sealed{ 18 | public: 19 | typedef PVOID PCustomParam; 20 | 21 | struct TDI_DECLSPEC TTab{ 22 | typedef LPCVOID PContent; 23 | 24 | typedef void (WINAPI *TShowContent)(PCustomParam,PContent); 25 | typedef void (WINAPI *THideContent)(PCustomParam,PContent); 26 | typedef void (WINAPI *TRepaintContent)(PContent); 27 | typedef HWND (WINAPI *TGetContentHwnd)(PContent); 28 | 29 | typedef bool (WINAPI *TCanBeClosed)(PContent); 30 | typedef void (WINAPI *TOnClosing)(PContent); 31 | }; 32 | 33 | typedef const struct TDI_DECLSPEC TParams sealed{ 34 | const PCustomParam customParam; 35 | const TTab::TShowContent fnShowContent; 36 | const TTab::THideContent fnHideContent; 37 | const TTab::TRepaintContent fnRepaintContent; 38 | const TTab::TGetContentHwnd fnGetHwnd; 39 | 40 | TParams(PCustomParam customParam,TTab::TShowContent fnShowContent,TTab::THideContent fnHideContent,TTab::TRepaintContent fnRepaintContent,TTab::TGetContentHwnd fnGetHwnd); 41 | } *PCParams; 42 | 43 | static HWND WINAPI Create(HINSTANCE hInstance,LPCTSTR windowName,UINT style,int width,int height,HWND hParent,UINT id,PCParams params); 44 | static void WINAPI SubclassWnd(HINSTANCE hInstance,HWND hTabCtrl,PCParams params); 45 | static TTab::PContent GetTabContent(HWND hTdi,int iIndex); 46 | static bool WINAPI GetCurrentTabContentRect(HWND hTdi,LPRECT pOutRect); 47 | static void WINAPI InsertTabA(HWND hTdi,int iIndex,LPCSTR tabName,TTab::PContent tabContent,bool makeCurrent,TTab::TCanBeClosed fnCanBeClosed,TTab::TOnClosing fnOnTabClosing); 48 | static void WINAPI InsertTabW(HWND hTdi,int iIndex,LPCWSTR tabName,TTab::PContent tabContent,bool makeCurrent,TTab::TCanBeClosed fnCanBeClosed,TTab::TOnClosing fnOnTabClosing); 49 | static void WINAPI AddTabLastA(HWND hTdi,LPCSTR tabName,TTab::PContent tabContent,bool makeCurrent,TTab::TCanBeClosed fnCanBeClosed,TTab::TOnClosing fnOnTabClosing); 50 | static void WINAPI AddTabLastW(HWND hTdi,LPCWSTR tabName,TTab::PContent tabContent,bool makeCurrent,TTab::TCanBeClosed fnCanBeClosed,TTab::TOnClosing fnOnTabClosing); 51 | static void WINAPI UpdateTabCaptionA(HWND hTdi,TTab::PContent tabContent,LPCSTR tabNewName); 52 | static void WINAPI UpdateTabCaptionW(HWND hTdi,TTab::PContent tabContent,LPCWSTR tabNewName); 53 | static void WINAPI RemoveTab(HWND hTdi,int tabId); 54 | static void WINAPI RemoveTab(HWND hTdi,TTab::PContent tabContent); 55 | static void WINAPI RemoveCurrentTab(HWND hTdi); 56 | static void WINAPI SwitchToTab(HWND hTdi,int tabId); 57 | static void WINAPI SwitchToTab(HWND hTdi,TTab::PContent tabContent); 58 | static void WINAPI SwitchToNextTab(HWND hTdi); 59 | static void WINAPI SwitchToPrevTab(HWND hTdi); 60 | }; 61 | 62 | #ifdef UNICODE 63 | #else 64 | #define InsertTab InsertTabA 65 | #define AddTabLast AddTabLastA 66 | #define UpdateTabCaption UpdateTabCaptionA 67 | #endif 68 | 69 | #endif // TDI_API_H 70 | -------------------------------------------------------------------------------- /Tdi/src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #define OEMRESOURCE /* aby mozno pouzit preddefinovane OBM_* zdroje */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "api.h" 11 | #include "Tdi.h" 12 | 13 | #ifdef RELEASE_MFC42 14 | #if _MSC_VER<=1600 15 | #define noexcept 16 | #endif 17 | 18 | void __cdecl operator delete(PVOID ptr, UINT sz) noexcept; 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /_cleanup.bat: -------------------------------------------------------------------------------- 1 | REM --- General clean-up --- 2 | del _.d80 _.d40 _.dsk _.ima _.img _.trd _.scl _.tap _.mgt _.mbd _.scp _.hfe ride.sdf 3 | del ride.vc.db 4 | del /a:h ride.suo 5 | del C:\WINDOWS\ride.ini 6 | rd /s /q debug ipch release "Release MFC 4.2" "Debug in RAMdisk" 7 | rd /s /q r:\ipch r:\ride 8 | attrib -h -s /d "%~dp0\.vs" 9 | rd /s /q "%~dp0\.vs" 10 | 11 | REM --- Main project clean-up --- 12 | cd Main 13 | del res\resource.aps 14 | rd /s /q debug ipch release "Release MFC 4.2" "Debug in RAMdisk" 15 | cd.. 16 | 17 | REM --- PropGrid project clean-up --- 18 | cd PropGrid 19 | rd /s /q debug ipch release "Release MFC 4.2" "Debug in RAMdisk" 20 | cd.. 21 | 22 | REM --- TDI project clean-up --- 23 | cd Tdi 24 | rd /s /q debug ipch release "Release MFC 4.2" "Debug in RAMdisk" 25 | cd.. 26 | 27 | REM --- Yahel module clean-up --- 28 | cd Yahel 29 | _cleanup.bat 30 | cd.. 31 | --------------------------------------------------------------------------------