Merge branch 'master' into MB-class2

This commit is contained in:
tomcw 2023-01-22 18:09:18 +00:00
commit 0bca091b55
132 changed files with 5368 additions and 4329 deletions

View File

@ -1,57 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Applewin", "AppleWinExpress2008.vcproj", "{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}"
ProjectSection(ProjectDependencies) = postProject
{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F} = {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}
{7935B998-C713-42AE-8F6D-9FF9080A1B1B} = {7935B998-C713-42AE-8F6D-9FF9080A1B1B}
{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2} = {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B} = {709278B8-C583-4BD8-90DE-4E4F35A3BD8B}
{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB} = {0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib-Express2008.vcproj", "{7935B998-C713-42AE-8F6D-9FF9080A1B1B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip_lib", "zip_lib\zip_lib2008.vcproj", "{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCPU6502", "test\TestCPU6502\TestCPU6502-vs2008.vcproj", "{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "libyaml\win32\yaml2008.vcproj", "{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestDebugger", "test\TestDebugger\TestDebugger.vcproj", "{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}.Debug|Win32.ActiveCfg = Debug|Win32
{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}.Debug|Win32.Build.0 = Debug|Win32
{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}.Release|Win32.ActiveCfg = Release|Win32
{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}.Release|Win32.Build.0 = Release|Win32
{7935B998-C713-42AE-8F6D-9FF9080A1B1B}.Debug|Win32.ActiveCfg = Debug|Win32
{7935B998-C713-42AE-8F6D-9FF9080A1B1B}.Debug|Win32.Build.0 = Debug|Win32
{7935B998-C713-42AE-8F6D-9FF9080A1B1B}.Release|Win32.ActiveCfg = Release|Win32
{7935B998-C713-42AE-8F6D-9FF9080A1B1B}.Release|Win32.Build.0 = Release|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Debug|Win32.ActiveCfg = Debug|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Debug|Win32.Build.0 = Debug|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Release|Win32.ActiveCfg = Release|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Release|Win32.Build.0 = Release|Win32
{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Debug|Win32.ActiveCfg = Debug|Win32
{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Debug|Win32.Build.0 = Debug|Win32
{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Release|Win32.ActiveCfg = Release|Win32
{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Release|Win32.Build.0 = Release|Win32
{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Debug|Win32.ActiveCfg = Debug|Win32
{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Debug|Win32.Build.0 = Debug|Win32
{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Release|Win32.ActiveCfg = Release|Win32
{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Release|Win32.Build.0 = Release|Win32
{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Debug|Win32.ActiveCfg = Debug|Win32
{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Debug|Win32.Build.0 = Debug|Win32
{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Release|Win32.ActiveCfg = Release|Win32
{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@
<ClInclude Include="source\Configuration\PropertySheet.h" />
<ClInclude Include="source\Configuration\PropertySheetDefs.h" />
<ClInclude Include="source\Configuration\PropertySheetHelper.h" />
<ClInclude Include="source\CopyProtectionDongles.h" />
<ClInclude Include="source\Core.h" />
<ClInclude Include="source\CPU.h" />
<ClInclude Include="source\CPU\cpu6502.h" />
@ -115,6 +116,8 @@
<ClInclude Include="source\StrFormat.h" />
<ClInclude Include="source\SynchronousEventManager.h" />
<ClInclude Include="source\Tape.h" />
<ClInclude Include="source\Tfe\DNS.h" />
<ClInclude Include="source\Tfe\IPRaw.h" />
<ClInclude Include="source\Tfe\NetworkBackend.h" />
<ClInclude Include="source\Tfe\Bpf.h" />
<ClInclude Include="source\Tfe\Ip6_misc.h" />
@ -157,6 +160,7 @@
<ClCompile Include="source\CardManager.cpp" />
<ClCompile Include="source\CmdLine.cpp" />
<ClCompile Include="source\Configuration\About.cpp" />
<ClCompile Include="source\Configuration\Config.cpp" />
<ClCompile Include="source\Configuration\PageAdvanced.cpp" />
<ClCompile Include="source\Configuration\PageConfig.cpp" />
<ClCompile Include="source\Configuration\PageConfigTfe.cpp" />
@ -165,6 +169,7 @@
<ClCompile Include="source\Configuration\PageSound.cpp" />
<ClCompile Include="source\Configuration\PropertySheet.cpp" />
<ClCompile Include="source\Configuration\PropertySheetHelper.cpp" />
<ClCompile Include="source\CopyProtectionDongles.cpp" />
<ClCompile Include="source\Core.cpp" />
<ClCompile Include="source\CPU.cpp" />
<ClCompile Include="source\Debugger\Debugger_Disassembler.cpp" />
@ -224,6 +229,8 @@
<ClCompile Include="source\StrFormat.cpp" />
<ClCompile Include="source\SynchronousEventManager.cpp" />
<ClCompile Include="source\Tape.cpp" />
<ClCompile Include="source\Tfe\DNS.cpp" />
<ClCompile Include="source\Tfe\IPRaw.cpp" />
<ClCompile Include="source\Tfe\NetworkBackend.cpp" />
<ClCompile Include="source\Tfe\PCapBackend.cpp" />
<ClCompile Include="source\Tfe\tfearch.cpp">
@ -469,7 +476,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
@ -497,7 +504,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;ddraw_lib\x86\dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw_lib\x86\ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;ddraw_lib\x86\dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw_lib\x86\ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
@ -524,7 +531,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
@ -555,7 +562,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
@ -588,7 +595,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;ddraw_lib\x86\dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw_lib\x86\ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;ddraw_lib\x86\dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;ddraw_lib\x86\ddraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
@ -621,7 +628,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>iphlpapi.lib;htmlhelp.lib;comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib;comdlg32.lib;ole32.lib;wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>

View File

@ -259,6 +259,18 @@
<ClCompile Include="source\Uthernet2.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Tfe\IPRaw.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Tfe\DNS.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Configuration\Config.cpp">
<Filter>Source Files\Configuration</Filter>
</ClCompile>
<ClCompile Include="source\CopyProtectionDongles.cpp">
<Filter>Source Files\Emulator</Filter>
</ClCompile>
<ClCompile Include="source\MockingboardCardManager.cpp">
<Filter>Source Files\Emulator</Filter>
</ClCompile>
@ -597,6 +609,15 @@
<ClInclude Include="source\Uthernet2.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Tfe\IPRaw.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Tfe\DNS.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\CopyProtectionDongles.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
<ClInclude Include="source\MockingboardCardManager.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>

View File

@ -24,20 +24,44 @@ Before submitting an enhancement, search the existing issues to see if this enha
### Pull Requests
The process described here has several goals:
- Maintain AppleWin's quality
- Enforce a workable solution for AppleWin maintainers to review contributions
Thank you for wanting to make the project better! However, before you submit a PR (Pull Request) please read the following carefully as the process described here has several goals:
Please review the simple [Coding Conventions](https://github.com/AppleWin/AppleWin/blob/master/docs/CodingConventions.txt).
- Maintain AppleWin's quality,
- Enforce a workable solution for AppleWin maintainers to review contributions, and
- Explain the development philosophy.
Smaller PRs are highly desirable, as they should be simpler to review and approve. Large changes are likely to be rejected or not get looked at (resulting in them going stale, and ultimately diverging further from the mainline repo).
Firstly,
# Do NOT submit one big patch!
The AppleWin developers work on AppleWin in their spare time. This means we have limited time to review PRs. Smaller PRs are highly desirable, as they should be simpler to review and approve. Large changes are likely to be rejected or not get looked at (resulting in them going stale, and ultimately diverging further from the mainline repo).
For large changes being submitted for review, then it's HIGHLY recommended to split the large PR into smaller PRs, and submit them piece by piece. This means that no dependencies can exist between each smaller PR.
For a PR, don't make changes that are unrelated to the PR. These can be done in separate PRs.
For a PR, don't make changes that are unrelated to the PR as this adds unnecessary noise and time to review. These can and should be done in separate PRs.
Follow the coding style in the source file(s) that are being changed. Since this is a mature codebase, then bear in mind that different coding styles can exist in different source files.
Next, please make sure your code matches the existing style by reviewing the simple [Coding Conventions](https://github.com/AppleWin/AppleWin/blob/master/docs/CodingConventions.txt).
Follow the coding style in the source file(s) that are being changed. Since this is a mature codebase, then bear in mind that different coding styles can and do exist in different source files due to many different authors over the past 25+ years.
For new (large) features, then link the PR back to an enhancement issue, where the proposed feature had been discussed with AppleWin maintainers first and justified using suitable use-cases. In this enhancement issue be sure to include a specification of the feature, and a design if necessary. Having a design (doc, diagrams) that explains the logic/algorithms/protocol etc will help in the long term maintenance of this feature.
When changing project metadata files (eg. .sln, .vcproj, .rc) then different versions of Visual Studio may decide to reorder or re-format other sections of the file. This can result in lots of churn in the file each time a trivial edit is made. So before committing the PR, check the difference, and if there's been lots of unnecessary changes then just make the required change using a non-Visual Studio editor.
When submitting UI changes please discuss WHY you are making changes.
* **Our userbase expects things to work the way they are used to.** Changing default behavior without a "migration path" causes users to submit bug reports asking us to revert changes which wastes everyone's time.
* **Functionality should be prioritized over Form.** The _entire_ point of UI is to empower the user to do the thing they want to do and _then get out of their way._ A pretty UI, but one that frustrates users, is not empowering them.
* Also keep in mind many so called modern UI/UX "experts" tend to make changes for the sake of change in order to sell a product. Worse they tend to focus on mobile design even when it makes little or no sense on a desktop platform. There is a time and a place to focus on Form but as a mature project we are more interested in stability and functionality than throwing on a fresh coat of paint that more likely introduces a new set of bugs.
Understand that not everyone will agree to UI changes. The developers have been using computers a very long time and are not interested in chasing modern UI fads unless a good reason can be shown _why_ the UI should be changed. For example, take a poll, or even better raise an issue asking for feedback. This way we have hard data showing that there is interest instead of assuming that a change is automatically "better".
Trivial changes such as updating art are much easier to accept than rewriting the UI moving buttons around.
When discussing topics focus on the problem and potential solutions and not people. Please keep things professional.
Lasty, there are many reasons why we may reject a feature or PR. This does NOT mean we aren't interested; it just means that the feature or PR doesn't meet the developer's expectations and project goals _at this time._
Thanks again for your interest in wanting to make AppleWin better.

View File

@ -5,7 +5,7 @@ AppleWin
AppleWin is a fully-featured emulator supporting different Apple II models and clones. A variety of peripheral cards and video display modes are supported (eg. NTSC, RGB); and there's an extensive built-in symbolic debugger.
Peripheral cards supported:
Peripheral cards and add-on hardware supported:
- Mockingboard, Phasor and SAM sound cards
- Disk II interface for floppy disk drives
- Hard disk controller
@ -13,16 +13,18 @@ Peripheral cards supported:
- Parallel printer card
- Mouse interface
- Apple IIe Extended 80-Column Text Card and RamWorks III (8MB)
- RGB cards: Apple's Extended 80-Column Text/AppleColor Adaptor Card, 'Le Chat Mauve' Féline and Eve.
- RGB cards: Apple's Extended 80-Column Text/AppleColor Adaptor Card and 'Le Chat Mauve' Féline.
- CP/M SoftCard
- Uthernet I (ethernet card)
- Uthernet I and II (ethernet cards)
- Language Card and Saturn 64/128K for Apple II/II+
- 4Play and SNES MAX joystick cards
- VidHD card (functionality limited to IIgs' Super Hi-Res video modes)
- No Slot Clock (NSC)
Download latest (stable) release: [AppleWin v1.29.16.0](https://github.com/AppleWin/AppleWin/releases/download/v1.29.16.0/AppleWin1.29.16.0.zip)
Download latest (stable) release: [AppleWin v1.30.13.0](https://github.com/AppleWin/AppleWin/releases/download/v1.30.13.0/AppleWin1.30.13.0.zip)
Release Notes: [v1.29.16.0](https://github.com/AppleWin/AppleWin/releases/tag/v1.29.16.0)
Release Notes: [v1.30.13.0](https://github.com/AppleWin/AppleWin/releases/tag/v1.30.13.0)
Building
@ -32,6 +34,11 @@ To compile from source see:
* [docs/compiling.txt](https://github.com/AppleWin/AppleWin/blob/master/docs/compiling.txt)
Contributing
============
Please see the [CONTRIBUTING](https://github.com/AppleWin/AppleWin/blob/master/CONTRIBUTING.md) doc before raising new bugs, features and _especially_ PRs.
Next Version
============
Experimental build: pending

View File

@ -1,4 +1,5 @@
; Apple 2 Applesoft Symbol Table
; Version 3 Fix AppleWin GH#1144
; Version 2 Cross-referenced/Sync'd with APPLE2E.SYM & A2_BASIC.SYM
; Version 1 by Michael Pohoreski - AppleWin Debugger Dev
; Based on Bob Sander-Cederlof's "S-C DocuMentor: Applesoft"
@ -562,13 +563,14 @@ EA2B OUTOFRNG
DB5A OUTQUES
DB57 OUTSP
E8D5 OVERFLOW
79 P.ADD
50 P.AND
7B P.MUL
7F P.NEQ
46 P.OR
7D P.PWR
64 P.REL
; NB. these 7 P.xxx values are constants used in MATHTBL (a MATH OPERATOR BRANCH TABLE) - see AppleWin GH#1144
; 79 P.ADD
; 50 P.AND
; 7B P.MUL
; 7F P.NEQ
; 46 P.OR
; 7D P.PWR
; 64 P.REL
DEB2 PARCHK
D56C PARSE
.01=D56D .02=D578 .03=D588 .04=D590 .05=D5A2 .06=D5A7 .07=D5A8

View File

@ -8,6 +8,97 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
1.30.13.0 - 2 Jan 2023
----------------------
. [Change #1153] Support Game I/O Connector copy protection dongles. [@medasaro]
- SDS SpeedStar dongle
. [Change #1141,1142,1148,1149,1150] SNES MAX support for various controllers via mapping files. [@eriknoc]
- EG. -snes-max-user-joy1 snesmax\controller_Logitech_F310.yaml
. [Change #1134] Add disk activity indicators for drives in Slot 5.
- Only visible in 2x Windowed mode.
- Add a new UI toggle in Config->Disk tab to "Show status" (ie. the track/sector status).
- Hovering over this status will show a tooltip with both decimal and hexadecimal values,
and the track includes the full fractional quarter track value too.
. [Change #1133] Add a new command line '-s<n> diskii13' to put a diskii card into slot-n and force it to use the 13-sector firmware.
. [Bug #1157] Fix video junk on RHS edge for TV & Monitor video modes. (Regression at 1.13.11.0)
. [Bug #1144] Fix some ZP symbols in A2_BASIC.SYM.
. [Bug #1143] Fix graphical glitches on penultimate scan line when in non-"50% Scan Lines" mode.
. [Bug #1138] Fix Mousecard - wasn't generating VBL interrupt for mode byte of $08. Fixes 'Jeeves'.
. [Bug #1131] Fix MIXED issue when in 'Color (PAL Monitor)' video mode.
. Change: Debugger: for LBR, support the unset/undefined case (eg. reset to undefined when beginning a new debug session).
. Change: Debugger: extend to support DISK commands for Disk II cards in other slots:
- DISK SLOT n
- Now DISK INFO will provide info for the new slot.
. Change: Debugger: add new command: 'bpv <vpos,[len]>'
- break when video-scanner's vertical position matches vpos.
- NB. auto disable when hit.
. Change: Debugger: extend watches: 'WA <n> v' to show video scanner address & video data (aux and/or main or shr 4-byte).
1.30.12.0 - 27 Sep 2022
-----------------------
. [Bug #1128] Increase paddle maximum offset - fixes 'Learning with Leepers'.
. [Bug #1127] Debugger: fix memory search command.
. [Bug #1126] Fix rare crash bug (when unprotected WOZ in drive).
. [Bug #1125] Improve WOZ support: fixes 'Accolade Comics'.
. [Bug #1121] Fix for aspect ratio in full-screen:
- Now revert to uniformly scaling in both x & y directions unless user specifies resolution.
- NB. Regression at 1.30.7.0 when adding VidHD support.
. [Bug #1119] Fix render issue in 'Color (PAL Monitor)' video mode.
. [Bug #1022] WOZ support: Better cross-track positioning - fixes 'Balance of Power'.
. Fix for loading old save-states with Phasor card (bumps MB version in save-state to v9).
- NB. Regression at 1.30.10.0 when fixed Phasor to "use correct primary AY8913".
. Change: Command line: support '-s2 ssc'.
1.30.11.0 - 23 Jun 2022
-----------------------
. [Change #1103] Debugger: support memory breakpoints for HDD DMA r/w's:
- When the debugger is active (eg. breakpoints enabled) then trap on HDD r/w's that match the BPM[R|W].
- NB. the breakpoint will fire after the whole HDD r/w operation has completed.
. [Bug #1113] Fix for Uthernet II registers repeating in DEVICE SELECT I/O space. [@audetto]
. [Bug #1110] Fix for WOZ and quarter tracks for A2osX's 192K floppy image.
- Support two adjacent phases turned off in rapid sequence.
. [Bug #1108] Fix for C3 ROM not set correctly when loading a save-state with a VidHD (in slot 3).
. [Bug #1106] Fix for minor screen corruption with VidHD enabled.
- Debugger: fix for mouse-click hit-tests with VidHD enabled.
. [Bug #1104] Fix for rare Mockingboard speech race condition when debugger-stepping.
. [PR #1098] Internal: refactor debugger. [@kiyolee]
. Change: Mockingboard's SSI263: support reg3's amplitude (fix for TR speaking during SSI263 detection).
. Change: DebuggerAutoRun.txt: extend search path to first try CurrentDir, then ProgramDir.
1.30.10.0 - 27 May 2022
-----------------------
. [Change #1097] Extend Uthernet II to support DNS offloading. [audetto]
- Details: https://github.com/a2retrosystems/uthernet2/wiki/Virtual-W5100-with-DNS
- No need for ethernet, so now works with host PC's WiFi.
- Supported by @oliverschmidt's A2Stream v1.2.
- NB. This virtual DNS is enable by default (but can be disabled via the Config UI).
- NB. Real W5100 chips don't offer this!
. [Bug #1078] WOZ support: Better LSS support for reading write-protect.
- Fix images 'Run For It' and 'Stickybear Town Builder' (both when write-protected).
. [PR #1100] Uthernet II fixes for UDP and IPRAW modes. [audetto]
. [PR #1084 + others] Internal: refactor debugger. [kiyolee]
. Fix Phasor card: use correct primary AY8913 for Phasor-native & MB modes (now checked in mb-audit v1.2).
. Command line: add -wav-speaker <file> & -wav-mockingboard <file>
- Save a .wav of either Speaker or Mockingboard audio output during the emulation session.
- Warning: there's no file size limit, so it just keeps saving until AppleWin exits.
1.30.9.0 - 23 Mar 2022
----------------------
. [Change #518] Support Uthernet II card in slot 3. [audetto]
- EG. Use with Contiki, A2osX, ii-vision, A2Stream etc.
- Support for W5100 modes: TCP, UDP, IPRAW and MACRAW (no support for PPPoE mode, interrupts and SPI).
. [Bug #1066] Fix for save-states where (eg) disk image name contains '#' character.
. [Bug #1017] Fix for printer interface where character got output twice.
. [PR #1031 + others] Internal: refactor string output handling. [kiyolee]
. Change: default install of AppleWin now sets slot 3 as empty (was Uthernet I card)
. Fix 6522 bug: IFR.T2 was always set when counter.b15=1
1.30.8.0 - 8 Feb 2022
---------------------
. [Bug #1023] WOZ support: Tweak to track sync support.
@ -15,7 +106,7 @@ Tom Charlesworth
- Fixes: What's My Logic, Forbidden Quest, The Isle of Mem.
. [Bug #1018] Support AN3 for //e models.
. [Bug #1015] Registry: fix support for legacy 'Harddisk Enable' key.
. [PR #1028] Internal: Split 6522 out of MB code and into own class (bumps MB version in save-state).
. [PR #1028] Internal: Split 6522 out of MB code and into own class (bumps MB version in save-state to v8).
. [PR #1025] Load save-state for Cards: improve error messages. [audetto]
. [PR #1014] Correct BMP creation. [audetto]
. SSC: Fix for command line -dcd not being honoured. (Regression)

View File

@ -12,6 +12,8 @@
@COPY /Y "%APPLEWIN_ROOT%\docs\Debugger_Changelog.txt" "%~1"
@COPY /Y "%APPLEWIN_ROOT%\help\AppleWin.chm" "%~1"
@COPY /Y "%APPLEWIN_ROOT%\Release v141_xp\AppleWin.exe" "%~1"
@MKDIR "%~1\snesmax"
@COPY /Y "%APPLEWIN_ROOT%\snesmax\*" "%~1\snesmax"
CD "%~1"
"C:\Program Files (x86)\7-Zip\7z.exe" a ..\AppleWin"%~1".zip *
"C:\Program Files (x86)\7-Zip\7z.exe" a ..\AppleWin"%~1"-PDB.zip "%APPLEWIN_ROOT%\Release v141_xp\AppleWin.pdb"

View File

@ -2,6 +2,11 @@ Coding Conventions for AppleWin
===============================
History:
v6 - 12-Jan-2023 (TC)
. Avoid global vars & provide getter/setter accessor functions.
. Avoid C++11 empty initializer lists. (PR#634)
v5 - 03-Apr-2022 (TC)
. #1072: Add a space after keywords.
v4 - 05-Mar-2022 (TC)
. #1050: Added info about Platform Toolset v141_xp
. Use of C++11/14/17
@ -117,9 +122,21 @@ It is recommended (but not mandatory):
. to have/use explicit parenthesis
. to have spaces between operators
Eg:
EG:
. Prefer: z = ((a + b) + 1) instead of: z=((a+b)+1)
2.8: Add a space after keywords (if, for, switch, while, etc).
EG:
for (int i=0; i<10; i++)
Not:
for(int i=0; i<10; i++)
2.9: Avoid global variables.
If a free variable exists within a C++ file, then declare it static and provide getter & setter accessor functions.
-------------------------------------------------------------------------------
3) Use of sprintf() etc.
@ -141,6 +158,13 @@ Use type deduction only if it makes the code clearer to readers who aren't famil
or if it makes the code safer. Do not use it merely to avoid the inconvenience of writing an explicit type.
(Ref: https://google.github.io/styleguide/cppguide.html#Type_deduction)
4.2: Avoid C++11 empty initializer lists
This notation can be too obscure, compared to using regular initialization (for POD) or ctors (for classes).
EG, avoid this:
int var {};
struct s {};
-------------------------------------------------------------------------------
Appendix: Legacy Hungarian notation

View File

@ -1,4 +1,11 @@
/*
2.9.1.14 Fix disassembly when in middle of data
Example:
ASC 7D0:7D7
ASC 7D8:7DF
7CF:EA 40 41 42 43 44 45 46 47 48
U 7D7
2.9.1.13 Added: CD now detects ".." to change to the previous directory and chops the trailing sub-directory from the current path.
It worked before but would clutter up the current directory with a trailing "..\".
2.9.1.12 Added: New commands HGR0, HGR3, HGR4, HGR5 to see pseudo pages $00, $60, $80, $A0 respectively.
@ -35,7 +42,7 @@
X 2002:2003
Released post 1.30.7.0
2.9.1.0 Added: Bookmarks now have their own indicator (a number with a box around it) and replace the ":" seperator. Updated Debug_Font.bmp
2.9.1.0 Added: Bookmarks now have their own indicator (a number with a box around it) and replace the ":" separator. Updated Debug_Font.bmp
.18 Fixed: Resetting bookmarks wasn't setting the total bookmarks back to zero.
.17 Fixed: If all bookmarks were used then setting a new one wouldn't update an existing one to the new address.

View File

@ -24,9 +24,9 @@
Start with a floppy disk in slot 6 drive-2.<br>
NB. -s6d2 has the meaning same as -d2.<br><br>
-s5d1 &lt;pathname&gt;<br>
Start with a floppy disk in slot 5 drive-1 (must be used with '-s5 diskii').<br><br>
Start with a floppy disk in slot 5 drive-1 (must be used with '-s5 diskii' or '-s5 diskii13').<br><br>
-s5d2 &lt;pathname&gt;<br>
Start with a floppy disk in slot 5 drive-2 (must be used with '-s5 diskii').<br><br>
Start with a floppy disk in slot 5 drive-2 (must be used with '-s5 diskii' or '-s5 diskii13').<br><br>
-h1 &lt;pathname&gt;<br>
Start with hard disk 1 plugged-in (and auto power-on the Apple II). NB. Hard disk controller card gets enabled.<br><br>
-h2 &lt;pathname&gt;<br>
@ -43,15 +43,23 @@
Insert an Apple 16K Language Card into slot 0 in the original Apple II and use the F8 auto-start ROM.<br>
NB. The Apple II+ already defaults to having a Language Card, so this switch is not required.<br><br>
-s1 empty<br>
Remove the printer card from slot 1.<br><br>
Remove the parallel printer card from slot 1.<br><br>
-s1 parallel<br>
Insert a parallel printer card into slot 1.<br><br>
-s2 empty<br>
Remove the SSC card from slot 2.<br><br>
-s2 ssc<br>
Insert a SSC into slot 2.<br><br>
-s3 empty<br>
Remove the Uthernet card from slot 3.<br><br>
Remove any card from slot 3.<br><br>
-s3 vidhd<br>
Insert a VidHD card into slot 3.<br><br>
-s5 diskii<br>
Insert a 2nd Disk II controller card into slot 5.<br><br>
-s6 diskii<br>
Insert a Disk II controller card into slot 5 or 6.<br><br>
-s5 diskii13<br>
-s6 diskii13<br>
Insert a Disk II controller card (with 13-sector firmware) into slot 5 or 6.<br><br>
-s6 empty<br>
Remove the Disk II controller card from slot 6.<br><br>
-s7 empty<br>
@ -78,6 +86,9 @@
<li>best: picks the highest resolution where the height is an integer multiple of (192*2)</li>
<li>nnnn: select a specific resolution with height=nnnn pixels</li>
</ul>
-fs-width=&lt;nnnn&gt;<br>
Use in conjunction with -fs-height to select a better aspect ratio for full-screen mode.<br>
EG. for 4:3 aspect ratio on monitors that support it: -no-full-screen -fs-width=1600 -fs-height=1200<br><br>
NB. Combine with <em>-no-full-screen</em> to start in Windowed mode. Without this it'll just default to full-screen.<br>
NB. When switching to Windowed mode the default desktop resolution will be restored, and when switching back to full-screen mode this better resolution will again be used.<br><br>
-rom &lt;file&gt;<br>
@ -156,6 +167,10 @@
<li>NB. Both these apple/sl7 cards support an extra foreground/background hi-res mode that can be triggered by AN3 switching, resulting in corrupt color graphics! See <a href="Troubleshooting.html">troubleshooting</a>.
</ul>
<li><i>eve/feline</i> are Le Chat Mauve variants.</li>
<ul>
<li>Eve is currently unsupported, so the behavior just defaults to 'apple' RGB card type.
<li>Feline differs from 'apple' card type in that it doesn't support the 160 color pixel mode (so falls back to 140 mode) and has a slightly different color palette.
</ul>
</ul>
Use in conjunction with the 'Color (RGB Card/Monitor)' video mode.<br><br>
-rgb-card-foreground &lt;n&gt;<br>
@ -175,7 +190,19 @@
Force a power-on.<br>
Use to auto power-on when not using -d1, -h1 or -load-state.<br><br>
-snes-max-alt-joy1 or -snes-max-alt-joy2<br>
Use alternate button mappings for the SNES MAX card. See <a href="cfg-input.html">Input Settings</a>.<br>
Use alternate button mappings for the SNES MAX card. See <a href="cfg-input.html">Input Settings</a>.<br><br>
-snes-max-user-joy1 &lt;file.yaml&gt; or -snes-max-user-joy2 &lt;file.yaml&gt;<br>
Use a user specified button mappings file for the SNES MAX card.<br>
For some examples, see the supplied <i>controller_*.yaml</i> files in the <i>snesmax</i> folder.<br>
<br>
-wav-speaker &lt;file.wav&gt;<br>
Save the speaker audio to a .wav file.<br>
Warning: there's no file size limit, so it just keeps saving until AppleWin exits (~5MB per minute).<br>
<br>
Save the Mockingboard audio to a .wav file.<br>
-wav-mockingboard &lt;file.wav&gt;<br>
Warning: there's no file size limit, so it just keeps saving until AppleWin exits (~10MB per minute).<br>
<br>
<br>
<P style="FONT-WEIGHT: bold">Debug arguments:

View File

@ -10,7 +10,7 @@
<hr size="4">
<p>The team would like to thank the following people for their contributions:</p>
<p style="MARGIN-LEFT: 40px">Brian Broker: This HTML / CHM help file</p>
<p style="MARGIN-LEFT: 40px">Thomas Stahl: TV emulation mode (up to v1.25.0.4)</p>
<p style="MARGIN-LEFT: 40px">Thomas Stahl: TV emulation mode</p>
<p style="MARGIN-LEFT: 40px">Greg Hedger: SSI263 phoneme samples</p>
<p style="MARGIN-LEFT: 40px">Robert Hoem: Hard disk card (source module &amp; f/w)</p>
<p style="MARGIN-LEFT: 40px">VICE team: TFE, Z80, MC6821 PIA emulation modules (<a href="http://vice-emu.sourceforge.net/index.html#developers">http://vice-emu.sourceforge.net/index.html#developers</a>)<br>
@ -21,10 +21,12 @@
<p style="MARGIN-LEFT: 40px">Bob Sander-Cederlof: Applesoft Symbols (<a href="http://www.txbobsc.com/scsc/scdocumentor/index.html">http://www.txbobsc.com/scsc/scdocumentor/</a> S-C DocuMentor: Applesoft)</p>
<p style="MARGIN-LEFT: 40px">David Schmidt: Updates to this help file</p>
<p style="MARGIN-LEFT: 40px">Mike Harvey, Founder &amp; Editor of Nibble Magazine: For providing us Apple fans the pleasure of eagerly awaiting each next month's issue to learn about the Apple! (<a href="http://www.nibblemagazine.com/">http://www.nibblemagazine.com/</a>)</p>
<p style="MARGIN-LEFT: 40px">Andrea Odetti: working on making the source code more portable</p>
<p style="MARGIN-LEFT: 40px">Andrea Odetti: working on making the source code more portable & Uthernet II card support</p>
<p style="MARGIN-LEFT: 40px">Iván Izaguirre: Taiwanese Copam Base64A Apple II clone</p>
<p style="MARGIN-LEFT: 40px">Arnaud C: debugger suggestions and help with 6502/6522/video timing issues</p>
<p style="MARGIN-LEFT: 40px">Cyril Lambin: RGB card/monitor rendering, debugger improvements</p>
<p style="MARGIN-LEFT: 40px">Alex Lukacz: 4Play & SNES MAX card support</p>
<p style="MARGIN-LEFT: 40px">Matthew D'Asaro: Game I/O Controller copy-protection dongle support</p>
<p style="MARGIN-LEFT: 40px">Erik Struiksma: SNES MAX controller mapping files</p>
</body>
</html>

View File

@ -3,8 +3,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Advanced Settings</title></head>
<body style="background-color: rgb(255, 255, 255); font-family: verdana;" alink="#008000" link="#008000" vlink="#008000">
<h2 style="color: rgb(0, 128, 0);">Advanced Settings</h2>
<hr size="4"><img style="width: 354px; height: 460px; float: right;" src="img/advanced.png" alt="Advanced settings" hspace="5" vspace="5">
<p><strong>Save State File Name:</strong><br>
<hr size="4"><img style="width: 354px; height: 497px; float: right;" src="img/advanced.png" alt="Advanced settings" hspace="5" vspace="5">
<p><strong>Save State Filename:</strong><br>
This is the file name to use for save-state files. The default
directory is the same as where your AppleWin.exe program is stored.</p>
<p><strong>Save State on Exit:</strong><br>
@ -19,18 +20,7 @@ emulation by pressing the F11 key.</p>
Press this button to load the specified state file into
the emulator. &nbsp;You can also load the system state during
emulation by pressing the F12 key.</p>
<p><strong>Clone:</strong><br>
If you have specified Computer as 'Clone' on the main Configuration
page, then this drop-down menu can be used to specify the clone type.<br>
NB. Pravets 82, 8M and 8A are Bulgarian Apple II clones;
TK3000 is a Brazilian //e clone;
Base 64A is a Taiwanese Apple II clone.<br>
<ul>
<li>Pravets 8A: Use F10 for the Pravets Caps Lock (and the PC's Caps Lock key controls Cyrillic/Latin lock).
<li>TK3000: Use Scroll Lock for the 'mode' key. Use to switch between standard Apple II and accented characters.
<li>Base 64A: Use Delete for the 'F2' key (eg. press F2, release F2 then press a key to auto-type a BASIC keyword).
</ul>
</p>
<p><strong>Printer settings </strong>(Printer is emulated in slot 1)
</p>
<p style="margin-left: 40px;"><strong>Printer dump filename:<br>
@ -67,7 +57,21 @@ disable appending when dumping to a real printer.)
</strong>When printing is started, a printer file is created and it is
closed either after the specified time expires, or when
the emulator is reset. This setting is emulation speed dependent.
</p>
</p>
<p><strong>Clone:</strong><br>
If you have specified Computer as 'Clone' on the main Configuration
page, then this drop-down menu can be used to specify the clone type.<br>
NB. Pravets 82, 8M and 8A are Bulgarian Apple II clones;
TK3000 is a Brazilian //e clone;
Base 64A is a Taiwanese Apple II clone.<br>
<ul>
<li>Pravets 8A: Use F10 for the Pravets Caps Lock (and the PC's Caps Lock key controls Cyrillic/Latin lock).
<li>TK3000: Use Scroll Lock for the 'mode' key. Use to switch between standard Apple II and accented characters.
<li>Base 64A: Use Delete for the 'F2' key (eg. press F2, release F2 then press a key to auto-type a BASIC keyword).
</ul>
</p>
<p><strong>The Freeze's non-autostart F8 rom:</strong><br>
If you have specified Computer as 'Apple ][' or 'Apple ][+' on the main
Configuration page, then you will be able to enable this setting.
@ -75,4 +79,16 @@ The Freeze F8 rom is a hacker's rom that replaces the normal 2K rom at
$F800. <a href="cfg-advanced-freeze-rom.html">Here's the
original release note</a>
</p>
</body></html>
<p><strong>Game I/O Connector:</strong><br>
From the drop-down menu, select a device to use in the internal Game I/O Connector.
Supported devices are:
<ul>
<li> Empty
<li> SDS Datakey - SpeedStar (copy protection dongle)
</ul>
NB. Copy protection dongles can interfere with joysticks (eg. buttons may be hardwired to a fixed state), so only use dongles with the intended software.<br>
NB. For Apple II/II+ models, when a joystick is selected (from the <a href="cfg-input.html">Input</a> tab), then there is also an implicit joystick connected at the same time as the device selected here.
</p>
</body></html>

View File

@ -78,7 +78,7 @@
<strong>Ethernet Settings...:</strong><br>
This allows to choose which network interface card (NIC) you want to
use with the Uthernet card.<br>
use with the Uthernet or Uthernet II card.<br>
<br>
<strong>Emulation Speed Control:</strong><br>

View File

@ -6,7 +6,7 @@
</head>
<body style="background-color: rgb(255, 255, 255); font-family: verdana;" alink="#008000" link="#008000" vlink="#008000">
<h2 style="color: rgb(0, 128, 0);">Disk Settings</h2>
<hr size="4"><img style="width: 354px; height: 460px; float: right;" src="img/disk.png" alt="Disk settings" hspace="5" vspace="5">
<hr size="4"><img style="width: 354px; height: 497px; float: right;" src="img/disk.png" alt="Disk settings" hspace="5" vspace="5">
<h3>Floppy Controller Settings:</h3>
<p><strong>Enhanced disk access speed:</strong><br>
@ -19,6 +19,10 @@ properly. This is the speed at which the real hardware
would access data from your drives.
</p>
<p><strong>Show status:</strong><br>
In 2x windowed-mode, optionally show the Track and Sector values for Drives 1 and 2 (for any Disk II cards in slots 5 and/or 6).
Hovering over this status will show a tooltip with both decimal and hexadecimal values, and the track includes the full fractional quarter track value too.
<p><strong>Disk 1/2 drop-down menus (slot 6):</strong><br>
These menus allow you to select floppy disk images to 'insert' into the
emulated floppy drives 1 and 2. This can also be done during emulation by <a href="toolbar.html">using the toolbar</a> or using the F3/F4 keys. Diskettes can be swapped by pressing F5 during emulation. You can also eject images from this menu.

View File

@ -98,6 +98,14 @@ Default comparison operator is equal
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPV vpos[,len]</span></b></font></font></p>
</td>
<td width="75%">
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">Add Breakpoint trigger when video-scanner's vertical position matches vpos. (NB. Auto-disable when hit.)</span></i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPD</span></b></font></font></p>
</td>
@ -105,7 +113,7 @@ Default comparison operator is equal
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">Disable Breakpoint (grayed out).</span></i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPE</span></b></font></font></p>
</td>
@ -113,7 +121,7 @@ Default comparison operator is equal
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">Enable Breakpoint (colored red).</span></i></p>
</td>
</tr>
<tr bgcolor="#999999">
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPC #</span></b></font></font></p>
</td>
@ -122,7 +130,7 @@ Default comparison operator is equal
Note: The asterisk * may be used to clear all breakpoints.</span></i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPL</span></b></font></font></p>
</td>
@ -130,7 +138,7 @@ Note: The asterisk
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">List Breakpoints.</span></i></p>
</td>
</tr>
<tr bgcolor="#999999">
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPIO</span></b></font></font></p>
</td>
@ -138,7 +146,7 @@ Note: The asterisk
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">(In a future version, will add Breakpoint trigger on memory read or write.)</span></i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPP</span></b></font></font></p>
</td>
@ -146,7 +154,7 @@ Note: The asterisk
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">(In a future version, will add Breakpoint trigger on specific flag cleared or set.)</span></i></p>
</td>
</tr>
<tr bgcolor="#999999">
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BRK [0|1|2|3|all] [on|off]</span></b></font></font></p>
</td>
@ -154,7 +162,7 @@ Note: The asterisk
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">Break on BRK or Invalid 1-3 byte opcodes</span></i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BRKOP [opcode]</span></b></font></font></p>
</td>
@ -162,7 +170,7 @@ Note: The asterisk
<p><i><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">Break on Opcode</span></i></p>
</td>
</tr>
<tr bgcolor="#999999">
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b><span style="BACKGROUND: 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BRKINT [on|off]</span></b></font></font></p>
</td>
@ -399,6 +407,14 @@ Note: The asterisk
<p><font color="#ffffff"><i>Add Breakpoint when Stack has had something pushed onto it.</i></font></p>
</td>
</tr>
<tr bgcolor="#000000">
<td bgcolor="#000000" width="25%">
<p><font color="#00b8ff"><font face="Courier"><b><span style="BACKGROUND: rgb(0,0,0) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BPV A0</span></b></font></font></p>
</td>
<td bgcolor="#000000" width="75%">
<p><font color="#ffffff"><i>Add Breakpoint when video-scanner is at line 160 ($A0) which is the start of the MIXED area.</i></font></p>
</td>
</tr>
<tr bgcolor="#000000">
<td bgcolor="#000000" width="25%">
<p><font color="#00b8ff"><font face="Courier"><b><span style="BACKGROUND: rgb(0,0,0) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">BRK ON</span></b></font></font></p>

View File

@ -230,8 +230,10 @@ MODE 2</span></b></font></font></p>
You can run custom batch or script files that contain debugger commands.&nbsp;
Scripts files do not echo their input; to print a string to the output console
window, use the <b>ECHO</b> command. NB. When AppleWin initially starts-up, it
will attempt to auto-run '<b>DebuggerAutoRun.txt</b>' (located in the same folder
as AppleWin.exe).
will attempt to auto-run '<b>DebuggerAutoRun.txt</b>' (searching starts in the "Current Directory"[1], otherwise in the same folder
as AppleWin.exe).</br>
</br>
[1] "Current Directory" is implicitly set when inserting disk/harddisk images and ultimately by the command line switch: -current-dir &lt;path&gt;.
</p>
<br>
<table border="0" cellpadding="2" cellspacing="0" width="80%">

View File

@ -98,7 +98,7 @@
</tr>
</tbody>
</table>
<p><font size="4"><b>Examples</b>:</font></p>
<p><font size="3"><b>Examples</b>:</font></p>
<table bgcolor="#000000" border="0" cellpadding="2" cellspacing="0" width="90%">
<COLGROUP>
<col width="64">
@ -151,6 +151,142 @@ FF0A</span></b></font></font></p>
</tbody>
</table>
<br>
<h3>Zero-page Watches</h3>
<p>Add a zero-page watch at the indirect address (nn).</p>
<table border="0" cellpadding="2" cellspacing="0" width="75%">
<COLGROUP>
<col width="64">
<col width="192">
<tbody>
<tr bgcolor="#000000">
<td bgcolor="#000000" width="25%">
<p><font color="#ffffff"><b>Command</b></font></p>
</td>
<td bgcolor="#000000" width="75%">
<p style="FONT-STYLE: normal"><font color="#ffffff"><b>Effect</b></font></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPA (or ZP) nn</b></font></font></p>
</td>
<td width="75%">
<p><i>Add/Update address to next zero page pointer</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPA (or ZP) # nn</b></font></font></p>
</td>
<td width="75%">
<p><i>Add/Update address to specific zero page pointer</i></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPC #</b></font></font></p>
</td>
<td width="75%">
<p><i>Clear (remove) zero page pointer</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPD #</b></font></font></p>
</td>
<td width="75%">
<p><i>Disable zero page pointer - it is still in the list, just not active</i></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPE #</b></font></font></p>
</td>
<td width="75%">
<p><i>(Re)Enable disabled zero page pointer</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>ZPL</b></font></font></p>
</td>
<td width="75%">
<p><i>List all zero page pointers</i></p>
</td>
</tr>
</tbody>
</table>
<br>
<h3>Memory Watches</h3>
<p>Add a 16-bit memory watch at the 16-bit address nnnn.<br>
NB. For 'WA # v': specifying 'v' instead of an address will watch the video scanner.</p>
<table border="0" cellpadding="2" cellspacing="0" width="75%">
<COLGROUP>
<col width="64">
<col width="192">
<tbody>
<tr bgcolor="#000000">
<td bgcolor="#000000" width="25%">
<p><font color="#ffffff"><b>Command</b></font></p>
</td>
<td bgcolor="#000000" width="75%">
<p style="FONT-STYLE: normal"><font color="#ffffff"><b>Effect</b></font></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WA (or W) nnnn|symbol</b></font></font></p>
</td>
<td width="75%">
<p><i>Add/Update address or symbol to next watch</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WA (or W) # nnnn|symbol|v</b></font></font></p>
</td>
<td width="75%">
<p><i>Add/Update address or symbol to specific watch</i></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WC #</b></font></font></p>
</td>
<td width="75%">
<p><i>Clear (remove) watch</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WD #</b></font></font></p>
</td>
<td width="75%">
<p><i>Disable specific watch - it is still in the list, just not active</i></p>
</td>
</tr>
<tr bgcolor="#999999">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WE #</b></font></font></p>
</td>
<td width="75%">
<p><i>(Re)Enable disabled watch</i></p>
</td>
</tr>
<tr bgcolor="#cccccc">
<td width="25%">
<p><font color="#000000"><font face="Courier"><b>WL</b></font></font></p>
</td>
<td width="75%">
<p><i>List all watches</i></p>
</td>
</tr>
</tbody>
</table>
<br>
<h3><a name="Memory_Search">Searching Memory</a></h3>
<p>You can search memory for hex values.&nbsp; Wildcard support is also supported
via the '<b>?</b>' wildcard operator, including nibble searching. &nbsp; A

View File

@ -83,7 +83,7 @@ Apple II would not last six months.</p>
late and
suffered from poor backwards compatibility and a nearly 100%
hardware failure rate. Although Apple eventually addressed these
issues, they were not able overcome the Apple III's bad
issues, they were not able to overcome the Apple III's bad
reputation. Apple III sales remained poor, while sales of the
older Apple II continued to climb. </p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -32,7 +32,7 @@
<li>Parallel Printer card</li>
<li>Super Serial card</li>
<li>No-Slot clock</li>
<li>Uthernet card</li>
<li>Uthernet & Uthernet II cards</li>
<li>4Play & SNES MAX joystick cards</li>
<li>VidHD card</li>
</ul>

View File

@ -12,7 +12,7 @@
Copyright © 1994-1996, Michael O'Brien<br>
Copyright © 2001, Oliver Schmidt<br>
Copyright © 2002-2005, Tom Charlesworth<br>
Copyright © 2006-2022, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis<br>
Copyright © 2006-2023, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis<br>
<br>
<a href="applewin-team.html">AppleWin team</a>
<br>
@ -31,7 +31,7 @@
<li><a href="sound.html">Sound</a>
<li><a href="clock.html">Clock</a>
<li><a href="card-ssc.html">Super Serial card</a>
<li><a href="uthernet.html">Uthernet network card</a>
<li><a href="uthernet.html">Uthernet network cards</a>
<li><a href="configuration.html">AppleWin Configuration</a>
<li><a href="dbg-toc-intro.html">Using the Debugger</a>
<li><a href="resources.html">Resources</a></li>

View File

@ -1,22 +1,23 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Uthernet network card</title>
<title>Uthernet network cards</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
</head>
<body style="FONT-FAMILY: verdana; BACKGROUND-COLOR: rgb(255,255,255)" alink="#008000"
link="#008000" vlink="#008000">
<h2 style="COLOR: rgb(0,128,0)">Uthernet network card</h2>
<h2 style="COLOR: rgb(0,128,0)">Uthernet network cards</h2>
<hr size="4">
<p style="FONT-WEIGHT: bold">Overview:
</p>
<P>The Uthernet network card coupled with the Contiki OS allows you to browse the
<P>The Uthernet network cards coupled with the Contiki OS allow you to browse the
internet on your Apple.</P>
<P style="FONT-WEIGHT: bold">Acknowledgment:
</P>
<P>Uthernet (TFE) support in Applewin was made possible by implementing the GPL
<P>Uthernet (TFE) support in AppleWin was made possible by implementing the GPL
source written by Spiro Trikaliotis for the Vice emulator - <A href="http://vice-emu.sourceforge.net/index.html#developers">
http://vice-emu.sourceforge.net/index.html#developers</A></P>
<P><A href="https://a2retrosystems.com/">Uthernet II</A> support in AppleWin has been contributed by Andrea (audetto) Odetti.</P>
<P style="FONT-WEIGHT: bold">Details:
</P>
<P>To enable ethernet support in AppleWin you must first download and install
@ -35,15 +36,15 @@
<P>After AppleWin starts, select the settings icon and then select the ethernet
settings button.
</P>
<P>Uthernet will be disabled. Select Uthernet from the list of available ethernet
emulations (currently the only one).
<P>Uthernet will be disabled. Select Uthernet or Uthernet II from the list of available ethernet
emulations.
</P>
<P>Select the ethernet interface you want to work with. This must be a physical
ethernet interface.
</P>
<P>If you have more than one interface you may need to select them in turn in order
to get the text description for each interface vs what Npcap likes to use for
a reference. Select Ok. and then close AppleWin.
a reference.
</P>
<P><span style="font-weight: bold;">Note:</span> Wireless does not work
with WinPcap (but see <A href="uthernet-wifi-workaround.html">WiFi Workaround</A>).
@ -56,7 +57,7 @@
also grab a copy of the Uthernet/Contiki getting started guide <A href="http://www.a2retrosystems.com/a2UtherManual.pdf">
http://www.a2retrosystems.com/a2UtherManual.pdf</A>
</P>
<P>When you run AppleWin again, select the contiki80pri.dsk image. Boot AppleWin.
<P>Select the contiki80pri.dsk image. Boot AppleWin.
</P>
<P>Once Contiki is loaded then press Enter to clear the welcome screen and press
ESC for a menu.
@ -87,5 +88,17 @@
if you are still having difficulty then you should refer to the VICE network
support page for additional information - <A href="http://vicekb.trikaliotis.net/13-005.shtml">
http://vicekb.trikaliotis.net/13-005.shtml</A></P>
</body>
<P style="FONT-WEIGHT: bold">Uthernet II:
</P>
<P>Most features of the Uthernet II are emulated, with the following caveats:
<ul>
<li>PPPoE, interrupts and SPI are not implemented</li>
<li>server side is not well tested</li>
<li>after loading a save-state file, TCP and UDP sockets are closed</li>
</ul>
</P>
<P>The card implements a <A href="https://github.com/a2retrosystems/uthernet2/wiki/Virtual-W5100-with-DNS">Virtual DNS</A>
interface (not found on real hardware) for Apple II software to run without raw sockets:
this allows operation on any type of network.</P>
</body>
</html>

View File

@ -180,14 +180,15 @@ CAPTION "Disk"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
GROUPBOX "Floppy Disk Drives",IDC_STATIC,5,7,200,125
CONTROL "&Enhanced disk access speed (all drives)",IDC_ENHANCE_DISK_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,19,150,10
CONTROL "&Enhanced disk access speed (all drives)",IDC_ENHANCE_DISK_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,19,135,10
CONTROL "Show status",IDC_DISKII_STATUS_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,19,50,10
LTEXT "Disk 1:",IDC_STATIC,10,36,23,8
LTEXT "Disk 2:",IDC_STATIC,10,53,23,8
COMBOBOX IDC_COMBO_DISK1,40,35,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_DISK2,40,52,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Enable &Disk II controller in slot 5",IDC_DISKII_SLOT5_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,76,122,10
CONTROL "Enable &Disk II controller in slot 5",IDC_DISKII_SLOT5_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,76,115,10
LTEXT "Disk 1:",IDC_STATIC,11,93,23,8
LTEXT "Disk 2:",IDC_STATIC,11,110,23,8
COMBOBOX IDC_COMBO_DISK1_SLOT5,40,92,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
@ -206,19 +207,22 @@ BEGIN
PUSHBUTTON "&Browse...",IDC_CIDERPRESS_BROWSE,161,202,50,14
END
IDD_TFE_SETTINGS_DIALOG DIALOGEX 0, 0, 270, 100
IDD_TFE_SETTINGS_DIALOG DIALOGEX 0, 0, 271, 155
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Ethernet Settings"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
LTEXT "Ethernet",IDC_TFE_SETTINGS_ENABLE_T,9,7,30,8
COMBOBOX IDC_TFE_SETTINGS_ENABLE,45,5,60,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Virtual DNS",IDC_CHECK_TFE_VIRTUAL_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,7,50,8
LTEXT "Interface",IDC_TFE_SETTINGS_INTERFACE_T,9,24,30,8
COMBOBOX IDC_TFE_SETTINGS_INTERFACE,45,22,210,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "",IDC_TFE_SETTINGS_INTERFACE_NAME,9,44,250,8
LTEXT "",IDC_TFE_SETTINGS_INTERFACE_DESC,9,60,250,8
DEFPUSHBUTTON "Ok",IDOK,20,75,50,14
PUSHBUTTON "Cancel",IDCANCEL,80,75,50,14
GROUPBOX "Npcap",IDC_STATIC,5,75,260,55
LTEXT "",IDC_TFE_NPCAP_INFO,12,86,240,36
DEFPUSHBUTTON "Ok",IDOK,20,135,50,14
PUSHBUTTON "Cancel",IDCANCEL,80,135,50,14
END
IDD_PROPPAGE_ADVANCED DIALOGEX 0, 0, 210, 217
@ -251,7 +255,9 @@ BEGIN
LTEXT "&Clone:",IDC_STATIC,5,187,40,8
COMBOBOX IDC_CLONETYPE,35,185,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "The Free&ze's non-autostart F8 rom (Apple ][ or ][+ only)",IDC_THE_FREEZES_F8_ROM_FW,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,201,194,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,201,194,10
LTEXT "&Game I/O Connector:",IDC_STATIC,5,220,82,8
COMBOBOX IDC_COMBO_GAME_IO_CONNECTOR,89,218,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
END
@ -292,7 +298,7 @@ BEGIN
VALUE "FileDescription", "Apple //e Emulator for Windows"
VALUE "FileVersion", APPLEWIN_VERSION_STR
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2021 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "LegalCopyright", " 1994-2023 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
VALUE "ProductVersion", APPLEWIN_VERSION_STR

View File

@ -61,7 +61,8 @@
#define IDC_MB_VOLUME 1010
#define IDC_SAVESTATE_BROWSE 1011
#define IDC_MONOCOLOR 1012
#define IDC_DISKII_SLOT5_ENABLE 1020
#define IDC_DISKII_SLOT5_ENABLE 1019
#define IDC_DISKII_STATUS_ENABLE 1020
#define IDC_HDD_ENABLE 1021
#define IDC_HDD_SWAP 1022
#define IDC_PASTE_FROM_CLIPBOARD 1023
@ -119,6 +120,9 @@
#define IDC_FOURPLAY_CONFIG 1087
#define IDC_SNESMAX_CONFIG 1088
#define IDC_CHECK_VIDHD_IN_SLOT3 1089
#define IDC_CHECK_TFE_VIRTUAL_DNS 1090
#define IDC_TFE_NPCAP_INFO 1091
#define IDC_COMBO_GAME_IO_CONNECTOR 1092
#define IDM_EXIT 40001
#define IDM_HELP 40002
#define IDM_ABOUT 40003
@ -134,7 +138,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 149
#define _APS_NEXT_COMMAND_VALUE 40012
#define _APS_NEXT_CONTROL_VALUE 1082
#define _APS_NEXT_CONTROL_VALUE 1083
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1,4 +1,4 @@
#define APPLEWIN_VERSION 1,30,8,0
#define APPLEWIN_VERSION 1,30,13,0
#define xstr(a) str(a)
#define str(a) #a

View File

@ -0,0 +1,21 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_0810&PID_0001
Description: Chinese PS2 USB Dual Controller adapter # Description to be used in AppleWin's GUI
1: X # triangle
2: A # circle
3: B # x
4: Y # square
5: "" # L2
6: "" # R2
7: LB # L1
8: RB # R1
9: SELECT # Select
10: START # Start
11: "" # X/Y Axis button
12: "" # Z Axis/Rotation button
...

View File

@ -0,0 +1,25 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_6666&PID_0667
Description: Lik-Sang Super Smartjoy adapter # Description to be used in AppleWin's GUI
1: X # mirrors to 10 & Z-Rot up
2: A # mirrors to 5 & Z-Axis right
3: B # mirrors to 6 & Z-Rot down
4: Y # mirrors to 11 & Z-Axis left
5: "" # A (dup)
6: "" # B (dup)
7: LB
8: RB
9: SELECT
10: "" # X (dup)
11: "" # Y (dup)
12: START
13: "" # mirrors to X-Axis up
14: "" # mirrors to Y-Axis right
15: "" # mirrors to X-Axis down
16: "" # mirrors to Y-Axis left
...

View File

@ -0,0 +1,19 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_046D&PID_C21D
Description: Logitech F310 # Description to be used in AppleWin's GUI
1: B # A
2: A # B
3: Y # X
4: X # Y
5: LB # LB
6: RB # RB
7: SELECT # BACK
8: START # START
9: "" # X/Y Axis button
10: "" # Z Axis/Rotation button
...

View File

@ -0,0 +1,21 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_289B&PID_0042
Description: Raphnet Dual NES adapter V2 # Description to be used in AppleWin's GUI
1: Y # SNES Y = NES B
2: B # SNES B = NES A
3: SELECT
4: START
5: "" # n/a : SNES A
6: "" # n/a : SNES X
7: "" # n/a : SNES LB
8: "" # n/a : SNES RB
9: ""
10: ""
11: ""
12: ""
...

View File

@ -0,0 +1,21 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_289B&PID_0057
Description: Raphnet Dual SNES adapter V2 # Description to be used in AppleWin's GUI
1: Y
2: B
3: SELECT
4: START
5: A
6: X
7: LB
8: RB
9: ""
10: ""
11: ""
12: ""
...

View File

@ -0,0 +1,21 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_06A3&PID_FF0C
Description: Saitek P2500 Cyborg Force Rumble Pad # Description to be used in AppleWin's GUI
1: Y # upper-left
2: X # upper-center
3: B # lower-left
4: A # lower-center
5: LB # upper-right
6: RB # lower-right
7: LB # LB
8: RB # RB
9: SELECT # button for X/Y Axis {analog left }
10: START # button for Z Axis/Rotation {analog right} | AKA Rudder/Throttle
11: START # S (FPS)
12: SELECT # Digital
...

View File

@ -0,0 +1,23 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_06A3&PID_040C
Description: Saitek P2900 Wireless Pad # Description to be used in AppleWin's GUI
1: Y # upper-left
2: B # lower-left
3: A # lower-center
4: X # upper-center
5: LB # L1
6: RB # R1
7: SELECT # L2
8: START # R2
9: RB # lower-right (black)
10: LB # upper-right (grey)
11: SELECT # button for X/Y Axis {analog left }
12: START # button for Z Axis/Rotation {analog right}
13: "" # FPS {AppleWin does not read}
14: "" # analog "
...

View File

@ -0,0 +1,23 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_06A3&PID_040B
Description: Saitek P990 Dual Analog Pad # Description to be used in AppleWin's GUI
1: Y # upper-left
2: B # lower-left
3: A # lower-center
4: X # upper-center
5: LB # L1
6: RB # R1
7: SELECT # L2
8: START # R2
9: RB # lower-right (black)
10: LB # upper-right (grey)
11: SELECT # button for X/Y Axis {analog left }
12: START # button for Z Axis/Rotation {analog right}
13: "" # FPS {AppleWin does not read}
14: "" # analog "
...

View File

@ -0,0 +1,21 @@
---
File_hdr:
Tag: AppleWin Controller Button Remapping
Version: 1
Unit:
HID: VID_054C&PID_05C4
Description: Sony DualShock 4 # Description to be used in AppleWin's GUI
1: Y
2: B
3: A
4: X
5: LB
6: RB
7: ""
8: ""
9: SELECT
10: START
11: ""
12: ""
...

View File

@ -388,7 +388,9 @@ static __forceinline bool NMI(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
PUSH(regs.pc & 0xFF)
EF_TO_AF
PUSH(regs.ps & ~AF_BREAK)
regs.ps = regs.ps | AF_INTERRUPT & ~AF_DECIMAL;
regs.ps |= AF_INTERRUPT;
if (GetMainCpu() == CPU_65C02) // GH#1099
regs.ps &= ~AF_DECIMAL;
regs.pc = * (WORD*) (mem+0xFFFA);
UINT uExtraCycles = 0; // Needed for CYC(a) macro
CYC(7);
@ -431,7 +433,9 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
PUSH(regs.pc & 0xFF)
EF_TO_AF
PUSH(regs.ps & ~AF_BREAK)
regs.ps = (regs.ps | AF_INTERRUPT) & (~AF_DECIMAL);
regs.ps |= AF_INTERRUPT;
if (GetMainCpu() == CPU_65C02) // GH#1099
regs.ps &= ~AF_DECIMAL;
regs.pc = * (WORD*) (mem+0xFFFE);
UINT uExtraCycles = 0; // Needed for CYC(a) macro
CYC(7);
@ -681,7 +685,9 @@ void CpuReset()
_ASSERT(mem != NULL);
// 7 cycles
regs.ps = (regs.ps | AF_INTERRUPT) & ~AF_DECIMAL;
regs.ps |= AF_INTERRUPT;
if (GetMainCpu() == CPU_65C02) // GH#1099
regs.ps &= ~AF_DECIMAL;
regs.pc = *(WORD*)(mem + 0xFFFC);
regs.sp = 0x0100 | ((regs.sp - 3) & 0xFF);

View File

@ -62,7 +62,7 @@ static DWORD Cpu6502(DWORD uTotalCycles, const bool bVideoUpdate)
switch (iOpcode)
{
// TODO-MP Optimization Note: ?? Move CYC(#) to array ??
case 0x00: BRK CYC(7) break;
case 0x00: BRKn CYC(7) break;
case 0x01: idx ORA CYC(6) break;
case 0x02: HLT CYC(2) break; // invalid
case 0x03: idx ASO CYC(8) break; // invalid

View File

@ -62,7 +62,7 @@ static DWORD Cpu65C02(DWORD uTotalCycles, const bool bVideoUpdate)
switch (iOpcode)
{
// TODO-MP Optimization Note: ?? Move CYC(#) to array ??
case 0x00: BRK CYC(7) break;
case 0x00: BRKc CYC(7) break;
case 0x01: idx ORA CYC(6) break;
case 0x02: IMM NOP CYC(2) break; // invalid
case 0x03: NOP CYC(1) break; // invalid

View File

@ -56,7 +56,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef BNE
#undef BPL
#undef BRA
#undef BRK
#undef BRK_NMOS
#undef BRK_CMOS
#undef BVC
#undef BVS
#undef CLC
@ -137,6 +138,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef ADCn
#undef ASLn
#undef BRKn
#undef LSRn
#undef ROLn
#undef RORn
@ -144,6 +146,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ADCn ADC_NMOS
#define ASLn ASL_NMOS
#define BRKn BRK_NMOS
#define LSRn LSR_NMOS
#define ROLn ROL_NMOS
#define RORn ROR_NMOS
@ -153,6 +156,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef ADCc
#undef ASLc
#undef BRKC
#undef LSRc
#undef ROLc
#undef RORc
@ -160,6 +164,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ADCc ADC_CMOS
#define ASLc ASL_CMOS
#define BRKc BRK_CMOS
#define LSRc LSR_CMOS
#define ROLc ROL_CMOS
#define RORc ROR_CMOS
@ -303,13 +308,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define BNE if (!flagz) BRANCH_TAKEN;
#define BPL if (!flagn) BRANCH_TAKEN;
#define BRA BRANCH_TAKEN;
#define BRK regs.pc++; \
#define BRK_NMOS regs.pc++; \
PUSH(regs.pc >> 8) \
PUSH(regs.pc & 0xFF) \
EF_TO_AF \
PUSH(regs.ps); \
regs.ps |= AF_INTERRUPT; \
regs.pc = *(LPWORD)(mem+0xFFFE);
#define BRK_CMOS regs.pc++; \
PUSH(regs.pc >> 8) \
PUSH(regs.pc & 0xFF) \
EF_TO_AF \
PUSH(regs.ps); \
regs.ps |= AF_INTERRUPT; \
regs.ps &= ~AF_DECIMAL; /*CMOS clears D flag*/ \
regs.pc = *(LPWORD)(mem+0xFFFE);
#define BVC if (!flagv) BRANCH_TAKEN;
#define BVS if ( flagv) BRANCH_TAKEN;
#define CLC flagc = 0;

View File

@ -69,9 +69,6 @@ void DummyCard::InitializeIO(LPBYTE pCxRomPeripheral)
{
switch (QueryType())
{
case CT_GenericPrinter:
PrintLoadRom(pCxRomPeripheral, m_slot);
break;
case CT_GenericClock:
break; // nothing to do
case CT_Z80:
@ -86,11 +83,6 @@ void DummyCard::Update(const ULONG nExecutedCycles)
{
switch (QueryType())
{
case CT_GenericPrinter:
PrintUpdate(nExecutedCycles);
break;
case CT_GenericClock:
break; // nothing to do
case CT_Z80:
break; // nothing to do
default:
@ -103,9 +95,6 @@ void DummyCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
switch (QueryType())
{
case CT_GenericPrinter:
Printer_SaveSnapshot(yamlSaveHelper, m_slot);
break;
case CT_Z80:
Z80_SaveSnapshot(yamlSaveHelper, m_slot);
default:
@ -118,8 +107,6 @@ bool DummyCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
{
switch (QueryType())
{
case CT_GenericPrinter:
return Printer_LoadSnapshot(yamlLoadHelper, m_slot, version);
case CT_Z80:
return Z80_LoadSnapshot(yamlLoadHelper, m_slot, version);
default:
@ -150,7 +137,7 @@ std::string Card::GetCardName(const SS_CARDTYPE cardType)
case CT_MockingboardC:
return MockingboardCard::GetSnapshotCardName();
case CT_GenericPrinter:
return Printer_GetSnapshotCardName();
return ParallelPrinterCard::GetSnapshotCardName();
case CT_GenericHDD:
return HarddiskInterfaceCard::GetSnapshotCardName();
case CT_GenericClock:
@ -182,7 +169,7 @@ std::string Card::GetCardName(const SS_CARDTYPE cardType)
SS_CARDTYPE Card::GetCardType(const std::string & card)
{
if (card == Printer_GetSnapshotCardName())
if (card == ParallelPrinterCard::GetSnapshotCardName())
{
return CT_GenericPrinter;
}

View File

@ -27,7 +27,7 @@ enum SS_CARDTYPE
CT_Uthernet2,
};
enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX };
enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX, GAME_IO_CONNECTOR };
class YamlSaveHelper;
class YamlLoadHelper;

View File

@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Harddisk.h"
#include "Mockingboard.h"
#include "MouseInterface.h"
#include "ParallelPrinter.h"
#include "SAM.h"
#include "SerialComms.h"
#include "SNESMAX.h"
@ -68,7 +69,9 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
m_slot[slot] = new MockingboardCard(slot, type);
break;
case CT_GenericPrinter:
m_slot[slot] = new DummyCard(type, slot);
_ASSERT(m_pParallelPrinterCard == NULL);
if (m_pParallelPrinterCard) break; // Only support one Printer card
m_slot[slot] = m_pParallelPrinterCard = new ParallelPrinterCard(slot);
break;
case CT_GenericHDD:
m_slot[slot] = new HarddiskInterfaceCard(slot);
@ -154,6 +157,9 @@ void CardManager::RemoveInternal(UINT slot)
case CT_SSC:
m_pSSC = NULL;
break;
case CT_GenericPrinter:
m_pParallelPrinterCard = NULL;
break;
case CT_LanguageCard:
case CT_Saturn128K:
case CT_LanguageCardIIe:
@ -161,6 +167,7 @@ void CardManager::RemoveInternal(UINT slot)
break;
}
UnregisterIoHandler(slot);
delete m_slot[slot];
m_slot[slot] = NULL;
}

View File

@ -11,12 +11,13 @@ public:
CardManager(void) :
m_pMouseCard(NULL),
m_pSSC(NULL),
m_pLanguageCard(NULL)
m_pLanguageCard(NULL),
m_pParallelPrinterCard(NULL)
{
InsertInternal(SLOT0, CT_Empty);
InsertInternal(SLOT1, CT_GenericPrinter);
InsertInternal(SLOT2, CT_SSC);
InsertInternal(SLOT3, CT_Uthernet);
InsertInternal(SLOT3, CT_Empty);
InsertInternal(SLOT4, CT_Empty);
InsertInternal(SLOT5, CT_Empty);
InsertInternal(SLOT6, CT_Disk2);
@ -56,6 +57,8 @@ public:
bool IsMouseCardInstalled(void) { return m_pMouseCard != NULL; }
class CSuperSerialCard* GetSSC(void) { return m_pSSC; }
bool IsSSCInstalled(void) { return m_pSSC != NULL; }
class ParallelPrinterCard* GetParallelPrinterCard(void) { return m_pParallelPrinterCard; }
bool IsParallelPrinterCardInstalled(void) { return m_pParallelPrinterCard != NULL; }
class LanguageCardUnit* GetLanguageCard(void) { return m_pLanguageCard; }
@ -78,4 +81,5 @@ private:
class CMouseInterface* m_pMouseCard;
class CSuperSerialCard* m_pSSC;
class LanguageCardUnit* m_pLanguageCard;
class ParallelPrinterCard* m_pParallelPrinterCard;
};

View File

@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Keyboard.h"
#include "Joystick.h"
#include "SoundCore.h"
#include "SNESMAX.h"
#include "ParallelPrinter.h"
#include "Interface.h"
@ -48,6 +49,7 @@ bool g_bHookSystemKey = true;
bool g_bHookAltTab = false;
bool g_bHookAltGrControl = false;
static LPSTR GetCurrArg(LPSTR lpCmdLine)
{
if (*lpCmdLine == '\"')
@ -167,6 +169,25 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
g_cmdLine.bSlotEmpty[slot] = true;
if (strcmp(lpCmdLine, "diskii") == 0)
g_cmdLine.slotInsert[slot] = CT_Disk2;
if (strcmp(lpCmdLine, "diskii13") == 0)
{
g_cmdLine.slotInsert[slot] = CT_Disk2;
g_cmdLine.slotInfo[slot].isDiskII13 = true;
}
if (strcmp(lpCmdLine, "parallel") == 0)
{
if (slot == SLOT1)
g_cmdLine.slotInsert[slot] = CT_GenericPrinter;
else
LogFileOutput("Parallel Printer card currently only supported in slot 1\n");
}
if (strcmp(lpCmdLine, "ssc") == 0)
{
if (slot == SLOT2)
g_cmdLine.slotInsert[slot] = CT_SSC;
else
LogFileOutput("SSC currently only supported in slot 2\n");
}
if (strcmp(lpCmdLine, "vidhd") == 0)
{
if (slot == SLOT3)
@ -394,7 +415,7 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
}
else if (strcmp(lpCmdLine, "-use-real-printer") == 0) // Enable control in Advanced config to allow dumping to a real printer
{
g_bEnableDumpToRealPrinter = true;
g_cmdLine.enableDumpToRealPrinter = true;
}
else if (strcmp(lpCmdLine, "-speech") == 0)
{
@ -530,6 +551,36 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
{
g_cmdLine.snesMaxAltControllerType[1] = true;
}
else if (strcmp(lpCmdLine, "-snes-max-user-joy1") == 0 || strcmp(lpCmdLine, "-snes-max-user-joy2") == 0)
{
const unsigned int joyNum = (strcmp(lpCmdLine, "-snes-max-user-joy1") == 0) ? 0 : 1;
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
std::string errorMsg;
if (!SNESMAXCard::ParseControllerMappingFile(joyNum, lpCmdLine, errorMsg))
{
LogFileOutput("%s", errorMsg.c_str());
GetFrame().FrameMessageBox(errorMsg.c_str(), TEXT("AppleWin Error"), MB_OK);
}
}
else if (strcmp(lpCmdLine, "-wav-speaker") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
g_cmdLine.wavFileSpeaker = lpCmdLine;
}
else if (strcmp(lpCmdLine, "-wav-mockingboard") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
g_cmdLine.wavFileMockingboard = lpCmdLine;
}
else if (strcmp(lpCmdLine, "-no-disk2-stepper-defer") == 0) // a debug switch (likely to be removed in a future version)
{
g_cmdLine.noDisk2StepperDefer = true;
}
else // unsupported
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);

View File

@ -9,6 +9,16 @@
struct CmdLine
{
struct SlotInfo
{
SlotInfo()
{
isDiskII13 = false;
}
bool isDiskII13;
};
CmdLine()
{
bShutdown = false;
@ -21,6 +31,8 @@ struct CmdLine
snesMaxAltControllerType[0] = false;
snesMaxAltControllerType[1] = false;
supportDCD = false;
enableDumpToRealPrinter = false;
noDisk2StepperDefer = false;
szImageName_harddisk[HARDDISK_1] = NULL;
szImageName_harddisk[HARDDISK_2] = NULL;
szSnapshotName = NULL;
@ -61,7 +73,10 @@ struct CmdLine
bool bRemoveNoSlotClock;
bool snesMaxAltControllerType[2];
bool supportDCD;
bool enableDumpToRealPrinter;
bool noDisk2StepperDefer; // debug
SS_CARDTYPE slotInsert[NUM_SLOTS];
SlotInfo slotInfo[NUM_SLOTS];
LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];
bool driveConnected[NUM_SLOTS][NUM_DRIVES];
LPCSTR szImageName_harddisk[NUM_HARDDISKS];
@ -82,6 +97,8 @@ struct CmdLine
bool bestFullScreenResolution;
UINT userSpecifiedWidth;
UINT userSpecifiedHeight;
std::string wavFileSpeaker;
std::string wavFileMockingboard;
};
bool ProcessCmdLine(LPSTR lpCmdLine);

View File

@ -23,6 +23,7 @@ enum AppMode_e
, MODE_DEBUG // 6502 is paused
, MODE_STEPPING // 6502 is running at normal/full speed (Debugger breakpoints always active)
, MODE_BENCHMARK
, MODE_UNDEFINED // Used in SoundCore_SetFade()
};
#define SPEED_MIN 0
@ -67,6 +68,7 @@ enum AppMode_e
#define REGVALUE_OLD_APPLE2_TYPE "Computer Emulation" // Deprecated
#define REGVALUE_CONFIRM_REBOOT "Confirm Reboot" // Added at 1.24.1 PageConfig
#define REGVALUE_FS_SHOW_SUBUNIT_STATUS "Full-screen show subunit status"
#define REGVALUE_SHOW_DISKII_STATUS "Show Disk II Status"
#define REGVALUE_SOUND_EMULATION "Sound Emulation"
#define REGVALUE_SPKR_VOLUME "Speaker Volume"
#define REGVALUE_MB_VOLUME "Mockingboard Volume"
@ -108,12 +110,15 @@ enum AppMode_e
#define REGVALUE_WINDOW_SCALE "Window Scale"
#define REGVALUE_UTHERNET_ACTIVE "Uthernet Active" // GH#977: Deprecated from 1.30.5
#define REGVALUE_UTHERNET_INTERFACE "Uthernet Interface"
#define REGVALUE_UTHERNET_VIRTUAL_DNS "Uthernet Virtual DNS"
#define REGVALUE_SLOT4 "Slot 4" // GH#977: Deprecated from 1.30.4
#define REGVALUE_SLOT5 "Slot 5" // GH#977: Deprecated from 1.30.4
#define REGVALUE_VERSION "Version"
#define REG_CONFIG_SLOT_AUX "Slot Auxiliary"
#define REG_CONFIG_SLOT "Slot "
#define REGVALUE_CARD_TYPE "Card type"
#define REG_CONFIG_GAME_IO_CONNECTOR "Game I/O Connector"
#define REGVALUE_GAME_IO_TYPE "Game I/O type"
#define REGVALUE_LAST_DISK_1 "Last Disk Image 1"
#define REGVALUE_LAST_DISK_2 "Last Disk Image 2"
#define REGVALUE_LAST_HARDDISK_1 "Last Harddisk Image 1"

View File

@ -0,0 +1,98 @@
/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
#include "Config.h"
#include "../CardManager.h"
#include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate()
#include "../Uthernet2.h"
#include "../Tfe/PCapBackend.h"
// zero initialise
CConfigNeedingRestart::CConfigNeedingRestart()
{
m_Apple2Type = A2TYPE_APPLE2;
m_CpuType = CPU_UNKNOWN;
memset(m_Slot, 0, sizeof(m_Slot));
m_SlotAux = CT_Empty;
m_tfeVirtualDNS = false;
m_bEnableTheFreezesF8Rom = 0;
m_uSaveLoadStateMsg = 0;
m_videoRefreshRate = VR_NONE;
}
// create from current global configuration
CConfigNeedingRestart CConfigNeedingRestart::Create()
{
CConfigNeedingRestart config;
config.Reload();
return config;
}
// update from current global configuration
void CConfigNeedingRestart::Reload()
{
m_Apple2Type = GetApple2Type();
m_CpuType = GetMainCpu();
CardManager& cardManager = GetCardMgr();
for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++)
m_Slot[slot] = cardManager.QuerySlot(slot);
m_SlotAux = cardManager.QueryAux();
m_tfeInterface = PCapBackend::GetRegistryInterface(SLOT3);
m_tfeVirtualDNS = Uthernet2::GetRegistryVirtualDNS(SLOT3);
m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom();
m_uSaveLoadStateMsg = 0;
m_videoRefreshRate = GetVideo().GetVideoRefreshRate();
}
const CConfigNeedingRestart& CConfigNeedingRestart::operator= (const CConfigNeedingRestart& other)
{
m_Apple2Type = other.m_Apple2Type;
m_CpuType = other.m_CpuType;
memcpy(m_Slot, other.m_Slot, sizeof(m_Slot));
m_SlotAux = other.m_SlotAux;
m_tfeInterface = other.m_tfeInterface;
m_tfeVirtualDNS = other.m_tfeVirtualDNS;
m_bEnableTheFreezesF8Rom = other.m_bEnableTheFreezesF8Rom;
m_uSaveLoadStateMsg = other.m_uSaveLoadStateMsg;
m_videoRefreshRate = other.m_videoRefreshRate;
return *this;
}
bool CConfigNeedingRestart::operator== (const CConfigNeedingRestart& other) const
{
return m_Apple2Type == other.m_Apple2Type &&
m_CpuType == other.m_CpuType &&
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
m_SlotAux == other.m_SlotAux &&
m_tfeInterface == other.m_tfeInterface &&
m_tfeVirtualDNS == other.m_tfeVirtualDNS &&
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg &&
m_videoRefreshRate == other.m_videoRefreshRate;
}
bool CConfigNeedingRestart::operator!= (const CConfigNeedingRestart& other) const
{
return !operator==(other);
}

View File

@ -1,86 +1,33 @@
#pragma once
#include "../Core.h"
#include "../CardManager.h"
#include "../CPU.h"
#include "../DiskImage.h" // Disk_Status_e
#include "../Harddisk.h"
#include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate()
#include "../Tfe/PCapBackend.h"
#include "../Video.h"
class CConfigNeedingRestart
{
public:
// zero initialise
CConfigNeedingRestart()
{
m_Apple2Type = A2TYPE_APPLE2;
m_CpuType = CPU_UNKNOWN;
memset(m_Slot, 0, sizeof(m_Slot));
m_SlotAux = CT_Empty;
m_bEnableTheFreezesF8Rom = 0;
m_uSaveLoadStateMsg = 0;
m_videoRefreshRate = VR_NONE;
}
CConfigNeedingRestart();
// create from current global configuration
static CConfigNeedingRestart Create()
{
CConfigNeedingRestart config;
config.Reload();
return config;
}
static CConfigNeedingRestart Create();
// update from current global configuration
void Reload()
{
m_Apple2Type = GetApple2Type();
m_CpuType = GetMainCpu();
CardManager& cardManager = GetCardMgr();
for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++)
m_Slot[slot] = cardManager.QuerySlot(slot);
m_SlotAux = cardManager.QueryAux();
m_tfeInterface = PCapBackend::tfe_interface;
m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom();
m_uSaveLoadStateMsg = 0;
m_videoRefreshRate = GetVideo().GetVideoRefreshRate();
}
void Reload();
const CConfigNeedingRestart& operator= (const CConfigNeedingRestart& other)
{
m_Apple2Type = other.m_Apple2Type;
m_CpuType = other.m_CpuType;
memcpy(m_Slot, other.m_Slot, sizeof(m_Slot));
m_SlotAux = other.m_SlotAux;
m_tfeInterface = other.m_tfeInterface;
m_bEnableTheFreezesF8Rom = other.m_bEnableTheFreezesF8Rom;
m_uSaveLoadStateMsg = other.m_uSaveLoadStateMsg;
m_videoRefreshRate = other.m_videoRefreshRate;
return *this;
}
const CConfigNeedingRestart& operator= (const CConfigNeedingRestart& other);
bool operator== (const CConfigNeedingRestart& other) const
{
return m_Apple2Type == other.m_Apple2Type &&
m_CpuType == other.m_CpuType &&
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
m_SlotAux == other.m_SlotAux &&
m_tfeInterface == other.m_tfeInterface &&
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg &&
m_videoRefreshRate == other.m_videoRefreshRate;
}
bool operator== (const CConfigNeedingRestart& other) const;
bool operator!= (const CConfigNeedingRestart& other) const
{
return !operator==(other);
}
bool operator!= (const CConfigNeedingRestart& other) const;
eApple2Type m_Apple2Type;
eCpuType m_CpuType;
SS_CARDTYPE m_Slot[NUM_SLOTS];
SS_CARDTYPE m_SlotAux;
std::string m_tfeInterface;
bool m_tfeVirtualDNS;
UINT m_bEnableTheFreezesF8Rom;
UINT m_uSaveLoadStateMsg;
VideoRefreshRate_e m_videoRefreshRate;

View File

@ -30,6 +30,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../ParallelPrinter.h"
#include "../Registry.h"
#include "../SaveState.h"
#include "../CardManager.h"
#include "../CopyProtectionDongles.h"
#include "../resource/resource.h"
CPageAdvanced* CPageAdvanced::ms_this = 0; // reinit'd in ctor
@ -42,6 +44,11 @@ const TCHAR CPageAdvanced::m_CloneChoices[] =
TEXT("TK3000 //e\0") // Brazilian
TEXT("Base 64A\0"); // Taiwanese
//enum GAMEIOCONNECTOR_CHOICE { MENUITEM_EMPTY, MENUITEM_SPEEDSTAR };
const TCHAR CPageAdvanced::m_gameIOConnectorChoices[] =
TEXT("Empty\0")
TEXT("SDS DataKey - SpeedStar\0"); // Protection dongle for Southwestern Data Systems "SpeedStar" Applesoft Compiler
INT_PTR CALLBACK CPageAdvanced::DlgProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
@ -122,6 +129,13 @@ INT_PTR CPageAdvanced::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, L
m_PropertySheetHelper.GetConfigNew().m_Apple2Type = NewCloneType;
m_PropertySheetHelper.GetConfigNew().m_CpuType = ProbeMainCpuDefault(NewCloneType);
}
case IDC_COMBO_GAME_IO_CONNECTOR:
if (HIWORD(wparam) == CBN_SELCHANGE)
{
const DONGLETYPE newCopyProtectionDongleMenuItem = (DONGLETYPE)SendDlgItemMessage(hWnd, IDC_COMBO_GAME_IO_CONNECTOR, CB_GETCURSEL, 0, 0);
SetCopyProtectionDongleType(newCopyProtectionDongleMenuItem);
}
break;
}
break;
@ -131,19 +145,34 @@ INT_PTR CPageAdvanced::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, L
SendDlgItemMessage(hWnd,IDC_SAVESTATE_FILENAME,WM_SETTEXT,0,(LPARAM)Snapshot_GetFilename().c_str());
CheckDlgButton(hWnd, IDC_SAVESTATE_ON_EXIT, g_bSaveStateOnExit ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_DUMPTOPRINTER, g_bDumpToPrinter ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_CONVERT_ENCODING, g_bConvertEncoding ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_FILTER_UNPRINTABLE, g_bFilterUnprintable ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_APPEND, g_bPrinterAppend ? BST_CHECKED : BST_UNCHECKED);
SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE, UDM_SETRANGE, 0, MAKELONG(999,0));
SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE, UDM_SETPOS, 0, MAKELONG(Printer_GetIdleLimit (),0));
SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, WM_SETTEXT, 0, (LPARAM)Printer_GetFilename().c_str());
if (GetCardMgr().IsParallelPrinterCardInstalled())
{
ParallelPrinterCard* card = GetCardMgr().GetParallelPrinterCard();
CheckDlgButton(hWnd, IDC_DUMPTOPRINTER, card->GetDumpToPrinter() ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_CONVERT_ENCODING, card->GetConvertEncoding() ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_FILTER_UNPRINTABLE, card->GetFilterUnprintable() ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_PRINTER_APPEND, card->GetPrinterAppend() ? BST_CHECKED : BST_UNCHECKED);
SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE, UDM_SETRANGE, 0, MAKELONG(999, 0));
SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE, UDM_SETPOS, 0, MAKELONG(card->GetIdleLimit(), 0));
SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, WM_SETTEXT, 0, (LPARAM)card->GetFilename().c_str());
// Need to specify cmd-line switch: -printer-real to enable this control
EnableWindow(GetDlgItem(hWnd, IDC_DUMPTOPRINTER), card->GetEnableDumpToRealPrinter() ? TRUE : FALSE);
}
else
{
EnableWindow(GetDlgItem(hWnd, IDC_DUMPTOPRINTER), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_PRINTER_CONVERT_ENCODING), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_PRINTER_FILTER_UNPRINTABLE), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_PRINTER_APPEND), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_SPIN_PRINTER_IDLE), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_PRINTER_DUMP_FILENAME), FALSE);
}
InitOptions(hWnd);
// Need to specify cmd-line switch: -printer-real to enable this control
EnableWindow(GetDlgItem(hWnd, IDC_DUMPTOPRINTER), g_bEnableDumpToRealPrinter ? TRUE : FALSE);
break;
}
}
@ -160,42 +189,42 @@ void CPageAdvanced::DlgOK(HWND hWnd)
m_PropertySheetHelper.SaveStateUpdate();
}
// Update printer dump filename
{
char szFilename[MAX_PATH];
memset(szFilename, 0, sizeof(szFilename));
* (USHORT*) szFilename = sizeof(szFilename);
UINT nLineLength = SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, EM_LINELENGTH, 0, 0);
SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, EM_GETLINE, 0, (LPARAM)szFilename);
nLineLength = nLineLength > sizeof(szFilename)-1 ? sizeof(szFilename)-1 : nLineLength;
szFilename[nLineLength] = 0x00;
Printer_SetFilename(szFilename);
RegSaveString(TEXT(REG_CONFIG), REGVALUE_PRINTER_FILENAME, 1, Printer_GetFilename());
}
g_bSaveStateOnExit = IsDlgButtonChecked(hWnd, IDC_SAVESTATE_ON_EXIT) ? true : false;
REGSAVE(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), g_bSaveStateOnExit ? 1 : 0);
g_bDumpToPrinter = IsDlgButtonChecked(hWnd, IDC_DUMPTOPRINTER ) ? true : false;
REGSAVE(TEXT(REGVALUE_DUMP_TO_PRINTER), g_bDumpToPrinter ? 1 : 0);
// Save the copy protection dongle type
RegSetConfigGameIOConnectorNewDongleType(GAME_IO_CONNECTOR, GetCopyProtectionDongleType());
g_bConvertEncoding = IsDlgButtonChecked(hWnd, IDC_PRINTER_CONVERT_ENCODING ) ? true : false;
REGSAVE(TEXT(REGVALUE_CONVERT_ENCODING), g_bConvertEncoding ? 1 : 0);
if (GetCardMgr().IsParallelPrinterCardInstalled())
{
ParallelPrinterCard* card = GetCardMgr().GetParallelPrinterCard();
g_bFilterUnprintable = IsDlgButtonChecked(hWnd, IDC_PRINTER_FILTER_UNPRINTABLE ) ? true : false;
REGSAVE(TEXT(REGVALUE_FILTER_UNPRINTABLE), g_bFilterUnprintable ? 1 : 0);
// Update printer dump filename
{
char szFilename[MAX_PATH];
memset(szFilename, 0, sizeof(szFilename));
*(USHORT*)szFilename = sizeof(szFilename);
g_bPrinterAppend = IsDlgButtonChecked(hWnd, IDC_PRINTER_APPEND) ? true : false;
REGSAVE(TEXT(REGVALUE_PRINTER_APPEND), g_bPrinterAppend ? 1 : 0);
UINT nLineLength = SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, EM_LINELENGTH, 0, 0);
//
SendDlgItemMessage(hWnd, IDC_PRINTER_DUMP_FILENAME, EM_GETLINE, 0, (LPARAM)szFilename);
Printer_SetIdleLimit((short)SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE , UDM_GETPOS, 0, 0));
REGSAVE(TEXT(REGVALUE_PRINTER_IDLE_LIMIT),Printer_GetIdleLimit());
nLineLength = nLineLength > sizeof(szFilename) - 1 ? sizeof(szFilename) - 1 : nLineLength;
szFilename[nLineLength] = 0x00;
card->SetFilename(szFilename);
}
card->SetDumpToPrinter(IsDlgButtonChecked(hWnd, IDC_DUMPTOPRINTER) ? true : false);
card->SetConvertEncoding(IsDlgButtonChecked(hWnd, IDC_PRINTER_CONVERT_ENCODING) ? true : false);
card->SetFilterUnprintable(IsDlgButtonChecked(hWnd, IDC_PRINTER_FILTER_UNPRINTABLE) ? true : false);
card->SetPrinterAppend(IsDlgButtonChecked(hWnd, IDC_PRINTER_APPEND) ? true : false);
card->SetIdleLimit((short)SendDlgItemMessage(hWnd, IDC_SPIN_PRINTER_IDLE, UDM_GETPOS, 0, 0));
// Now save all the above to Registry
card->SetRegistryConfig();
}
m_PropertySheetHelper.PostMsgAfterClose(hWnd, m_Page);
}
@ -204,6 +233,7 @@ void CPageAdvanced::InitOptions(HWND hWnd)
{
InitFreezeDlgButton(hWnd);
InitCloneDropdownMenu(hWnd);
InitGameIOConnectorDropdownMenu(hWnd);
}
// Advanced->Clone: Menu item to eApple2Type
@ -269,3 +299,10 @@ void CPageAdvanced::InitCloneDropdownMenu(HWND hWnd)
const bool bIsClone = IsClone( m_PropertySheetHelper.GetConfigNew().m_Apple2Type );
EnableWindow(GetDlgItem(hWnd, IDC_CLONETYPE), bIsClone ? TRUE : FALSE);
}
void CPageAdvanced::InitGameIOConnectorDropdownMenu(HWND hWnd)
{
// Set copy protection dongle menu choice
const int nCurrentChoice = GetCopyProtectionDongleType();
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_GAME_IO_CONNECTOR, m_gameIOConnectorChoices, nCurrentChoice);
}

View File

@ -35,9 +35,11 @@ private:
int GetCloneMenuItem(void);
void InitFreezeDlgButton(HWND hWnd);
void InitCloneDropdownMenu(HWND hWnd);
void InitGameIOConnectorDropdownMenu(HWND hWnd);
static CPageAdvanced* ms_this;
static const TCHAR m_CloneChoices[];
static const TCHAR m_gameIOConnectorChoices[];
const PAGETYPE m_Page;
CPropertySheetHelper& m_PropertySheetHelper;

View File

@ -30,6 +30,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Windows/Win32Frame.h"
#include "../Registry.h"
#include "../SerialComms.h"
#include "../CardManager.h"
#include "../Uthernet2.h"
#include "../Tfe/PCapBackend.h"
#include "../Interface.h"
#include "../resource/resource.h"
CPageConfig* CPageConfig::ms_this = 0; // reinit'd in ctor
@ -114,6 +118,7 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
ui_tfe_settings_dialog(hWnd);
m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = m_PageConfigTfe.m_tfe_selected;
m_PropertySheetHelper.GetConfigNew().m_tfeInterface = m_PageConfigTfe.m_tfe_interface_name;
m_PropertySheetHelper.GetConfigNew().m_tfeVirtualDNS = m_PageConfigTfe.m_tfe_virtual_dns;
InitOptions(hWnd);
break;
@ -261,7 +266,8 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
break;
}
m_PageConfigTfe.m_tfe_interface_name = PCapBackend::tfe_interface;
m_PageConfigTfe.m_tfe_interface_name = PCapBackend::GetRegistryInterface(SLOT3);
m_PageConfigTfe.m_tfe_virtual_dns = Uthernet2::GetRegistryVirtualDNS(SLOT3);
}
InitOptions(hWnd);

View File

@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Registry.h"
#include "../resource/resource.h"
#include "../Tfe/PCapBackend.h"
#include "../Tfe/tfesupp.h"
CPageConfigTfe* CPageConfigTfe::ms_this = 0; // reinit'd in ctor
@ -109,26 +108,23 @@ void CPageConfigTfe::DlgCANCEL(HWND window)
EndDialog(window, 0);
}
BOOL CPageConfigTfe::get_tfename(int number, char **ppname, char **ppdescription)
BOOL CPageConfigTfe::get_tfename(int number, std::string & name, std::string & description)
{
if (PCapBackend::tfe_enumadapter_open())
{
char *pname = NULL;
char *pdescription = NULL;
std::string adapterName;
std::string adapterDescription;
while (number--)
{
if (!PCapBackend::tfe_enumadapter(&pname, &pdescription))
if (!PCapBackend::tfe_enumadapter(adapterName, adapterDescription))
break;
lib_free(pname);
lib_free(pdescription);
}
if (PCapBackend::tfe_enumadapter(&pname, &pdescription))
if (PCapBackend::tfe_enumadapter(adapterName, adapterDescription))
{
*ppname = pname;
*ppdescription = pdescription;
name = adapterName;
description = adapterDescription;
PCapBackend::tfe_enumadapter_close();
return TRUE;
}
@ -139,44 +135,21 @@ BOOL CPageConfigTfe::get_tfename(int number, char **ppname, char **ppdescription
return FALSE;
}
int CPageConfigTfe::gray_ungray_items(HWND hwnd)
void CPageConfigTfe::gray_ungray_items(HWND hwnd)
{
int enable;
int number;
int disabled = 0;
PCapBackend::get_disabled_state(&disabled);
if (disabled)
{
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE_T), 0);
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), 0);
EnableWindow(GetDlgItem(hwnd, IDOK), 0);
SetWindowText(GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE_NAME), "");
SetWindowText(GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE_DESC), "");
enable = 0;
}
else
{
enable = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0) ? 1 : 0;
}
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_T), enable);
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), enable);
const int enable = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
if (enable)
{
char *pname = NULL;
char *pdescription = NULL;
std::string name;
std::string description;
number = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), CB_GETCURSEL, 0, 0);
const int number = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), CB_GETCURSEL, 0, 0);
if (get_tfename(number, &pname, &pdescription))
if (get_tfename(number, name, description))
{
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), pname);
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), pdescription);
lib_free(pname);
lib_free(pdescription);
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), name.c_str());
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), description.c_str());
}
}
else
@ -185,7 +158,7 @@ int CPageConfigTfe::gray_ungray_items(HWND hwnd)
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), "");
}
return disabled ? 1 : 0;
EnableWindow(GetDlgItem(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS), enable == 2);
}
void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
@ -199,6 +172,23 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
uilib_adjust_group_width(hwnd, ms_leftgroup);
uilib_move_group(hwnd, ms_rightgroup, xsize + 30);
if (PCapBackend::tfe_is_npcap_loaded())
{
const char * version = PCapBackend::tfe_lib_version();
SetWindowText(GetDlgItem(hwnd, IDC_TFE_NPCAP_INFO), version);
}
else
{
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), 0);
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), 0);
SetWindowText(GetDlgItem(hwnd, IDC_TFE_NPCAP_INFO),
"Limited Uthernet support is available on your system.\n\n"
"Install Npcap from https://npcap.com\n"
"or select Uthernet II with Virtual DNS.");
}
switch (m_tfe_selected)
{
case CT_Uthernet:
@ -212,6 +202,8 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
break;
}
CheckDlgButton(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS, m_tfe_virtual_dns ? BST_CHECKED : BST_UNCHECKED);
temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_ENABLE);
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Disabled");
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Uthernet");
@ -222,25 +214,23 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
{
int cnt = 0;
char *pname;
char *pdescription;
std::string name;
std::string description;
temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE);
for (cnt = 0; PCapBackend::tfe_enumadapter(&pname, &pdescription); cnt++)
for (cnt = 0; PCapBackend::tfe_enumadapter(name, description); cnt++)
{
BOOL this_entry = FALSE;
if (strcmp(pname, m_tfe_interface_name.c_str()) == 0)
if (name == m_tfe_interface_name)
{
this_entry = TRUE;
}
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), pname);
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), pdescription);
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)pname);
lib_free(pname);
lib_free(pdescription);
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), name.c_str());
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), description.c_str());
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)name.c_str());
if (this_entry)
{
@ -252,22 +242,7 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
PCapBackend::tfe_enumadapter_close();
}
if (gray_ungray_items(hwnd))
{
/* we have a problem: TFE is disabled. Give a message to the user */
// TC (18 Dec 2017) this vicekb URL is a broken link now, so I copied it to the AppleWin repo, here:
// . https://github.com/AppleWin/AppleWin/blob/master/docs/VICE%20Knowledge%20Base%20-%20Article%2013-005.htm
MessageBox( hwnd,
"Uthernet support is not available on your system,\n"
"WPCAP.DLL cannot be loaded.\n\n"
"Install Npcap from\n\n"
" https://npcap.com\n\n"
"to activate networking with AppleWin.",
"Uthernet support", MB_ICONINFORMATION|MB_OK);
/* just quit the dialog before it is open */
SendMessage( hwnd, WM_COMMAND, IDCANCEL, 0);
}
gray_ungray_items(hwnd);
}
void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
@ -278,27 +253,21 @@ void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
buffer[255] = 0;
GetDlgItemText(hwnd, IDC_TFE_SETTINGS_INTERFACE, buffer, sizeof(buffer)-1);
// RGJ - Added check for NULL interface so we don't set it active without a valid interface selected
if (strlen(buffer) > 0)
{
m_tfe_interface_name = buffer;
active_value = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
switch (active_value)
{
case 1:
m_tfe_selected = CT_Uthernet;
break;
case 2:
m_tfe_selected = CT_Uthernet2;
break;
default:
m_tfe_selected = CT_Empty;
break;
}
}
else
m_tfe_interface_name = buffer;
active_value = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
switch (active_value)
{
case 1:
m_tfe_selected = CT_Uthernet;
break;
case 2:
m_tfe_selected = CT_Uthernet2;
break;
default:
m_tfe_selected = CT_Empty;
m_tfe_interface_name.clear();
break;
}
m_tfe_virtual_dns = IsDlgButtonChecked(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS) ? 1 : 0;
}

View File

@ -13,6 +13,7 @@ public:
{
CPageConfigTfe::ms_this = this;
m_tfe_selected = CT_Empty;
m_tfe_virtual_dns = false;
}
virtual ~CPageConfigTfe(){}
@ -20,6 +21,7 @@ public:
SS_CARDTYPE m_tfe_selected;
std::string m_tfe_interface_name;
bool m_tfe_virtual_dns;
protected:
// IPropertySheetPage
@ -28,8 +30,8 @@ protected:
virtual void DlgCANCEL(HWND window);
private:
BOOL get_tfename(int number, char **ppname, char **ppdescription);
int gray_ungray_items(HWND hwnd);
BOOL get_tfename(int number, std::string & name, std::string & description);
void gray_ungray_items(HWND hwnd);
void init_tfe_dialog(HWND hwnd);
void save_tfe_dialog(HWND hwnd);

View File

@ -27,9 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PropertySheet.h"
#include "../Windows/AppleWin.h"
#include "../Windows/Win32Frame.h"
#include "../CardManager.h"
#include "../Disk.h" // Drive_e, Disk_Status_e
#include "../Harddisk.h"
#include "../Registry.h"
#include "../Interface.h"
#include "../resource/resource.h"
CPageDisk* CPageDisk::ms_this = 0; // reinit'd in ctor
@ -180,6 +183,7 @@ INT_PTR CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARA
case WM_INITDIALOG:
{
CheckDlgButton(hWnd, IDC_ENHANCE_DISK_ENABLE, GetCardMgr().GetDisk2CardMgr().GetEnhanceDisk() ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_DISKII_STATUS_ENABLE, Win32Frame::GetWin32Frame().GetWindowedModeShowDiskiiStatus() ? BST_CHECKED : BST_UNCHECKED);
const UINT slot = SLOT6;
if (GetCardMgr().QuerySlot(slot) == CT_Disk2) // NB. SLOT6 not setup in m_PropertySheetHelper.GetConfigNew().m_Slot[]
@ -277,6 +281,18 @@ void CPageDisk::DlgOK(HWND hWnd)
REGSAVE(TEXT(REGVALUE_ENHANCE_DISK_SPEED), (DWORD)bNewEnhanceDisk);
}
Win32Frame& win32Frame = Win32Frame::GetWin32Frame();
const bool bNewDiskiiStatus = IsDlgButtonChecked(hWnd, IDC_DISKII_STATUS_ENABLE) ? true : false;
if (win32Frame.GetWindowedModeShowDiskiiStatus() != bNewDiskiiStatus)
{
REGSAVE(REGVALUE_SHOW_DISKII_STATUS, bNewDiskiiStatus ? 1 : 0);
win32Frame.SetWindowedModeShowDiskiiStatus(bNewDiskiiStatus);
if (!win32Frame.IsFullScreen())
win32Frame.FrameRefreshStatus(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS);
}
m_PropertySheetHelper.PostMsgAfterClose(hWnd, m_Page);
}

View File

@ -28,10 +28,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Windows/AppleWin.h" // g_nAppMode, g_uScrollLockToggle, sg_PropertySheet
#include "../CardManager.h"
#include "../Memory.h"
#include "../Disk.h"
#include "../Log.h"
#include "../Registry.h"
#include "../SaveState.h"
#include "../Interface.h"
#include "../Uthernet2.h"
#include "../Tfe/PCapBackend.h"
/*
@ -130,6 +133,7 @@ void CPropertySheetHelper::SetSlot(UINT slot, SS_CARDTYPE newCardType)
return;
GetCardMgr().Insert(slot, newCardType);
GetCardMgr().GetRef(slot).InitializeIO(GetCxRomPeripheral());
}
// Used by:
@ -334,7 +338,8 @@ void CPropertySheetHelper::ApplyNewConfig(const CConfigNeedingRestart& ConfigNew
SetSlot(slot, ConfigNew.m_Slot[slot]);
// unconditionally save it, as the previous SetSlot might have removed the setting
PCapBackend::tfe_SetRegistryInterface(slot, ConfigNew.m_tfeInterface);
PCapBackend::SetRegistryInterface(slot, ConfigNew.m_tfeInterface);
Uthernet2::SetRegistryVirtualDNS(slot, ConfigNew.m_tfeVirtualDNS);
slot = SLOT4;
if (CONFIG_CHANGED_LOCAL(m_Slot[slot]))
@ -453,6 +458,9 @@ bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
if (CONFIG_CHANGED(m_tfeInterface))
strMsgMain += ". Uthernet interface has changed\n";
if (CONFIG_CHANGED(m_tfeVirtualDNS))
strMsgMain += ". Uthernet Virtual DNS has changed\n";
if (CONFIG_CHANGED(m_Slot[SLOT4]))
strMsgMain += GetSlot(SLOT4);

View File

@ -0,0 +1,130 @@
/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2022, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
CopyProtectionDongles.cpp
Emulate hardware copy protection dongles for Apple II
Currently supported:
- Southwestern Data Systems DataKey for SpeedStar Applesoft Compiler
Matthew D'Asaro Dec 2022
*/
#include "StdAfx.h"
#include <sstream>
#include "CopyProtectionDongles.h"
#include "Memory.h"
#include "YamlHelper.h"
static DONGLETYPE copyProtectionDongleType = DT_EMPTY;
void SetCopyProtectionDongleType(DONGLETYPE type)
{
copyProtectionDongleType = type;
}
DONGLETYPE GetCopyProtectionDongleType(void)
{
return copyProtectionDongleType;
}
// This protection dongle consists of a NAND gate connected with AN1 and AN2 on the inputs
// PB2 on the output, and AN0 connected to power it.
bool SdsSpeedStar(void)
{
return !MemGetAnnunciator(0) || !(MemGetAnnunciator(1) && MemGetAnnunciator(2));
}
// Returns the copy protection dongle state of PB0. A return value of -1 means not used by copy protection dongle
int CopyProtectionDonglePB0(void)
{
return -1;
}
// Returns the copy protection dongle state of PB1. A return value of -1 means not used by copy protection dongle
int CopyProtectionDonglePB1(void)
{
return -1;
}
// Returns the copy protection dongle state of PB2. A return value of -1 means not used by copy protection dongle
int CopyProtectionDonglePB2(void)
{
switch (copyProtectionDongleType)
{
case DT_SDSSPEEDSTAR: // Southwestern Data Systems DataKey for SpeedStar Applesoft Compiler
return SdsSpeedStar();
break;
default:
return -1;
break;
}
}
//===========================================================================
static const UINT kUNIT_VERSION = 1;
static const std::string& GetSnapshotStructName_SDSSpeedStar(void)
{
static const std::string name("SDS SpeedStar dongle");
return name;
}
void CopyProtectionDongleSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
if (copyProtectionDongleType == DT_SDSSPEEDSTAR)
{
yamlSaveHelper.SaveString(SS_YAML_KEY_DEVICE, GetSnapshotStructName_SDSSpeedStar());
// NB. No state for this dongle
}
else
{
_ASSERT(0);
}
}
void CopyProtectionDongleLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
{
if (version < 1 || version > kUNIT_VERSION)
{
std::ostringstream msg;
msg << "Version " << version;
msg << " is not supported for game I/O device.";
throw std::runtime_error(msg.str());
}
std::string device = yamlLoadHelper.LoadString(SS_YAML_KEY_DEVICE);
if (device == GetSnapshotStructName_SDSSpeedStar())
{
copyProtectionDongleType = DT_SDSSPEEDSTAR;
}
else
{
_ASSERT(0);
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "Common.h"
// Must be in the same order as in PageAdvanced.cpp
enum DONGLETYPE { DT_EMPTY, DT_SDSSPEEDSTAR };
void SetCopyProtectionDongleType(DONGLETYPE type);
DONGLETYPE GetCopyProtectionDongleType(void);
int CopyProtectionDonglePB0(void);
int CopyProtectionDonglePB1(void);
int CopyProtectionDonglePB2(void);
bool SdsSpeedStar(void);
void CopyProtectionDongleSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void CopyProtectionDongleLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,9 @@
, BP_HIT_INTERRUPT = (1 << 7)
, BP_DMA_TO_IO_MEM = (1 << 8)
, BP_DMA_FROM_IO_MEM = (1 << 9)
, BP_DMA_TO_MEM = (1 << 10)
, BP_DMA_FROM_MEM = (1 << 11)
, BP_HIT_VIDEO_POS = (1 << 12)
};
extern int g_nBreakpoints;
@ -183,4 +186,5 @@
void DebuggerMouseClick( int x, int y );
bool IsDebugSteppingAtFullSpeed(void);
void DebuggerBreakOnDmaToOrFromIoMemory(WORD addr, bool isDmaToMemory);
void DebuggerBreakOnDmaToOrFromIoMemory(WORD nAddress, bool isDmaToMemory);
bool DebuggerCheckMemBreakpoints(WORD nAddress, WORD nSize, bool isDmaToMemory);

View File

@ -493,17 +493,19 @@ int _6502_GetOpmodeOpbyte ( const int nBaseAddress, int & iOpmode_, int & nOpby
// 2.7.0.0 TODO: FIXME: Opcode length that over-lap data, should be shortened ... if (nOpbyte_ > 1) if Disassembly_IsDataAddress( nBaseAddress + 1 ) nOpbyte_ = 1;
DisasmData_t* pData = Disassembly_IsDataAddress( nBaseAddress );
if( pData )
if ( pData )
{
if( pData_ )
if ( pData_ )
*pData_ = pData;
nSlack = pData->nEndAddress - pData->nStartAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
const DWORD nEndAddress = pData->nEndAddress;
const int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
nSlack = nDisplayLen;
// Data Disassembler
// Smart Disassembly - Data Section
// Assemblyer Directives - Psuedo Mnemonics
switch( pData->eElementType )
switch ( pData->eElementType )
{
case NOP_BYTE_1: nOpbyte_ = 1; iOpmode_ = AM_M; break;
case NOP_BYTE_2: nOpbyte_ = 2; iOpmode_ = AM_M; break;
@ -880,8 +882,8 @@ Hash_t AssemblerHashMnemonic ( const TCHAR * pMnemonic )
}
#endif
while( *pText )
// for( int iChar = 0; iChar < 4; iChar++ )
while ( *pText )
// for ( int iChar = 0; iChar < 4; iChar++ )
{
char c = tolower( *pText ); // TODO: based on ALLOW_INPUT_LOWERCASE ??
@ -904,7 +906,7 @@ void AssemblerHashOpcodes ()
Hash_t nMnemonicHash;
int iOpcode;
for( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
for ( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
{
const TCHAR *pMnemonic = g_aOpcodes65C02[ iOpcode ].sMnemonic;
nMnemonicHash = AssemblerHashMnemonic( pMnemonic );
@ -924,7 +926,7 @@ void AssemblerHashDirectives ()
Hash_t nMnemonicHash;
int iOpcode;
for( iOpcode = 0; iOpcode < NUM_ASM_M_DIRECTIVES; iOpcode++ )
for ( iOpcode = 0; iOpcode < NUM_ASM_M_DIRECTIVES; iOpcode++ )
{
int iNopcode = FIRST_M_DIRECTIVE + iOpcode;
//. const TCHAR *pMnemonic = g_aAssemblerDirectivesMerlin[ iOpcode ].m_pMnemonic;
@ -949,7 +951,7 @@ void _CmdAssembleHashDump ()
HashOpcode_t tHash;
int iOpcode;
for( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
for ( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
{
tHash.m_iOpcode = iOpcode;
tHash.m_nValue = g_aOpcodesHash[ iOpcode ];
@ -961,7 +963,7 @@ void _CmdAssembleHashDump ()
// Hash_t nPrevHash = vHashes.at( 0 ).m_nValue;
Hash_t nThisHash = 0;
for( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
for ( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
{
tHash = vHashes.at( iOpcode );
@ -1020,7 +1022,7 @@ bool AssemblerPokeOpcodeAddress( const WORD nBaseAddress )
int iOpcode;
int nOpcodes = m_vAsmOpcodes.size();
for( iOpcode = 0; iOpcode < nOpcodes; iOpcode++ )
for ( iOpcode = 0; iOpcode < nOpcodes; iOpcode++ )
{
int nOpcode = m_vAsmOpcodes.at( iOpcode ); // m_iOpcode;
int nOpmode = g_aOpcodes[ nOpcode ].nAddressMode;
@ -1405,7 +1407,7 @@ void AssemblerProcessDelayedSymols()
bModified = false;
std::vector<DelayedTarget_t>::iterator iSymbol;
for( iSymbol = m_vDelayedTargets.begin(); iSymbol != m_vDelayedTargets.end(); ++iSymbol )
for ( iSymbol = m_vDelayedTargets.begin(); iSymbol != m_vDelayedTargets.end(); ++iSymbol )
{
DelayedTarget_t *pTarget = & (*iSymbol); // m_vDelayedTargets.at( iSymbol );
@ -1485,7 +1487,7 @@ bool Assemble( int iArg, int nArgs, WORD nAddress )
int iOpcode;
// Ugh! Linear search.
for( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
for ( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
{
if (nMnemonicHash == g_aOpcodesHash[ iOpcode ])
{

View File

@ -90,6 +90,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{TEXT("BPM") , CmdBreakpointAddMemA , CMD_BREAKPOINT_ADD_MEM , "Add breakpoint on memory access" }, // SoftICE
{TEXT("BPMR") , CmdBreakpointAddMemR , CMD_BREAKPOINT_ADD_MEMR , "Add breakpoint on memory read access" },
{TEXT("BPMW") , CmdBreakpointAddMemW , CMD_BREAKPOINT_ADD_MEMW , "Add breakpoint on memory write access" },
{TEXT("BPV") , CmdBreakpointAddVideo, CMD_BREAKPOINT_ADD_VIDEO , "Add breakpoint on video scanner position" },
{TEXT("BPC") , CmdBreakpointClear , CMD_BREAKPOINT_CLEAR , "Clear (remove) breakpoint" }, // SoftICE
{TEXT("BPD") , CmdBreakpointDisable , CMD_BREAKPOINT_DISABLE , "Disable breakpoint- it is still in the list, just not active" }, // SoftICE
@ -273,7 +274,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{TEXT("DHGR2") , CmdViewOutput_DHGR2 , CMD_VIEW_DHGR2 , "View Double Hi-res Page 2" },
{TEXT("SHR") , CmdViewOutput_SHR , CMD_VIEW_SHR , "View Super Hi-res" },
// Watch
{TEXT("W") , CmdWatch , CMD_WATCH , "Alias for WA (Watch Add)" },
{TEXT("W") , CmdWatchAdd , CMD_WATCH , "Alias for WA (Watch Add)" },
{TEXT("WA") , CmdWatchAdd , CMD_WATCH_ADD , "Add/Update address or symbol to watch" },
{TEXT("WC") , CmdWatchClear , CMD_WATCH_CLEAR , "Clear (remove) watch" },
{TEXT("WD") , CmdWatchDisable , CMD_WATCH_DISABLE , "Disable specific watch - it is still in the list, just not active" },
@ -299,7 +300,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// {TEXT("WINSOURCE") , CmdWindowShowSource , CMD_WINDOW_SOURCE },
// {TEXT("ZEROPAGE") , CmdWindowShowZeropage, CMD_WINDOW_ZEROPAGE },
// Zero Page
{TEXT("ZP") , CmdZeroPage , CMD_ZEROPAGE_POINTER , "Alias for ZPA (Zero Page Add)" },
{TEXT("ZP") , CmdZeroPageAdd , CMD_ZEROPAGE_POINTER , "Alias for ZPA (Zero Page Add)" },
{TEXT("ZP0") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_0 , "Set/Update/Remove ZP watch 0 " },
{TEXT("ZP1") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_1 , "Set/Update/Remove ZP watch 1" },
{TEXT("ZP2") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_2 , "Set/Update/Remove ZP watch 2" },
@ -441,8 +442,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{TEXT("SPACES") , NULL, PARAM_CONFIG_SPACES },
{TEXT("TARGET") , NULL, PARAM_CONFIG_TARGET },
// Disk
{TEXT("EJECT") , NULL, PARAM_DISK_EJECT },
{TEXT("INFO") , NULL, PARAM_DISK_INFO },
{TEXT("SLOT") , NULL, PARAM_DISK_SET_SLOT },
{TEXT("EJECT") , NULL, PARAM_DISK_EJECT },
{TEXT("PROTECT") , NULL, PARAM_DISK_PROTECT },
{TEXT("READ") , NULL, PARAM_DISK_READ },
// Font (Config)
@ -519,30 +521,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
void VerifyDebuggerCommandTable()
{
char sText[ CONSOLE_WIDTH * 2 ];
for (int iCmd = 0; iCmd < NUM_COMMANDS; iCmd++ )
{
if ( g_aCommands[ iCmd ].iCommand != iCmd)
{
sprintf( sText, "*** ERROR *** Enumerated Commands mis-matched at #%d!", iCmd );
GetFrame().FrameMessageBox(sText, TEXT("ERROR"), MB_OK );
std::string sText = StrFormat( "*** ERROR *** Enumerated Commands mis-matched at #%d!", iCmd );
GetFrame().FrameMessageBox(sText.c_str(), "ERROR", MB_OK);
PostQuitMessage( 1 );
}
}
// _tcscmp
if (strcmp( g_aCommands[ NUM_COMMANDS ].m_sName, DEBUGGER__COMMANDS_VERIFY_TXT__))
{
sprintf( sText, "*** ERROR *** Total Commands mis-matched!" );
GetFrame().FrameMessageBox(sText, TEXT("ERROR"), MB_OK );
GetFrame().FrameMessageBox("*** ERROR *** Total Commands mis-matched!", "ERROR", MB_OK);
PostQuitMessage( 1 );
}
if (strcmp( g_aParameters[ NUM_PARAMS ].m_sName, DEBUGGER__PARAMS_VERIFY_TXT__))
{
sprintf( sText, "*** ERROR *** Total Parameters mis-matched!" );
GetFrame().FrameMessageBox(sText, TEXT("ERROR"), MB_OK );
GetFrame().FrameMessageBox("*** ERROR *** Total Parameters mis-matched!", "ERROR", MB_OK);
PostQuitMessage( 2 );
}
}

View File

@ -292,7 +292,8 @@ void ConsoleBufferPush ( const char * pText )
{
g_nConsoleBuffer++;
}
pSrc++;
if (c == '\n')
pSrc++;
pDst = & g_aConsoleBuffer[ g_nConsoleBuffer ][ 0 ];
}
else
@ -578,7 +579,7 @@ Update_t ConsoleScrollPageDn ()
//===========================================================================
Update_t ConsoleBufferTryUnpause (int nLines)
{
for( int y = 0; y < nLines; y++ )
for ( int y = 0; y < nLines; y++ )
{
ConsoleBufferToDisplay();
}

View File

@ -196,11 +196,11 @@
const char *pSrc = pText;
/* */ int nLen = 0;
if( pText )
if ( pText )
{
while( *pSrc )
while ( *pSrc )
{
if( ConsoleColor_IsCharMeta( *pSrc ) )
if ( ConsoleColor_IsCharMeta( *pSrc ) )
pSrc++;
else
nLen++;

View File

@ -27,6 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Memory.h"
inline static void _memsetz(void* dst, int val, size_t len)
{
memset(dst, val, len);
static_cast<char*>(dst)[len] = 0;
}
//===========================================================================
std::string FormatAddress(WORD nAddress, int nBytes)
{
@ -42,9 +48,9 @@ std::string FormatAddress(WORD nAddress, int nBytes)
}
//===========================================================================
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen)
char* FormatCharCopy(char* pDst, const char* pEnd, const char* pSrc, const int nLen)
{
for (int i = 0; i < nLen; i++)
for (int i = 0; i < nLen && pDst < pEnd; i++)
*pDst++ = FormatCharTxtCtrl(*pSrc++);
return pDst;
}
@ -236,22 +242,22 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
nTarget = nBaseAddress + 2 + (int)(signed char)nTarget;
line_.nTarget = nTarget;
sprintf(line_.sTargetValue, "%04X", nTarget & 0xFFFF);
strncpy_s(line_.sTargetValue, WordToHexStr(nTarget & 0xFFFF).c_str(), _TRUNCATE);
// Always show branch indicators
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
if (nTarget < nBaseAddress)
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorUp[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorUp[g_iConfigDisasmBranchType], _TRUNCATE);
else
if (nTarget > nBaseAddress)
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorDown[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorDown[g_iConfigDisasmBranchType], _TRUNCATE);
else
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorEqual[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorEqual[g_iConfigDisasmBranchType], _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
sprintf(line_.sTargetPointer, "%04X", nTarget & 0xFFFF);
strncpy_s(line_.sTargetPointer, WordToHexStr(nTarget & 0xFFFF).c_str(), _TRUNCATE);
}
// intentional re-test AM_R ...
@ -273,7 +279,7 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
std::string const* pTarget = NULL;
std::string const* pSymbol = FindSymbolFromAddress(nTarget, &line_.iTargetTable);
std::string strAddressBuf;
std::string sAddressBuf;
// Data Assembler
if (pData && (!pData->bSymbolLookup))
@ -322,15 +328,15 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
if (!(bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
{
strAddressBuf = FormatAddress(nTarget, (iOpmode != AM_R) ? nOpbyte : 3); // GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
pTarget = &strAddressBuf;
sAddressBuf = FormatAddress(nTarget, (iOpmode != AM_R) ? nOpbyte : 3); // GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
pTarget = &sAddressBuf;
}
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
//sTarget = StrFormat( g_aOpmodes[ iOpmode ].m_sFormat, pTarget->c_str() );
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
{
int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : -line_.nTargetOffset;
sprintf(line_.sTargetOffset, "%d", nAbsTargetOffset);
strncpy_s(line_.sTargetOffset, StrFormat("%d", nAbsTargetOffset).c_str(), _TRUNCATE);
}
strncpy_s(line_.sTarget, pTarget->c_str(), _TRUNCATE);
@ -348,70 +354,72 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
// if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
//if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
// sTargetValue_ = WordToHexStr( nTargetValue ); // & 0xFFFF
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
sprintf(line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF);
strncpy_s(line_.sTargetPointer, WordToHexStr(nTargetPointer & 0xFFFF).c_str(), _TRUNCATE);
if (iOpcode != OPCODE_JMP_NA && iOpcode != OPCODE_JMP_IAX)
{
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
sprintf(line_.sTargetValue, "%02X", nTargetValue & 0xFF);
strncpy_s(line_.sTargetValue, ByteToHexStr(nTargetValue & 0xFF).c_str(), _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
line_.nImmediate = (BYTE)nTargetValue;
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
sprintf(line_.sImmediate, "%c", _char);
const char _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
_memsetz(line_.sImmediate, _char, 1);
// if (ConsoleColorIsEscapeMeta( nImmediate_ ))
//if (ConsoleColorIsEscapeMeta( nImmediate_ ))
#if OLD_CONSOLE_COLOR
if (ConsoleColorIsEscapeMeta(_char))
sprintf(line_.sImmediate, "%c%c", _char, _char);
_memsetz(line_.sImmediate, _char, 2);
else
sprintf(line_.sImmediate, "%c", _char);
_memsetz(line_.sImmediate, _char, 1);
#endif
}
// if (iOpmode == AM_NA ) // Indirect Absolute
// sprintf( sTargetValue_, "%04X", nTargetPointer & 0xFFFF );
// else
// // sprintf( sTargetValue_, "%02X", nTargetValue & 0xFF );
// sprintf( sTargetValue_, "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
//if (iOpmode == AM_NA ) // Indirect Absolute
// sTargetValue_ = WordToHexStr( nTargetPointer & 0xFFFF );
//else
// //sTargetValue_ = ByteToHexStr( nTargetValue & 0xFF );
// sTargetValue_ = StrFormat( "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
}
}
else
{
if (iOpmode == AM_M)
{
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, (unsigned)nTarget );
sprintf(line_.sTarget , "%02X", (unsigned)nTarget);
strncpy_s(line_.sTarget, ByteToHexStr((BYTE)nTarget).c_str(), _TRUNCATE);
if (nTarget == 0)
line_.sImmediateSignedDec[0] = 0; // nothing
else
if (nTarget < 128)
sprintf(line_.sImmediateSignedDec, "+%d" , nTarget );
strncpy_s(line_.sImmediateSignedDec, StrFormat("+%d", nTarget).c_str(), _TRUNCATE);
else
if (nTarget >= 128)
sprintf(line_.sImmediateSignedDec, "-%d" , (~nTarget + 1) & 0xFF );
strncpy_s(line_.sImmediateSignedDec, StrFormat("-%d" , (~nTarget + 1) & 0xFF).c_str(), _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
line_.nImmediate = (BYTE)nTarget;
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
sprintf(line_.sImmediate, "%c", _char);
const char _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
_memsetz(line_.sImmediate, _char, 1);
#if OLD_CONSOLE_COLOR
if (ConsoleColorIsEscapeMeta(_char))
sprintf(line_.sImmediate, "%c%c", _char, _char);
_memsetz(line_.sImmediate, _char, 2);
else
sprintf(line_.sImmediate, "%c", _char);
_memsetz(line_.sImmediate, _char, 1);
#endif
}
}
}
sprintf(line_.sAddress, "%04X", nBaseAddress);
strncpy_s(line_.sAddress, WordToHexStr(nBaseAddress).c_str(), _TRUNCATE);
// Opcode Bytes
FormatOpcodeBytes(nBaseAddress, line_);
@ -429,11 +437,11 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
strcpy(line_.sMnemonic, g_aOpcodes[line_.iOpcode].sMnemonic);
}
int nSpaces = strlen(line_.sOpCodes);
while (nSpaces < (int)nMinBytesLen)
const size_t nOpCodesLen = strlen(line_.sOpCodes);
if (nOpCodesLen < nMinBytesLen)
{
strcat(line_.sOpCodes, " ");
nSpaces++;
memset(line_.sOpCodes + nOpCodesLen, ' ', nMinBytesLen - nOpCodesLen);
line_.sOpCodes[nMinBytesLen] = '\0';
}
return bDisasmFormatFlags;
@ -442,32 +450,31 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
//===========================================================================
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
{
int nOpbyte = line_.nOpbyte;
char* pDst = line_.sOpCodes;
int nMaxOpBytes = nOpbyte;
if (nMaxOpBytes > DISASM_DISPLAY_MAX_OPCODES) // 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
nMaxOpBytes = DISASM_DISPLAY_MAX_OPCODES;
// 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
const int nMaxOpBytes = min(line_.nOpbyte, DISASM_DISPLAY_MAX_OPCODES);
char* cp = line_.sOpCodes;
const char* const ep = cp + sizeof(line_.sOpCodes);
for (int iByte = 0; iByte < nMaxOpBytes; iByte++)
{
BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
sprintf(pDst, "%02X", nMem); // sBytes+strlen(sBytes)
pDst += 2;
const BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
if ((cp+2) < ep)
cp = StrBufferAppendByteAsHex(cp, nMem);
// TODO: If Disassembly_IsDataAddress() don't show spaces...
if (g_bConfigDisasmOpcodeSpaces)
{
strcat(pDst, " ");
pDst++; // 2.5.3.3 fix
if ((cp+1) < ep)
*cp++ = ' ';
}
}
*cp = '\0';
}
struct FAC_t
{
uint8_t negative;
int8_t exponent;
uint8_t negative;
int8_t exponent;
uint32_t mantissa;
bool isZero;
@ -507,13 +514,12 @@ void FAC_Unpack(WORD nAddress, FAC_t& fac_)
//===========================================================================
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
{
char* pDst = line_.sTarget;
const char* pSrc = 0;
DWORD nStartAddress = line_.pDisasmData->nStartAddress;
DWORD nEndAddress = line_.pDisasmData->nEndAddress;
// int nDataLen = nEndAddress - nStartAddress + 1 ;
int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
int len = nDisplayLen;
// TODO: One day, line_.sTarget should become a std::string and things would be much simpler.
char* pDst = line_.sTarget;
const char* const pEnd = pDst + sizeof(line_.sTarget);
const DWORD nStartAddress = line_.pDisasmData->nStartAddress;
const DWORD nEndAddress = line_.pDisasmData->nEndAddress;
const int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
for (int iByte = 0; iByte < line_.nOpbyte; )
{
@ -526,14 +532,18 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
case NOP_BYTE_2:
case NOP_BYTE_4:
case NOP_BYTE_8:
sprintf(pDst, "%02X", nTarget8); // sBytes+strlen(sBytes)
pDst += 2;
if ((pDst + 2) < pEnd)
pDst = StrBufferAppendByteAsHex(pDst, nTarget8);
iByte++;
if (line_.iNoptype == NOP_BYTE_1)
{
if (iByte < line_.nOpbyte)
{
*pDst++ = ',';
if ((pDst + 1) < pEnd)
*pDst++ = ',';
}
}
*pDst = '\0';
break;
case NOP_FAC:
@ -542,27 +552,38 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
FAC_Unpack( nBaseAddress, fac );
const char aSign[2] = { '+', '-' };
if (fac.isZero)
sprintf( pDst, "0" );
{
if ((pDst + 1) < pEnd)
*pDst++ = '0';
}
else
{
double f = fac.mantissa * pow( 2.0, fac.exponent - 32 );
//sprintf( "s%1X m%04X e%02X", fac.negative, fac.mantissa, fac.exponent );
sprintf( pDst, "%c%f", aSign[ fac.negative ], f );
const double f = fac.mantissa * pow( 2.0, fac.exponent - 32 );
//std::string sFac = StrFormat( "s%1X m%04X e%02X", fac.negative, fac.mantissa, fac.exponent );
std::string sFac = StrFormat( "%c%f", aSign[ fac.negative ], f );
if ((pDst + sFac.length()) < pEnd)
{
memcpy(pDst, sFac.c_str(), sFac.length());
pDst += sFac.length();
}
}
iByte += 5;
*pDst = '\0';
break;
}
case NOP_WORD_1:
case NOP_WORD_2:
case NOP_WORD_4:
sprintf(pDst, "%04X", nTarget16); // sBytes+strlen(sBytes)
pDst += 4;
if ((pDst + 4) < pEnd)
pDst = StrBufferAppendWordAsHex(pDst, nTarget16);
iByte += 2;
if (iByte < line_.nOpbyte)
{
*pDst++ = ',';
if ((pDst + 1) < pEnd)
*pDst++ = ',';
}
*pDst = '\0';
break;
case NOP_ADDRESS:
@ -572,113 +593,124 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
case NOP_STRING_APPLESOFT:
iByte = line_.nOpbyte;
strncpy(pDst, (const char*)(mem + nBaseAddress), iByte);
pDst += iByte;
*pDst = 0;
case NOP_STRING_APPLE:
iByte = line_.nOpbyte; // handle all bytes of text
pSrc = (const char*)mem + nStartAddress;
if (len > (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
if ((pDst + iByte) < pEnd)
{
if (len > DISASM_DISPLAY_MAX_IMMEDIATE_LEN) // no; need extra characters for ellipsis?
len = (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 3); // ellipsis = true
memcpy(pDst, mem + nBaseAddress, iByte);
pDst += iByte;
}
*pDst = 0;
break;
case NOP_STRING_APPLE:
{
iByte = line_.nOpbyte; // handle all bytes of text
const char* pSrc = (const char*)mem + nStartAddress;
if (nDisplayLen > (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
{
const bool ellipsis = (nDisplayLen > DISASM_DISPLAY_MAX_IMMEDIATE_LEN);
const int len = (ellipsis) ? (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 3)
: nDisplayLen // no need of extra characters for ellipsis
;
// DISPLAY: text_longer_18...
FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
pDst = FormatCharCopy(pDst, pEnd, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
if (nDisplayLen > len) // ellipsis
if (ellipsis && (pDst + 3) < pEnd)
{
*pDst++ = '.';
*pDst++ = '.';
*pDst++ = '.';
}
}
else { // DISPLAY: "max_18_char"
*pDst++ = '"';
pDst = FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
*pDst++ = '"';
else
{ // DISPLAY: "max_18_char"
if ((pDst + 1) < pEnd)
*pDst++ = '"';
pDst = FormatCharCopy(pDst, pEnd, pSrc, nDisplayLen); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
if ((pDst + 1) < pEnd)
*pDst++ = '"';
}
*pDst = 0;
break;
}
default:
#if _DEBUG // Unhandled data disassembly!
int* FATAL = 0;
*FATAL = 0xDEADC0DE;
#endif
#if _DEBUG // Unhandled data disassembly!
assert(false);
#endif
iByte++;
break;
}
}
} // switch.
} // for.
}
//===========================================================================
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly, const int nBufferSize)
std::string FormatDisassemblyLine(const DisasmLine_t& line)
{
//> Address Seperator Opcodes Label Mnemonic Target [Immediate] [Branch]
//> Address Separator Opcodes Label Mnemonic Target [Immediate] [Branch]
//
// Data Disassembler
// Label Directive [Immediate]
const char* pMnemonic = g_aOpcodes[line.iOpcode].sMnemonic;
sprintf(sDisassembly, "%s:%s %s "
std::string sDisassembly = StrFormat( "%s:%s %s "
, line.sAddress
, line.sOpCodes
, pMnemonic
, g_aOpcodes[line.iOpcode].sMnemonic
);
/*
if (line.bTargetIndexed || line.bTargetIndirect)
{
strcat( sDisassembly, "(" );
}
if (line.bTargetIndexed || line.bTargetIndirect)
sDisassembly += '(';
if (line.bTargetImmediate)
strcat( sDisassembly, "#$" );
if (line.bTargetImmediate)
sDisassembly += "#$";
if (line.bTargetValue)
strcat( sDisassembly, line.sTarget );
if (line.bTargetValue)
sDisassembly += line.sTarget;
if (line.bTargetIndirect)
{
if (line.bTargetX)
strcat( sDisassembly, ", X" );
if (line.bTargetY)
strcat( sDisassembly, ", Y" );
}
if (line.bTargetIndirect)
{
if (line.bTargetX)
sDisassembly += ", X";
if (line.bTargetY)
sDisassembly += ", Y";
}
if (line.bTargetIndexed || line.bTargetIndirect)
{
strcat( sDisassembly, ")" );
}
if (line.bTargetIndexed || line.bTargetIndirect)
sDisassembly += ')';
if (line.bTargetIndirect)
{
if (line.bTargetY)
strcat( sDisassembly, ", Y" );
}
if (line.bTargetIndirect)
{
if (line.bTargetY)
sDisassembly += ", Y";
}
*/
char sTarget[32];
if (line.bTargetValue || line.bTargetRelative || line.bTargetImmediate)
{
if (line.bTargetRelative)
strcpy(sTarget, line.sTargetValue);
{
sDisassembly += '$';
sDisassembly += line.sTargetValue;
}
else
{
if (line.bTargetImmediate)
{
strcat(sDisassembly, "#");
strncpy(sTarget, line.sTarget, sizeof(sTarget));
sTarget[sizeof(sTarget) - 1] = 0;
sDisassembly += "#$";
sDisassembly += line.sTarget;
}
else
sprintf(sTarget, g_aOpmodes[line.iOpmode].m_sFormat, line.nTarget);
strcat(sDisassembly, "$");
strcat(sDisassembly, sTarget);
{
sDisassembly += '$';
sDisassembly += StrFormat( g_aOpmodes[line.iOpmode].m_sFormat, line.nTarget );
}
}
}
return sDisassembly;
}
// Given an Address, and Line to display it on
@ -758,13 +790,12 @@ void DisasmCalcTopFromCurAddress(bool bUpdateTop)
// Moving the cursor line around is not really a good idea, since we're breaking consistency paradigm for the user.
// g_nDisasmCurLine = 0;
#if 0 // _DEBUG
TCHAR sText[CONSOLE_WIDTH * 2];
sprintf(sText, TEXT("DisasmCalcTopFromCurAddress()\n"
"\tTop: %04X\n"
"\tLen: %04X\n"
"\tMissed: %04X"),
std::string sText = StrFormat("DisasmCalcTopFromCurAddress()\n"
"\tTop: %04X\n"
"\tLen: %04X\n"
"\tMissed: %04X",
g_nDisasmCurAddress - nLen, nLen, g_nDisasmCurAddress);
GetFrame().FrameMessageBox(sText, "ERROR", MB_OK);
GetFrame().FrameMessageBox(sText.c_str(), "ERROR", MB_OK);
#endif
}
}

View File

@ -1,16 +1,12 @@
#pragma once
int GetDisassemblyLine(const WORD nOffset, DisasmLine_t& line_);
// , int iOpcode, int iOpmode, int nOpbytes
// char *sAddress_, char *sOpCodes_,
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char *sTargetValue_,
// char * sImmediate_, char & nImmediate_, char *sBranch_ );
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly_, const int nBufferSize);
std::string FormatDisassemblyLine(const DisasmLine_t& line);
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
std::string FormatAddress(WORD nAddress, int nBytes);
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen);
char* FormatCharCopy(char* pDst, const char* pEnd, const char* pSrc, const int nLen);
char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_ = NULL);
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_ = NULL);

View File

@ -32,35 +32,31 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// __ Debugger Interface ____________________________________________________________________________
void _GetAutoSymbolName ( const Nopcode_e &nopcode, const WORD nStartAddress, char *pSymbolName )
std::string _GetAutoSymbolName(const Nopcode_e& nopcode, const WORD nStartAddress)
{
switch (nopcode)
{
case NOP_ADDRESS:
sprintf( pSymbolName, "A_%04X", nStartAddress ); // DA range
break;
return StrFormat( "A_%04X", nStartAddress ); // DA range
case NOP_FAC:
sprintf( pSymbolName, "F_%04X", nStartAddress ); // DF range
return StrFormat( "F_%04X", nStartAddress ); // DF range
case NOP_STRING_ASCII:
case NOP_STRING_APPLE:
sprintf( pSymbolName, "T_%04X", nStartAddress ); // ASC range
break;
return StrFormat( "T_%04X", nStartAddress ); // ASC range
case NOP_WORD_1:
case NOP_WORD_2:
case NOP_WORD_4:
sprintf( pSymbolName, "W_%04X", nStartAddress ); // DW range
break;
return StrFormat( "W_%04X", nStartAddress ); // DW range
case NOP_BYTE_1:
case NOP_BYTE_2:
case NOP_BYTE_4:
case NOP_BYTE_8:
default:
sprintf( pSymbolName, "B_%04X", nStartAddress ); // DB range
break;
return StrFormat( "B_%04X", nStartAddress ); // DB range
}
}
@ -113,9 +109,9 @@ WORD _GetDataRange (int nArgs, int iArg, DisasmData_t& tData_)
// 2.7.0.35 DW address -- round the length up to even number for convenience.
// Example: 'DW 6062' is equivalent to: 'DW 6062:6063'
if( g_iCommand == CMD_DEFINE_DATA_WORD1 )
if ( g_iCommand == CMD_DEFINE_DATA_WORD1 )
{
if( ~nLen & 1 )
if ( ~nLen & 1 )
nLen++;
}
@ -135,22 +131,21 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_)
nAddress = _GetDataRange(nArgs,iArg,tData_);
const char *pSymbolName = "";
char aSymbolName[ MAX_SYMBOLS_LEN+1 ];
std::string sSymbolName;
SymbolTable_Index_e eSymbolTable = SYMBOLS_ASSEMBLY;
bool bAutoDefineName = false; // 2.7.0.34
if( nArgs > 1 )
if ( nArgs > 1 )
{
if( g_aArgs[ 2 ].eToken == TOKEN_COLON ) // 2.7.0.31 Bug fix: DB range, i.e. DB 174E:174F
if ( g_aArgs[ 2 ].eToken == TOKEN_COLON ) // 2.7.0.31 Bug fix: DB range, i.e. DB 174E:174F
{
bAutoDefineName = true;
}
else
{
g_aArgs[ 1 ].sArg[MAX_SYMBOLS_LEN] = 0; // truncate to max symbol length
pSymbolName = g_aArgs[1].sArg;
sSymbolName = g_aArgs[1].sArg;
}
}
else
@ -162,33 +157,32 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_)
// Old name: auto define D_# DB $XX
// Example 'DB' or 'DW' with 1 arg
// DB 801
Nopcode_e nopcode = NOP_BYTE_1;
Nopcode_e nopcode = NOP_BYTE_1;
bool isFloat = (g_iCommand == CMD_DEFINE_DATA_FLOAT);
if( isFloat )
nopcode = NOP_FAC;
bool isFloat = (g_iCommand == CMD_DEFINE_DATA_FLOAT);
if ( isFloat )
nopcode = NOP_FAC;
bool isString = (g_iCommand == CMD_DEFINE_DATA_STR);
if( isString )
nopcode = NOP_STRING_ASCII;
bool isString = (g_iCommand == CMD_DEFINE_DATA_STR);
if ( isString )
nopcode = NOP_STRING_ASCII;
bool isWord1 = (g_iCommand == CMD_DEFINE_DATA_WORD1);
if( isWord1 )
nopcode = NOP_WORD_1;
bool isWord1 = (g_iCommand == CMD_DEFINE_DATA_WORD1);
if ( isWord1 )
nopcode = NOP_WORD_1;
bool isAddr = (g_iCommand == CMD_DEFINE_ADDR_WORD);
if( isAddr )
nopcode = NOP_ADDRESS;
bool isAddr = (g_iCommand == CMD_DEFINE_ADDR_WORD);
if ( isAddr )
nopcode = NOP_ADDRESS;
if( bAutoDefineName )
if ( bAutoDefineName )
{
_GetAutoSymbolName( nopcode, tData_.nStartAddress , aSymbolName );
pSymbolName = aSymbolName;
sSymbolName = _GetAutoSymbolName( nopcode, tData_.nStartAddress );
}
// bRemoveSymbol = false // use arg[2]
// bUpdateSymbol = true // add the symbol to the table
SymbolUpdate( eSymbolTable, pSymbolName, nAddress, false, true );
SymbolUpdate( eSymbolTable, sSymbolName.c_str(), nAddress, false, true );
// TODO: Note: need to call ConsoleUpdate(), as may print symbol has been updated
@ -196,7 +190,7 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_)
// tData_.eElementType = nopcode;
// As that is done by the caller.
strcpy_s( tData_.sSymbol, sizeof(tData_.sSymbol), pSymbolName );
strncpy_s( tData_.sSymbol, sSymbolName.c_str(), _TRUNCATE );
return nAddress;
}
@ -264,7 +258,7 @@ Update_t CmdDisasmDataDefCode (int nArgs)
while (nAddress <= tData.nEndAddress)
{
DisasmData_t *pData = Disassembly_IsDataAddress( nAddress );
if( pData )
if ( pData )
{
if (( nAddress <= pData->nStartAddress)
&& (tData.nEndAddress >= pData->nEndAddress ))
@ -294,12 +288,11 @@ Update_t CmdDisasmDataDefCode (int nArgs)
DisasmData_t tSplit = *pData;
pData->nEndAddress = nAddress - 1;
const char *pSymbolName = tSplit.sSymbol;
tSplit.nStartAddress = tData.nEndAddress + 1; // nAddress + 1;
_GetAutoSymbolName( pData->eElementType, tSplit.nStartAddress, tSplit.sSymbol );
std::string sSymbolName = _GetAutoSymbolName( pData->eElementType, tSplit.nStartAddress );
strncpy_s(tSplit.sSymbol, sSymbolName.c_str(), _TRUNCATE);
SymbolUpdate( eSymbolTable, pSymbolName, tSplit.nStartAddress, false, true );
SymbolUpdate( eSymbolTable, tSplit.sSymbol, tSplit.nStartAddress, false, true );
Disassembly_AddData( tSplit );
}
@ -342,24 +335,20 @@ Update_t CmdDisasmDataList (int nArgs)
// Need to iterate through all blocks
DisasmData_t* pData = NULL;
while( (pData = Disassembly_Enumerate( pData )) )
while ( (pData = Disassembly_Enumerate( pData )) )
{
if (pData->iDirective != _NOP_REMOVED)
{
int nLen = strlen( pData->sSymbol );
bool hasSymbol = pData->sSymbol[0] != '\0';
// <smbol> <type> <start>:<end>
// <symbol> <type> <start>:<end>
// `TEST `300`:`320
ConsolePrintFormat( "%s%s %s%*s %s%04X%s:%s%04X"
, CHC_CATEGORY
ConsolePrintFormat( CHC_CATEGORY "%s %s%*s " CHC_ADDRESS "%04X" CHC_ARG_SEP ":" CHC_ADDRESS "%04X"
, g_aNopcodeTypes[ pData->eElementType ]
, (nLen > 0) ? CHC_SYMBOL : CHC_DEFAULT
, hasSymbol ? CHC_SYMBOL : CHC_DEFAULT
, MAX_SYMBOLS_LEN
, (nLen > 0) ? pData->sSymbol : "???"
, CHC_ADDRESS
, hasSymbol ? pData->sSymbol : "???"
, pData->nStartAddress
, CHC_ARG_SEP
, CHC_ADDRESS
, pData->nEndAddress // Disassembly_IsDataAddress() is *inclusive* // KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
);
}
@ -411,7 +400,7 @@ Update_t _CmdDisasmDataDefByteX (int nArgs)
// Already exists, so update
DisasmData_t *pData = Disassembly_IsDataAddress( nAddress );
if( pData )
if ( pData )
{
*pData = tData;
}
@ -462,7 +451,7 @@ Update_t _CmdDisasmDataDefWordX (int nArgs)
// Already exists, so update
DisasmData_t *pData = Disassembly_IsDataAddress( nAddress );
if( pData )
if ( pData )
{
*pData = tData;
}
@ -514,7 +503,7 @@ Update_t CmdDisasmDataDefAddress16 (int nArgs)
// Already exists, so update
DisasmData_t *pData = Disassembly_IsDataAddress( nAddress );
if( pData )
if ( pData )
{
*pData = tData;
}
@ -629,7 +618,7 @@ Update_t CmdDisasmDataDefString ( int nArgs )
// Already exists, so update
DisasmData_t *pData = Disassembly_IsDataAddress( nAddress );
if( pData )
if ( pData )
{
*pData = tData;
}
@ -646,14 +635,14 @@ Update_t CmdDisasmDataDefString ( int nArgs )
DisasmData_t* Disassembly_Enumerate( DisasmData_t *pCurrent )
{
DisasmData_t *pData = NULL; // bIsNopcode = false
int nDataTargets = g_aDisassemblerData.size();
size_t nDataTargets = g_aDisassemblerData.size();
if( nDataTargets )
if ( nDataTargets > 0 )
{
DisasmData_t *pBegin = & g_aDisassemblerData[ 0 ];
DisasmData_t *pEnd = & g_aDisassemblerData[ nDataTargets - 1 ];
if( pCurrent )
if ( pCurrent )
{
pCurrent++;
if (pCurrent <= pEnd)
@ -670,17 +659,17 @@ DisasmData_t* Disassembly_Enumerate( DisasmData_t *pCurrent )
DisasmData_t* Disassembly_IsDataAddress ( WORD nAddress )
{
DisasmData_t *pData = NULL; // bIsNopcode = false
int nDataTargets = g_aDisassemblerData.size();
size_t nDataTargets = g_aDisassemblerData.size();
if( nDataTargets )
if ( nDataTargets > 0 )
{
// TODO: Replace with binary search -- should store data in sorted order, via start address
pData = & g_aDisassemblerData[ 0 ];
for( int iTarget = 0; iTarget < nDataTargets; iTarget++ )
for ( size_t iTarget = 0; iTarget < nDataTargets; iTarget++ )
{
if( pData->iDirective != _NOP_REMOVED )
if ( pData->iDirective != _NOP_REMOVED )
{
if( (nAddress >= pData->nStartAddress) && (nAddress <= pData->nEndAddress) )
if ( (nAddress >= pData->nStartAddress) && (nAddress <= pData->nEndAddress) )
{
return pData;
}
@ -703,7 +692,7 @@ void Disassembly_AddData( DisasmData_t tData)
//===========================================================================
void Disassembly_GetData ( WORD nBaseAddress, const DisasmData_t *pData, DisasmLine_t & line_ )
{
if( !pData )
if ( !pData )
{
#if _DEBUG
ConsoleDisplayError( "Disassembly_GetData() but we don't have a valid DisasmData_t *" );
@ -719,13 +708,13 @@ void Disassembly_DelData( DisasmData_t tData)
WORD nAddress = tData.nStartAddress;
DisasmData_t *pData = NULL; // bIsNopcode = false
int nDataTargets = g_aDisassemblerData.size();
size_t nDataTargets = g_aDisassemblerData.size();
if( nDataTargets )
if ( nDataTargets > 0 )
{
// TODO: Replace with binary search -- should store data in sorted order, via start address
pData = & g_aDisassemblerData[ 0 ];
for( int iTarget = 0; iTarget < nDataTargets; iTarget++ )
for ( size_t iTarget = 0; iTarget < nDataTargets; iTarget++ )
{
if (pData->iDirective != _NOP_REMOVED)
{

File diff suppressed because it is too large Load Diff

View File

@ -52,65 +52,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// tests if pSrc fits into pDst
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
bool TestStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
bool bOverflow = (nSpcDst <= nLenSrc); // 2.5.6.25 BUGFIX
if (bOverflow)
{
return false;
}
return true;
}
// tests if pSrc fits into pDst
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
bool TryStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
int nChars = MIN( nLenSrc, nSpcDst );
bool bOverflow = (nSpcDst < nLenSrc);
if (bOverflow)
{
return false;
}
_tcsncat( pDst, pSrc, nChars );
return true;
}
// cats string as much as possible
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
int StringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
int nChars = MIN( nLenSrc, nSpcDst );
_tcsncat( pDst, pSrc, nChars );
bool bOverflow = (nSpcDst < nLenSrc);
if (bOverflow)
return 0;
return nChars;
}
// Help ___________________________________________________________________________________________
@ -136,74 +77,48 @@ Update_t Help_Arg_1( int iCommandHelp )
//===========================================================================
void Help_Categories()
{
const int nBuf = CONSOLE_WIDTH * 2;
char sText[ nBuf ] = "";
int nLen = 0;
// TODO/FIXME: Colorize( sText, ... )
// Colorize("Usage:")
nLen += StringCat( sText, CHC_USAGE , nBuf );
nLen += StringCat( sText, "Usage", nBuf );
nLen += StringCat( sText, CHC_DEFAULT, nBuf );
nLen += StringCat( sText, ": " , nBuf );
nLen += StringCat( sText, CHC_ARG_OPT, nBuf );
nLen += StringCat( sText, "[ ", nBuf );
nLen += StringCat( sText, CHC_ARG_MAND, nBuf );
nLen += StringCat( sText, "< ", nBuf );
std::string sText = CHC_USAGE "Usage" CHC_DEFAULT ": " CHC_ARG_OPT "[ " CHC_ARG_MAND "< ";
for (int iCategory = _PARAM_HELPCATEGORIES_BEGIN ; iCategory < _PARAM_HELPCATEGORIES_END; iCategory++)
{
char *pName = g_aParameters[ iCategory ].m_sName;
const char *pName = g_aParameters[ iCategory ].m_sName;
if (nLen + strlen( pName ) >= (CONSOLE_WIDTH - 1))
if (sText.length() + strlen(pName) >= (CONSOLE_WIDTH - 1))
{
ConsolePrint( sText );
sText[ 0 ] = 0;
nLen = StringCat( sText, " ", nBuf ); // indent
ConsolePrint( sText.c_str() );
sText = " "; // indent
}
StringCat( sText, CHC_COMMAND, nBuf );
nLen += StringCat( sText, pName , nBuf );
sText += CHC_COMMAND;
sText += pName;
if (iCategory < (_PARAM_HELPCATEGORIES_END - 1))
{
char sSep[] = " | ";
const char sSep[] = " | ";
if (nLen + strlen( sSep ) >= (CONSOLE_WIDTH - 1))
if (sText.length() + strlen(sSep) >= (CONSOLE_WIDTH - 1))
{
ConsolePrint( sText );
sText[ 0 ] = 0;
nLen = StringCat( sText, " ", nBuf ); // indent
ConsolePrint( sText.c_str() );
sText = " "; // indent
}
StringCat( sText, CHC_ARG_SEP, nBuf );
nLen += StringCat( sText, sSep, nBuf );
sText += CHC_ARG_SEP;
sText += sSep;
}
}
StringCat( sText, CHC_ARG_MAND, nBuf );
StringCat( sText, " >", nBuf);
sText += CHC_ARG_MAND " >" CHC_ARG_OPT " ]";
StringCat( sText, CHC_ARG_OPT, nBuf );
StringCat( sText, " ]", nBuf);
// ConsoleBufferPush( sText );
ConsolePrint( sText ); // Transcode colored text to native console color text
// ConsoleBufferPush( sText.c_str() );
ConsolePrint( sText.c_str() ); // Transcode colored text to native console color text
ConsolePrintFormat( "%sNotes%s: %s<>%s = mandatory, %s[]%s = optional, %s|%s argument option"
, CHC_USAGE
, CHC_DEFAULT
, CHC_ARG_MAND
, CHC_DEFAULT
, CHC_ARG_OPT
, CHC_DEFAULT
, CHC_ARG_SEP
, CHC_DEFAULT
);
// ConsoleBufferPush( sText );
ConsolePrintFormat( CHC_USAGE "Notes" CHC_DEFAULT ": "
CHC_ARG_MAND "<>" CHC_DEFAULT " = mandatory, "
CHC_ARG_OPT "[]" CHC_DEFAULT " = optional, "
CHC_ARG_SEP "|" CHC_DEFAULT " argument option" );
// ConsoleBufferPush( sText.c_str() );
}
void Help_Examples()
@ -249,29 +164,26 @@ void Help_Operators()
ConsolePrintFormat( " %s#%s Designate number in hex" , CHC_USAGE, CHC_DEFAULT );
// ConsoleBufferPush( " Operators: (Range)" );
ConsolePrintFormat( " Operators: (%sRange%s)" , CHC_USAGE, CHC_DEFAULT );
ConsolePrintFormat( " %s,%s range seperator (2nd address is relative)", CHC_USAGE, CHC_DEFAULT );
ConsolePrintFormat( " %s:%s range seperator (2nd address is absolute)", CHC_USAGE, CHC_DEFAULT );
ConsolePrintFormat( " %s,%s range separator (2nd address is relative)", CHC_USAGE, CHC_DEFAULT );
ConsolePrintFormat( " %s:%s range separator (2nd address is absolute)", CHC_USAGE, CHC_DEFAULT );
// ConsolePrintFormat( " Operators: (Misc)" );
ConsolePrintFormat( " Operators: (%sMisc%s)" , CHC_USAGE, CHC_DEFAULT );
ConsolePrintFormat( " %s//%s comment until end of line" , CHC_USAGE, CHC_DEFAULT );
// ConsoleBufferPush( " Operators: (Breakpoint)" );
ConsolePrintFormat( " Operators: (%sBreakpoint%s)" , CHC_USAGE, CHC_DEFAULT );
char sText[CONSOLE_WIDTH];
_tcscpy( sText, " " );
strcat( sText, CHC_USAGE );
int iBreakOp = 0;
for( iBreakOp = 0; iBreakOp < NUM_BREAKPOINT_OPERATORS; iBreakOp++ )
std::string sText = " " CHC_USAGE;
for ( int iBreakOp = 0; iBreakOp < NUM_BREAKPOINT_OPERATORS; iBreakOp++ )
{
if ((iBreakOp >= PARAM_BP_LESS_EQUAL) &&
(iBreakOp <= PARAM_BP_GREATER_EQUAL))
{
strcat( sText, g_aBreakpointSymbols[ iBreakOp ] );
strcat( sText, " " );
sText += g_aBreakpointSymbols[ iBreakOp ];
sText += ' ';
}
}
strcat( sText, CHC_DEFAULT );
ConsolePrint( sText );
sText += CHC_DEFAULT;
ConsolePrint( sText.c_str() );
}
void Help_KeyboardShortcuts()
@ -452,7 +364,7 @@ bool Colorize( char * pDst, size_t /*nDstSz*/, const char* pSrc)
const char *start = pSrc;
const char *end = pSrc;
while( isHexDigit( *end ) )
while ( isHexDigit( *end ) )
end++;
size_t nDigits = end - start;
@ -580,11 +492,11 @@ Update_t CmdHelpSpecific (int nArgs)
{
// int nFoundCategory = FindParam( g_aArgs[ iArg ].sArg, MATCH_EXACT, iParam, _PARAM_HELPCATEGORIES_BEGIN, _PARAM_HELPCATEGORIES_END );
int nFoundCategory = FindParam( g_aArgs[ iArg ].sArg, MATCH_FUZZY, iParam, _PARAM_HELPCATEGORIES_BEGIN, _PARAM_HELPCATEGORIES_END );
if( nFoundCategory )
if ( nFoundCategory )
bCategory = true;
else
bCategory = false;
switch( iParam )
switch ( iParam )
{
case PARAM_CAT_BOOKMARKS : iCmdBegin = CMD_BOOKMARK ; iCmdEnd = CMD_BOOKMARK_SAVE ; break;
case PARAM_CAT_BREAKPOINTS: iCmdBegin = CMD_BREAK_INVALID ; iCmdEnd = CMD_BREAKPOINT_SAVE ; break;
@ -646,7 +558,7 @@ Update_t CmdHelpSpecific (int nArgs)
if (nFound) {
bCategory = false;
} else // 2.7.0.17: HELP <category> wasn't displaying when category was one of: FLAGS, OUTPUT, WATCHES
if( nFoundCategory )
if ( nFoundCategory )
{
iCmdBegin = CMD_WATCH_ADD ; iCmdEnd = CMD_WATCH_LIST ;
}
@ -735,62 +647,62 @@ Update_t CmdHelpSpecific (int nArgs)
// if (nFound && (! bAllCommands) && (! bCategory))
if (nFound && (! bAllCommands) && bDisplayCategory)
{
const char* pszCategory = "";
const char* pCategory = "";
int iCmd = g_aCommands[ iCommand ].iCommand; // Unaliased command
// HACK: Major kludge to display category!!!
if (iCmd <= CMD_UNASSEMBLE)
pszCategory = g_aParameters[ PARAM_CAT_CPU ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_CPU ].m_sName;
else
if (iCmd <= CMD_BOOKMARK_SAVE)
pszCategory = g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName;
else
if (iCmd <= CMD_BREAKPOINT_SAVE)
pszCategory = g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName;
else
if (iCmd <= CMD_CONFIG_SET_DEBUG_DIR)
pszCategory = g_aParameters[ PARAM_CAT_CONFIG ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_CONFIG ].m_sName;
else
if (iCmd <= CMD_CURSOR_PAGE_DOWN_4K)
pszCategory = "Scrolling";
pCategory = "Scrolling";
else
if (iCmd <= CMD_FLAG_SET_N)
pszCategory = g_aParameters[ PARAM_CAT_FLAGS ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_FLAGS ].m_sName;
else
if (iCmd <= CMD_MOTD)
pszCategory = g_aParameters[ PARAM_CAT_HELP ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_HELP ].m_sName;
else
if (iCmd <= CMD_MEMORY_FILL)
pszCategory = g_aParameters[ PARAM_CAT_MEMORY ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_MEMORY ].m_sName;
else
if (iCmd <= CMD_OUTPUT_RUN)
pszCategory = g_aParameters[ PARAM_CAT_OUTPUT ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_OUTPUT ].m_sName;
else
if (iCmd <= CMD_SYNC)
pszCategory = "Source";
pCategory = "Source";
else
if (iCmd <= CMD_SYMBOLS_LIST)
pszCategory = g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName;
else
if (iCmd <= CMD_VIEW_DHGR2)
pszCategory = g_aParameters[ PARAM_CAT_VIEW ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_VIEW ].m_sName;
else
if (iCmd <= CMD_WATCH_SAVE)
pszCategory = g_aParameters[ PARAM_CAT_WATCHES ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_WATCHES ].m_sName;
else
if (iCmd <= CMD_WINDOW_OUTPUT)
pszCategory = g_aParameters[ PARAM_CAT_WINDOW ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_WINDOW ].m_sName;
else
if (iCmd <= CMD_ZEROPAGE_POINTER_SAVE)
pszCategory = g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName;
pCategory = g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName;
else
pszCategory = "Unknown!";
pCategory = "Unknown!";
ConsolePrintFormat( "%sCategory%s: %s%s"
, CHC_USAGE
, CHC_DEFAULT
, CHC_CATEGORY
, pszCategory );
, pCategory );
if (bCategory)
bDisplayCategory = false;
@ -801,8 +713,8 @@ Update_t CmdHelpSpecific (int nArgs)
const char *const pHelp = pCommand->pHelpSummary;
if (pHelp)
{
std::string strText = StrFormat((bCategory) ? "%s%8s%s%s%s, "
: "%s%s%s%s%s, ",
std::string strText = StrFormat((bCategory) ? "%s%8s%s, %s%s"
: "%s%s%s, %s%s",
CHC_COMMAND, pCommand->m_sName, CHC_ARG_SEP,
CHC_DEFAULT, pHelp);
//ConsoleBufferPush( strText.c_str() );
@ -937,15 +849,17 @@ Update_t CmdHelpSpecific (int nArgs)
break;
// Breakpoints
case CMD_BREAK_INVALID:
ConsoleColorizePrintFormat( " Usage: [%s%s | %s%s] | [# | # %s%s | # %s%s]"
ConsoleColorizePrintFormat( " Usage: [%s%s | %s%s]"
, CHC_COMMAND
, g_aParameters[ PARAM_ON ].m_sName
, g_aParameters[PARAM_ON].m_sName
, CHC_COMMAND
, g_aParameters[ PARAM_OFF ].m_sName
, g_aParameters[PARAM_OFF].m_sName
);
ConsoleColorizePrintFormat(" Usage: [# | # %s%s | # %s%s]"
, CHC_COMMAND
, g_aParameters[ PARAM_ON ].m_sName
, g_aParameters[PARAM_ON].m_sName
, CHC_COMMAND
, g_aParameters[ PARAM_OFF ].m_sName
, g_aParameters[PARAM_OFF].m_sName
);
ConsoleColorizePrintFormat( " Usage: [%s%s %s%s | %s%s %s%s]"
, CHC_COMMAND
@ -1026,7 +940,10 @@ Update_t CmdHelpSpecific (int nArgs)
ConsoleColorizePrint( " Usage: <range>" );
Help_Range();
break;
// Config - Load / Save
case CMD_BREAKPOINT_ADD_VIDEO:
ConsoleColorizePrint( " Usage: <vpos[,length]>" );
break;
// Config - Load / Save
case CMD_CONFIG_LOAD:
ConsoleColorizePrint( " Usage: [\"filename\"]" );
ConsoleBufferPushFormat( " Load debugger configuration from '%s', or the specificed file.", g_sFileNameConfig.c_str() );
@ -1485,33 +1402,23 @@ Update_t CmdHelpSpecific (int nArgs)
//===========================================================================
Update_t CmdHelpList (int nArgs)
{
const int nBuf = CONSOLE_WIDTH * 2;
char sText[ nBuf ] = "";
int nMaxWidth = g_nConsoleDisplayWidth - 1;
int iCommand;
const size_t nMaxWidth = g_nConsoleDisplayWidth - 1;
extern std::vector<Command_t> g_vSortedCommands;
if (! g_vSortedCommands.size())
{
for (iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ )
for ( int iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ )
{
g_vSortedCommands.push_back( g_aCommands[ iCommand ] );
}
std::sort( g_vSortedCommands.begin(), g_vSortedCommands.end(), commands_functor_compare() );
}
int nLen = 0;
// Colorize( sText, "Commands: " );
StringCat( sText, CHC_USAGE , nBuf );
nLen += StringCat( sText, "Commands", nBuf );
//Colorize( sText, "Commands: " );
std::string sText = CHC_USAGE "Commands" CHC_DEFAULT ": ";
StringCat( sText, CHC_DEFAULT, nBuf );
nLen += StringCat( sText, ": " , nBuf );
for( iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ ) // aliases are not printed
for ( int iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ ) // aliases are not printed
{
Command_t *pCommand = & g_vSortedCommands.at( iCommand );
// Command_t *pCommand = & g_aCommands[ iCommand ];
@ -1520,27 +1427,22 @@ Update_t CmdHelpList (int nArgs)
if (! pCommand->pFunction)
continue; // not implemented function
int nLenCmd = strlen( pName );
if ((nLen + nLenCmd) < (nMaxWidth))
if ((sText.length() + strlen(pName)) < nMaxWidth)
{
StringCat( sText, CHC_COMMAND, nBuf );
nLen += StringCat( sText, pName , nBuf );
sText += CHC_COMMAND;
}
else
{
ConsolePrint( sText );
nLen = 1;
strcpy( sText, " " );
StringCat( sText, CHC_COMMAND, nBuf );
nLen += StringCat( sText, pName, nBuf );
ConsolePrint( sText.c_str() );
sText = " " CHC_COMMAND;
}
sText += pName;
strcat( sText, " " );
nLen++;
sText += ' ';
}
//ConsoleBufferPush( sText );
ConsolePrint( sText );
//ConsoleBufferPush( sText.c_str() );
ConsolePrint( sText.c_str() );
ConsoleUpdate();
return UPDATE_CONSOLE_DISPLAY;

View File

@ -26,8 +26,4 @@ inline void UnpackVersion( const unsigned int nVersion,
nFixMinor_ = (nVersion >> 0) & 0xFF;
}
bool TestStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize );
bool TryStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize );
int StringCat( TCHAR * pDst, LPCSTR pSrc, const int nDstSize );
#endif

View File

@ -286,7 +286,7 @@ int ArgsGet ( TCHAR * pInput )
if (iTokenSrc == TOKEN_SEMI)
{
// TODO - command seperator, must handle non-quoted though!
// TODO - command separator, must handle non-quoted though!
}
if (iTokenSrc == TOKEN_QUOTE_DOUBLE)
@ -366,7 +366,7 @@ bool ArgsGetRegisterValue ( Arg_t *pArg, WORD * pAddressValue_ )
if (pArg && pAddressValue_)
{
// Check if we refer to reg A X Y P S
for( int iReg = 0; iReg < (NUM_BREAKPOINT_SOURCES-1); iReg++ )
for ( int iReg = 0; iReg < (NUM_BREAKPOINT_SOURCES-1); iReg++ )
{
// Skip Opcode/Instruction/Mnemonic
if (iReg == BP_SRC_OPCODE)
@ -379,7 +379,7 @@ bool ArgsGetRegisterValue ( Arg_t *pArg, WORD * pAddressValue_ )
// Handle one char names
if ((pArg->nArgLen == 1) && (pArg->sArg[0] == g_aBreakpointSource[ iReg ][0]))
{
switch( iReg )
switch ( iReg )
{
case BP_SRC_REG_A : *pAddressValue_ = regs.a & 0xFF; bStatus = true; break;
case BP_SRC_REG_P : *pAddressValue_ = regs.ps & 0xFF; bStatus = true; break;
@ -912,7 +912,7 @@ void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDst
if ((nCur + nGap) >= nDstSize)
break;
for( int iSpc = 0; iSpc < nGap; iSpc++ )
for ( int iSpc = 0; iSpc < nGap; iSpc++ )
{
*pDst++ = CHAR_SPACE;
}

View File

@ -75,9 +75,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Utils _ ________________________________________________________________________________________
void _CmdSymbolsInfoHeader( int iTable, char * pText, int nDisplaySize = 0 );
void _PrintCurrentPath();
Update_t _PrintSymbolInvalidTable();
std::string _CmdSymbolsInfoHeader( int iTable, int nDisplaySize = 0 );
void _PrintCurrentPath();
Update_t _PrintSymbolInvalidTable();
// Private ________________________________________________________________________________________
@ -90,33 +90,28 @@ void _PrintCurrentPath()
Update_t _PrintSymbolInvalidTable()
{
char sText[ CONSOLE_WIDTH * 2 ];
char sTemp[ CONSOLE_WIDTH * 2 ];
// TODO: display the user specified file name
ConsoleBufferPush( "Invalid symbol table." );
ConsolePrintFormat( "Only %s%d%s symbol tables are supported:"
, CHC_NUM_DEC, NUM_SYMBOL_TABLES
, CHC_DEFAULT
ConsolePrintFormat( "Only " CHC_NUM_DEC "%d" CHC_DEFAULT " symbol tables are supported:"
, NUM_SYMBOL_TABLES
);
std::string sText;
// Similar to _CmdSymbolsInfoHeader()
sText[0] = 0;
for( int iTable = 0; iTable < NUM_SYMBOL_TABLES; iTable++ )
for ( int iTable = 0; iTable < NUM_SYMBOL_TABLES; iTable++ )
{
sprintf( sTemp, "%s%s%s%c " // %s"
, CHC_USAGE, g_aSymbolTableNames[ iTable ]
, CHC_ARG_SEP
sText += StrFormat( CHC_USAGE "%s" CHC_ARG_SEP "%c "
, g_aSymbolTableNames[ iTable ]
, (iTable != (NUM_SYMBOL_TABLES-1))
? ','
: '.'
);
strcat( sText, sTemp );
}
// return ConsoleDisplayError( sText );
ConsolePrint( sText );
// return ConsoleDisplayError( sText.c_str() );
ConsolePrint( sText.c_str() );
return ConsoleUpdate();
}
@ -125,13 +120,13 @@ Update_t _PrintSymbolInvalidTable()
//===========================================================================
std::string const& GetSymbol (WORD nAddress, int nBytes, std::string& strAddressBuf)
std::string const& GetSymbol (WORD nAddress, int nBytes, std::string& sAddressBuf)
{
std::string const* pSymbol = FindSymbolFromAddress( nAddress );
if (pSymbol)
return *pSymbol;
return strAddressBuf = FormatAddress( nAddress, nBytes );
return sAddressBuf = FormatAddress( nAddress, nBytes );
}
//===========================================================================
@ -160,7 +155,7 @@ std::string const* FindSymbolFromAddress (WORD nAddress, int * iTable_ )
continue;
std::map<WORD, std::string>::iterator iSymbols = g_aSymbols[iTable].find(nAddress);
if(g_aSymbols[iTable].find(nAddress) != g_aSymbols[iTable].end())
if (g_aSymbols[iTable].find(nAddress) != g_aSymbols[iTable].end())
{
if (iTable_)
{
@ -286,7 +281,7 @@ Update_t CmdSymbolsClear (int nArgs)
// Format the summary of the specified symbol table
//===========================================================================
void _CmdSymbolsInfoHeader( int iTable, char * pText, int nDisplaySize /* = 0 */ )
std::string _CmdSymbolsInfoHeader( int iTable, int nDisplaySize /* = 0 */ )
{
// Common case is to use/calc the table size
bool bActive = (g_bDisplaySymbolTables & (1 << iTable)) ? true : false;
@ -295,25 +290,17 @@ void _CmdSymbolsInfoHeader( int iTable, char * pText, int nDisplaySize /* = 0 */
// Short Desc: `MAIN`: `1000`
// // 2.6.2.19 Color for name of symbol table: _CmdPrintSymbol() "SYM HOME" _CmdSymbolsInfoHeader "SYM"
// CHC_STRING and CHC_NUM_DEC are both cyan, using CHC_USAGE instead of CHC_STRING
sprintf( pText, "%s%s%s:%s%d " // %s"
, CHC_USAGE, g_aSymbolTableNames[ iTable ]
, CHC_ARG_SEP
return StrFormat(CHC_USAGE "%s" CHC_ARG_SEP ":%s%d " // CHC_DEFAULT
, g_aSymbolTableNames[ iTable ]
, bActive ? CHC_NUM_DEC : CHC_WARNING, nSymbols
// , CHC_DEFAULT
);
}
//===========================================================================
Update_t CmdSymbolsInfo (int nArgs)
{
const char sIndent[] = " ";
char sText[ CONSOLE_WIDTH * 4 ] = "";
char sTemp[ CONSOLE_WIDTH * 2 ] = "";
int bDisplaySymbolTables = 0;
strcpy( sText, sIndent ); // Indent new line
if (! nArgs)
{
// default to all tables
@ -333,26 +320,27 @@ Update_t CmdSymbolsInfo (int nArgs)
//sprintf( sText, " Symbols Main: %s%d%s User: %s%d%s Source: %s%d%s"
// "Main:# Basic:# Asm:# User1:# User2:# Src1:# Src2:# Dos:# Prodos:#
int bTable = 1;
int iTable = 0;
for( ; bTable <= bDisplaySymbolTables; iTable++, bTable <<= 1 )
std::string const sIndent = " ";
std::string sText = sIndent; // Indent new line
for ( int iTable = 0, bTable = 1; bTable <= bDisplaySymbolTables; iTable++, bTable <<= 1 )
{
if( bDisplaySymbolTables & bTable )
if ( !!(bDisplaySymbolTables & bTable) )
{
_CmdSymbolsInfoHeader( iTable, sTemp ); // 15 chars per table
std::string hdr = _CmdSymbolsInfoHeader( iTable ); // 15 chars per table
// 2.8.0.4 BUGFIX: Check for buffer overflow and wrap text
int nLen = ConsoleColor_StringLength( sTemp );
int nDst = ConsoleColor_StringLength( sText );
if((nDst + nLen) > CONSOLE_WIDTH )
int nLen = ConsoleColor_StringLength( hdr.c_str() );
int nDst = ConsoleColor_StringLength( sText.c_str() );
if ( (nDst + nLen) > CONSOLE_WIDTH )
{
ConsolePrint( sText );
strcpy( sText, sIndent ); // Indent new line
ConsolePrint( sText.c_str() );
sText = sIndent; // Indent new line
}
strcat( sText, sTemp );
sText += hdr;
}
}
ConsolePrint( sText );
ConsolePrint( sText.c_str() );
return ConsoleUpdate();
}
@ -381,7 +369,7 @@ bool _FindSymbolTable( int bSymbolTables, int iTable )
// iTable is enumeration
// bSymbolTables is bit-flags of enabled tables to search
if( bSymbolTables & (1 << iTable) )
if ( bSymbolTables & (1 << iTable) )
{
return true;
}
@ -396,9 +384,9 @@ int _GetSymbolTableFromFlag( int bSymbolTables )
int iTable = 0;
int bTable = 1;
for( ; bTable <= bSymbolTables; iTable++, bTable <<= 1 )
for ( ; bTable <= bSymbolTables; iTable++, bTable <<= 1 )
{
if( bTable & bSymbolTables )
if ( bTable & bSymbolTables )
break;
}
@ -475,25 +463,23 @@ Update_t _CmdSymbolsListTables (int nArgs, int bSymbolTables )
SYMBOL B = $2000
SYM B
*/
TCHAR sText[ CONSOLE_WIDTH ] = "";
for( int iArgs = 1; iArgs <= nArgs; iArgs++ )
for ( int iArgs = 1; iArgs <= nArgs; iArgs++ )
{
WORD nAddress = g_aArgs[iArgs].nValue;
LPCTSTR pSymbol = g_aArgs[iArgs].sArg;
// Dump all symbols for this table
if( g_aArgRaw[iArgs].eToken == TOKEN_STAR)
if ( g_aArgRaw[iArgs].eToken == TOKEN_STAR)
{
// int iWhichTable = (g_iCommand - CMD_SYMBOLS_MAIN);
// bDisplaySymbolTables = (1 << iWhichTable);
int iTable = 0;
int bTable = 1;
for( ; bTable <= bSymbolTables; iTable++, bTable <<= 1 )
for ( ; bTable <= bSymbolTables; iTable++, bTable <<= 1 )
{
if( bTable & bSymbolTables )
if ( bTable & bSymbolTables )
{
int nSymbols = g_aSymbols[iTable].size();
if (nSymbols)
@ -507,8 +493,7 @@ Update_t _CmdSymbolsListTables (int nArgs, int bSymbolTables )
++iSymbol;
}
}
_CmdSymbolsInfoHeader( iTable, sText );
ConsolePrint( sText );
ConsolePrint(_CmdSymbolsInfoHeader(iTable).c_str() );
}
}
}
@ -564,12 +549,12 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
if (pPathFileName.empty())
return nSymbolsLoaded;
std::string strFormat1 = StrFormat( "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s"
std::string strFormat2 = StrFormat( "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x"
std::string sFormat1 = StrFormat( "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s"
std::string sFormat2 = StrFormat( "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x"
FILE *hFile = fopen( pPathFileName.c_str(), "rt" );
if( !hFile && g_bSymbolsDisplayMissingFile )
if ( !hFile && g_bSymbolsDisplayMissingFile )
{
// TODO: print filename! Bug #242 Help file (.chm) description for "Symbols" #242
ConsoleDisplayError( "Symbol File not found:" );
@ -578,9 +563,9 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
}
bool bDupSymbolHeader = false;
if( hFile )
if ( hFile )
{
while( !feof(hFile) )
while ( !feof(hFile) )
{
// Support 2 types of symbols files:
// 1) AppleWin:
@ -596,24 +581,24 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
const int MAX_LINE = 256;
char szLine[ MAX_LINE ] = "";
if( !fgets(szLine, MAX_LINE-1, hFile) ) // Get next line
if ( !fgets(szLine, MAX_LINE-1, hFile) ) // Get next line
{
//ConsolePrint("<<EOF");
break;
}
if(strstr(szLine, "$") == NULL)
if (strstr(szLine, "$") == NULL)
{
sscanf(szLine, strFormat1.c_str(), &nAddress, sName);
sscanf(szLine, sFormat1.c_str(), &nAddress, sName);
}
else
{
char* p = strstr(szLine, "="); // Optional
if(p) *p = ' ';
if (p) *p = ' ';
p = strstr(szLine, "$");
if(p) *p = ' ';
if (p) *p = ' ';
p = strstr(szLine, ";"); // Optional
if(p) *p = 0;
if (p) *p = 0;
p = strstr(szLine, " "); // 1st space between name & value
if (p)
{
@ -623,13 +608,13 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
memset(&szLine[MAX_SYMBOLS_LEN], ' ', nLen - MAX_SYMBOLS_LEN); // sscanf fails for nAddress if string too long
}
}
sscanf(szLine, strFormat2.c_str(), sName, &nAddress);
sscanf(szLine, sFormat2.c_str(), sName, &nAddress);
}
// SymbolOffset
nAddress += nSymbolOffset;
if( (nAddress > _6502_MEM_END) || (sName[0] == 0) )
if ( (nAddress > _6502_MEM_END) || (sName[0] == 0) )
continue;
// 2.9.0.11 Bug #479
@ -655,9 +640,9 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
// 2.8.0.5 Bug #244 (Debugger) Duplicate symbols for identical memory addresses in APPLE2E.SYM
std::string const* pSymbolPrev = FindSymbolFromAddress( (WORD)nAddress, &iTable ); // don't care which table it is in
if( pSymbolPrev )
if ( pSymbolPrev )
{
if( !bFileDisplayed )
if ( !bFileDisplayed )
{
bFileDisplayed = true;
@ -712,9 +697,9 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
WORD nAddressPrev = 0;
bool bExists = FindAddressFromSymbol( sName, &nAddressPrev, &iTable );
if( bExists )
if ( bExists )
{
if( !bDupSymbolHeader )
if ( !bDupSymbolHeader )
{
bDupSymbolHeader = true;
ConsolePrintFormat( " %sDup Symbol Name%s (%s%s%s) %s"
@ -773,7 +758,7 @@ Update_t CmdSymbolsLoad (int nArgs)
{
std::string pFileName;
if( g_aArgs[ iArg ].bType & TYPE_QUOTED_2 )
if ( g_aArgs[ iArg ].bType & TYPE_QUOTED_2 )
{
pFileName = g_aArgs[ iArg ].sArg;
@ -788,15 +773,15 @@ Update_t CmdSymbolsLoad (int nArgs)
unsigned int nOffsetAddr = 0;
iArg++;
if( iArg <= nArgs)
if ( iArg <= nArgs)
{
if (g_aArgs[ iArg ].eToken == TOKEN_COMMA)
{
iArg++;
if( iArg <= nArgs )
if ( iArg <= nArgs )
{
nOffsetAddr = g_aArgs[ iArg ].nValue;
if( (nOffsetAddr < _6502_MEM_BEGIN) || (nOffsetAddr > _6502_MEM_END) )
if ( (nOffsetAddr < _6502_MEM_BEGIN) || (nOffsetAddr > _6502_MEM_END) )
{
nOffsetAddr = 0;
}
@ -804,13 +789,13 @@ Update_t CmdSymbolsLoad (int nArgs)
}
}
if( !pFileName.empty() )
if ( !pFileName.empty() )
{
nSymbols = ParseSymbolTable( sFileName, (SymbolTable_Index_e) iSymbolTable, nOffsetAddr );
}
}
if( nSymbols > 0 )
if ( nSymbols > 0 )
{
g_nSymbolsLoaded = nSymbols;
}
@ -926,7 +911,7 @@ Update_t _CmdSymbolsUpdate( int nArgs, int bSymbolTables )
bSymbolTables = SYMBOL_TABLE_USER_2; // Autogenerated symbol names go in table 2 for organization when reverse engineering. Table 1 = known, Table 2 = unknown.
nAddress = g_aArgs[2].nValue;
sprintf( g_aArgs[1].sArg, "_%04X", nAddress ); // Autogenerated symbol name
strncpy_s( g_aArgs[1].sArg, StrFormat("_%04X", nAddress).c_str(), _TRUNCATE ); // Autogenerated symbol name
bUpdateSymbol = true;
}
@ -954,8 +939,6 @@ Update_t _CmdSymbolsCommon ( int nArgs, int bSymbolTables )
if (iUpdate != UPDATE_NOTHING)
return iUpdate;
TCHAR sText[ CONSOLE_WIDTH ];
int iArg = 0;
while (iArg++ <= nArgs)
{
@ -992,15 +975,9 @@ Update_t _CmdSymbolsCommon ( int nArgs, int bSymbolTables )
int iTable = _GetSymbolTableFromFlag( bSymbolTables );
if (iTable != NUM_SYMBOL_TABLES)
{
if( bUpdate & UPDATE_SYMBOLS )
if ( bUpdate & UPDATE_SYMBOLS )
{
//sprintf( sText, " Symbol Table: %s%s%s, %sloaded symbols: %s%d"
// , CHC_STRING, g_aSymbolTableNames[ iTable ]
// , CHC_DEFAULT, CHC_DEFAULT
// , CHC_NUM_DEC, g_nSymbolsLoaded
//);
_CmdSymbolsInfoHeader( iTable, sText, g_nSymbolsLoaded );
ConsolePrint( sText );
ConsolePrint( _CmdSymbolsInfoHeader( iTable, g_nSymbolsLoaded ).c_str() );
}
}
else
@ -1022,8 +999,7 @@ Update_t _CmdSymbolsCommon ( int nArgs, int bSymbolTables )
int iTable = _GetSymbolTableFromFlag( bSymbolTables );
if (iTable != NUM_SYMBOL_TABLES)
{
_CmdSymbolsInfoHeader( iTable, sText );
ConsolePrint( sText );
ConsolePrint( _CmdSymbolsInfoHeader( iTable ).c_str() );
}
return ConsoleUpdate() | UPDATE_DISASM;
}
@ -1034,8 +1010,7 @@ Update_t _CmdSymbolsCommon ( int nArgs, int bSymbolTables )
int iTable = _GetSymbolTableFromFlag( bSymbolTables );
if (iTable != NUM_SYMBOL_TABLES)
{
_CmdSymbolsInfoHeader( iTable, sText );
ConsolePrint( sText );
ConsolePrint( _CmdSymbolsInfoHeader( iTable ).c_str() );
}
return ConsoleUpdate() | UPDATE_DISASM;
}

View File

@ -183,6 +183,7 @@
BP_SRC_MEM_RW,
BP_SRC_MEM_READ_ONLY,
BP_SRC_MEM_WRITE_ONLY,
BP_SRC_VIDEO_SCANNER,
NUM_BREAKPOINT_SOURCES
};
@ -334,6 +335,7 @@
, CMD_BREAKPOINT_ADD_MEM // break on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_ADD_MEMR // break on read on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_ADD_MEMW // break on write on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_ADD_VIDEO // break on video scanner position
, CMD_BREAKPOINT_CLEAR
// , CMD_BREAKPOINT_REMOVE = CMD_BREAKPOINT_CLEAR // alias
@ -516,7 +518,7 @@
, CMD_VIEW_DHGR2
, CMD_VIEW_SHR
// Watch
, CMD_WATCH // TODO: Deprecated ?
, CMD_WATCH
, CMD_WATCH_ADD
, CMD_WATCH_CLEAR
, CMD_WATCH_DISABLE
@ -641,6 +643,7 @@
Update_t CmdBreakpointAddMemA (int nArgs);
Update_t CmdBreakpointAddMemR (int nArgs);
Update_t CmdBreakpointAddMemW (int nArgs);
Update_t CmdBreakpointAddVideo (int nArgs);
Update_t CmdBreakpointClear (int nArgs);
Update_t CmdBreakpointDisable (int nArgs);
Update_t CmdBreakpointEdit (int nArgs);
@ -1271,7 +1274,7 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
, TOKEN_PLUS // + Delta Argument1 += Argument2
, TOKEN_QUOTE_SINGLE // '
, TOKEN_QUOTE_DOUBLE // "
, TOKEN_SEMI // ; Command Seperator
, TOKEN_SEMI // ; Command Separator
, TOKEN_SPACE // Token Delimiter
, TOKEN_STAR // *
// , TOKEN_TAB // '\t'
@ -1393,8 +1396,9 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
// Disk
, _PARAM_DISK_BEGIN = _PARAM_CONFIG_END // Daisy Chain
, PARAM_DISK_EJECT = _PARAM_DISK_BEGIN // DISK 1 EJECT
, PARAM_DISK_INFO // DISK 1 INFO
, PARAM_DISK_INFO = _PARAM_DISK_BEGIN // DISK INFO
, PARAM_DISK_SET_SLOT // DISK SLOT 6
, PARAM_DISK_EJECT // DISK 1 EJECT
, PARAM_DISK_PROTECT // DISK 1 PROTECT
, PARAM_DISK_READ // DISK 1 READ Track Sector NumSectors MemAddress
, _PARAM_DISK_END

View File

@ -339,7 +339,8 @@ void DebuggerMouseClick(int x, int y)
// do picking
const int nOffsetX = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetX() : win32Frame.Get3DBorderWidth();
// NB. Full-screen + VidHD isn't centred yet
const int nOffsetX = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetX() : win32Frame.Get3DBorderWidth() + GetVideo().GetFrameBufferCentringOffsetX() * win32Frame.GetViewportScale();
const int nOffsetY = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetY() : win32Frame.Get3DBorderHeight();
const int nOffsetInScreenX = x - nOffsetX;

View File

@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Util_Text.h"
#include "Util_MemoryTextFile.h"
#include "StrFormat.h"
// MemoryTextFile _________________________________________________________________________________
@ -121,9 +122,9 @@ void MemoryTextFile_t::GetLinePointers()
//===========================================================================
void MemoryTextFile_t::PushLine( char *pLine )
void MemoryTextFile_t::PushLine( const char *pLine )
{
char *pSrc = pLine;
const char *pSrc = pLine;
while (pSrc && *pSrc)
{
if (*pSrc == CHAR_CR)
@ -141,4 +142,10 @@ void MemoryTextFile_t::PushLine( char *pLine )
m_bDirty = true;
}
void MemoryTextFile_t::PushLineFormat( const char *pFormat, ... )
{
va_list va;
va_start(va, pFormat);
PushLine(StrFormatV(pFormat, va).c_str());
va_end(va);
}

View File

@ -1,5 +1,7 @@
#pragma once
#include "StrFormat.h"
// Memory Text File _________________________________________________________
class MemoryTextFile_t
@ -43,6 +45,7 @@ inline char *GetLine( const int iLine ) const
void GetLine( const int iLine, char *pLine, const int n );
void PushLine( char *pLine );
void PushLine( const char *pLine );
void PushLineFormat( const char *pFormat, ... ) ATTRIBUTE_FORMAT_PRINTF(2, 3); // 1 is "this"
};

View File

@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Interface.h"
#include "Core.h"
#include "CardManager.h"
#include "CPU.h"
#include "DiskImage.h"
#include "Log.h"
@ -58,7 +59,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
const BYTE Disk2InterfaceCard::m_T00S00Pattern[] = {0xD5,0xAA,0x96,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xDE};
Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
Card(CT_Disk2, slot)
Card(CT_Disk2, slot),
m_syncEvent(slot, 0, SyncEventCallback) // use slot# as "unique" id for Disk2InterfaceCards
{
if (m_slot != 5 && m_slot != 6) // fixme
ThrowErrorInvalidSlot();
@ -71,13 +73,13 @@ Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
m_diskLastReadLatchCycle = 0;
m_enhanceDisk = true;
m_is13SectorFirmware = false;
m_force13SectorFirmware = false;
m_deferredStepperEvent = false;
m_deferredStepperAddress = 0;
m_deferredStepperCumulativeCycles = 0;
ResetLogicStateSequencer();
// if created by user in Config->Disk, then MemInitializeIO() won't be called
if (GetCxRomPeripheral())
InitializeIO(GetCxRomPeripheral()); // During regular start-up, Initialize() will be called later by MemInitializeIO()
// Debug:
#if LOG_DISK_NIBBLES_USE_RUNTIME_VAR
m_bLogDisk_NibblesRW = false;
@ -93,8 +95,8 @@ Disk2InterfaceCard::~Disk2InterfaceCard(void)
EjectDiskInternal(DRIVE_1);
EjectDiskInternal(DRIVE_2);
// if destroyed by user in Config->Disk, then ensure that old object's reference is removed
UnregisterIoHandler(m_slot);
if (m_syncEvent.m_active)
g_SynchronousEventMgr.Remove(m_syncEvent.m_id);
}
bool Disk2InterfaceCard::GetEnhanceDisk(void) { return m_enhanceDisk; }
@ -103,27 +105,31 @@ void Disk2InterfaceCard::SetEnhanceDisk(bool bEnhanceDisk) { m_enhanceDisk = bEn
int Disk2InterfaceCard::GetCurrentDrive(void) { return m_currDrive; }
int Disk2InterfaceCard::GetCurrentTrack(void) { return ImagePhaseToTrack(m_floppyDrive[m_currDrive].m_disk.m_imagehandle, m_floppyDrive[m_currDrive].m_phasePrecise, false); }
float Disk2InterfaceCard::GetCurrentPhase(void) { return m_floppyDrive[m_currDrive].m_phasePrecise; }
int Disk2InterfaceCard::GetCurrentOffset(void) { return m_floppyDrive[m_currDrive].m_disk.m_byte; }
BYTE Disk2InterfaceCard::GetCurrentLSSBitMask(void) { return m_floppyDrive[m_currDrive].m_disk.m_bitMask; }
UINT Disk2InterfaceCard::GetCurrentBitOffset(void) { return m_floppyDrive[m_currDrive].m_disk.m_bitOffset; }
double Disk2InterfaceCard::GetCurrentExtraCycles(void) { return m_floppyDrive[m_currDrive].m_disk.m_extraCycles; }
float Disk2InterfaceCard::GetPhase(const int drive) { return m_floppyDrive[drive].m_phasePrecise; }
int Disk2InterfaceCard::GetTrack(const int drive) { return ImagePhaseToTrack(m_floppyDrive[drive].m_disk.m_imagehandle, m_floppyDrive[drive].m_phasePrecise, false); }
std::string Disk2InterfaceCard::FormatPhaseString(float phase)
std::string Disk2InterfaceCard::FormatIntFracString(float phase, bool hex)
{
const UINT phaseInt = (UINT)phase;
const UINT phaseFrac = (UINT)((phase - (float)phaseInt) * 100 + 0.5);
return StrFormat("%02X.%2d", phaseInt, phaseFrac); // "$NN.nn"
if (hex)
return StrFormat("%02X.%02d", phaseInt, phaseFrac); // (hex)"NN.nn"
else
return StrFormat("%02d.%02d", phaseInt, phaseFrac); // (dec)"NN.nn"
}
std::string Disk2InterfaceCard::GetCurrentTrackString(void)
{
return FormatPhaseString(m_floppyDrive[m_currDrive].m_phasePrecise / 2);
return FormatIntFracString(m_floppyDrive[m_currDrive].m_phasePrecise / 2, true);
}
std::string Disk2InterfaceCard::GetCurrentPhaseString(void)
{
return FormatPhaseString(m_floppyDrive[m_currDrive].m_phasePrecise);
return FormatIntFracString(m_floppyDrive[m_currDrive].m_phasePrecise, true);
}
LPCTSTR Disk2InterfaceCard::GetCurrentState(void)
@ -300,8 +306,15 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
UpdateBitStreamPosition(*pFloppy, bitCellDelta);
}
const UINT32 currentPosition = pFloppy->m_byte;
const UINT32 currentTrackLength = pFloppy->m_nibbles;
if (ImageIsWOZ(pFloppy->m_imagehandle) && (pFloppy->m_bitCount == 0))
{
// WOZ: m_bitCount only ever 0 on initial power on
pFloppy->m_bitOffset = 0;
pFloppy->m_bitCount = 8;
}
const UINT32 currentBitPosition = pFloppy->m_bitOffset;
const UINT32 currentBitTrackLength = pFloppy->m_bitCount;
ImageReadTrack(
pFloppy->m_imagehandle,
@ -311,12 +324,18 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
&pFloppy->m_bitCount,
m_enhanceDisk);
if (!ImageIsWOZ(pFloppy->m_imagehandle) || (currentTrackLength == 0))
if (!ImageIsWOZ(pFloppy->m_imagehandle))
{
pFloppy->m_byte = 0;
}
else
{
// NB. This function is only called for a new track when there's a latch read, ie. only for *even* DEVICE SELECT I/O accesses.
// . So when seeking across tracks (ie. sequencing through the magnet phases), then not all (quarter) tracks will need reading.
// . eg. for 'Balance of Power'(GH#1022), for seek T00->T35: this only reads: 00.00, 00.25, 00.75, 01.25, 01.75, ... 34.25, 34.75, 35.00 (skipping the NN.00, NN.50 tracks).
// . And so the bitOffset "round-up" below isn't called for every track.
// TODO: consider forcing this function be be called for every track (and appropriately adjust the "round-up" amount - ie. halve it)
_ASSERT(pFloppy->m_nibbles && pFloppy->m_bitCount);
if (pFloppy->m_nibbles == 0 || pFloppy->m_bitCount == 0)
{
@ -324,18 +343,28 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
pFloppy->m_bitCount = 8;
}
pFloppy->m_byte = (currentPosition * pFloppy->m_nibbles) / currentTrackLength; // Ref: WOZ-1.01
pFloppy->m_bitOffset = (currentBitPosition * pFloppy->m_bitCount) / currentBitTrackLength; // Ref: WOZ-1.01
pFloppy->m_bitOffset += 7; // Round-up for sensitive cross-track sync check (GH#1022)
if (pFloppy->m_byte == (pFloppy->m_nibbles-1)) // Last nibble may not be complete, so advance by 1 nibble
pFloppy->m_byte = 0;
if (pFloppy->m_bitOffset >= pFloppy->m_bitCount)
pFloppy->m_bitOffset = 0;
#if LOG_DISK_WOZ_READTRACK
LOG_DISK("T%05.2f: %04X->%04X, Len=%04X\n", pDrive->m_phasePrecise / 2, currentBitPosition, pFloppy->m_bitOffset, pFloppy->m_bitCount);
#endif
pFloppy->m_byte = pFloppy->m_bitOffset / 8;
pFloppy->m_bitMask = 1 << (7 - (pFloppy->m_bitOffset % 8));
pFloppy->m_bitOffset = pFloppy->m_byte*8;
pFloppy->m_bitMask = 1 << 7;
pFloppy->m_extraCycles = 0.0;
pDrive->m_headWindow = 0;
FindTrackSeamWOZ(*pFloppy, pDrive->m_phasePrecise/2);
}
pFloppy->m_trackimagedata = (pFloppy->m_nibbles != 0);
pFloppy->m_initialBitOffset = pFloppy->m_bitOffset;
pFloppy->m_revs = 0;
}
}
@ -462,7 +491,6 @@ void __stdcall Disk2InterfaceCard::ControlMotor(WORD, WORD address, BYTE, BYTE,
void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
{
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
FloppyDisk* pFloppy = &pDrive->m_disk;
if (!m_floppyMotorOn) // GH#525
{
@ -491,16 +519,80 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
m_magnetStates &= ~phase_bit; // phase off
}
#if LOG_DISK_PHASES
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - pDrive->m_lastStepperCycle);
#endif
pDrive->m_lastStepperCycle = g_nCumulativeCycles;
if (!GetCardMgr().GetDisk2CardMgr().IsStepperDeferred())
{
m_deferredStepperAddress = address;
m_deferredStepperCumulativeCycles = g_nCumulativeCycles;
ControlStepperDeferred();
return;
}
if (m_syncEvent.m_active)
{
// Check for adjacent magnets being turned off/on in a very short interval (10 cycles is purely based on A2osX). (GH#1110)
g_SynchronousEventMgr.Remove(m_syncEvent.m_id);
m_deferredStepperEvent = false;
int addrDelta = (m_deferredStepperAddress & 7) - (address & 7);
if (addrDelta < 0) addrDelta = -addrDelta;
if (addrDelta == 2 || addrDelta == 6) // adjacent magnets: both turned off or both turned on
{
if ((address & 1) == 0) // adjacent magnets off
{
// 2 adjacent magnets off in quick succession don't move the cog (GH#1110)
// . also DOS3.2, Pascal and ProDOS rapidly turning off all 4 magnets.
ControlStepperLogging(m_deferredStepperAddress, m_deferredStepperCumulativeCycles);
ControlStepperLogging(address, g_nCumulativeCycles);
return;
}
else // adjacent magnets turned on
{
// take no action - can't find any titles that ever do this!
const std::string msg = "Disk: ControlStepper() - adjacent magnets turned on\n";
LogOutput("%s", msg.c_str());
LogFileOutput("%s", msg.c_str());
}
}
// complete the deferred stepper event
// eg. Glutton, EDD III - both just combinations of turning off all 4 magnets
ControlStepperDeferred();
}
// defer the effect of changing the phase
m_deferredStepperAddress = address;
m_deferredStepperCumulativeCycles = g_nCumulativeCycles;
InsertSyncEvent();
m_deferredStepperEvent = true;
}
void Disk2InterfaceCard::InsertSyncEvent(void)
{
m_syncEvent.m_cyclesRemaining = 10; // NB. same cycle delay for magnet off and on - but perhaps they take different times?
g_SynchronousEventMgr.Insert(&m_syncEvent);
}
int Disk2InterfaceCard::SyncEventCallback(int id, int cycles, ULONG uExecutedCycles)
{
Disk2InterfaceCard& disk2Card = dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(id));
disk2Card.ControlStepperDeferred();
return 0; // Don't repeat event
}
void Disk2InterfaceCard::ControlStepperDeferred(void)
{
m_deferredStepperEvent = false;
const WORD address = m_deferredStepperAddress;
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
FloppyDisk* pFloppy = &pDrive->m_disk;
// check for any stepping effect from a magnet
// - move only when the magnet opposite the cog is off
// - move in the direction of an adjacent magnet if one is on
// - do not move if both adjacent magnets are on (ie. quarter track)
// momentum and timing are not accounted for ... maybe one day!
// - timing is accounted for in the case when "two phases [are] turned off in rapid sequence" (UTAIIe page 9-13) (GH#1110)
// momentum is not accounted for ... maybe one day!
int direction = 0;
if (m_magnetStates & (1 << ((pDrive->m_phase + 1) & 3)))
direction += 1;
@ -536,9 +628,21 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
GetFrame().FrameDrawDiskStatus(); // Show track status (GH#201)
}
ControlStepperLogging(address, m_deferredStepperCumulativeCycles);
}
void Disk2InterfaceCard::ControlStepperLogging(WORD address, unsigned __int64 cumulativeCycles)
{
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
#if LOG_DISK_PHASES
const ULONG cycleDelta = (ULONG)(cumulativeCycles - pDrive->m_lastStepperCycle);
#endif
pDrive->m_lastStepperCycle = cumulativeCycles; // NB. Persisted to save-state
#if LOG_DISK_PHASES
LOG_DISK("%08X: track $%s magnet-states %d%d%d%d phase %d %s address $%4X last-stepper %.3fms\r\n",
(UINT32)g_nCumulativeCycles,
(UINT32)cumulativeCycles,
GetCurrentTrackString().c_str(),
(m_magnetStates >> 3) & 1,
(m_magnetStates >> 2) & 1,
@ -547,7 +651,7 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
(address >> 1) & 3, // phase
(address & 1) ? "on " : "off",
address,
((float)cycleDelta)/(CLK_6502_NTSC/1000.0));
((float)cycleDelta) / (CLK_6502_NTSC / 1000.0));
#endif
}
@ -1035,7 +1139,6 @@ void Disk2InterfaceCard::ResetLogicStateSequencer(void)
{
m_shiftReg = 0;
m_latchDelay = 0;
m_resetSequencer = true;
m_writeStarted = false;
m_dbgLatchDelayedCnt = 0;
@ -1087,8 +1190,6 @@ void Disk2InterfaceCard::UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG
floppy.m_bitOffset %= floppy.m_bitCount;
UpdateBitStreamOffsets(floppy);
m_resetSequencer = false;
}
void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
@ -1114,6 +1215,9 @@ __forceinline void Disk2InterfaceCard::IncBitStream(FloppyDisk& floppy)
floppy.m_bitOffset = 0;
floppy.m_byte = 0;
}
if (floppy.m_bitOffset == floppy.m_initialBitOffset)
floppy.m_revs++;
}
void Disk2InterfaceCard::PreJitterCheck(int phase, BYTE latch)
@ -1158,6 +1262,29 @@ void Disk2InterfaceCard::AddJitter(int phase, FloppyDisk& floppy)
m_foundT00S00Pattern = false;
}
// GH#1125: For T$21 (track 33.0) or above (and sufficiently long sync FF/10 run-length), then randomly skip 1 bit-cell at the start of the FF/2 track seam.
// Example of high sync FF/10 run-lengths for tracks 33.0+:
// . Accolade Comics:114, Silent Service:117, Wings of Fury:140, Wizardry I:127, Wizardry III:283
// NB. Restrict to higher FF/10 run-lengths to limit the titles affected by this jitter.
void Disk2InterfaceCard::AddTrackSeamJitter(float phasePrecise, FloppyDisk& floppy)
{
if (phasePrecise >= (33.0 * 2) && floppy.m_longestSyncFFRunLength > 110)
{
if (floppy.m_bitOffset == floppy.m_longestSyncFFBitOffsetStart)
{
if (rand() < RAND_THRESHOLD(5, 10))
{
LogOutput("Disk: T%05.2f jitter - slip 1 bitcell (revs=%d) (PC=%04X)\n", phasePrecise / 2, floppy.m_revs, regs.pc);
IncBitStream(floppy);
}
else
{
LogOutput("Disk: T%05.2f jitter - *** SKIP *** (revs=%d) (PC=%04X)\n", phasePrecise / 2, floppy.m_revs, regs.pc);
}
}
}
}
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles)
{
_ASSERT(m_seqFunc.function != dataShiftWrite);
@ -1166,7 +1293,11 @@ void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYT
FloppyDisk& floppy = drive.m_disk;
if (!floppy.m_trackimagedata && floppy.m_imagehandle)
{
ReadTrack(m_currDrive, uExecutedCycles);
// NB. ReadTrack() has called GetBitCellDelta(), so the subsequent call to GetBitCellDelta() below just returns bitCellDelta==0
// So could just return at this point.
}
if (!floppy.m_trackimagedata)
{
@ -1260,13 +1391,7 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
IncBitStream(floppy);
if (m_resetSequencer)
{
m_resetSequencer = false; // LSS takes some cycles to reset (ref?)
continue;
}
//
AddTrackSeamJitter(drive.m_phasePrecise, floppy);
m_shiftReg <<= 1;
m_shiftReg |= outputBit;
@ -1354,6 +1479,8 @@ void Disk2InterfaceCard::DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemain
LOG_DISK("load shiftReg with %02X (was: %02X)\n", m_floppyLatch, m_shiftReg);
#endif
m_shiftReg = m_floppyLatch;
floppy.m_longestSyncFFBitOffsetStart = -1; // invalidate the track seam location after a write
}
void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles)
@ -1372,6 +1499,12 @@ void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCy
return;
}
if (!drive.m_spinning)
return;
if (!floppy.m_trackimagedata) // GH#1126
return;
#if LOG_DISK_WOZ_SHIFTWRITE
LOG_DISK("T$%02X, bitOffset=%04X: %02X (%d bits)\n", drive.m_phase/2, floppy.m_bitOffset, m_shiftReg, bitCellRemainder);
#endif
@ -1394,6 +1527,107 @@ void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCy
//===========================================================================
// For now all that's needed is this basic case:
// . find [start,end] of longest run of FF/10 sync nibbles
void Disk2InterfaceCard::FindTrackSeamWOZ(FloppyDisk& floppy, float track)
{
const UINT oldBitOffset = floppy.m_bitOffset; // Save current state
BYTE shiftReg = 0;
UINT zeroCount = 0;
int startBitOffset = -1; // NB. change this to start of first FF/10
floppy.m_bitOffset = 0;
UpdateBitStreamOffsets(floppy);
int nibbleStartBitOffset = -1;
int syncFFStartBitOffset = -1;
int syncFFRunLength = 0;
int longestSyncFFStartBitOffset = -1;
int longestSyncFFRunLength = 0;
floppy.m_longestSyncFFBitOffsetStart = -1;
while (1)
{
BYTE n = floppy.m_trackimage[floppy.m_byte];
BYTE outputBit = (n & floppy.m_bitMask) ? 1 : 0;
IncBitStream(floppy);
if ((startBitOffset < 0 && floppy.m_bitOffset == 0) || (startBitOffset == floppy.m_bitOffset)) // done complete track?
break;
if (shiftReg & 0x80)
{
if (outputBit == 0) // zero, so LSS holds nibble in latch
{
zeroCount++;
continue;
}
// else: start of next nibble
if (shiftReg == 0xff && zeroCount == 2)
{
if (syncFFStartBitOffset < 0)
syncFFStartBitOffset = nibbleStartBitOffset;
syncFFRunLength++;
}
if ((shiftReg != 0xff || zeroCount != 2) && syncFFStartBitOffset >= 0)
{
// Longest FF/2 run could straddle end/start of track's bit buffer
if (startBitOffset < 0)
startBitOffset = nibbleStartBitOffset;
if (longestSyncFFRunLength < syncFFRunLength)
{
longestSyncFFStartBitOffset = syncFFStartBitOffset;
longestSyncFFRunLength = syncFFRunLength;
}
syncFFStartBitOffset = -1;
syncFFRunLength = 0;
}
shiftReg = 0;
zeroCount = 0;
}
shiftReg <<= 1;
shiftReg |= outputBit;
if (shiftReg == 0x01)
{
nibbleStartBitOffset = floppy.m_bitOffset - 1;
if (nibbleStartBitOffset < 0) nibbleStartBitOffset += floppy.m_bitCount;
}
}
if (longestSyncFFRunLength)
{
const int longestSyncFFBitOffsetEnd = (longestSyncFFStartBitOffset + longestSyncFFRunLength * 10 - 1) % floppy.m_bitCount;
#if LOG_DISK_WOZ_TRACK_SEAM
LOG_DISK("Track seam: T%05.2f: FF/10 (run=%d), start=%04X, end=%04X\n", track, longestSyncFFRunLength, longestSyncFFStartBitOffset, longestSyncFFBitOffsetEnd);
#endif
floppy.m_longestSyncFFBitOffsetStart = longestSyncFFStartBitOffset;
floppy.m_longestSyncFFRunLength = longestSyncFFRunLength;
}
else
{
#if LOG_DISK_WOZ_TRACK_SEAM
LOG_DISK("Track seam: T%05.2f: FF/10 (none)\n", track);
#endif
}
// Restore state
floppy.m_bitOffset = oldBitOffset;
UpdateBitStreamOffsets(floppy);
}
//===========================================================================
#ifdef _DEBUG
// Dump nibbles from current position bitstream wraps to same position
// NB. Need to define LOG_DISK_NIBBLES_READ so that GetReadD5AAxxDetectedString() works.
@ -1405,21 +1639,22 @@ void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_flo
UINT zeroCount = 0;
UINT nibbleCount = 0;
const UINT startBitOffset = 0; // NB. may need to tweak this offset, since the bistream is a circular buffer
const UINT startBitOffset = 0; // NB. may need to tweak this offset, since the bitstream is a circular buffer
floppy.m_bitOffset = startBitOffset;
UpdateBitStreamOffsets(floppy);
floppy.m_byte = floppy.m_bitOffset / 8;
const UINT remainder = 7 - (floppy.m_bitOffset & 7);
floppy.m_bitMask = 1 << remainder;
int nibbleStartBitOffset = -1;
bool newLine = true;
bool doneLastBit = false;
while (1)
{
if (newLine)
if (newLine && nibbleStartBitOffset >= 0)
{
newLine = false;
LogOutput("%04X:", floppy.m_bitOffset & 0xffff);
LogOutput("%04X:", nibbleStartBitOffset);
nibbleStartBitOffset = -1;
}
BYTE n = floppy.m_trackimage[floppy.m_byte];
@ -1428,53 +1663,67 @@ void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_flo
IncBitStream(floppy);
if (startBitOffset == floppy.m_bitOffset) // done complete track?
doneLastBit = true;
else if (doneLastBit)
break;
if (shiftReg == 0 && outputBit == 0)
if (shiftReg & 0x80)
{
zeroCount++;
continue;
if (outputBit == 0) // zero, so LSS holds nibble in latch
{
zeroCount++;
continue;
}
// else: start of next nibble
nibbleCount++;
char syncBits = zeroCount <= 9 ? '0' + zeroCount : '+';
if (zeroCount == 0) LogOutput("%02X ", shiftReg);
else LogOutput("%02X(%c)", shiftReg, syncBits);
formatTrack.DecodeLatchNibbleRead(shiftReg);
if ((nibbleCount % 32) == 0)
{
std::string strReadDetected = formatTrack.GetReadD5AAxxDetectedString();
if (!strReadDetected.empty())
{
OutputDebugString("\t; ");
OutputDebugString(strReadDetected.c_str());
}
OutputDebugString("\n");
newLine = true;
}
shiftReg = 0;
zeroCount = 0;
}
shiftReg <<= 1;
shiftReg |= outputBit;
if ((shiftReg & 0x80) == 0)
continue;
nibbleCount++;
char syncBits = zeroCount <= 9 ? '0'+zeroCount : '+';
if (zeroCount == 0) LogOutput(" %02X", shiftReg);
else LogOutput("(%c)%02X", syncBits, shiftReg);
formatTrack.DecodeLatchNibbleRead(shiftReg);
if ((nibbleCount % 32) == 0)
if (shiftReg == 0x01)
{
std::string strReadDetected = formatTrack.GetReadD5AAxxDetectedString();
if (!strReadDetected.empty())
{
OutputDebugString("\t; ");
OutputDebugString(strReadDetected.c_str());
}
OutputDebugString("\n");
newLine = true;
nibbleStartBitOffset = floppy.m_bitOffset - 1;
if (nibbleStartBitOffset < 0) nibbleStartBitOffset += floppy.m_bitCount;
}
shiftReg = 0;
zeroCount = 0;
}
// Output any remaining zeroCount
if (zeroCount)
{
char syncBits = zeroCount <= 9 ? '0'+zeroCount : '+';
LogOutput("(%c)", syncBits);
}
// Output any partial nibble
if (shiftReg)
if (shiftReg & 0x80)
{
LogOutput("%02X", shiftReg);
// Output any remaining zeroCount
if (zeroCount)
{
char syncBits = zeroCount <= 9 ? '0' + zeroCount : '+';
LogOutput("(%c)", syncBits);
}
}
else if (shiftReg)
{
LogOutput("%02X/Partial Nibble", shiftReg);
}
@ -1587,10 +1836,6 @@ bool Disk2InterfaceCard::UserSelectNewDiskImage(const int drive, LPCSTR pszFilen
void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG uExecutedCycles)
{
// NB. Only reads in LOAD mode can issue the SR (shift write-protect) operation - UTAIIe page 9-20, fig 9.11
// But STA $C08D,X (no PX) does a read from $C08D+X, followed by the write to $C08D+X
// So just want to ignore: STA $C0ED or eg. STA $BFFF,X (PX, X=$EE)
// Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
// "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
// Note: Gemstone Warrior sets load mode with the drive off.
@ -1598,17 +1843,19 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE
return;
// Notes:
// . Only READ-LOAD mode ($C08E,X & $C08D,X) can issue the SR (shift write-protect) operation - UTAIIe page 9-20, fig 9.11
// . Phase 1 on also forces write protect in the Disk II drive (UTAIIe page 9-7) but we don't implement that.
// . write mode doesn't prevent reading write protect (GH#537):
// "If for some reason the above write protect check were entered with the READ/WRITE switch in WRITE,
// the write protect switch would still be read correctly" (UTAIIe page 9-21)
// . Sequencer "SR" (Shift Right) command only loads QA (bit7) of data register (UTAIIe page 9-21)
// . Sequencer "SR" (Shift Right) command shifts the data register right and loads QA (bit7) with write protect (UTAIIe page 9-21)
// . A read or write will shift 'write protect' in QA.
// . The LSS saturates the data register before the CPU can read an intermediate value: so set to 0xFF or 0x00 (GH#1078)
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
if (floppy.m_bWriteProtected)
m_floppyLatch |= 0x80;
m_floppyLatch = 0xFF;
else
m_floppyLatch &= 0x7F;
m_floppyLatch = 0x00;
if (m_writeStarted) // Prevent ResetLogicStateSequencer() from resetting m_writeStarted
return;
@ -1622,9 +1869,7 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE
const UINT bitCellDelta = GetBitCellDelta(uExecutedCycles);
UpdateBitStreamPosition(floppy, bitCellDelta); // Fix E7-copy protection
// UpdateBitStreamPosition() must be done before ResetLSS, as the former clears m_resetSequencer (and the latter sets it).
// . Commando.woz is sensitive to this. EG. It can crash after pressing 'J' (1 failure in 20 reboot repeats)
ResetLogicStateSequencer(); // reset sequencer (UTAIIe page 9-21)
ResetLogicStateSequencer(); // "Set the sequencer to State 0" (UTAIIe page 9-21)
}
}
@ -1765,7 +2010,10 @@ void Disk2InterfaceCard::InitFirmware(LPBYTE pCxRomPeripheral)
ImageInfo* pImage = m_floppyDrive[DRIVE_1].m_disk.m_imagehandle;
m_is13SectorFirmware = ImageIsBootSectorFormatSector13(pImage);
if (m_force13SectorFirmware)
m_is13SectorFirmware = true;
else
m_is13SectorFirmware = ImageIsBootSectorFormatSector13(pImage);
if (m_is13SectorFirmware)
memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, m_13SectorFirmware, DISK2_FW_SIZE);
@ -1795,21 +2043,35 @@ void Disk2InterfaceCard::InitializeIO(LPBYTE pCxRomPeripheral)
//===========================================================================
void Disk2InterfaceCard::SetSequencerFunction(WORD addr)
void Disk2InterfaceCard::SetSequencerFunction(WORD addr, ULONG executedCycles)
{
if ((addr & 0xf) < 0xc)
return;
const SEQFUNC oldSeqFunc = m_seqFunc.function;
switch ((addr & 3) ^ 2)
{
case 0: m_seqFunc.writeMode = 0; break; // $C08E,X (sequence addr A2 input)
case 1: m_seqFunc.writeMode = 1; break; // $C08F,X (sequence addr A2 input)
case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A3 input)
case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A3 input)
case 0: m_seqFunc.writeMode = 0; break; // $C08E,X (sequence addr A3 input)
case 1: m_seqFunc.writeMode = 1; break; // $C08F,X (sequence addr A3 input)
case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A2 input)
case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A2 input)
}
if (!m_seqFunc.writeMode)
m_writeStarted = false;
if (oldSeqFunc == checkWriteProtAndInitWrite && m_seqFunc.function != checkWriteProtAndInitWrite)
{
// Use up remaining cycles before switching out of "checkWriteProtAndInitWrite" mode
// Done when checking write-protect, but also for bit-slip (eg. E7) copy-protections
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
if (ImageIsWOZ(floppy.m_imagehandle))
{
const UINT bitCellDelta = GetBitCellDelta(executedCycles);
UpdateBitStreamPosition(floppy, bitCellDelta);
}
}
}
BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
@ -1825,7 +2087,7 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE
if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite) // Occurs at end of sector write ($C0EE)
pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write
pCard->SetSequencerFunction(addr);
pCard->SetSequencerFunction(addr, nExecutedCycles);
switch (addr & 0xF)
{
@ -1872,7 +2134,7 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite)
pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write
pCard->SetSequencerFunction(addr);
pCard->SetSequencerFunction(addr, nExecutedCycles);
switch (addr & 0xF)
{
@ -1915,13 +2177,15 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
// Split up 'Unit' putting some state into a new 'Floppy'
// 5: Added: Sequencer Function
// 6: Added: Drive Connected & Motor On Cycle
static const UINT kUNIT_VERSION = 6;
// 7: Deprecated SS_YAML_KEY_LSS_RESET_SEQUENCER, SS_YAML_KEY_DISK_ACCESSED
// 8: Added: deferred stepper: event, address & cycle
static const UINT kUNIT_VERSION = 8;
#define SS_YAML_VALUE_CARD_DISK2 "Disk]["
#define SS_YAML_KEY_PHASES "Phases"
#define SS_YAML_KEY_CURRENT_DRIVE "Current Drive"
#define SS_YAML_KEY_DISK_ACCESSED "Disk Accessed"
#define SS_YAML_KEY_DISK_ACCESSED "Disk Accessed" // deprecated at v7
#define SS_YAML_KEY_ENHANCE_DISK "Enhance Disk"
#define SS_YAML_KEY_FLOPPY_LATCH "Floppy Latch"
#define SS_YAML_KEY_FLOPPY_MOTOR_ON "Floppy Motor On"
@ -1930,8 +2194,11 @@ static const UINT kUNIT_VERSION = 6;
#define SS_YAML_KEY_LAST_READ_LATCH_CYCLE "Last Read Latch Cycle"
#define SS_YAML_KEY_LSS_SHIFT_REG "LSS Shift Reg"
#define SS_YAML_KEY_LSS_LATCH_DELAY "LSS Latch Delay"
#define SS_YAML_KEY_LSS_RESET_SEQUENCER "LSS Reset Sequencer"
#define SS_YAML_KEY_LSS_RESET_SEQUENCER "LSS Reset Sequencer" // deprecated at v7
#define SS_YAML_KEY_LSS_SEQUENCER_FUNCTION "LSS Sequencer Function"
#define SS_YAML_KEY_DEFERRED_STEPPER_EVENT "Deferred Stepper Event"
#define SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS "Deferred Stepper Address"
#define SS_YAML_KEY_DEFERRED_STEPPER_CYCLE "Deferred Stepper Cycle"
#define SS_YAML_KEY_DISK2UNIT "Unit"
#define SS_YAML_KEY_DRIVE_CONNECTED "Drive Connected"
@ -2004,7 +2271,6 @@ void Disk2InterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveUint(SS_YAML_KEY_CURRENT_DRIVE, m_currDrive);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_PHASES, m_magnetStates);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DISK_ACCESSED, false); // deprecated
yamlSaveHelper.SaveBool(SS_YAML_KEY_ENHANCE_DISK, m_enhanceDisk);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_FLOPPY_LATCH, m_floppyLatch);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_MOTOR_ON, m_floppyMotorOn == TRUE);
@ -2012,8 +2278,10 @@ void Disk2InterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE, m_diskLastReadLatchCycle); // v3
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LSS_SHIFT_REG, m_shiftReg); // v4
yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_LATCH_DELAY, m_latchDelay); // v4
yamlSaveHelper.SaveBool(SS_YAML_KEY_LSS_RESET_SEQUENCER, m_resetSequencer); // v4
yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_SEQUENCER_FUNCTION, m_seqFunc.function); // v5
yamlSaveHelper.SaveBool(SS_YAML_KEY_DEFERRED_STEPPER_EVENT, m_deferredStepperEvent); // v8
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS, m_deferredStepperAddress); // v8
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_DEFERRED_STEPPER_CYCLE, m_deferredStepperCumulativeCycles); // v8
m_formatTrack.SaveSnapshot(yamlSaveHelper); // v2
SaveSnapshotDriveUnit(yamlSaveHelper, DRIVE_1);
@ -2170,7 +2438,6 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
m_currDrive = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_DRIVE);
m_magnetStates = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASES);
(void) yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED); // deprecated - but retrieve the value to avoid the "State: Unknown key (Disk Accessed)" warning
m_enhanceDisk = yamlLoadHelper.LoadBool(SS_YAML_KEY_ENHANCE_DISK);
m_floppyLatch = yamlLoadHelper.LoadUint(SS_YAML_KEY_FLOPPY_LATCH);
m_floppyMotorOn = yamlLoadHelper.LoadBool(SS_YAML_KEY_FLOPPY_MOTOR_ON);
@ -2190,7 +2457,11 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
{
m_shiftReg = yamlLoadHelper.LoadUint(SS_YAML_KEY_LSS_SHIFT_REG) & 0xff;
m_latchDelay = yamlLoadHelper.LoadInt(SS_YAML_KEY_LSS_LATCH_DELAY);
m_resetSequencer = yamlLoadHelper.LoadBool(SS_YAML_KEY_LSS_RESET_SEQUENCER);
}
if (version >= 4 && version <= 6)
{
(void) yamlLoadHelper.LoadBool(SS_YAML_KEY_LSS_RESET_SEQUENCER); // deprecated
}
if (version >= 5)
@ -2203,6 +2474,18 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
m_seqFunc.loadMode = 0; // Wasn't saved until v5
}
if (version <= 6)
{
(void) yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED); // deprecated - but retrieve the value to avoid the "State: Unknown key (Disk Accessed)" warning
}
if (version >= 8)
{
m_deferredStepperEvent = yamlLoadHelper.LoadBool(SS_YAML_KEY_DEFERRED_STEPPER_EVENT);
m_deferredStepperAddress = yamlLoadHelper.LoadUint(SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS);
m_deferredStepperCumulativeCycles = yamlLoadHelper.LoadUint64(SS_YAML_KEY_DEFERRED_STEPPER_CYCLE);
}
// Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
for (UINT i=0; i<NUM_DRIVES; i++)
{
@ -2215,5 +2498,8 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS);
if (m_deferredStepperEvent)
InsertSyncEvent();
return true;
}

View File

@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "DiskLog.h"
#include "DiskFormatTrack.h"
#include "DiskImage.h"
#include "SynchronousEventManager.h"
enum Drive_e
{
@ -67,6 +68,10 @@ public:
m_trackimage = NULL;
m_trackimagedata = false;
m_trackimagedirty = false;
m_longestSyncFFRunLength = 0;
m_longestSyncFFBitOffsetStart = -1;
m_initialBitOffset = 0;
m_revs = 0;
}
public:
@ -84,6 +89,10 @@ public:
LPBYTE m_trackimage;
bool m_trackimagedata;
bool m_trackimagedirty;
UINT m_longestSyncFFRunLength;
int m_longestSyncFFBitOffsetStart;
UINT m_initialBitOffset; // debug
UINT m_revs; // debug
};
class FloppyDrive
@ -154,17 +163,18 @@ public:
int GetCurrentDrive(void);
int GetCurrentTrack(void);
float GetCurrentPhase(void);
int GetCurrentOffset(void);
BYTE GetCurrentLSSBitMask(void);
UINT GetCurrentBitOffset(void);
double GetCurrentExtraCycles(void);
float GetPhase(const int drive);
int GetTrack(const int drive);
static std::string FormatPhaseString(float phase);
static std::string FormatIntFracString(float phase, bool hex);
std::string GetCurrentTrackString(void);
std::string GetCurrentPhaseString(void);
LPCTSTR GetCurrentState(void);
bool UserSelectNewDiskImage(const int drive, LPCSTR pszFilename="");
bool DriveSwap(void);
bool IsDriveConnected(int drive) { return m_floppyDrive[drive].m_isConnected; }
void SetFirmware13Sector(void) { m_force13SectorFirmware = true; }
static const std::string& GetSnapshotCardName(void);
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
@ -201,14 +211,20 @@ private:
void DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
void DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
void DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles);
void SetSequencerFunction(WORD addr);
void SetSequencerFunction(WORD addr, ULONG executedCycles);
void FindTrackSeamWOZ(FloppyDisk& floppy, float track);
void DumpTrackWOZ(FloppyDisk floppy);
bool GetFirmware(WORD lpNameId, BYTE* pDst);
void InitFirmware(LPBYTE pCxRomPeripheral);
void UpdateLatchForEmptyDrive(FloppyDrive* pDrive);
void InsertSyncEvent(void);
static int SyncEventCallback(int id, int cycles, ULONG uExecutedCycles);
void ControlStepperDeferred(void);
void ControlStepperLogging(WORD address, unsigned __int64 cumulativeCycles);
void PreJitterCheck(int phase, BYTE latch);
void AddJitter(int phase, FloppyDisk& floppy);
void AddTrackSeamJitter(float phasePrecise, FloppyDisk& floppy);
void SaveSnapshotFloppy(YamlSaveHelper& yamlSaveHelper, UINT unit);
void SaveSnapshotDriveUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
@ -236,6 +252,7 @@ private:
BYTE m_13SectorFirmware[DISK2_FW_SIZE];
BYTE m_16SectorFirmware[DISK2_FW_SIZE];
bool m_is13SectorFirmware;
bool m_force13SectorFirmware;
WORD m_currDrive;
FloppyDrive m_floppyDrive[NUM_DRIVES];
@ -259,7 +276,6 @@ private:
// Logic State Sequencer (for WOZ):
BYTE m_shiftReg;
int m_latchDelay;
bool m_resetSequencer;
bool m_writeStarted;
enum SEQFUNC {readSequencing=0, dataShiftWrite, checkWriteProtAndInitWrite, dataLoadWrite}; // UTAIIe 9-14
@ -276,6 +292,11 @@ private:
SEQUENCER_FUNCTION m_seqFunc;
UINT m_dbgLatchDelayedCnt;
bool m_deferredStepperEvent;
WORD m_deferredStepperAddress;
unsigned __int64 m_deferredStepperCumulativeCycles;
SyncEvent m_syncEvent;
// Jitter (GH#930)
static const BYTE m_T00S00Pattern[];
UINT m_T00S00PatternIdx;

View File

@ -139,3 +139,8 @@ void Disk2CardManager::GetFilenameAndPathForSaveState(std::string& filename, std
}
}
}
void Disk2CardManager::SetStepperDefer(bool defer)
{
m_stepperDeferred = defer;
}

View File

@ -3,7 +3,7 @@
class Disk2CardManager
{
public:
Disk2CardManager(void) {}
Disk2CardManager(void) : m_stepperDeferred(true) {}
~Disk2CardManager(void) {}
bool IsConditionForFullSpeed(void);
@ -15,4 +15,9 @@ public:
void Destroy(void);
bool IsAnyFirmware13Sector(void);
void GetFilenameAndPathForSaveState(std::string& filename, std::string& path);
void SetStepperDefer(bool defer);
bool IsStepperDeferred(void) { return m_stepperDeferred; }
private:
bool m_stepperDeferred; // debug: can disable via cmd-line
};

View File

@ -273,7 +273,7 @@ void FormatTrack::DecodeLatchNibble(BYTE floppylatch, bool bIsWrite, bool bIsSyn
addrPrologue, m_VolTrkSecChk[0], m_VolTrkSecChk[1], m_VolTrkSecChk[2], m_VolTrkSecChk[3], chk?"":"(bad)");
if (!m_bSuppressReadD5AAxxDetected)
{
LOG_DISK("%s\r\n", str);
LOG_DISK("%s\r\n", m_strReadD5AAxxDetected.c_str());
}
}
#endif

View File

@ -14,6 +14,8 @@
#define LOG_DISK_NIBBLES_USE_RUNTIME_VAR 1
#define LOG_DISK_WOZ_LOADWRITE 1
#define LOG_DISK_WOZ_SHIFTWRITE 1
#define LOG_DISK_WOZ_READTRACK 1
#define LOG_DISK_WOZ_TRACK_SEAM 1
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
#if (LOG_DISK_ENABLED)

View File

@ -28,6 +28,7 @@ public:
virtual void FrameSetCursorPosByMousePos() = 0;
virtual void SetFullScreenShowSubunitStatus(bool bShow) = 0;
virtual void SetWindowedModeShowDiskiiStatus(bool bShow) = 0;
virtual bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedWidth=0, UINT userSpecifiedHeight=0) = 0;
virtual int SetViewportScale(int nNewScale, bool bForce = false) = 0;
virtual void SetAltEnterToggleFullScreen(bool mode) = 0;
@ -45,7 +46,7 @@ public:
// create the network backed for Uthernet 1 and 2
// useful to use libslirp in Linux
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend() = 0;
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend(const std::string & interfaceName) = 0;
// FindResource, MAKEINTRESOURCE, SizeofResource, LoadResource, LockResource
// Return pointer to resource if size is correct.

View File

@ -143,19 +143,12 @@ HarddiskInterfaceCard::HarddiskInterfaceCard(UINT slot) :
m_notBusyCycle = 0;
m_saveDiskImage = true; // Save the DiskImage name to Registry
// if created by user in Config->Disk, then MemInitializeIO() won't be called
if (GetCxRomPeripheral())
InitializeIO(GetCxRomPeripheral()); // During regular start-up, Initialize() will be called later by MemInitializeIO()
}
HarddiskInterfaceCard::~HarddiskInterfaceCard(void)
{
CleanupDriveInternal(HARDDISK_1);
CleanupDriveInternal(HARDDISK_2);
// if destroyed by user in Config->Disk, then ensure that old object's reference is removed
UnregisterIoHandler(m_slot);
}
void HarddiskInterfaceCard::Reset(const bool powerCycle)
@ -469,6 +462,7 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
CpuCalcCycles(nExecutedCycles);
const UINT CYCLES_FOR_DMA_RW_BLOCK = HD_BLOCK_SIZE;
const UINT PAGE_SIZE = 256;
BYTE r = DEVICE_OK;
pHDD->m_status_next = DISK_STATUS_READ;
@ -493,17 +487,15 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
case 0x01: //read
if ((pHDD->m_diskblock * HD_BLOCK_SIZE) < ImageGetImageSize(pHDD->m_imagehandle))
{
bool breakpointHit = false;
bool bRes = ImageReadBlock(pHDD->m_imagehandle, pHDD->m_diskblock, pHDD->m_buf);
if (bRes)
{
pHDD->m_error = 0;
r = 0;
pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK;
pHDD->m_buf_ptr = 0;
// Apple II's MMU could be setup so that read & write memory is different,
// so can't use 'mem' (like we can for HDD block writes)
const UINT PAGE_SIZE = 256;
WORD dstAddr = pHDD->m_memblock;
UINT remaining = HD_BLOCK_SIZE;
BYTE* pSrc = pHDD->m_buf;
@ -518,7 +510,6 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
DebuggerBreakOnDmaToOrFromIoMemory(dstAddr, true); // GH#1007
//else // Show MessageBox?
pCard->m_notBusyCycle = 0; // DMA complete
bRes = false;
break;
}
@ -527,15 +518,26 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
UINT size = PAGE_SIZE - (dstAddr & 0xff);
if (size > remaining) size = remaining; // clip the last memcpy for the unaligned case
if (g_nAppMode == MODE_STEPPING)
breakpointHit = DebuggerCheckMemBreakpoints(dstAddr, size, true); // GH#1103
memcpy(page + (dstAddr & 0xff), pSrc, size);
pSrc += size;
dstAddr += size;
dstAddr = (dstAddr + size) & (MEMORY_LENGTH-1); // wraps at 64KiB boundary
remaining -= size;
}
}
if (!bRes)
if (bRes)
{
pHDD->m_error = 0;
r = 0;
if (!breakpointHit)
pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK;
}
else
{
pHDD->m_error = 1;
r = DEVICE_IO_ERROR;
@ -552,6 +554,7 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
pHDD->m_status_next = DISK_STATUS_WRITE; // or DISK_STATUS_PROT if we ever enable write-protect on HDD
bool bRes = true;
const bool bAppendBlocks = (pHDD->m_diskblock * HD_BLOCK_SIZE) >= ImageGetImageSize(pHDD->m_imagehandle);
bool breakpointHit = false;
if (bAppendBlocks)
{
@ -578,20 +581,28 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
DebuggerBreakOnDmaToOrFromIoMemory(dstAddr, false);
//else // Show MessageBox?
pCard->m_notBusyCycle = 0; // DMA complete
bRes = false;
}
else
{
if (pHDD->m_memblock <= (MEMORY_LENGTH - HD_BLOCK_SIZE))
// NB. Do the writes in units of PAGE_SIZE so that DMA breakpoints are consistent with reads
WORD srcAddr = pHDD->m_memblock;
UINT remaining = HD_BLOCK_SIZE;
BYTE* pDst = pHDD->m_buf;
while (remaining)
{
memcpy(pHDD->m_buf, mem + pHDD->m_memblock, HD_BLOCK_SIZE);
}
else // wraps on 64KiB boundary (GH#1007)
{
const UINT size = MEMORY_LENGTH - pHDD->m_memblock;
memcpy(pHDD->m_buf, mem + pHDD->m_memblock, size);
memcpy(pHDD->m_buf + size, mem, HD_BLOCK_SIZE - size);
UINT size = PAGE_SIZE - (srcAddr & 0xff);
if (size > remaining) size = remaining; // clip the last memcpy for the unaligned case
if (g_nAppMode == MODE_STEPPING)
breakpointHit = DebuggerCheckMemBreakpoints(srcAddr, size, false);
memcpy(pDst, mem + srcAddr, size);
pDst += size;
srcAddr = (srcAddr + size) & (MEMORY_LENGTH - 1); // wraps at 64KiB boundary
remaining -= size;
}
}
@ -602,7 +613,9 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
{
pHDD->m_error = 0;
r = 0;
pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK;
if (!breakpointHit)
pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK;
}
else
{

View File

@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Memory.h"
#include "YamlHelper.h"
#include "Interface.h"
#include "CopyProtectionDongles.h"
#include "Configuration/PropertySheet.h"
@ -576,6 +577,8 @@ BYTE __stdcall JoyReadButton(WORD pc, WORD address, BYTE, BYTE, ULONG nExecutedC
pressed = !swapButtons0and1 ? CheckButton0Pressed() : CheckButton1Pressed();
const UINT button0 = !swapButtons0and1 ? 0 : 1;
DoAutofire(button0, pressed);
if(CopyProtectionDonglePB0() >= 0) //If a copy protection dongle needs PB0, this overrides the joystick
pressed = CopyProtectionDonglePB0();
}
break;
@ -584,11 +587,15 @@ BYTE __stdcall JoyReadButton(WORD pc, WORD address, BYTE, BYTE, ULONG nExecutedC
pressed = !swapButtons0and1 ? CheckButton1Pressed() : CheckButton0Pressed();
const UINT button1 = !swapButtons0and1 ? 1 : 0;
DoAutofire(button1, pressed);
if (CopyProtectionDonglePB1() >= 0) //If a copy protection dongle needs PB1, this overrides the joystick
pressed = CopyProtectionDonglePB1();
}
break;
case 0x63:
if (IS_APPLE2 && (joyinfo[joytype[1]] == DEVICE_NONE))
if (CopyProtectionDonglePB2() >= 0) //If a copy protection dongle needs PB2, this overrides the joystick
pressed = CopyProtectionDonglePB2();
else if (IS_APPLE2 && (joyinfo[joytype[1]] == DEVICE_NONE))
{
// Apple II/II+ with no joystick has the "SHIFT key mod"
// See Sather's Understanding The Apple II p7-36
@ -665,9 +672,9 @@ void JoyResetPosition(ULONG nExecutedCycles)
const UINT joyNum = (pdl & 2) ? 1 : 0;
UINT pdlPos = (pdl & 1) ? ypos[joyNum] : xpos[joyNum];
// This is from KEGS. It helps games like Championship Lode Runner & Boulderdash
// This is from KEGS. It helps games like Championship Lode Runner, Boulderdash & Learning with Leeper(GH#1128)
if (pdlPos >= 255)
pdlPos = 280;
pdlPos = 287;
g_paddleInactiveCycle[pdl] = g_nCumulativeCycles + (UINT64)((double)pdlPos * PDL_CNTR_INTERVAL);
}

View File

@ -443,7 +443,7 @@ bool Saturn128K::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
}
// "Memory Bankxx"
std::string memName = GetSnapshotMemStructName() + StrFormat("%02X", uBank);
std::string memName = GetSnapshotMemStructName() + ByteToHexStr(uBank);
if (!yamlLoadHelper.GetSubMap(memName))
throw std::runtime_error("Memory: Missing map name: " + memName);

View File

@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Tape.h"
#include "RGBMonitor.h"
#include "VidHD.h"
#include "CopyProtectionDongles.h"
#include "z80emu.h"
#include "Z80VICE/z80.h"
@ -744,7 +745,7 @@ inline bool IsPotentialNoSlotClockAccess(const WORD address)
(SW_INTCXROM && (AddrHi == 0xC8)) ); // Internal ROM at [$C100-CFFF] && AddrHi == $C8
}
static bool IsCardInSlot(const UINT uSlot);
static bool IsCardInSlot(UINT slot);
// Enabling expansion ROM ($C800..$CFFF]:
// . Enable if: Enable1 && Enable2
@ -944,7 +945,6 @@ BYTE __stdcall IO_F8xx(WORD programcounter, WORD address, BYTE write, BYTE value
static struct SlotInfo
{
bool bHasCard;
iofunction IOReadCx;
iofunction IOWriteCx;
} g_SlotInfo[NUM_SLOTS] = {0};
@ -977,7 +977,6 @@ static void InitIoHandlers()
for (i=0; i<NUM_SLOTS; i++)
{
g_SlotInfo[i].bHasCard = false;
g_SlotInfo[i].IOReadCx = IO_Cxxx;
g_SlotInfo[i].IOWriteCx = IO_Cxxx;
ExpansionRom[i] = NULL;
@ -990,12 +989,17 @@ void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, io
_ASSERT(uSlot < NUM_SLOTS);
SlotParameters[uSlot] = lpSlotParameter;
if (IOReadC0 == NULL) IOReadC0 = IO_Null;
if (IOWriteC0 == NULL) IOWriteC0 = IO_Null;
IORead[uSlot+8] = IOReadC0;
IOWrite[uSlot+8] = IOWriteC0;
if (uSlot == 0) // Don't trash C0xx handlers
return;
//
if (IOReadCx == NULL) IOReadCx = IO_Cxxx;
if (IOWriteCx == NULL) IOWriteCx = IO_Cxxx;
@ -1005,7 +1009,6 @@ void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, io
IOWrite[uSlot*16+i] = IOWriteCx;
}
g_SlotInfo[uSlot].bHasCard = true;
g_SlotInfo[uSlot].IOReadCx = IOReadCx;
g_SlotInfo[uSlot].IOWriteCx = IOWriteCx;
@ -1016,7 +1019,6 @@ void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, io
void UnregisterIoHandler(UINT uSlot)
{
RegisterIoHandler(uSlot, NULL, NULL, NULL, NULL, NULL, NULL);
g_SlotInfo[uSlot].bHasCard = false;
}
// From UTAIIe:5-28: Since INTCXROM==1 then state of SLOTC3ROM is not important
@ -1024,7 +1026,7 @@ static void IoHandlerCardsOut(void)
{
_ASSERT( SW_INTCXROM );
for (UINT uSlot=1; uSlot<NUM_SLOTS; uSlot++)
for (UINT uSlot=SLOT1; uSlot<NUM_SLOTS; uSlot++)
{
for (UINT i=0; i<16; i++)
{
@ -1034,33 +1036,45 @@ static void IoHandlerCardsOut(void)
}
}
// From UTAIIe:5-28: If INTCXROM==0 && SLOTC3ROM==0 Then $C300-C3FF is internal ROM
static void IoHandlerSlot3CardOut(void)
{
_ASSERT(!SW_INTCXROM && !SW_SLOTC3ROM);
for (UINT i = 0; i < 16; i++)
{
IORead[SLOT3 * 16 + i] = IO_Cxxx;
IOWrite[SLOT3 * 16 + i] = IO_Cxxx;
}
}
static void IoHandlerCardsIn(void)
{
_ASSERT( !SW_INTCXROM );
for (UINT uSlot=1; uSlot<NUM_SLOTS; uSlot++)
for (UINT uSlot=SLOT1; uSlot<NUM_SLOTS; uSlot++)
{
iofunction ioreadcx = g_SlotInfo[uSlot].IOReadCx;
iofunction iowritecx = g_SlotInfo[uSlot].IOWriteCx;
if (uSlot == 3 && !SW_SLOTC3ROM)
if (uSlot == SLOT3 && !SW_SLOTC3ROM)
{
// From UTAIIe:5-28: If INTCXROM==0 && SLOTC3ROM==0 Then $C300-C3FF is internal ROM
ioreadcx = IO_Cxxx;
iowritecx = IO_Cxxx;
IoHandlerSlot3CardOut();
}
for (UINT i=0; i<16; i++)
else
{
IORead[uSlot*16+i] = ioreadcx;
IOWrite[uSlot*16+i] = iowritecx;
iofunction ioreadcx = g_SlotInfo[uSlot].IOReadCx;
iofunction iowritecx = g_SlotInfo[uSlot].IOWriteCx;
for (UINT i = 0; i < 16; i++)
{
IORead[uSlot * 16 + i] = ioreadcx;
IOWrite[uSlot * 16 + i] = iowritecx;
}
}
}
}
static bool IsCardInSlot(const UINT uSlot)
static bool IsCardInSlot(UINT slot)
{
return g_SlotInfo[uSlot].bHasCard;
return GetCardMgr().QuerySlot(slot) != CT_Empty;
}
//===========================================================================
@ -1478,8 +1492,8 @@ bool MemIsAddrCodeMemory(const USHORT addr)
if (addr <= APPLE_SLOT_END) // [$C100..C7FF]
{
const UINT uSlot = (addr >> 8) & 0x7;
return IsCardInSlot(uSlot);
UINT slot = (addr >> 8) & 0x7;
return IsCardInSlot(slot);
}
// [$C800..CFFF]
@ -1744,8 +1758,14 @@ void MemInitializeFromSnapshot(void)
//
// Remove all the cards' ROMs at $Csnn if internal ROM is enabled
if (IsAppleIIeOrAbove(GetApple2Type()) && SW_INTCXROM)
IoHandlerCardsOut();
// Or just $C3nn if SLOT3 ROM is disabled
if (IsAppleIIeOrAbove(GetApple2Type()))
{
if (SW_INTCXROM)
IoHandlerCardsOut();
else if (!SW_SLOTC3ROM)
IoHandlerSlot3CardOut();
}
// Potentially init a card's expansion ROM
const UINT uSlot = g_uPeripheralRomSlot;
@ -2442,7 +2462,7 @@ static void MemLoadSnapshotAuxCommon(YamlLoadHelper& yamlLoadHelper, const std::
}
// "Auxiliary Memory Bankxx"
std::string auxMemName = MemGetSnapshotAuxMemStructName() + StrFormat("%02X", uBank-1);
std::string auxMemName = MemGetSnapshotAuxMemStructName() + ByteToHexStr(uBank-1);
if (!yamlLoadHelper.GetSubMap(auxMemName))
throw std::runtime_error("Memory: Missing map name: " + auxMemName);

View File

@ -546,11 +546,11 @@ BYTE MockingboardCard::IOReadInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nVa
bool bAccessedDevice = (CS & 3) ? true : false;
bool CS_SSI263 = !(nAddr & 0x80) && (nAddr & 0x60); // SSI263 at $Cn2x and/or $Cn4x
bool CS_SSI263 = !(nAddr & 0x10) && (nAddr & 0x60) && !(nAddr & 0x80); // SSI263 at $Cn2x and/or $Cn4x
if (m_phasorMode == PH_Phasor && CS_SSI263) // NB. Mockingboard mode: SSI263.bit7 not readable
{
_ASSERT(!bAccessedDevice);
_ASSERT(!bAccessedDevice); // In Phasor native mode, 6522 & SSI263 are interleaved in $Cn10-$Cn7F card I/O memory
if (nAddr & 0x40) // Primary SSI263
nRes = m_MBSubUnit[1].ssi263.Read(nExecutedCycles); // SSI263 only drives bit7
if (nAddr & 0x20) // Secondary SSI263
@ -650,16 +650,19 @@ BYTE MockingboardCard::IOWriteInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nV
WriteToORB(SY6522_DEVICE_B);
}
bool CS_SSI263 = !(nAddr & 0x80) && (nAddr & 0x60); // SSI263 at $Cn2x and/or $Cn4x
bool CS_SSI263_A = (g_phasorMode == PH_Phasor) ? !(nAddr & 0x80) && (nAddr & 0x40) // SSI263 at $Cn4x, $Cn6x
: nAddr & 0x40; // SSI263 at $Cn4x-Cn7x, $CnCx-CnFx
if ((m_phasorMode == PH_Mockingboard || m_phasorMode == PH_Phasor) && CS_SSI263) // No SSI263 for Echo+
bool CS_SSI263_B = (g_phasorMode == PH_Phasor) ? !(nAddr & 0x80) && (nAddr & 0x20) // SSI263 at $Cn2x, $Cn6x
: nAddr & 0x20; // SSI263 at $Cn2x-Cn3x, $Cn6x-Cn7x, $CnAx-CnBx, $CnEx-CnFx
if (g_phasorMode == PH_Mockingboard || g_phasorMode == PH_Phasor) // No SSI263 for Echo+
{
// NB. Mockingboard mode: writes to $Cn4x/SSI263 also get written to 1st 6522 (have confirmed on real Phasor h/w)
_ASSERT( (m_phasorMode == PH_Mockingboard && (CS==0 || CS==1)) || (m_phasorMode == PH_Phasor && (CS==0)) );
if (nAddr & 0x40) // Primary SSI263
m_MBSubUnit[1].ssi263.Write(nAddr&0x7, nValue); // 2nd 6522 is used for 1st speech chip
if (nAddr & 0x20) // Secondary SSI263
m_MBSubUnit[0].ssi263.Write(nAddr&0x7, nValue); // 1st 6522 is used for 2nd speech chip
if (CS_SSI263_A) // Primary SSI263
g_MB[1].ssi263.Write(nAddr&0x7, nValue); // 2nd 6522 is used for 1st speech chip
if (CS_SSI263_B) // Secondary SSI263
g_MB[0].ssi263.Write(nAddr&0x7, nValue); // 1st 6522 is used for 2nd speech chip
}
return 0;
@ -1015,9 +1018,9 @@ UINT MockingboardCard::AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, BYTE
// 7: Added SS_YAML_KEY_SSI263_REG_ACTIVE_PHONEME to SSI263 sub-unit
// 8: Moved Timer1 & Timer2 active to 6522 sub-unit
// Removed Timer1/Timer2/Speech IRQ Pending
// Changed at AppleWin 1.30.8
// 9: Phasor AY's are swapped (means that AppleWin 1.30.10 and 1.30.11 are wrong)
// Changed at AppleWin 1.30.12
const UINT kUNIT_VERSION = 9;
#define SS_YAML_KEY_MB_UNIT "Unit"
#define SS_YAML_KEY_AY_CURR_REG "AY Current Register"

View File

@ -111,7 +111,7 @@ Etc.
#define MODE_MOUSE_ON (1<<0) // | | | | | | | \--- Mouse off (0) or on (1)
#define MODE_INT_MOVEMENT (1<<1) // | | | | | | \----- Interrupt if mouse is moved
#define MODE_INT_BUTTON (1<<2) // | | | | | \------- Interrupt if button is pressed
#define MODE_INT_VBL (1<<3) // | | | | \--------- Interrupt on VBL
#define MODE_INT_VBL (1<<3) // | | | | \--------- Interrupt on VBL [*1]
#define MODE_RESERVED4 (1<<4) // | | | \----------- Reserved
#define MODE_RESERVED5 (1<<5) // | | \------------- Reserved
#define MODE_RESERVED6 (1<<6) // | \--------------- Reserved
@ -119,6 +119,9 @@ Etc.
#define MODE_INT_ALL STAT_INT_ALL
// [*1] "A mode byte of $08 (mouse off but VBL interrupt on) will generate VBL interrupts."
// Ref. Apple II Technical Notes - Mouse #3: "Mode Byte of the SetMouse Routine"
//===========================================================================
void M6821_Listener_B( void* objTo, BYTE byData )
@ -449,22 +452,26 @@ void CMouseInterface::OnMouseEvent(bool bEventVBL)
{
int byState = 0;
if ( !( m_byMode & MODE_MOUSE_ON ) ) // Mouse Off
return;
if ( m_nX != m_iX || m_nY != m_iY )
{
byState |= STAT_INT_MOVEMENT|STAT_MOVEMENT_SINCE_READMOUSE; // X/Y moved since last READMOUSE | Movement interrupt
m_byState |= STAT_MOVEMENT_SINCE_READMOUSE; // [TC] Used by CopyII+9.1 and ProTERM3.1
}
if ( m_bBtn0 != m_bButtons[0] || m_bBtn1 != m_bButtons[1] )
byState |= STAT_INT_BUTTON; // Button 0/1 interrupt
if ( bEventVBL )
if ((m_byMode & MODE_INT_VBL) && bEventVBL)
byState |= STAT_INT_VBL;
//byState &= m_byMode & 0x2E;
byState &= ((m_byMode & MODE_INT_ALL) | STAT_MOVEMENT_SINCE_READMOUSE); // [TC] Keep "X/Y moved since last READMOUSE" for next MOUSE_READ (Contiki v1.3 uses this)
if (m_byMode & MODE_MOUSE_ON)
{
if (m_nX != m_iX || m_nY != m_iY)
{
byState |= STAT_INT_MOVEMENT | STAT_MOVEMENT_SINCE_READMOUSE; // X/Y moved since last READMOUSE | Movement interrupt
m_byState |= STAT_MOVEMENT_SINCE_READMOUSE; // [TC] Used by CopyII+9.1 and ProTERM3.1
}
if (m_bBtn0 != m_bButtons[0] || m_bBtn1 != m_bButtons[1])
byState |= STAT_INT_BUTTON; // Button 0/1 interrupt
byState &= ((m_byMode & MODE_INT_ALL) | STAT_MOVEMENT_SINCE_READMOUSE); // [TC] Keep "X/Y moved since last READMOUSE" for next MOUSE_READ (Contiki v1.3 uses this)
}
else // if MOUSE OFF then only consider VBL (GH#1138)
{
byState &= STAT_INT_VBL;
}
if ( byState & STAT_INT_ALL )
{

View File

@ -69,8 +69,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Globals (Public) ___________________________________________________
uint16_t g_nVideoClockVert = 0; // 9-bit: VC VB VA V5 V4 V3 V2 V1 V0 = 0 .. 262
uint16_t g_nVideoClockHorz = 0; // 6-bit: H5 H4 H3 H2 H1 H0 = 0 .. 64, 25 >= visible (NB. final hpos is 2 cycles long, so a line is 65 cycles)
static uint16_t g_nVideoClockVert = 0; // 9-bit: VC VB VA V5 V4 V3 V2 V1 V0 = 0 .. 262
static uint16_t g_nVideoClockHorz = 0; // 6-bit: H5 H4 H3 H2 H1 H0 = 0 .. 64, 25 >= visible (NB. final hpos is 2 cycles long, so a line is 65 cycles)
// Globals (Private) __________________________________________________
static int g_nVideoCharSet = 0;
@ -113,7 +113,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static unsigned short (*g_pHorzClockOffset)[VIDEO_SCANNER_MAX_HORZ] = 0;
typedef void (*UpdateScreenFunc_t)(long);
static UpdateScreenFunc_t g_apFuncVideoUpdateScanline[VIDEO_SCANNER_Y_DISPLAY];
static UpdateScreenFunc_t g_pFuncUpdateTextScreen = 0; // updateScreenText40;
static UpdateScreenFunc_t g_pFuncUpdateGraphicsScreen = 0; // updateScreenText40;
static UpdateScreenFunc_t g_pFuncModeSwitchDelayed = 0;
@ -320,8 +319,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INLINE void updatePixels( uint16_t bits );
INLINE void updateVideoScannerHorzEOL();
INLINE void updateVideoScannerAddress();
INLINE uint16_t getVideoScannerAddressTXT();
INLINE uint16_t getVideoScannerAddressHGR();
static void initChromaPhaseTables();
static real initFilterChroma (real z);
@ -663,6 +660,12 @@ inline void updateVideoScannerHorzEOLSimple()
{
if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
{
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) // Only write to video memory when in visible part of display (GH#1143)
{
*(uint32_t*)g_pVideoAddress = 0 | ALPHA32_MASK; // VT_COLOR_IDEALIZED: TEXT -> HGR can leave junk on RHS (GH#1106)
*(getScanlineNextInbetween()) = 0 | ALPHA32_MASK; // ...and clear junk on RHS for non-'50% Scan lines'
}
g_nVideoClockHorz = 0;
if (++g_nVideoClockVert == g_videoScannerMaxVert)
@ -689,15 +692,21 @@ inline void updateVideoScannerHorzEOL()
if (!GetColorBurst())
{
// Only for: VF_TEXT && !VF_MIXED (ie. full 24-row TEXT40 or TEXT80)
g_pFuncUpdateBnWPixel(g_nLastColumnPixelNTSC);
g_pFuncUpdateBnWPixel(0);
g_pFuncUpdateBnWPixel(0);
g_pFuncUpdateBnWPixel(g_nLastColumnPixelNTSC); // last pixel in 14M video modes
g_pFuncUpdateBnWPixel(0); // 14M ringing pixel! (better definition for 80COL char's right-hand edge)
// Direct write instead of g_pFuncUpdateBnWPixel(0) to avoid random pixels on RHS in VT_COLOR_MONITOR_NTSC
*(uint32_t*)g_pVideoAddress++ = 0 | ALPHA32_MASK;
*(uint32_t*)g_pVideoAddress++ = 0 | ALPHA32_MASK;
}
else
{
g_pFuncUpdateHuePixel(g_nLastColumnPixelNTSC);
g_pFuncUpdateHuePixel(0);
g_pFuncUpdateHuePixel(0);
g_pFuncUpdateHuePixel(g_nLastColumnPixelNTSC); // last pixel in 14M video modes
g_pFuncUpdateHuePixel(0); // 14M ringing pixel! (better definition for 80COL char's right-hand edge)
// Direct write instead of g_pFuncUpdateHuePixel(0) to avoid random pixels on RHS in VT_COLOR_MONITOR_NTSC
*(uint32_t*)g_pVideoAddress = 0 | ALPHA32_MASK;
*(getScanlineNextInbetween()) = 0 | ALPHA32_MASK; g_pVideoAddress++; // Clear junk on RHS for TV (Color/B&W) & Monitor (NTSC/PAL). (GH#1157)
*(uint32_t*)g_pVideoAddress = 0 | ALPHA32_MASK;
*(getScanlineNextInbetween()) = 0 | ALPHA32_MASK; g_pVideoAddress++; // Clear junk on RHS for TV (Color/B&W) & Monitor (NTSC/PAL). (GH#1157)
}
}
@ -738,8 +747,13 @@ inline void updateVideoScannerHorzEOL_SHR()
//===========================================================================
inline void updateVideoScannerAddress()
{
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && GetVideo().GetVideoRefreshRate() == VR_50HZ) // GH#763
g_nColorBurstPixels = 0; // instantaneously kill color-burst!
if (g_nVideoMixed && GetVideo().GetVideoRefreshRate() == VR_50HZ) // GH#763
{
if (g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
g_nColorBurstPixels = 0; // instantaneously kill color-burst!
else if (g_nVideoClockVert == 0 && (GetVideo().GetVideoMode() & VF_TEXT) == 0)
g_nColorBurstPixels = 1024; // setup for line-0 (when TEXT is off), ie. so GetColorBurst() returns true below (GH#1119)
}
if (g_pFuncUpdateGraphicsScreen == updateScreenSHR)
{
@ -772,11 +786,74 @@ inline void updateVideoScannerAddress()
// Centre the older //e video modes when running with a VidHD
g_pVideoAddress += GetVideo().GetFrameBufferCentringValue();
if (GetVideo().HasVidHD())
{
if (GetVideo().GetVideoType() == VT_COLOR_MONITOR_NTSC)
{
// EG. Switching between TEXT (full 24 lines) and MIXED (HGR with purple vertical line-0)
// - AppleWin-Test repo, Tests-Various.dsk, option-C
g_pVideoAddress -= 2;
*(uint32_t*)g_pVideoAddress++ = 0 | ALPHA32_MASK;
*(uint32_t*)g_pVideoAddress++ = 0 | ALPHA32_MASK;
}
}
g_nColorPhaseNTSC = INITIAL_COLOR_PHASE;
g_nLastColumnPixelNTSC = 0;
g_nSignalBitsNTSC = 0;
}
//===========================================================================
#if 1
#define CLEAR_COLOUR_TOP 0
#define CLEAR_COLOUR_SIDE 0
#else // debug
#define CLEAR_COLOUR_TOP 0x0000FF00 // green
#define CLEAR_COLOUR_SIDE 0x00FF0000 // red
#endif
static void ClearOverscanVideoArea(void)
{
if (g_pFuncUpdateGraphicsScreen == updateScreenSHR)
return;
bgra_t* pSaveVideoAddress = g_pVideoAddress; // save g_pVideoAddress
g_pVideoAddress = g_pScanLines[0];
uint32_t* pLine1Prev = getScanlinePreviousInbetween();
g_pVideoAddress = pSaveVideoAddress; // restore g_pVideoAddress
const int kOverscanOffsetL = 3; // In updateVideoScannerAddress(), g_pVideoAddress could be adjusted by: -2 + -1 = -3
const int kOverscanSpanL = 3;
const int kOverscanOverlapL = kOverscanSpanL - kOverscanOffsetL;
const int kOverscanOffsetR = 2;
const int kOverscanSpanR = 4; // In updateVideoScannerHorzEOL() it writes 4 extra pixels
const int kOverscanOverlapR = kOverscanSpanR - kOverscanOffsetR;
const int kHorzPixels = (VIDEO_SCANNER_MAX_HORZ - VIDEO_SCANNER_HORZ_START) * 14;
pLine1Prev += GetVideo().GetFrameBufferCentringValue() - kOverscanOffsetL; // Centre the older //e video modes when running with a VidHD
// Clear this line at Y=-1
for (uint32_t i = 0; i < (kHorzPixels + (kOverscanSpanL - kOverscanOverlapL) + (kOverscanSpanR - kOverscanOverlapR)); i++)
*pLine1Prev++ = CLEAR_COLOUR_TOP | ALPHA32_MASK;
// Clear overscan before & after display area
for (uint32_t i = 0; i < VIDEO_SCANNER_Y_DISPLAY*2; i++)
{
uint32_t* pScanLine = ((uint32_t*)g_pScanLines[i]);
pScanLine += GetVideo().GetFrameBufferCentringValue() - kOverscanOffsetL; // Centre the older //e video modes when running with a VidHD
for (uint32_t j = 0; j < kOverscanSpanL + 1; j++)
pScanLine[j] = CLEAR_COLOUR_SIDE | ALPHA32_MASK;
pScanLine += kOverscanOffsetL + kHorzPixels - kOverscanOffsetR;
for (uint32_t j = 0; j < kOverscanSpanR; j++)
pScanLine[j] = CLEAR_COLOUR_SIDE | ALPHA32_MASK;
}
}
//===========================================================================
INLINE uint16_t getVideoScannerAddressTXT()
{
@ -796,6 +873,29 @@ INLINE uint16_t getVideoScannerAddressHGR()
return nAddress;
}
//===========================================================================
INLINE uint16_t getVideoScannerAddressTXTorHGR()
{
const bool isTextAddr = ((g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED) ||
(g_uNewVideoModeFlags & VF_TEXT) ||
!(g_uNewVideoModeFlags & VF_HIRES));
if (isTextAddr)
return getVideoScannerAddressTXT();
else
return getVideoScannerAddressHGR();
}
//===========================================================================
INLINE uint16_t getVideoScannerAddressSHR()
{
// 2 pixels per byte in 320-pixel mode = 160 bytes/scanline
// 4 pixels per byte in 640-pixel mode = 160 bytes/scanline
const UINT kBytesPerScanline = 160;
const UINT kBytesPerCycle = 4;
return 0x2000 + kBytesPerScanline * g_nVideoClockVert + kBytesPerCycle * (g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START);
}
// Non-Inline _________________________________________________________
// Build the 4 phase chroma lookup table
@ -1749,14 +1849,10 @@ void updateScreenSHR(long cycles6502)
{
for (; cycles6502 > 0; --cycles6502)
{
// 2 pixels per byte in 320-pixel mode = 160 bytes/scanline
// 4 pixels per byte in 640-pixel mode = 160 bytes/scanline
const UINT kBytesPerScanline = 160;
const UINT kBytesPerCycle = 4;
uint16_t addr = 0x2000 + kBytesPerScanline * g_nVideoClockVert + kBytesPerCycle * (g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START);
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY_IIGS)
{
uint16_t addr = getVideoScannerAddressSHR();
if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
{
uint32_t* pAux = (uint32_t*) MemGetAuxPtr(addr); // 8 pixels (320 mode) / 16 pixels (640 mode)
@ -1836,12 +1932,7 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
g_nVideoClockVert = g_videoScannerMaxVert-1;
}
uint16_t addr;
bool bHires = (GetVideo().GetVideoMode() & VF_HIRES) && !(GetVideo().GetVideoMode() & VF_TEXT); // SW_HIRES && !SW_TEXT
if( bHires )
addr = getVideoScannerAddressHGR();
else
addr = getVideoScannerAddressTXT();
uint16_t addr = getVideoScannerAddressTXTorHGR();
g_nVideoClockVert = currVideoClockVert;
g_nVideoClockHorz = currVideoClockHorz;
@ -1849,10 +1940,19 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
return addr;
}
uint16_t NTSC_VideoGetScannerAddressForDebugger(void)
void NTSC_GetVideoVertHorzForDebugger(uint16_t& vert, uint16_t& horz)
{
ResetCyclesExecutedForDebugger(); // if in full-speed, then reset cycles so that CpuCalcCycles() doesn't ASSERT
return NTSC_VideoGetScannerAddress(0);
NTSC_VideoGetScannerAddress(0);
vert = g_nVideoClockVert;
horz = g_nVideoClockHorz;
}
uint16_t NTSC_GetVideoVertForDebugger(void)
{
uint16_t vert, horz;
NTSC_GetVideoVertHorzForDebugger(vert, horz);
return vert;
}
//===========================================================================
@ -1874,6 +1974,8 @@ void NTSC_SetVideoTextMode( int cols )
//===========================================================================
void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
{
g_uNewVideoModeFlags = uVideoModeFlags;
if (uVideoModeFlags & VF_SHR)
{
g_pFuncUpdateGraphicsScreen = updateScreenSHR;
@ -1892,7 +1994,6 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
// (GH#670) NB. if g_bFullSpeed then NTSC_VideoUpdateCycles() won't be called on the next 6502 opcode.
// - Instead it's called when !g_bFullSpeed (eg. drive motor off), then the stale g_uNewVideoModeFlags will get used for NTSC_SetVideoMode()!
g_bDelayVideoMode = true;
g_uNewVideoModeFlags = uVideoModeFlags;
return;
}
@ -1952,7 +2053,8 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
}
else
{
g_nColorBurstPixels = 1024; // (For mid-line video mode change)
if (!g_nVideoMixed || g_nVideoClockVert < VIDEO_SCANNER_Y_MIXED) // 50HZ(PAL) will kill color-burst if 'mixed and >=160' - so don't re-enable color-burst! (GH#1131)
g_nColorBurstPixels = 1024; // (For mid-line video mode change)
// Switching mid-line from TEXT to graphics
if (GetVideo().GetVideoType() == VT_COLOR_MONITOR_NTSC &&
@ -2181,7 +2283,9 @@ _mono:
else
g_pFuncUpdateBnWPixel = g_pFuncUpdateHuePixel = updatePixelBnWMonitorDoubleScanline;
break;
}
}
ClearOverscanVideoArea();
}
//===========================================================================
@ -2632,7 +2736,82 @@ UINT NTSC_GetCyclesUntilVBlank(int cycles)
(cyclesPerFrames - cycleCurrentPos + cycleVBl);
}
bool NTSC_GetVblBar(void)
{
const UINT visibleScanLines = ((g_uNewVideoModeFlags & VF_SHR) == 0) ? VIDEO_SCANNER_Y_DISPLAY : VIDEO_SCANNER_Y_DISPLAY_IIGS;
return g_nVideoClockVert < visibleScanLines;
}
bool NTSC_IsVisible(void)
{
return (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START);
return NTSC_GetVblBar() && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START);
}
// For debugger
uint16_t NTSC_GetScannerAddressAndData(uint32_t& data, int& dataSize)
{
if (g_uNewVideoModeFlags & VF_SHR)
{
uint16_t addr = getVideoScannerAddressSHR();
uint32_t* pAux = (uint32_t*)MemGetAuxPtr(addr); // 8 pixels (320 mode) / 16 pixels (640 mode)
data = pAux[0];
dataSize = 4;
return addr;
}
//
// Copy logic from NTSC_SetVideoMode()
if (g_uNewVideoModeFlags & VF_TEXT)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else if (g_uNewVideoModeFlags & VF_HIRES)
{
if (g_uNewVideoModeFlags & VF_DHIRES)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else
{
dataSize = 1;
}
}
else
{
if (g_uNewVideoModeFlags & VF_DHIRES)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else
{
dataSize = 1;
}
}
// Extra logic for MIXED mode
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && (g_uNewVideoModeFlags & VF_80COL))
dataSize = 2;
uint16_t addr = getVideoScannerAddressTXTorHGR();
data = 0;
if (dataSize == 2)
{
uint8_t* pAux = MemGetAuxPtr(addr);
data = pAux[0] << 8;
}
uint8_t* pMain = MemGetMainPtr(addr);
data |= pMain[0];
return addr;
}

View File

@ -3,8 +3,6 @@
#include "Video.h" // NB. needed by GCC (for fwd enum declaration)
// Globals (Public)
extern uint16_t g_nVideoClockVert;
extern uint16_t g_nVideoClockHorz;
extern uint32_t g_nChromaSize;
// Prototypes (Public) ________________________________________________
@ -14,7 +12,8 @@ void NTSC_SetVideoTextMode(int cols);
uint32_t* NTSC_VideoGetChromaTable(bool bHueTypeMonochrome, bool bMonitorTypeColorTV);
void NTSC_VideoClockResync(const DWORD dwCyclesThisFrame);
uint16_t NTSC_VideoGetScannerAddress(const ULONG uExecutedCycles);
uint16_t NTSC_VideoGetScannerAddressForDebugger(void);
void NTSC_GetVideoVertHorzForDebugger(uint16_t& vert, uint16_t& horz);
uint16_t NTSC_GetVideoVertForDebugger(void);
void NTSC_Destroy(void);
void NTSC_VideoInit(uint8_t *pFramebuffer);
void NTSC_VideoReinitialize(DWORD cyclesThisFrame, bool bInitVideoScannerAddress);
@ -28,4 +27,6 @@ UINT NTSC_GetCyclesPerFrame(void);
UINT NTSC_GetCyclesPerLine(void);
UINT NTSC_GetVideoLines(void);
UINT NTSC_GetCyclesUntilVBlank(int cycles);
bool NTSC_GetVblBar(void);
bool NTSC_IsVisible(void);
uint16_t NTSC_GetScannerAddressAndData(uint32_t& data, int& dataSize);

View File

@ -38,113 +38,99 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../resource/resource.h"
static DWORD inactivity = 0;
static unsigned int g_PrinterIdleLimit = 10;
static FILE* file = NULL;
DWORD const PRINTDRVR_SIZE = APPLE_SLOT_SIZE;
#define DEFAULT_PRINT_FILENAME "Printer.txt"
static std::string g_szPrintFilename;
bool g_bDumpToPrinter = false;
bool g_bConvertEncoding = true;
bool g_bFilterUnprintable = true;
bool g_bPrinterAppend = false;
bool g_bEnableDumpToRealPrinter = false;
//===========================================================================
static BYTE __stdcall PrintStatus(WORD, WORD, BYTE, BYTE, ULONG);
static BYTE __stdcall PrintTransmit(WORD, WORD, BYTE, BYTE value, ULONG);
VOID PrintLoadRom(LPBYTE pCxRomPeripheral, const UINT uSlot)
void ParallelPrinterCard::InitializeIO(LPBYTE pCxRomPeripheral)
{
const DWORD PRINTDRVR_SIZE = APPLE_SLOT_SIZE;
BYTE* pData = GetFrame().GetResource(IDR_PRINTDRVR_FW, "FIRMWARE", PRINTDRVR_SIZE);
if(pData == NULL)
return;
memcpy(pCxRomPeripheral + uSlot*256, pData, PRINTDRVR_SIZE);
memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, pData, PRINTDRVR_SIZE);
//
RegisterIoHandler(uSlot, PrintStatus, PrintTransmit, NULL, NULL, NULL, NULL);
RegisterIoHandler(m_slot, IORead, IOWrite, NULL, NULL, this, NULL);
}
//===========================================================================
static BOOL CheckPrint()
bool ParallelPrinterCard::CheckPrint(void)
{
inactivity = 0;
if (file == NULL)
{
m_inactivity = 0;
if (m_file == NULL)
{
//TCHAR filepath[MAX_PATH * 2];
//_tcsncpy(filepath, g_sProgramDir, MAX_PATH);
//_tcsncat(filepath, _T("Printer.txt"), MAX_PATH);
//_tcsncat(filepath, _T("Printer.txt"), MAX_PATH);
//file = fopen(filepath, "wb");
if (g_bPrinterAppend )
file = fopen(Printer_GetFilename().c_str(), "ab");
if (m_bPrinterAppend )
m_file = fopen(ParallelPrinterCard::GetFilename().c_str(), "ab");
else
file = fopen(Printer_GetFilename().c_str(), "wb");
}
return (file != NULL);
m_file = fopen(ParallelPrinterCard::GetFilename().c_str(), "wb");
}
return (m_file != NULL);
}
//===========================================================================
static void ClosePrint()
void ParallelPrinterCard::ClosePrint(void)
{
if (file != NULL)
{
fclose(file);
file = NULL;
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL;
std::string ExtendedFileName = "copy \"";
ExtendedFileName.append (Printer_GetFilename());
ExtendedFileName.append (ParallelPrinterCard::GetFilename());
ExtendedFileName.append ("\" prn");
//if (g_bDumpToPrinter) ShellExecute(NULL, "print", Printer_GetFilename(), NULL, NULL, 0); //Print through Notepad
if (g_bDumpToPrinter)
if (m_bDumpToPrinter)
system (ExtendedFileName.c_str ()); //Print through console. This is supposed to be the better way, because it shall print images (with older printers only).
}
inactivity = 0;
}
m_inactivity = 0;
}
//===========================================================================
void PrintDestroy()
void ParallelPrinterCard::Destroy(void)
{
ClosePrint();
ClosePrint();
}
//===========================================================================
void PrintUpdate(DWORD totalcycles)
void ParallelPrinterCard::Update(const ULONG nExecutedCycles)
{
if (file == NULL)
{
return;
}
// if ((inactivity += totalcycles) > (Printer_GetIdleLimit () * 1000 * 1000)) //This line seems to give a very big deviation
if ((inactivity += totalcycles) > (Printer_GetIdleLimit () * 710000))
{
// inactive, so close the file (next print will overwrite or append to it, according to the settings made)
ClosePrint();
}
if (m_file == NULL)
return;
// if ((inactivity += totalcycles) > (Printer_GetIdleLimit () * 1000 * 1000)) //This line seems to give a very big deviation
if ((m_inactivity += nExecutedCycles) > (ParallelPrinterCard::GetIdleLimit () * 710000))
{
// inactive, so close the file (next print will overwrite or append to it, according to the settings made)
ClosePrint();
}
}
//===========================================================================
void PrintReset()
void ParallelPrinterCard::Reset(const bool powerCycle)
{
ClosePrint();
ClosePrint();
}
//===========================================================================
static BYTE __stdcall PrintStatus(WORD, WORD, BYTE, BYTE, ULONG)
BYTE __stdcall ParallelPrinterCard::IORead(WORD, WORD address, BYTE, BYTE, ULONG)
{
CheckPrint();
return 0xFF; // status - TODO?
UINT slot = ((address & 0xff) >> 4) - 8;
ParallelPrinterCard* card = (ParallelPrinterCard*)MemGetSlotParameters(slot);
card->CheckPrint();
return 0xFF; // status - TODO?
}
//===========================================================================
static BYTE __stdcall PrintTransmit(WORD, WORD address, BYTE, BYTE value, ULONG)
BYTE __stdcall ParallelPrinterCard::IOWrite(WORD, WORD address, BYTE, BYTE value, ULONG)
{
if (!CheckPrint())
UINT slot = ((address & 0xff) >> 4) - 8;
ParallelPrinterCard* card = (ParallelPrinterCard*)MemGetSlotParameters(slot);
if (!card->CheckPrint())
return 0;
// only allow writes to the load output port (i.e., $C090)
@ -155,44 +141,85 @@ static BYTE __stdcall PrintTransmit(WORD, WORD address, BYTE, BYTE value, ULONG)
if (IsPravets(GetApple2Type()))
{
if (g_bConvertEncoding)
if (card->m_bConvertEncoding)
c = GetPravets().ConvertToPrinterChar(value);
}
if ((g_bFilterUnprintable == false) || (c>31) || (c==13) || (c==10) || (c>0x7F)) //c>0x7F is needed for cyrillic characters
fwrite(&c, 1, 1, file);
if ((card->m_bFilterUnprintable == false) || (c>31) || (c==13) || (c==10) || (c>0x7F)) //c>0x7F is needed for cyrillic characters
fwrite(&c, 1, 1, card->m_file);
return 0;
}
//===========================================================================
const std::string & Printer_GetFilename()
const std::string& ParallelPrinterCard::GetFilename(void)
{
return g_szPrintFilename;
return m_szPrintFilename;
}
void Printer_SetFilename(const std::string & prtFilename)
#define DEFAULT_PRINT_FILENAME "Printer.txt"
void ParallelPrinterCard::SetFilename(const std::string& prtFilename)
{
if (!prtFilename.empty())
{
g_szPrintFilename = prtFilename;
m_szPrintFilename = prtFilename;
}
else //No registry entry is available
{
g_szPrintFilename = g_sProgramDir + DEFAULT_PRINT_FILENAME;
RegSaveString(REG_CONFIG, REGVALUE_PRINTER_FILENAME, 1, g_szPrintFilename);
m_szPrintFilename = g_sProgramDir + DEFAULT_PRINT_FILENAME;
RegSaveString(REG_CONFIG, REGVALUE_PRINTER_FILENAME, 1, m_szPrintFilename);
}
}
unsigned int Printer_GetIdleLimit()
UINT ParallelPrinterCard::GetIdleLimit(void)
{
return g_PrinterIdleLimit;
return m_printerIdleLimit;
}
void Printer_SetIdleLimit(unsigned int Duration)
void ParallelPrinterCard::SetIdleLimit(UINT Duration)
{
g_PrinterIdleLimit = Duration;
m_printerIdleLimit = Duration;
}
//===========================================================================
void ParallelPrinterCard::GetRegistryConfig(void)
{
std::string regSection = RegGetConfigSlotSection(m_slot);
DWORD dwTmp;
char szFilename[MAX_PATH];
if (RegLoadValue(regSection.c_str(), REGVALUE_DUMP_TO_PRINTER, TRUE, &dwTmp))
SetDumpToPrinter(dwTmp ? true : false);
if (RegLoadValue(regSection.c_str(), REGVALUE_CONVERT_ENCODING, TRUE, &dwTmp))
SetConvertEncoding(dwTmp ? true : false);
if (RegLoadValue(regSection.c_str(), REGVALUE_FILTER_UNPRINTABLE, TRUE, &dwTmp))
SetFilterUnprintable(dwTmp ? true : false);
if (RegLoadValue(regSection.c_str(), REGVALUE_PRINTER_APPEND, TRUE, &dwTmp))
SetPrinterAppend(dwTmp ? true : false);
if (RegLoadString(regSection.c_str(), REGVALUE_PRINTER_FILENAME, 1, szFilename, MAX_PATH, TEXT("")))
SetFilename(szFilename);
if (RegLoadValue(regSection.c_str(), REGVALUE_PRINTER_IDLE_LIMIT, TRUE, &dwTmp))
SetIdleLimit(dwTmp);
}
void ParallelPrinterCard::SetRegistryConfig(void)
{
std::string regSection = RegGetConfigSlotSection(m_slot);
RegSaveValue(regSection.c_str(), REGVALUE_DUMP_TO_PRINTER, TRUE, GetDumpToPrinter() ? 1 : 0);
RegSaveValue(regSection.c_str(), REGVALUE_CONVERT_ENCODING, TRUE, GetConvertEncoding() ? 1 : 0);
RegSaveValue(regSection.c_str(), REGVALUE_FILTER_UNPRINTABLE, TRUE, GetFilterUnprintable() ? 1 : 0);
RegSaveValue(regSection.c_str(), REGVALUE_PRINTER_APPEND, TRUE, GetPrinterAppend() ? 1 : 0);
RegSaveString(regSection.c_str(), REGVALUE_PRINTER_FILENAME, TRUE, GetFilename());
RegSaveValue(regSection.c_str(), REGVALUE_PRINTER_IDLE_LIMIT, TRUE, GetIdleLimit());
}
//===========================================================================
@ -209,57 +236,57 @@ void Printer_SetIdleLimit(unsigned int Duration)
#define SS_YAML_KEY_APPEND "Printer Append"
#define SS_YAML_KEY_DUMPTOREALPRINTER "Enable Dump To Real Printer"
const std::string& Printer_GetSnapshotCardName(void)
const std::string& ParallelPrinterCard::GetSnapshotCardName(void)
{
static const std::string name(SS_YAML_VALUE_CARD_PRINTER);
return name;
}
void Printer_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
void ParallelPrinterCard::SaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Slot slot(yamlSaveHelper, Printer_GetSnapshotCardName(), uSlot, 1);
YamlSaveHelper::Slot slot(yamlSaveHelper, ParallelPrinterCard::GetSnapshotCardName(), m_slot, 1);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveUint(SS_YAML_KEY_INACTIVITY, inactivity);
yamlSaveHelper.SaveUint(SS_YAML_KEY_IDLELIMIT, g_PrinterIdleLimit);
yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, g_szPrintFilename);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FILEOPEN, (file != NULL) ? true : false);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOPRINTER, g_bDumpToPrinter);
yamlSaveHelper.SaveBool(SS_YAML_KEY_CONVERTENCODING, g_bConvertEncoding);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FILTERUNPRINTABLE, g_bFilterUnprintable);
yamlSaveHelper.SaveBool(SS_YAML_KEY_APPEND, g_bPrinterAppend);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOREALPRINTER, g_bEnableDumpToRealPrinter);
yamlSaveHelper.SaveUint(SS_YAML_KEY_INACTIVITY, m_inactivity);
yamlSaveHelper.SaveUint(SS_YAML_KEY_IDLELIMIT, m_printerIdleLimit);
yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, m_szPrintFilename);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FILEOPEN, (m_file != NULL) ? true : false);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOPRINTER, m_bDumpToPrinter);
yamlSaveHelper.SaveBool(SS_YAML_KEY_CONVERTENCODING, m_bConvertEncoding);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FILTERUNPRINTABLE, m_bFilterUnprintable);
yamlSaveHelper.SaveBool(SS_YAML_KEY_APPEND, m_bPrinterAppend);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOREALPRINTER, m_bEnableDumpToRealPrinter);
}
bool Printer_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
bool ParallelPrinterCard::LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version)
{
if (slot != 1) // fixme
Card::ThrowErrorInvalidSlot(CT_GenericPrinter, slot);
if (m_slot != SLOT1) // fixme
Card::ThrowErrorInvalidSlot(CT_GenericPrinter, m_slot);
if (version != 1)
Card::ThrowErrorInvalidVersion(CT_GenericPrinter, version);
inactivity = yamlLoadHelper.LoadUint(SS_YAML_KEY_INACTIVITY);
g_PrinterIdleLimit = yamlLoadHelper.LoadUint(SS_YAML_KEY_IDLELIMIT);
g_szPrintFilename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME);
m_inactivity = yamlLoadHelper.LoadUint(SS_YAML_KEY_INACTIVITY);
m_printerIdleLimit = yamlLoadHelper.LoadUint(SS_YAML_KEY_IDLELIMIT);
m_szPrintFilename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME);
if (yamlLoadHelper.LoadBool(SS_YAML_KEY_FILEOPEN))
{
yamlLoadHelper.LoadBool(SS_YAML_KEY_APPEND); // Consume
g_bPrinterAppend = true; // Re-open print-file in append mode
m_bPrinterAppend = true; // Re-open print-file in append mode
BOOL bRes = CheckPrint();
if (!bRes)
throw std::runtime_error("Printer Card: Unable to resume printing to file");
}
else
{
g_bPrinterAppend = yamlLoadHelper.LoadBool(SS_YAML_KEY_APPEND);
m_bPrinterAppend = yamlLoadHelper.LoadBool(SS_YAML_KEY_APPEND);
}
g_bDumpToPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOPRINTER);
g_bConvertEncoding = yamlLoadHelper.LoadBool(SS_YAML_KEY_CONVERTENCODING);
g_bFilterUnprintable = yamlLoadHelper.LoadBool(SS_YAML_KEY_FILTERUNPRINTABLE);
g_bEnableDumpToRealPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOREALPRINTER);
m_bDumpToPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOPRINTER);
m_bConvertEncoding = yamlLoadHelper.LoadBool(SS_YAML_KEY_CONVERTENCODING);
m_bFilterUnprintable = yamlLoadHelper.LoadBool(SS_YAML_KEY_FILTERUNPRINTABLE);
m_bEnableDumpToRealPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOREALPRINTER);
return true;
}

View File

@ -1,20 +1,69 @@
#pragma once
void PrintDestroy();
void PrintLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot);
void PrintReset();
void PrintUpdate(DWORD);
void Printer_SetFilename(const std::string & pszFilename);
const std::string & Printer_GetFilename();
void Printer_SetIdleLimit(unsigned int Duration);
unsigned int Printer_GetIdleLimit();
#include "Card.h"
#include "Memory.h"
const std::string& Printer_GetSnapshotCardName(void);
void Printer_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
bool Printer_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
class ParallelPrinterCard : public Card
{
public:
ParallelPrinterCard(UINT slot) :
Card(CT_GenericPrinter, slot)
{
m_inactivity = 0;
m_printerIdleLimit = 10;
m_file = NULL;
extern bool g_bDumpToPrinter;
extern bool g_bConvertEncoding;
extern bool g_bFilterUnprintable;
extern bool g_bPrinterAppend;
extern bool g_bEnableDumpToRealPrinter; // Set by cmd-line: -printer-real
m_bDumpToPrinter = false;
m_bConvertEncoding = false;
m_bFilterUnprintable = false;
m_bPrinterAppend = false;
m_bEnableDumpToRealPrinter = false;
}
virtual ~ParallelPrinterCard(void) {}
virtual void Destroy(void);
virtual void Reset(const bool powerCycle);
virtual void Update(const ULONG nExecutedCycles);
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles);
static BYTE __stdcall IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles);
static const std::string& GetSnapshotCardName(void);
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
const std::string& GetFilename(void);
void SetFilename(const std::string& prtFilename);
UINT GetIdleLimit(void);
void SetIdleLimit(UINT Duration);
bool GetDumpToPrinter(void) { return m_bDumpToPrinter; }
void SetDumpToPrinter(bool value) { m_bDumpToPrinter = value; }
bool GetConvertEncoding(void) { return m_bConvertEncoding; }
void SetConvertEncoding(bool value) { m_bConvertEncoding = value; }
bool GetFilterUnprintable(void) { return m_bFilterUnprintable; }
void SetFilterUnprintable(bool value) { m_bFilterUnprintable = value; }
bool GetPrinterAppend(void) { return m_bPrinterAppend; }
void SetPrinterAppend(bool value) { m_bPrinterAppend = value; }
bool GetEnableDumpToRealPrinter(void) { return m_bEnableDumpToRealPrinter; }
void SetEnableDumpToRealPrinter(bool value) { m_bEnableDumpToRealPrinter = value; }
void GetRegistryConfig(void);
void SetRegistryConfig(void);
private:
bool CheckPrint(void);
void ClosePrint(void);
DWORD m_inactivity;
UINT m_printerIdleLimit;
FILE* m_file;
std::string m_szPrintFilename;
bool m_bDumpToPrinter;
bool m_bConvertEncoding;
bool m_bFilterUnprintable;
bool m_bPrinterAppend;
bool m_bEnableDumpToRealPrinter; // Set by cmd-line: -printer-real
};

View File

@ -155,6 +155,9 @@ void RegSaveValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD value) {
//===========================================================================
static inline std::string RegGetSlotSection(UINT slot)
{
if (slot == GAME_IO_CONNECTOR)
return std::string(REG_CONFIG_GAME_IO_CONNECTOR);
return (slot == SLOT_AUX)
? std::string(REG_CONFIG_SLOT_AUX)
: (std::string(REG_CONFIG_SLOT) + (char)('0' + slot));
@ -197,6 +200,8 @@ void RegDeleteConfigSlotSection(UINT slot)
void RegSetConfigSlotNewCardType(UINT slot, SS_CARDTYPE type)
{
_ASSERT(slot != GAME_IO_CONNECTOR);
RegDeleteConfigSlotSection(slot);
std::string regSection;
@ -204,3 +209,17 @@ void RegSetConfigSlotNewCardType(UINT slot, SS_CARDTYPE type)
RegSaveValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, type);
}
void RegSetConfigGameIOConnectorNewDongleType(UINT slot, DONGLETYPE type)
{
_ASSERT(slot == GAME_IO_CONNECTOR);
if (slot != GAME_IO_CONNECTOR)
return;
RegDeleteConfigSlotSection(slot);
std::string regSection;
regSection = RegGetConfigSlotSection(slot);
RegSaveValue(regSection.c_str(), REGVALUE_GAME_IO_TYPE, TRUE, type);
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "Card.h"
#include "CopyProtectionDongles.h"
#define REGLOAD(a, b) RegLoadValue(TEXT(REG_CONFIG), (a), TRUE, (b))
#define REGLOAD_DEFAULT(a, b, c) RegLoadValue(TEXT(REG_CONFIG), (a), TRUE, (b), (c))
@ -14,4 +15,5 @@ void RegSaveValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD value);
std::string RegGetConfigSlotSection(UINT slot);
void RegDeleteConfigSlotSection(UINT slot);
void RegSetConfigSlotNewCardType(UINT slot, enum SS_CARDTYPE type);
void RegSetConfigSlotNewCardType(UINT slot, SS_CARDTYPE type);
void RegSetConfigGameIOConnectorNewDongleType(UINT slot, DONGLETYPE type);

View File

@ -35,12 +35,12 @@ static DWORD dwDataOffset;
static DWORD g_dwTotalNumberOfBytesWritten = 0;
static unsigned int g_NumChannels = 2;
int RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned int NumChannels)
bool RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned int NumChannels)
{
g_hRiffFile = CreateFile(pszFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(g_hRiffFile == INVALID_HANDLE_VALUE)
return 1;
return false;
g_NumChannels = NumChannels;
@ -92,13 +92,13 @@ int RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned in
dwDataOffset = SetFilePointer(g_hRiffFile, 0, NULL, FILE_CURRENT);
WriteFile(g_hRiffFile, &temp32, 4, &dwNumberOfBytesWritten, NULL);
return 0;
return true;
}
int RiffFinishWriteFile()
bool RiffFinishWriteFile()
{
if(g_hRiffFile == INVALID_HANDLE_VALUE)
return 1;
return false;
//
@ -114,13 +114,13 @@ int RiffFinishWriteFile()
SetFilePointer(g_hRiffFile, dwDataOffset, NULL, FILE_BEGIN);
WriteFile(g_hRiffFile, &temp32, 4, &dwNumberOfBytesWritten, NULL);
return CloseHandle(g_hRiffFile);
return CloseHandle(g_hRiffFile) ? true : false;
}
int RiffPutSamples(const short* buf, unsigned int uSamples)
bool RiffPutSamples(const short* buf, unsigned int uSamples)
{
if(g_hRiffFile == INVALID_HANDLE_VALUE)
return 1;
return false;
//
@ -135,5 +135,5 @@ int RiffPutSamples(const short* buf, unsigned int uSamples)
g_dwTotalNumberOfBytesWritten += dwNumberOfBytesWritten;
return 0;
return true;
}

View File

@ -1,5 +1,5 @@
#pragma once
int RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned int NumChannels);
int RiffFinishWriteFile();
int RiffPutSamples(const short* buf, unsigned int uSamples);
bool RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned int NumChannels);
bool RiffFinishWriteFile(void);
bool RiffPutSamples(const short* buf, unsigned int uSamples);

View File

@ -43,11 +43,11 @@
Bit 6 = Controller 2, Active Low
Bit 7 = Controller 1, Active Low
Once data is read, button presses (for each controller) should be stored in the following structure
Byte 0: B:Y:Sl:St:U:D:L:R
Byte 1: A:X:Fl:Fr:x:x:x:x
Once data is read, button presses (for each controller) are stored in the following structure:
The variable controllerXButtons will stored in the reverse order.
bit# 16 / 11 10 9 8 / 7 6 5 4 3 2 1 0
m_controllerXButtons: *1 x:x:x:x:Fr:Fl:X:A / R:L:D:U:St:Sl:Y:B
*1 = Controller plugged in status
Alex Lukacz Aug 2021
*/
@ -57,6 +57,25 @@
#include "Memory.h"
#include "YamlHelper.h"
// Default to Sony DS4 / DualSense:
// b11,..,b0: St,Sl / -,-,R,L,X,A,B,Y
//
// infoEx.dwButtons bit definitions:
const UINT SNESMAXCard::m_mainControllerButtons[NUM_BUTTONS] =
{
Y,B,A,X,LB,RB,UNUSED,UNUSED, SELECT,START,UNUSED,UNUSED,UNUSED,UNUSED,UNUSED,UNUSED // bit0 -> Y, bit1 -> B, bit2 -> A, etc
};
// AltControllerType defaults to "8BitDo NES30 PRO" (can be reconfigured via command line + yaml mapping file)
// b11,..,b0: St,Sl,R,L / -,-,-,Y,X,-,B,A
//
// infoEx.dwButtons bit definitions:
UINT SNESMAXCard::m_altControllerButtons[2][NUM_BUTTONS] =
{
{A,B,UNUSED,X,Y,UNUSED,UNUSED,UNUSED, LB,RB,SELECT,START,UNUSED,UNUSED,UNUSED,UNUSED}, // bit0 -> A, bit1 -> B, bit2 -> unused, etc
{A,B,UNUSED,X,Y,UNUSED,UNUSED,UNUSED, LB,RB,SELECT,START,UNUSED,UNUSED,UNUSED,UNUSED}
};
BYTE __stdcall SNESMAXCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles)
{
const UINT slot = ((addr & 0xff) >> 4) - 8;
@ -100,95 +119,17 @@ BYTE __stdcall SNESMAXCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value,
result = joyGetPosEx(JOYSTICKID1, &infoEx);
if (result == JOYERR_NOERROR)
{
xAxis = (infoEx.dwXpos >> 8) & 0xFF;
yAxis = (infoEx.dwYpos >> 8) & 0xFF;
controller1Buttons = controller1Buttons | ((yAxis < 103 || infoEx.dwPOV == 0 || infoEx.dwPOV == 4500 || infoEx.dwPOV == 31500) << 4); // U Button
controller1Buttons = controller1Buttons | ((yAxis > 153 || (infoEx.dwPOV >= 13500 && infoEx.dwPOV <= 22500)) << 5); // D Button
controller1Buttons = controller1Buttons | ((xAxis < 103 || (infoEx.dwPOV >= 22500 && infoEx.dwPOV <= 31500)) << 6); // L Button
controller1Buttons = controller1Buttons | ((xAxis > 153 || (infoEx.dwPOV >= 4500 && infoEx.dwPOV <= 13500)) << 7); // R Button
// controller1Buttons = controller1Buttons | 0 * 0x1000; // spare Button
// controller1Buttons = controller1Buttons | 0 * 0x2000; // spare Button
// controller1Buttons = controller1Buttons | 0 * 0x4000; // spare Button
// controller1Buttons = controller1Buttons | 0 * 0x8000; // spare Button
if (pCard->m_altControllerType[0])
{
// 8BitDo NES30 PRO
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0002) >> 1); // B Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0010) >> 3); // Y Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0400) >> 8); // Sl Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0800) >> 8); // St Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0001) << 8); // A Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0008) << 6); // X Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0100) << 2) | ((infoEx.dwButtons & 0x0040) << 4); // Fl Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0200) << 2) | ((infoEx.dwButtons & 0x0080) << 4); // Fr Button
}
else
{
// Logitech F310, Dualshock 4
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0002) >> 1); // B Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0001) << 1); // Y Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0100) >> 6); // Sl Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0200) >> 6); // St Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0004) << 6); // A Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0008) << 6); // X Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0010) << 6) | ((infoEx.dwButtons & 0x0040) << 4); // Fl Button
controller1Buttons = controller1Buttons | ((infoEx.dwButtons & 0x0020) << 6) | ((infoEx.dwButtons & 0x0080) << 4); // Fr Button
}
controller1Buttons = controller1Buttons | 0x10000; // Controller plugged in status.
}
controller1Buttons = pCard->GetControllerButtons(JOYSTICKID1, infoEx, pCard->m_altControllerType[0]);
controller1Buttons = ~controller1Buttons;
result = joyGetPosEx(JOYSTICKID2, &infoEx);
if (result == JOYERR_NOERROR)
{
xAxis = (infoEx.dwXpos >> 8) & 0xFF;
yAxis = (infoEx.dwYpos >> 8) & 0xFF;
controller2Buttons = controller2Buttons | ((yAxis < 103 || infoEx.dwPOV == 0 || infoEx.dwPOV == 4500 || infoEx.dwPOV == 31500) << 4); // U Button
controller2Buttons = controller2Buttons | ((yAxis > 153 || (infoEx.dwPOV >= 13500 && infoEx.dwPOV <= 22500)) << 5); // D Button
controller2Buttons = controller2Buttons | ((xAxis < 103 || (infoEx.dwPOV >= 22500 && infoEx.dwPOV <= 31500)) << 6); // L Button
controller2Buttons = controller2Buttons | ((xAxis > 153 || (infoEx.dwPOV >= 4500 && infoEx.dwPOV <= 13500)) << 7); // R Button
// controller2Buttons = controller2Buttons | 0 * 0x1000; // spare Button
// controller2Buttons = controller2Buttons | 0 * 0x2000; // spare Button
// controller2Buttons = controller2Buttons | 0 * 0x4000; // spare Button
// controller2Buttons = controller2Buttons | 0 * 0x8000; // spare Button
if (pCard->m_altControllerType[1])
{
// 8BitDo NES30 PRO
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0002) >> 1); // B Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0010) >> 3); // Y Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0400) >> 8); // Sl Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0800) >> 8); // St Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0001) << 8); // A Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0008) << 6); // X Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0100) << 2) | ((infoEx.dwButtons & 0x0040) << 4); // Fl Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0200) << 2) | ((infoEx.dwButtons & 0x0080) << 4); // Fr Button
}
else
{
// Logitech F310, Dualshock 4
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0002) >> 1); // B Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0001) << 1); // Y Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0100) >> 6); // Sl Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0200) >> 6); // St Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0004) << 6); // A Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0008) << 6); // X Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0010) << 6) | ((infoEx.dwButtons & 0x0040) << 4); // Fl Button
controller2Buttons = controller2Buttons | ((infoEx.dwButtons & 0x0020) << 6) | ((infoEx.dwButtons & 0x0080) << 4); // Fr Button
}
controller2Buttons = controller2Buttons | 0x10000; // Controller plugged in status.
}
controller2Buttons = pCard->GetControllerButtons(JOYSTICKID2, infoEx, pCard->m_altControllerType[1]);
controller2Buttons = ~controller2Buttons;
break;
case 1: // Clock
if (pCard->m_buttonIndex <= 16)
if (pCard->m_buttonIndex <= NUM_BUTTONS) // NB. 17 bits (where last bit is: Controller plugged in status)
{
pCard->m_buttonIndex++;
controller1Buttons = controller1Buttons >> 1;
@ -202,11 +143,107 @@ BYTE __stdcall SNESMAXCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value,
return 0;
}
UINT SNESMAXCard::GetControllerButtons(UINT joyNum, JOYINFOEX& infoEx, bool altControllerType)
{
UINT xAxis = (infoEx.dwXpos >> 8) & 0xFF;
UINT yAxis = (infoEx.dwYpos >> 8) & 0xFF;
UINT controllerButtons = 0;
controllerButtons |= ((yAxis < 103 || infoEx.dwPOV == 0 || infoEx.dwPOV == 4500 || infoEx.dwPOV == 31500) << 4); // U Button
controllerButtons |= ((yAxis > 153 || (infoEx.dwPOV >= 13500 && infoEx.dwPOV <= 22500)) << 5); // D Button
controllerButtons |= ((xAxis < 103 || (infoEx.dwPOV >= 22500 && infoEx.dwPOV <= 31500)) << 6); // L Button
controllerButtons |= ((xAxis > 153 || (infoEx.dwPOV >= 4500 && infoEx.dwPOV <= 13500)) << 7); // R Button
UINT* controllerButtonMappings = !altControllerType ? (UINT*)m_mainControllerButtons : (UINT*)(&m_altControllerButtons[joyNum][0]);
for (UINT i = 0; i < NUM_BUTTONS; i++)
{
if (infoEx.dwButtons & (1 << i))
{
if (controllerButtonMappings[i] != UNUSED)
controllerButtons |= (1 << controllerButtonMappings[i]);
}
}
return controllerButtons | 0x10000; // Controller plugged in status.
}
void SNESMAXCard::InitializeIO(LPBYTE pCxRomPeripheral)
{
RegisterIoHandler(m_slot, &SNESMAXCard::IORead, &SNESMAXCard::IOWrite, IO_Null, IO_Null, this, NULL);
}
bool SNESMAXCard::ParseControllerMappingFile(UINT joyNum, const char* pathname, std::string& errorMsg)
{
bool res = true;
YamlHelper yamlHelper;
try
{
if (!yamlHelper.InitParser(pathname))
throw std::runtime_error("Controller mapping file: Failed to initialize parser or open file");
if (yamlHelper.ParseFileHdr("AppleWin Controller Button Remapping") != 1)
throw std::runtime_error("Controller mapping file: Version mismatch");
std::string scalar;
while (yamlHelper.GetScalar(scalar))
{
if (scalar == SS_YAML_KEY_UNIT)
{
yamlHelper.GetMapStartEvent();
YamlLoadHelper yamlLoadHelper(yamlHelper);
std::string hid = yamlLoadHelper.LoadString("HID");
std::string desc = yamlLoadHelper.LoadString("Description");
for (UINT i = 0; i < SNESMAXCard::NUM_BUTTONS; i++)
{
char szButtonNum[3] = "00";
sprintf_s(szButtonNum, "%d", i + 1); // +1 as 1-based
std::string buttonNum = szButtonNum;
bool found = false;
std::string buttonStr = yamlLoadHelper.LoadString_NoThrow(buttonNum, found);
SNESMAXCard::Button button = SNESMAXCard::UNUSED;
if (found)
{
if (buttonStr == "A") button = SNESMAXCard::A;
else if (buttonStr == "B") button = SNESMAXCard::B;
else if (buttonStr == "X") button = SNESMAXCard::X;
else if (buttonStr == "Y") button = SNESMAXCard::Y;
else if (buttonStr == "LB") button = SNESMAXCard::LB;
else if (buttonStr == "RB") button = SNESMAXCard::RB;
else if (buttonStr == "SELECT") button = SNESMAXCard::SELECT;
else if (buttonStr == "START") button = SNESMAXCard::START;
else if (buttonStr == "") button = SNESMAXCard::UNUSED;
else throw std::runtime_error("Controller mapping file: Unknown button: " + buttonStr);
}
m_altControllerButtons[joyNum][i] = button;
}
}
else
{
throw std::runtime_error("Unknown top-level scalar: " + scalar);
}
break; // TODO: extend to support multiple controllers
}
}
catch (const std::exception& szMessage)
{
errorMsg = "Error with yaml file: ";
errorMsg += pathname;
errorMsg += "\n";
errorMsg += szMessage.what();
res = false;
}
yamlHelper.FinaliseParser();
if (res)
g_cmdLine.snesMaxAltControllerType[joyNum] = true; // Enable the alt controller
return res;
}
//===========================================================================
static const UINT kUNIT_VERSION = 1;
@ -235,8 +272,8 @@ bool SNESMAXCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
m_buttonIndex = yamlLoadHelper.LoadUint(SS_YAML_KEY_BUTTON_INDEX);
// Initialise with no buttons pressed (loaded state maybe part way through reading the buttons)
m_controller1Buttons = 0xff;
m_controller2Buttons = 0xff;
m_controller1Buttons = 0x1ffff;
m_controller2Buttons = 0x1ffff;
return true;
}

View File

@ -31,10 +31,18 @@ public:
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
static bool ParseControllerMappingFile(UINT joyNum, const char* pathname, std::string& errorMsg);
private:
UINT GetControllerButtons(UINT joyNum, JOYINFOEX& infoEx, bool altControllerType);
enum Button { B, Y, SELECT, START, U, D, L, R, A, X, LB, RB, UNUSED1, UNUSED2, UNUSED3, UNUSED4, NUM_BUTTONS, UNUSED };
UINT m_buttonIndex;
UINT m_controller1Buttons;
UINT m_controller2Buttons;
static const UINT m_mainControllerButtons[NUM_BUTTONS];
bool m_altControllerType[2];
static UINT m_altControllerButtons[2][NUM_BUTTONS];
};

Some files were not shown because too many files have changed in this diff Show More