Merge branch 'master' into sdl4
# Conflicts: # source/CMakeLists.txt # source/frontends/ncurses/main.cpp # source/frontends/ncurses/resources.cpp
This commit is contained in:
commit
ae0194d5b1
185 changed files with 6641 additions and 3485 deletions
|
@ -70,7 +70,7 @@
|
|||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4819;4995;4996"
|
||||
DisableSpecificWarnings="4482;4819;4995;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
|
@ -169,7 +169,7 @@
|
|||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="4"
|
||||
DisableSpecificWarnings="4819;4995;4996"
|
||||
DisableSpecificWarnings="4482;4819;4995;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
|
@ -826,11 +826,11 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\CPU\cpu65d02.h"
|
||||
RelativePath=".\source\CPU\cpu_general.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\CPU\cpu_general.inl"
|
||||
RelativePath=".\source\CPU\cpu_heatmap.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -1087,6 +1087,14 @@
|
|||
RelativePath=".\resource\Apple2.rom"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource\Apple2_JPlus.rom"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource\Apple2_JPlus_Video.rom"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource\Apple2_Plus.rom"
|
||||
>
|
||||
|
@ -1177,6 +1185,10 @@
|
|||
RelativePath="RESOURCE\DISK.ICO"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource\Disk2-13sector.rom"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource\Disk2.rom"
|
||||
>
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
<ClInclude Include="source\CPU.h" />
|
||||
<ClInclude Include="source\CPU\cpu6502.h" />
|
||||
<ClInclude Include="source\CPU\cpu65C02.h" />
|
||||
<ClInclude Include="source\CPU\cpu65d02.h" />
|
||||
<ClInclude Include="source\Debugger\Debug.h" />
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
|
|
|
@ -237,9 +237,6 @@
|
|||
<ClInclude Include="source\CPU\cpu6502.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65d02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65C02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
<ClInclude Include="source\CPU.h" />
|
||||
<ClInclude Include="source\CPU\cpu6502.h" />
|
||||
<ClInclude Include="source\CPU\cpu65C02.h" />
|
||||
<ClInclude Include="source\CPU\cpu65d02.h" />
|
||||
<ClInclude Include="source\Debugger\Debug.h" />
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
|
|
|
@ -237,9 +237,6 @@
|
|||
<ClInclude Include="source\CPU\cpu6502.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65d02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65C02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
<ClInclude Include="source\CPU.h" />
|
||||
<ClInclude Include="source\CPU\cpu6502.h" />
|
||||
<ClInclude Include="source\CPU\cpu65C02.h" />
|
||||
<ClInclude Include="source\CPU\cpu65d02.h" />
|
||||
<ClInclude Include="source\Debugger\Debug.h" />
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
|
|
|
@ -237,9 +237,6 @@
|
|||
<ClInclude Include="source\CPU\cpu6502.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65d02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65C02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
<ClInclude Include="source\CPU.h" />
|
||||
<ClInclude Include="source\CPU\cpu6502.h" />
|
||||
<ClInclude Include="source\CPU\cpu65C02.h" />
|
||||
<ClInclude Include="source\CPU\cpu65d02.h" />
|
||||
<ClInclude Include="source\Debugger\Debug.h" />
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
|
@ -237,6 +236,8 @@
|
|||
<None Include="resource\Apple2e.rom" />
|
||||
<None Include="resource\Apple2e_Enhanced.rom" />
|
||||
<None Include="resource\Apple2_Plus.rom" />
|
||||
<None Include="resource\Base64A.rom" />
|
||||
<None Include="resource\Base64A_German_Video.rom" />
|
||||
<None Include="resource\DISK2.rom" />
|
||||
<None Include="resource\Freezes_Non-autostart_F8_Rom.rom" />
|
||||
<None Include="resource\Hddrvr.bin" />
|
||||
|
@ -298,6 +299,7 @@
|
|||
<Image Include="resource\LED_CAPS_ON_P8.BMP" />
|
||||
<Image Include="resource\RUN.BMP" />
|
||||
<Image Include="resource\RUN3000E.bmp" />
|
||||
<Image Include="resource\RUNBASE64A.BMP" />
|
||||
<Image Include="resource\RUNP.BMP" />
|
||||
<Image Include="resource\SETUP.BMP" />
|
||||
</ItemGroup>
|
||||
|
@ -372,7 +374,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>source;source\cpu;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
|
@ -399,7 +401,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>source;source\cpu;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
|
@ -427,7 +429,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>source;source\cpu;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
|
@ -459,7 +461,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>source;source\cpu;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
|
|
|
@ -237,9 +237,6 @@
|
|||
<ClInclude Include="source\CPU\cpu6502.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65d02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\CPU\cpu65C02.h">
|
||||
<Filter>Source Files\CPU</Filter>
|
||||
</ClInclude>
|
||||
|
@ -593,6 +590,9 @@
|
|||
<Image Include="resource\RUN3000E.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resource\RUNBASE64A.BMP">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="resource\Apple2.rom">
|
||||
|
@ -652,6 +652,12 @@
|
|||
<None Include="resource\TKClock.rom">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resource\Base64A.rom">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resource\Base64A_German_Video.rom">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="docs\CodingConventions.txt">
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
include(CPack)
|
||||
|
||||
project(applewin)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar -Werror=return-type")
|
||||
|
|
|
@ -4,9 +4,9 @@ AppleWin
|
|||
Apple II emulator for Windows
|
||||
|
||||
|
||||
Download latest (stable) release: [AppleWin v1.29.0.0](https://github.com/AppleWin/AppleWin/releases/download/v1.29.0.0/AppleWin1.29.0.0.zip)
|
||||
Download latest (stable) release: [AppleWin v1.29.13.0](https://github.com/AppleWin/AppleWin/releases/download/v1.29.13.0/AppleWin1.29.13.0.zip)
|
||||
|
||||
Release Notes: [v1.29.0.0](https://github.com/AppleWin/AppleWin/releases/tag/v1.29.0.0)
|
||||
Release Notes: [v1.29.13.0](https://github.com/AppleWin/AppleWin/releases/tag/v1.29.13.0)
|
||||
|
||||
|
||||
Building
|
||||
|
@ -26,8 +26,8 @@ Please report [new issues](https://github.com/AppleWin/AppleWin/issues/new)
|
|||
Previous Versions
|
||||
=================
|
||||
|
||||
* [AppleWin v1.28.0.0](https://github.com/AppleWin/AppleWin/releases/download/v1.28.0.0/AppleWin1.28.0.0.zip)
|
||||
* [AppleWin v1.28.8.0](https://github.com/AppleWin/AppleWin/releases/tag/v1.28.8.0)
|
||||
|
||||
Last pre-NTSC change:
|
||||
|
||||
* [AppleWin v1.25.0.4](https://github.com/AppleWin/AppleWin/releases/download/v1.25.0.4/AppleWin1.25.0.4.zip)
|
||||
* [AppleWin v1.25.0.4](https://github.com/AppleWin/AppleWin/releases/tag/v1.25.0.4)
|
||||
|
|
|
@ -121,11 +121,14 @@ C017 RDC3ROM
|
|||
C018 RD80STORE
|
||||
C019 RDVBLBAR
|
||||
C01A RDTEXT
|
||||
C01B RDMIXED
|
||||
C01C RDPAGE2
|
||||
C01D RDHIRES
|
||||
C01E ALTCHARSET
|
||||
C01F RD80COL
|
||||
C020 TAPEOUT
|
||||
C030 SPKR
|
||||
C040 STROBE
|
||||
C050 TXTCLR
|
||||
C051 TXTSET
|
||||
C052 MIXCLR
|
||||
|
@ -145,18 +148,48 @@ C05F CLRAN3
|
|||
C060 TAPEIN
|
||||
C061 BUTNO
|
||||
C062 BUTN1
|
||||
C063 BUTN2
|
||||
C064 PADDL0
|
||||
C065 PADDL1
|
||||
C066 PADDL2
|
||||
C067 PADDL3
|
||||
C070 PTRIG
|
||||
C080 STEPPER
|
||||
C081 ROMIN
|
||||
|
||||
; Slot-0: Language Card
|
||||
C080 LCRAMIN2
|
||||
C081 ROMIN2
|
||||
C082 LCROMIN2
|
||||
C083 LCBANK2
|
||||
C08A ENABLE1
|
||||
C08B LCBANK1/ENABLE2
|
||||
C08C DATASTROBE
|
||||
C08D LOADLATCH
|
||||
C08E SETREADMODE
|
||||
C08E WRITEPROT
|
||||
C08F SETWRITEMODE
|
||||
C084 LCRAMIN2_
|
||||
C085 ROMIN2_
|
||||
C086 LCROMIN2_
|
||||
C087 LCBANK2_
|
||||
C088 LCRAMIN1
|
||||
C089 ROMIN1
|
||||
C08A LCROMIN1
|
||||
C08B LCBANK1
|
||||
C08C LCRAMIN1_
|
||||
C08D ROMIN1_
|
||||
C08E LCROMIN1_
|
||||
C08F LCBANK1_
|
||||
|
||||
; Slot-6: DiskII interface
|
||||
C0E0 DRV_P0_OFF
|
||||
C0E1 DRV_P0_ON
|
||||
C0E2 DRV_P1_OFF
|
||||
C0E3 DRV_P1_ON
|
||||
C0E4 DRV_P2_OFF
|
||||
C0E5 DRV_P2_ON
|
||||
C0E6 DRV_P3_OFF
|
||||
C0E7 DRV_P3_ON
|
||||
C0E8 DRV_OFF
|
||||
C0E9 DRV_ON
|
||||
C0EA DRV_SEL1
|
||||
C0EB DRV_SEL2
|
||||
C0EC DRV_SHIFT
|
||||
C0ED DRV_LOAD
|
||||
C0EE DRV_READ
|
||||
C0EF DRV_WRITE
|
||||
|
||||
; Firmware
|
||||
; Renamed due to ROM name collision
|
||||
|
|
|
@ -8,6 +8,82 @@ https://github.com/AppleWin/AppleWin/issues/new
|
|||
|
||||
Tom Charlesworth
|
||||
|
||||
1.29.14.0 - 17 Aug 2020
|
||||
-----------------------
|
||||
. [Change #822] Updated Uthernet card support to use Npcap for Win10.
|
||||
. [Change #806] Added support for 'Base 64A' - a Taiwanese Apple II clone.
|
||||
. [Change #763] Support for PAL(50Hz) killing color-burst during TEXT video mode.
|
||||
- When 50Hz, then AppleWin's window title changes to "Color (PAL Monitor)" instead of "Color (NTSC Monitor)"
|
||||
. [Change #781] Loading a large save-state takes some time - added a busy indicator.
|
||||
. [Change #139] NIB disk image: added warning if any track's first D5-nibble triple isn't an address prologue.
|
||||
. [Bug #824] Fixed a regression in multi-zip support (introduced at 1.29.10.0).
|
||||
. [Bug #820] Fixed a GDI Object leak (occurring when accessing the Disk II with AppleWin minimised).
|
||||
. [Bug #813] Mockingboard playback looping after entering debugger then configuration.
|
||||
. [Bug #809] Fixed a memory leak.
|
||||
. [Bug #801] Wrong timing with LSR abs,X / ROR abs,X / ROL abs,X for the 6502 CPU.
|
||||
. [Bug #796] Fix for 'IRQ occurring on last cycle of opcode' not always true.
|
||||
. [Bug #751] No-Slot Clock running and power-cycle can causes lock-up on power-cycle.
|
||||
- NSC state persisted to save-state.
|
||||
- added a new switch '-no-nsc' to configure Apple II without an NSC.
|
||||
. [Bug #663, #691] Fixes for image loading switches (-d1,-d2,-h1,-h2,-s5d1,-s5d2):
|
||||
- support relative paths (#663).
|
||||
- updated the current directory with the path for each loaded image (#663) & when saving state (#691).
|
||||
- added a new switch '-current-dir <path>' to guarantee the current dir after using image loading switches.
|
||||
. [Bug #52] Fixed the 6502/65C02 false-read of 6522 issue for Willy Byte!
|
||||
. [PR #800] Improved debugger's rendering speed for PrintGlyph().
|
||||
|
||||
|
||||
1.29.13.0 - 31 May 2020
|
||||
-----------------------
|
||||
. [Bug #790] Fixed regression for -d1,-d2 & -s7-empty-on-exit (introduced at 1.29.7.0).
|
||||
. [Change #787] Debugger: Extended 'cycles part' command to do timings relative to a user-specified base.
|
||||
. [Change #783] Debugger: Extended 'tf' command to include cycle count.
|
||||
. [Change #720] Debugger: Added more symbols to APPLE2E.SYM.
|
||||
- NB. LC ($C08n) symbols are now correct for the LC, so 'LDA $C08C,X' will disassemble as 'LDA LCRAMIN1_,X'
|
||||
instead of 'LDA DATASTROBE,X'. So now perhaps less helpful when stepping Disk II code.
|
||||
. [PR #785] Debugger: Improvements to Bookmarks.
|
||||
- AppleWin.chm: Added debugger help about Bookmarks.
|
||||
. Fixed occasional speaker clicks in full-speed mode.
|
||||
|
||||
|
||||
1.29.12.0 - 26 Apr 2020
|
||||
-----------------------
|
||||
. [PR #757] Allow use of an INI-file for configuration instead of the Registry (fixes #709).
|
||||
- new command line switch: -conf <INI-file>
|
||||
. [Change #773] Added Apple II J-Plus support.
|
||||
. [Bug #778] Fixed for when Joystick(s) are disabled.
|
||||
. [Bug #777] Fixed Phasor speech (SSI263) to match Mockingboard (when in Mockingboard mode).
|
||||
- fixes: #698 (Rescue Raiders), #753 (Bejeweled).
|
||||
- also improvements to Phasor card's native Phasor mode.
|
||||
. [PR #775] Debugger: Fixed so that hitting "=" in the debugger sets PC to the current cursor address.
|
||||
|
||||
|
||||
1.29.11.0 - 27 Mar 2020
|
||||
-----------------------
|
||||
. [Change #771] Added new command line switch to load custom ROM: -rom <file>.
|
||||
- Supports 12KiB (at $D000) and 16KiB (at $C000) rom files.
|
||||
. [Bug #765] Lancaster (Total Replay) hangs when starting second game.
|
||||
. [Change #734] DiskII controller card: support 13-sector firmware.
|
||||
- The card auto-selects the firmware based on the .woz (v2 or higher) image properties.
|
||||
- Only change the firmware at reset/reboot to avoid changing whilst running in $C6xx space!
|
||||
- Fixes 'The Best of MUSE' & 'MicroChess 2.0' (#732)
|
||||
|
||||
|
||||
1.29.10.0 - 13 Feb 2020
|
||||
-----------------------
|
||||
. [PR #756] Write support for WOZ1/WOZ2 images.
|
||||
- Fixes titles that need write support (see: #686, #704, #705).
|
||||
- Allow creation of a blank (WOZ2) image (see AppleWin.chm: 'Creating Disk Images').
|
||||
- multi-file zip support extended to scan for the first valid image.
|
||||
- useful for most woz-a-day multi-file zips which have at least 2 entries and previously needed unzipping.
|
||||
. NB. files in multi-file zips are still write-protected (same for all image types, not just woz).
|
||||
|
||||
|
||||
1.29.9.0 - 26 Jan 2020
|
||||
----------------------
|
||||
. [Bug #750] Fixed double-clicking a registered file-type issue (regression introduced at 1.29.8.0).
|
||||
. [Bug #752] Fixed Ctrl+Alt+Break wasn't emulating CTRL+OA+RESET (regression introduced at 1.29.8.0).
|
||||
|
||||
|
||||
1.29.8.0 - 19 Jan 2020
|
||||
----------------------
|
||||
|
@ -15,7 +91,7 @@ Tom Charlesworth
|
|||
. [Bug #748] DiskII: data latch returns a rand() value when no disk is in drive.
|
||||
. [Bug #746] Debugger: correctly repaint Apple II screen when showing it from debugger.
|
||||
. [Bug #745] WOZ: Support for large tracks.
|
||||
. [Bug #743] Added new command line switches:
|
||||
. [Change #743] Added new command line switches:
|
||||
-left-alt-control-buttons : left-ctrl=button0, left-alt=button1
|
||||
-right-alt-control-buttons : right-alt=button0, right-ctrl=button1
|
||||
-swap-buttons : for swapping buttons 0 & 1
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
/*
|
||||
|
||||
|
||||
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
|
||||
|
||||
.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.
|
||||
.16 Fixed: Replacing an existing bookmark incorrectly increased the total bookmark count.
|
||||
.15 Cleanup: HELP CALC examples and See also.
|
||||
.14 Fixed: HELP JSR wasn't color-coding syntax.
|
||||
.13 Added: PROFILE LIST now shows how many clock cycles were executed.
|
||||
|
|
|
@ -98,3 +98,26 @@ N/A
|
|||
5. Clean & build:
|
||||
devenv AppleWinExpress2008.sln /clean
|
||||
cov-build --dir cov-int devenv AppleWinExpress2008.sln /build release
|
||||
|
||||
|
||||
|
||||
|
||||
How to disable F12 so it doesn't trigger a breakpoint
|
||||
=====================================================
|
||||
|
||||
When running AppleWin from Visual Studio (eg. F5), then F12 will trigger a breakpoint.
|
||||
|
||||
This is undesirable, since F12 is used to load a save-state.
|
||||
|
||||
AppleWin does also support CTRL+F12 to load a save-state too (for this very reason), but it's possible to disable F12 triggering the breakpoint.
|
||||
|
||||
Background:
|
||||
F12 is the OS's default UserDebuggerHotKey:
|
||||
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc786263(v=ws.10)
|
||||
|
||||
Fix:
|
||||
. Change this Registry key: "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" -> UserDebuggerHotKey to 0x07 (*)
|
||||
. And restart the PC for it to take effect.
|
||||
|
||||
(*) Where 0x07 = Undefined
|
||||
(See: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes)
|
|
@ -1,165 +0,0 @@
|
|||
Setting up CVS for AppleWin
|
||||
Revision 3
|
||||
+ Added pass-phrase, pageant, putty info
|
||||
Revision 2
|
||||
+ Added diff/merge
|
||||
|
||||
|
||||
This is the step-by-step tutorial in getting CVS setup for AppleWin.
|
||||
There are a few steps, but each one is quick and easy to do.
|
||||
|
||||
|
||||
1. Create an account BerliOS
|
||||
http://developer.berlios.de/
|
||||
|
||||
|
||||
2. Download and install TortoiseCVS.
|
||||
a) http://www.tortoisecvs.org/
|
||||
b) Reboot Windows (Grr...)
|
||||
|
||||
You can find a tutorial on how to use TortoiseCVS here:
|
||||
http://cedric.babault.free.fr/TortoiseCVSDoc/UserGuide_en.html
|
||||
|
||||
If you don't want to use TortoiseCVs, you have a few options:
|
||||
|
||||
i) WinCVS (which also has a Mac OS X port, called MacCVS)
|
||||
http://www.wincvs.org/
|
||||
|
||||
ii) cvsnt:
|
||||
http://www.march-hare.com/cvspro/
|
||||
|
||||
|
||||
3. Generate a SSH2 key, using "puttygen"
|
||||
Recommend: using a pass-phrase
|
||||
Recommend: using comment:
|
||||
<username>@shell.berlios.de
|
||||
|
||||
If you installed TortoiseCVS, you will notice it includes an older version of puttygen.exe:
|
||||
i.e.
|
||||
\Program Files\TortoiseCVS\puttygen.exe
|
||||
\Programs\VersionControl\TortoiseCVS\puttygen.exe
|
||||
|
||||
You can find the latest PuTTY here:
|
||||
http://www.chiark.greenend.org.uk/~sgtatham/putty/
|
||||
|
||||
And depending on where you installed it to:
|
||||
C:\Program Files\Putty\puttgygen.exe
|
||||
P:\Programs\Util\Shell\PuTTY\puttygen.exe
|
||||
|
||||
4. In your home directory, make a sub-directory called: .ssh
|
||||
i.e.
|
||||
C:\Document and Settings\<username>\.ssh
|
||||
\users\<username>\.ssh
|
||||
|
||||
|
||||
5. Save your public key into your home directory
|
||||
i.e.
|
||||
<username>\.ssh\identity.pub
|
||||
|
||||
|
||||
6. Save your private key into your home directory
|
||||
i.e.
|
||||
<username>\.ssh\identity
|
||||
|
||||
|
||||
7. Upload your Public SSH key to BerliOS
|
||||
a) http://developer.berlios.de/
|
||||
b) Account Options
|
||||
c) Edit Keys (at bottom of webpage)
|
||||
d) copy from puttygen, and paste into web form
|
||||
e) Verify: CVS/SVN/SSH Shared Keys: 1 <-- was zero
|
||||
|
||||
You will have to use your pass-phrase (may be up to a few hours),
|
||||
until BerliOS recognizes the uploaded ssh2 key.
|
||||
|
||||
|
||||
8. Using Windows Explorer, navigate to the parent directory where you will download AppleWin
|
||||
i.e.
|
||||
<username>\Projects\
|
||||
P:\<username>\Projects\
|
||||
|
||||
|
||||
9. (Optional) Specify a home folder.
|
||||
|
||||
If you have TortoiseCVS installed:
|
||||
a) right Click on any directory
|
||||
b) select CVS
|
||||
c) Preferences.
|
||||
TortoiseCVS should appear.
|
||||
d) Select "Advanced" Tab
|
||||
e) Home Folder: uncheck, always recalculate home folder
|
||||
f) Enter your home directory, for "Custom Home folder"
|
||||
|
||||
|
||||
10. (Optional) Set CVS environment variable: CVS_RSH
|
||||
If you are using TortoiseCVS you can skip this step.
|
||||
(TortoiseCVS uses 'plink' -- command line wrapper for ssh.)
|
||||
|
||||
For other cvs clients, you may need to set CVS_RSH:
|
||||
To set the environment variable "CVS_RSH" to "ssh" (without the quotes):
|
||||
Right-click the My Computer icon on your desktop, Properties, Advanced, Environment variables button.
|
||||
|
||||
|
||||
11. Setting CVSROOT.
|
||||
If you use TortoiseCVS
|
||||
a) right click on the AppleWin Parent directory (the folder where AppleWin will be downloaded to)
|
||||
b) CVS Checkout,
|
||||
and set CVSROOT to:
|
||||
:ext:<username>@cvs.applewin.berlios.de:/cvsroot/applewin
|
||||
|
||||
c) set Module (case sensitive!) to:
|
||||
AppleWin
|
||||
d) select OK, and wait to fetch the complete AppleWin directory.
|
||||
|
||||
Troubleshooting:
|
||||
* You can delete "Previous CVSROOTs":
|
||||
Right click on folder, CVS, Checkout, select appropiate, delete key
|
||||
You will have to press OK for the old entries to be deleted.
|
||||
When you do, a fetch attempt will also be made.
|
||||
* If you enter the wrong init param, you may have to rename / delete your local AppleWin folder!
|
||||
* If you still have problems, you may have to remove the SSH (host) entry from the registry:
|
||||
i.e.
|
||||
HKEY_CURRENT_USER\Software\SimonTatham\Putty\SshHostKeys
|
||||
|
||||
* You shouldn't have to edit, but if you need to, this CVS config file is plain text:
|
||||
AppleWin\CVS\Root
|
||||
|
||||
If you use another cvs client, such as WinCVS, or CVSNT, this may work:
|
||||
:ssh:<username>@cvs.applewin.berlios.de:/cvsroot/applewin
|
||||
|
||||
|
||||
12. You can download a free source-code 'diff' & 'merge' app for win32
|
||||
(which integrates into TortoiseCVS) from here:
|
||||
http://winmerge.sourceforge.net/
|
||||
|
||||
Alternatively you can download a free source-code 'diff' for Win32 here:
|
||||
http://www.prestosoft.com/ps.asp?page=edp_examdiff
|
||||
|
||||
|
||||
13. Start hacking the code!
|
||||
|
||||
|
||||
14. Automatically use your SSH2 key, instead of manually typing your pass-phrase.
|
||||
If you generated a SSH2 private/public key, and have uploaded it to BerliOS,
|
||||
you can tell TortoiseCVS to use your SSH2 key-pair instead of asking for your pass-phrase on every CVS action.
|
||||
|
||||
If you have PuTTY (pageant) installed:
|
||||
a) Run pageant
|
||||
C:\Program Files\PuTTY\pageant.exe
|
||||
|
||||
If you get a configuration error when starting pageant.exe on Win XP, this provides a workaround:
|
||||
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/xp-wont-run
|
||||
|
||||
b) Right Click on pageant in the system tool bar
|
||||
c) Add key
|
||||
d) Select your private key
|
||||
<username>\.ssh\identity.ppk
|
||||
|
||||
If you have TortoiseCVS installed:
|
||||
a) right Click on any directory
|
||||
b) select CVS
|
||||
c) Preferences.
|
||||
TortoiseCVS should appear.
|
||||
d) Select "Tools" Tab
|
||||
e) To the SSH paramaters, add: -2
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
Setting up SVN for AppleWin
|
||||
===========================
|
||||
|
||||
(This doc assumes you started with cvs_setup.txt)
|
||||
|
||||
|
||||
1. Download and install TortoiseSVN.
|
||||
a) http://tortoisesvn.sourceforge.net/
|
||||
b) Reboot Windows (Grr...)
|
||||
|
||||
==========
|
||||
|
||||
Start by reading the TortoiseSVN help... or just dive right in :)
|
||||
|
||||
|
||||
To browse the svn repository using:
|
||||
a) Web browser (WebSVN) : http://svn.berlios.de/wsvn/applewin
|
||||
b) Windows Explorer: TortoiseSVN -> Repro-browser
|
||||
|
||||
|
||||
Use 'SVN Checkout...' off the right-context menu in a Windows folder.
|
||||
|
||||
URL of repository:
|
||||
http://svn.berlios.de/svnroot/repos/applewin/trunk
|
||||
(to get trunk)
|
||||
|
||||
http://svn.berlios.de/svnroot/repos/applewin
|
||||
(to get everything! Or use [...] to browse for your specific branch)
|
|
@ -11,6 +11,11 @@
|
|||
<p style="FONT-WEIGHT: bold">AppleWin can be driven from the command line as
|
||||
follows:
|
||||
</p>
|
||||
-conf <pathname><br>
|
||||
Use an INI file for configuration instead of the Registry.<br><br>
|
||||
-current-dir <path><br>
|
||||
This is guaranteed to be processed after all the image loading switches (eg. -d1, -h1, etc).<br>
|
||||
Use this switch if you have a mix of (eg) -d1 and -h1 loading images from different folders, and you want to guarantee the current dir.<br><br>
|
||||
-d1 <pathname><br>
|
||||
Start with a floppy disk in slot 6 drive-1 (and auto power-on the Apple II).<br>
|
||||
NB. -s6d1 has the meaning same as -d1.<br><br>
|
||||
|
@ -25,8 +30,8 @@
|
|||
Start with hard disk 1 plugged-in (and auto power-on the Apple II). NB. Hard disk controller card gets enabled.<br><br>
|
||||
-h2 <pathname><br>
|
||||
Start with hard disk 2 plugged-in. NB. Hard disk controller card gets enabled.<br><br>
|
||||
-model <apple2|apple2p|apple2e|apple2ee><br>
|
||||
Select the machine model: Apple II, Apple II+, Apple //e, Enhanced Apple //e.<br><br>
|
||||
-model <apple2|apple2p|apple2jp|apple2e|apple2ee><br>
|
||||
Select the machine model: Apple II, Apple II+, Apple II J-Plus, Apple //e, Enhanced Apple //e.<br><br>
|
||||
-clock-multiplier <value><br>
|
||||
Where value is between 0.5 and 3.9, and is a base-clock multiplier, roughly mapping to 0.5MHz - 3.9MHz<br><br>
|
||||
-s0 <saturn|saturn64|saturn128><br>
|
||||
|
@ -50,10 +55,12 @@
|
|||
Useful to allow a floppy disk to boot from slot 6, drive 1. Use in combination with -d1.<br><br>
|
||||
-s7-empty-on-exit<br>
|
||||
Remove the hard disk controller card from slot 7 on AppleWin exit.<br><br>
|
||||
-no-nsc<br>
|
||||
Remove the No-Slot clock (NSC).<br><br>
|
||||
-r <number of pages><br>
|
||||
Emulate a RamWorks III card with 1 to 127 pages (each page is 64K, giving a max of 8MB) in the auxiliary slot in an Apple //e machine.<br><br>
|
||||
-load-state <savestate><br>
|
||||
Load a save-state file<br>
|
||||
Load a save-state file (and auto power-on the Apple II).<br>
|
||||
NB. This takes precedent over the -d1, -d2, -d#s#, -h1, -h2, s0-7, -model and -r switches.<br><br>
|
||||
-f<br>
|
||||
Start in full-screen mode<br><br>
|
||||
|
@ -64,8 +71,10 @@
|
|||
<li>nnnn: select a specific resolution with height=nnnn pixels</li>
|
||||
</ul>
|
||||
NB. This changes the display resolution (and restores on exit).<br><br>
|
||||
-rom <file><br>
|
||||
Use custom 12K ROM (at $D000) for Apple II machine, or 16K ROM (at $C000) for Apple //e machine.<br><br>
|
||||
-f8rom <file><br>
|
||||
Use custom 2K ROM for any Apple II machine at [$F800..$FFFF]. <file> must be 2048 bytes long<br><br>
|
||||
Use custom 2K ROM for any Apple II machine at [$F800..$FFFF]. <file> must be 2048 bytes long.<br><br>
|
||||
-videorom <file><br>
|
||||
Use an alternate custom 2K video ROM for Apple II or II+ machines (but not clones).<br>
|
||||
Use an alternate European or custom 4K, 8K or 16K (top 8K only) video ROM for the original or Enhanced //e (but not clones).<br><br>
|
||||
|
@ -89,16 +98,18 @@
|
|||
NB. Using this switch may prevent international keyboards from being able to type certain keys.<br><br>
|
||||
|
||||
-left-alt-control-buttons<br>
|
||||
Use LEFT CONTROL & LEFT ALT for Open Apple & Solid Apple keys respectively.<br><br>
|
||||
Use Left Control & Left Alt for Open Apple & Solid Apple keys respectively.<br>
|
||||
Caveat: Left Control + F2 will do the //e Ctrl+Open Apple+RESET (as Left Control is now both Ctrl and Open Apple!). A workaround is just to use the Right Control key.<br><br>
|
||||
-right-alt-control-buttons<br>
|
||||
Use RIGHT CONTROL & RIGHT ALT for Open Apple & Solid Apple keys respectively.<br><br>
|
||||
Use Right Alt (AltGr) & Right Control for Open Apple & Solid Apple keys respectively.<br>
|
||||
Caveat: Right Control + F2 will do the //e self test (as Right Control is now both Ctrl and Solid Apple!). A workaround is just to use the Left Control key.<br><br>
|
||||
-swap-buttons<br>
|
||||
Swap the Windows keys used for Open Apple & Solid Apple keys.<br><br>
|
||||
|
||||
-use-real-printer<br>
|
||||
Enables Advanced configuration control to allow dumping to a real printer<br><br>
|
||||
-noreg<br>
|
||||
Disable registration of file extensions (.do/.dsk/.nib/.po)<br><br>
|
||||
Disable registration of file extensions (.do/.dsk/.nib/.po/.woz)<br><br>
|
||||
-memclear <n><br>
|
||||
Where n is [0..7]:
|
||||
<ul>
|
||||
|
@ -132,7 +143,10 @@
|
|||
-50hz<br>
|
||||
Support 50Hz(PAL) video refresh rate and PAL 1.016MHz base CPU clock.<br><br>
|
||||
-60hz<br>
|
||||
Support 60Hz(NTSC) video refresh rate and NTSC 1.020MHz base CPU clock (default).<br>
|
||||
Support 60Hz(NTSC) video refresh rate and NTSC 1.020MHz base CPU clock (default).<br><br>
|
||||
-power-on<br>
|
||||
Force a power-on.<br>
|
||||
Use to auto power-on when not using -d1, -h1 or -load-state.<br>
|
||||
|
||||
<br>
|
||||
<P style="FONT-WEIGHT: bold">Debug arguments:
|
||||
|
|
|
@ -78,6 +78,10 @@
|
|||
<param name="Name" value="Save-state Files">
|
||||
<param name="Local" value="savestate.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Command line">
|
||||
<param name="Local" value="CommandLine.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Sound">
|
||||
<param name="Local" value="sound.html">
|
||||
|
@ -101,10 +105,6 @@
|
|||
<param name="Local" value="uthernet-wifi-workaround.html">
|
||||
</OBJECT>
|
||||
</UL>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Command line">
|
||||
<param name="Local" value="CommandLine.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="AppleWin Configuration">
|
||||
<param name="Local" value="configuration.html">
|
||||
|
@ -195,6 +195,10 @@
|
|||
<param name="Name" value="Breakpoints">
|
||||
<param name="Local" value="dbg-breakpoints.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Bookmarks">
|
||||
<param name="Local" value="dbg-bookmarks.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Configuration">
|
||||
<param name="Local" value="dbg-configuration.html">
|
||||
|
@ -211,7 +215,7 @@
|
|||
<param name="Local" value="newsgroups.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
<param name="Name" value="Internet FTP Sites">
|
||||
<param name="Name" value="Internet Sites">
|
||||
<param name="Local" value="ftp.html">
|
||||
</OBJECT>
|
||||
<LI> <OBJECT type="text/sitemap">
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
link="#008000" vlink="#008000">
|
||||
<h2 style="COLOR: rgb(0,128,0)">Acknowledgements</h2>
|
||||
<hr size="4">
|
||||
<p>The team would like to thank the following people for their contributions:</p>
|
||||
<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">Chris Foxwell: SSI263 phoneme samples</p>
|
||||
<p style="MARGIN-LEFT: 40px">Greg Hedger: SSI263 phoneme samples</p>
|
||||
<p style="MARGIN-LEFT: 40px">Robert Hoem: Hard disk card (source module & 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>
|
||||
- In particular, Spiro Trikaliotis for TFE, whose code Glenn Jones adapted for Uthernet support</p>
|
||||
|
@ -21,5 +21,9 @@
|
|||
<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 & 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: numerous pull-requests</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: debugger improvements</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -22,7 +22,9 @@ 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.<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>
|
||||
</p>
|
||||
<p><strong>Printer settings </strong>(Printer is emulated in slot 1)
|
||||
</p>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<ul>
|
||||
<li>Apple ][ : 48K non-autostarting, Integer BASIC, no lower-case, no 80-column, 6502 CPU
|
||||
<li>Apple ][+ : 64K autostarting, Applesoft BASIC version of the Apple ][
|
||||
<li>Apple ][ J-Plus : 64K autostarting, Applesoft BASIC, Japanese version of the Apple ][+
|
||||
<li>Apple //e : 128K machine, lower-case, 80-column, 6502 CPU</li>
|
||||
<li>Enhanced Apple //e : 128K machine, lower-case, 80-column, 65C02 CPU</li>
|
||||
<li>Clone (specific model selectable from Advanced page)</li>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<h3>Clock:</h3>
|
||||
<p>AppleWin emulates a No-Slot clock (aka NSC).</p>
|
||||
<p>This is a chip (a Dallas SmartWatch DS1216) that sits under one of the 28-pin ROM chips in the Apple II.<br>
|
||||
No hardware configuration is required: this chip is always present, but won't interfere with emulation when not in use.
|
||||
No hardware configuration is required: this chip is always present (unless -no-nsc is used), but won't interfere with emulation when not in use.
|
||||
</p>
|
||||
<p>It requires a software driver to be installed (for DOS and ProDOS). This driver then emulates the Thunderclock card.</p>
|
||||
<p>Here's a summary of NSC/ROM chip locations and which drivers work:</p>
|
||||
|
|
127
help/dbg-bookmarks.html
Normal file
127
help/dbg-bookmarks.html
Normal file
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>AppleWin Debugger Tutorial</title>
|
||||
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=windows-1252">
|
||||
</head>
|
||||
<body style="DIRECTION: ltr" lang="en-US">
|
||||
<h1>Bookmarks</h1>
|
||||
<p>Bookmarks allow you to "tag" an address and consequently jump back to them.<br>
|
||||
They appear as a number with a circle around them between where address and opcodes are listed (where the : separator is).
|
||||
</p>
|
||||
|
||||
<img src="img/debugger-bookmarks-annotated.png" hspace="5" vspace="5">
|
||||
|
||||
<br>
|
||||
<p><font size="4"><b>Notes</b>:</font></p>
|
||||
<ul>
|
||||
<li>Set a bookmark at the current disassembly cursor, use Ctrl-Shift-#, ie:
|
||||
<ul>
|
||||
<li>NB. Ctrl-Shift-0 can't be used, as it's not recognised by Windows
|
||||
<li>Ctrl-Shift-1 set bookmark 1
|
||||
<li>Ctrl-Shift-2 set bookmark 2
|
||||
<li>...
|
||||
<li>Ctrl-Shift-9 set bookmark 9
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<br>
|
||||
|
||||
<li>To jump to an existing bookmark, if it exists, press Ctrl-#, ie:
|
||||
<ul>
|
||||
<li>Ctrl-0 to jump to bookmark 0
|
||||
<li>Ctrl-1 to jump to bookmark 1
|
||||
<li>Ctrl-2 to jump to bookmark 2
|
||||
<li>...
|
||||
<li>Ctrl-9 to jump to bookmark 9
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<br>
|
||||
|
||||
<li>NB.
|
||||
<ul>
|
||||
<li>Bookmarks can appear in any order that you set - not just contiguous.
|
||||
<li>An address can only have ONE bookmark assigned to it. If you try setting a new bookmark over an existing one, the old one will become free for use.
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<p><font size="4"><b>Commands to manipulate bookmarks:</b></font></p>
|
||||
|
||||
<table border="1" cellpadding="2" cellspacing="0" width="75%">
|
||||
<COLGROUP>
|
||||
<col width="64">
|
||||
<col width="192">
|
||||
<tbody>
|
||||
<tr bgcolor="#000000">
|
||||
<td width="25%">
|
||||
<p><font color="#ffffff"><b>Command</b></font></p>
|
||||
</td>
|
||||
<td>
|
||||
<p><font color="#ffffff"><b>Description</b></font></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>help bookmarks</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Lists all bookmark related commands</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>help bma</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Lists specific help about the bma command</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>bma <address|label></p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Add a bookmark at an address or label</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>bmc #</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Clear a specific bookmarks, for example 'bmc 1' clears bookmark 1</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>bmc *</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Clears all bookmarks</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>bml</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Lists all boommarks</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%">
|
||||
<p>bmsave</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Not implemented yet</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -27,6 +27,7 @@
|
|||
<LI><A href="dbg-calculator.html">Calculator</A>
|
||||
<LI><A href="dbg-windows.html">Windows</A>
|
||||
<LI><A href="dbg-breakpoints.html">Breakpoints</A>
|
||||
<LI><A href="dbg-bookmarks.html">Bookmarks</A>
|
||||
<LI><A href="dbg-configuration.html">Configuration</A>
|
||||
<UL>
|
||||
<LI><A href="dbg-configuration.html#Colors">Colors</A>
|
||||
|
|
|
@ -47,9 +47,9 @@ do is make a nibble image of the disk. </p>
|
|||
<p>After nibble copiers became
|
||||
prevalent on
|
||||
the Apple, some software publishers developed tricky new ways of
|
||||
creating disks that even nibble copiers could not copy. It is
|
||||
unlikely that such a disk could be successfully transferred into
|
||||
a disk image. </p>
|
||||
creating disks that even nibble copiers could not copy. Such a
|
||||
disk can only be transferred onto a WOZ disk image using the
|
||||
AppleSauce hardware & software. </p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -63,9 +63,9 @@ Disk Images</a> topic for more information. </p>
|
|||
<p>Please note that not all disk image types supported by
|
||||
AppleWin can be created in this manner. Since there is no way
|
||||
to detect the image type from the image itself, it is determined by the
|
||||
given file extension only. Three extensions are allowed: (.DSK, .DO,
|
||||
.NIB). The first two create a "DOS Order Image" and then latter creates
|
||||
a "Nibble Image". If the extension is completely omitted,
|
||||
given file extension only. Four extensions are allowed: (.DSK, .DO,
|
||||
.NIB, .WOZ). The first two create a "DOS Order Image", .NIB creates
|
||||
a "Nibble Image" and .WOZ creates an empty .WOZ image. If the extension is completely omitted,
|
||||
".DSK" will be chosen by default. For more information, see <a href="ddi-formats.html">Disk Image Formats</a>.</p>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -44,11 +44,22 @@ To do this, click the checkbox for "Open as Read Only" in the Select
|
|||
Disk Image dialog. This works like the physical
|
||||
write-protection mechanism on a real Apple //e floppy disk.</p>
|
||||
|
||||
<p>If a Disk Image name is to
|
||||
<p>If a Disk Image name is too
|
||||
long to read in the Toolbar,
|
||||
simply pause the mouse cursor over a drive button to get a
|
||||
tool-tip with the full name.</p>
|
||||
|
||||
<p>Under the vertical Toolbar, are 2 LEDs, one for each floppy disk drive. The colors indicate drive status:
|
||||
<li>Black: drive is off
|
||||
<li>Green: drive is reading
|
||||
<li>Red: drive is writing
|
||||
<li>Orange: drive is reading (and floppy is write-protected)
|
||||
</p>
|
||||
|
||||
<p>By default the Disk II Controller card has the 16-sector firmware (as used by DOS 3.3 and ProDOS). But if a WOZ image that internally identifies as 13-sector format (eg. DOS 3.2) is put into drive 1, then from the start-up/logo screen (or the next reset), the Disk II Controller card's firmware will automatically be switched to the old 13-sector firmware, allowing the disk to boot. And it will automatically switch back if a non-13-sector WOZ (or any non-WOZ) image is put into drive 1 and the machine is reset.<br>
|
||||
NB. There is no support for this feature for non-WOZ images.
|
||||
</p>
|
||||
|
||||
<p><sub style="FONT-WEIGHT: bold">1</sub> To register the file types in Windows Vista, Windows 7 and Windows 10,
|
||||
you will need to run AppleWin with elevated privileges. This only needs to be done once.
|
||||
Right click the AppleWin.exe icon and select 'Run as Administrator'.</p>
|
||||
|
|
|
@ -48,7 +48,7 @@ Common programs for doing this work are ADTPro and Arme Leute Apple Disk Transfe
|
|||
|
||||
|
||||
<p style="font-weight: bold;">Ethernet Transfers:</p>
|
||||
Apples with an <a href="http://a2retrosystems.com/">A2RetroSystems</a> Uthernet
|
||||
Apples with an <a href="http://a2retrosystems.com/">A2RetroSystems</a>' Uthernet
|
||||
card can transfer disk images via ADTPro:
|
||||
<ul>
|
||||
<li>Apple Disk Transfer ProDOS (ADTPro) - <a target="_blank" href="http://adtpro.sourceforge.net/configethernet.html">http://adtpro.sourceforge.net/configethernet.html</a>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Internet FTP Sites</title>
|
||||
<title>Internet Sites</title>
|
||||
|
||||
|
||||
</head>
|
||||
|
@ -11,8 +11,7 @@
|
|||
|
||||
<body style="background-color: rgb(255, 255, 255); font-family: verdana;" alink="#008000" link="#008000" vlink="#008000">
|
||||
|
||||
<h2 style="color: rgb(0, 128, 0);">Internet
|
||||
FTP Sites</h2>
|
||||
<h2 style="color: rgb(0, 128, 0);">Internet Sites</h2>
|
||||
|
||||
<hr size="4">
|
||||
<p>Before transferring a program
|
||||
|
@ -23,11 +22,21 @@ typing the word "binary".</p>
|
|||
<p>
|
||||
<a style="font-weight: bold;" target="_blank" href="ftp://public.asimov.net/pub/apple_II/">ftp://public.asimov.net/pub/apple_II/</a><br>
|
||||
|
||||
This site is the largest Apple
|
||||
II emulation site, and the official release point for new
|
||||
versions of AppleWin. Under the /pub/apple_II directory, you will
|
||||
This site is the largest Apple II emulation site. Under the /pub/apple_II directory, you will
|
||||
find disk images, utilities for making your own disk images, and
|
||||
Apple emulators for other computers and operating systems.</p>
|
||||
|
||||
<p>
|
||||
<a style="font-weight: bold;" target="_blank" href="https://archive.org/details/softwarelibrary_apple">https://archive.org/details/softwarelibrary_apple/</a><br>
|
||||
|
||||
This site contains a number of collections of Apple II software. Including:
|
||||
<ul>
|
||||
<li><a style="font-weight: bold;" target="_blank" href="https://archive.org/details/wozaday">https://archive.org/details/wozaday/</a><br>
|
||||
This is an ever expanding collection of Apple II images in WOZ format.<br>
|
||||
<li><a style="font-weight: bold;" target="_blank" href="https://archive.org/details/softwarelibrary_apple_woz">https://archive.org/details/softwarelibrary_apple_woz/</a><br>
|
||||
Another collection of Apple II images in WOZ format.<br>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
BIN
help/img/debugger-bookmarks-annotated.png
Normal file
BIN
help/img/debugger-bookmarks-annotated.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
help/resources/debugger-bookmarks.png
Normal file
BIN
help/resources/debugger-bookmarks.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -31,20 +31,22 @@
|
|||
<li>CP/M SoftCard</li>
|
||||
<li>Parallel Printer card</li>
|
||||
<li>Super Serial card</li>
|
||||
<li>No-Slot clock</li>
|
||||
</ul>
|
||||
The following are not yet persisted to the file:
|
||||
<ul>
|
||||
<li>Uthernet card</li>
|
||||
<li>SAM card</li>
|
||||
<li>No-Slot clock (there's nothing to persist)</li>
|
||||
<li>Using The Freeze's F8 ROM</li>
|
||||
<li>Alternate F8 ROM</li>
|
||||
<li>Alternate ROM</li>
|
||||
<li>Alternate video ROM</li>
|
||||
</ul>
|
||||
<p>Note: Only the file names of the disk images are stored in the .yaml file (not the
|
||||
full path). This allows you to move your disk image around or distribute them.
|
||||
If AppleWin can't locate the disk image(s), then it will prompt for the new
|
||||
location.</p>
|
||||
<p>NB. Loading of the old v1 file format (.aws file) is still supported.</p>
|
||||
<p>NB. Loading of the old v1 file format (.aws file) is no longer supported. Use AppleWin 1.27.13 to load it at the AppleWin start-up/logo screen,
|
||||
then immediately save it (and it'll be saved in the v2 format).</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
<li><a href="toolbar.html">Using the Toolbar</a>
|
||||
<li><a href="keyboard.html">Using the Keyboard</a>
|
||||
<li><a href="savestate.html">Save-state Files</a>
|
||||
<li><a href="CommandLine.html">Command line</a>
|
||||
<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="CommandLine.html">Command line</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>
|
||||
|
|
|
@ -20,16 +20,17 @@
|
|||
<P style="FONT-WEIGHT: bold">Details:
|
||||
</P>
|
||||
<P>To enable ethernet support in AppleWin you must first download and install
|
||||
WinPcap.
|
||||
Npcap (or WinPcap).
|
||||
</P>
|
||||
<P>An alternative to downloading WinPcap is to get the Wireshark package which
|
||||
includes WinPcap along with Wireshark network analyzer code. To use Wireshark to
|
||||
<P>An alternative to downloading Npcap is to get the Wireshark package which
|
||||
includes Npcap along with Wireshark network analyzer code. To use Wireshark to
|
||||
capture traffic (other than your own) you must be plugged into a shared hub vs
|
||||
a switch. If you plan on doing any network programming Wireshark is a definite
|
||||
must have.
|
||||
</P>
|
||||
<P>WinPcap: <A href="http://www.WinPcap.org/install/default.htm">http://www.WinPcap.org/install/default.htm</A>
|
||||
or Wireshark: <A href="https://www.wireshark.org">https://www.wireshark.org</A>
|
||||
<P>Npcap: <A href="https://nmap.org/npcap/#download">https://nmap.org/npcap/#download</A>
|
||||
or Wireshark: <A href="https://www.wireshark.org">https://www.wireshark.org</A>
|
||||
(or WinPcap: <A href="https://www.winpcap.org/install/default.htm">https://www.winpcap.org/install/default.htm</A>)
|
||||
</P>
|
||||
<P>After AppleWin starts, select the settings icon and then select the ethernet
|
||||
settings button.
|
||||
|
@ -41,7 +42,7 @@
|
|||
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 WinPcap likes to use for
|
||||
to get the text description for each interface vs what Npcap likes to use for
|
||||
a reference. Select Ok. and then close AppleWin.
|
||||
</P>
|
||||
<P><span style="font-weight: bold;">Note:</span> Wireless does not work
|
||||
|
|
5
linux.md
5
linux.md
|
@ -38,13 +38,14 @@ Some key files have been completely reimplemented or discarded:
|
|||
* AppleWin.cpp
|
||||
* Frame.cpp
|
||||
* Video.cpp (partially)
|
||||
* Audio (including Mockingboard but excluding speech in QApple)
|
||||
|
||||
Some features totally ignored:
|
||||
|
||||
* ethernet
|
||||
* serial port
|
||||
* debugger
|
||||
* speech
|
||||
* speech (currently it hangs the emulator)
|
||||
|
||||
The rest is in a very usable state.
|
||||
|
||||
|
@ -79,6 +80,8 @@ This is based on Qt, currently tested with 5.10
|
|||
* the app runs at 60FPS with correction for uneven timer deltas.
|
||||
* full speed when disk spins execute up to 5 ms real wall clock of emulator code (then returns to Qt)
|
||||
* (standard) audio is supported and there are a few configuration options to tune the latency (default very conservative 200ms)
|
||||
* plain mockingboard is supported as well (not speech, which hang the emulator)
|
||||
* Open Apple and Closed Apple can be emulated using AltGr and Menu (unfortunately, Alt does not work well)
|
||||
|
||||
## Build
|
||||
|
||||
|
|
BIN
resource/Apple2_JPlus.rom
Normal file
BIN
resource/Apple2_JPlus.rom
Normal file
Binary file not shown.
BIN
resource/Apple2_JPlus_Video.rom
Normal file
BIN
resource/Apple2_JPlus_Video.rom
Normal file
Binary file not shown.
|
@ -55,6 +55,7 @@ FULLSCR_BUTTON BITMAP "FULLSCR.BMP"
|
|||
RUN_BUTTON BITMAP "RUN.BMP"
|
||||
RUNP_BUTTON BITMAP "RUNP.BMP"
|
||||
RUN3000E_BUTTON BITMAP "RUN3000E.BMP"
|
||||
RUNBASE64A_BUTTON BITMAP "RUNBASE64A.BMP"
|
||||
DEBUG_BUTTON BITMAP "DEBUG.BMP"
|
||||
DRIVE1_BUTTON BITMAP "DRIVE1.BMP"
|
||||
DRIVE2_BUTTON BITMAP "DRIVE2.BMP"
|
||||
|
@ -89,11 +90,11 @@ CAPTION "Configuration"
|
|||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "&Model:",IDC_STATIC,5,7,40,8
|
||||
COMBOBOX IDC_COMPUTER,45,5,90,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMPUTER,45,5,91,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Confirm reboot",IDC_CHECK_CONFIRM_REBOOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,8,62,10
|
||||
GROUPBOX "Video",IDC_STATIC,5,22,200,56
|
||||
LTEXT "Mo&de:",IDC_STATIC,12,33,33,8
|
||||
COMBOBOX IDC_VIDEOTYPE,45,30,90,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_VIDEOTYPE,33,30,103,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "Monochrome &Color...",IDC_MONOCOLOR,12,46,80,14
|
||||
CONTROL "50% Scan lines",IDC_CHECK_HALF_SCAN_LINES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,33,62,10
|
||||
CONTROL "Vertical blend",IDC_CHECK_VERTICAL_BLEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,48,62,10
|
||||
|
@ -175,21 +176,20 @@ BEGIN
|
|||
GROUPBOX "Floppy Disk Drives",IDC_STATIC,5,7,200,72
|
||||
LTEXT "&Disk access speed:",IDC_STATIC,12,21,64,8
|
||||
COMBOBOX IDC_DISKTYPE,80,18,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Hard Disk Drives",IDC_STATIC,5,83,200,64
|
||||
CONTROL "&Enable hard disk controller in slot 7",IDC_HDD_ENABLE,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,96,122,10
|
||||
PUSHBUTTON "Swap",IDC_HDD_SWAP,156,92,40,14
|
||||
LTEXT "&Path to CiderPress:",IDC_STATIC,7,155,74,8
|
||||
EDITTEXT IDC_CIDERPRESS_FILENAME,7,165,143,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
PUSHBUTTON "&Browse...",IDC_CIDERPRESS_BROWSE,156,164,50,14
|
||||
LTEXT "HDD 1:",IDC_STATIC,11,113,23,8
|
||||
LTEXT "HDD 2:",IDC_STATIC,11,130,23,8
|
||||
COMBOBOX IDC_COMBO_HDD1,46,112,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMBO_HDD2,46,128,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Disk 1:",IDC_STATIC,10,41,23,8
|
||||
LTEXT "Disk 2:",IDC_STATIC,10,58,23,8
|
||||
COMBOBOX IDC_COMBO_DISK1,40,40,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMBO_DISK2,40,57,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Hard Disk Drives",IDC_STATIC,5,83,200,64
|
||||
CONTROL "&Enable hard disk controller in slot 7",IDC_HDD_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,96,122,10
|
||||
PUSHBUTTON "Swap",IDC_HDD_SWAP,156,92,40,14
|
||||
LTEXT "HDD 1:",IDC_STATIC,11,113,23,8
|
||||
LTEXT "HDD 2:",IDC_STATIC,11,130,23,8
|
||||
COMBOBOX IDC_COMBO_HDD1,46,112,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMBO_HDD2,46,128,150,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "&Path to CiderPress:",IDC_STATIC,7,155,74,8
|
||||
EDITTEXT IDC_CIDERPRESS_FILENAME,7,165,143,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
PUSHBUTTON "&Browse...",IDC_CIDERPRESS_BROWSE,156,164,50,14
|
||||
END
|
||||
|
||||
IDD_TFE_SETTINGS_DIALOG DIALOGEX 0, 0, 270, 100
|
||||
|
@ -200,7 +200,7 @@ BEGIN
|
|||
LTEXT "Ethernet",IDC_TFE_SETTINGS_ENABLE_T,9,7,30,8
|
||||
COMBOBOX IDC_TFE_SETTINGS_ENABLE,45,5,50,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Interface",IDC_TFE_SETTINGS_INTERFACE_T,9,24,30,8
|
||||
COMBOBOX IDC_TFE_SETTINGS_INTERFACE,45,22,200,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
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
|
||||
|
@ -308,7 +308,8 @@ END
|
|||
// FIRMWARE
|
||||
//
|
||||
|
||||
IDR_DISK2_FW FIRMWARE "Disk2.rom"
|
||||
IDR_DISK2_13SECTOR_FW FIRMWARE "Disk2-13sector.rom"
|
||||
IDR_DISK2_16SECTOR_FW FIRMWARE "Disk2.rom"
|
||||
IDR_SSC_FW FIRMWARE "SSC.rom"
|
||||
IDR_HDDRVR_FW FIRMWARE "Hddrvr.bin"
|
||||
IDR_PRINTDRVR_FW FIRMWARE "Parallel.rom"
|
||||
|
@ -324,14 +325,24 @@ IDR_TKCLOCK_FW FIRMWARE "TKClock.rom"
|
|||
|
||||
IDR_APPLE2_ROM ROM "Apple2.rom"
|
||||
IDR_APPLE2_PLUS_ROM ROM "Apple2_Plus.rom"
|
||||
IDR_APPLE2_JPLUS_ROM ROM "Apple2_JPlus.rom"
|
||||
IDR_APPLE2E_ROM ROM "Apple2e.rom"
|
||||
IDR_APPLE2E_ENHANCED_ROM ROM "Apple2e_Enhanced.rom"
|
||||
IDR_PRAVETS_82_ROM ROM "Pravets82.rom"
|
||||
IDR_PRAVETS_8M_ROM ROM "Pravets8M.rom"
|
||||
IDR_PRAVETS_8C_ROM ROM "Pravets8C.rom"
|
||||
IDR_TK3000_2E_ROM ROM "TK3000e.rom"
|
||||
IDR_BASE_64A_ROM ROM "Base64A.rom"
|
||||
IDR_FREEZES_F8_ROM ROM "FREEZES_NON-AUTOSTART_F8_ROM.rom"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VIDEO ROM
|
||||
//
|
||||
|
||||
IDR_APPLE2_JPLUS_VIDEO_ROM ROM "Apple2_JPlus_Video.rom"
|
||||
IDR_BASE64A_VIDEO_ROM ROM "Base64A_German_Video.rom"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
|
|
BIN
resource/Base64A.rom
Normal file
BIN
resource/Base64A.rom
Normal file
Binary file not shown.
BIN
resource/Base64A_German_Video.rom
Normal file
BIN
resource/Base64A_German_Video.rom
Normal file
Binary file not shown.
BIN
resource/DISK2-13sector.rom
Normal file
BIN
resource/DISK2-13sector.rom
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 42 KiB |
BIN
resource/RUNBASE64A.BMP
Normal file
BIN
resource/RUNBASE64A.BMP
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
|
@ -34,7 +34,6 @@
|
|||
#define IDD_TFE_SETTINGS_DIALOG 131
|
||||
#define IDR_PRINTDRVR_FW 132
|
||||
#define IDD_PROPPAGE_ADVANCED 132
|
||||
#define IDR_DISK2_FW 133
|
||||
#define IDR_SSC_FW 134
|
||||
#define IDR_MOCKINGBOARD_D_FW 135
|
||||
#define IDR_MOUSEINTERFACE_FW 136
|
||||
|
@ -48,6 +47,12 @@
|
|||
#define IDC_CHECK_CONFIRM_REBOOT 146
|
||||
#define IDR_TK3000_2E_ROM 147
|
||||
#define IDR_TKCLOCK_FW 148
|
||||
#define IDR_DISK2_13SECTOR_FW 149
|
||||
#define IDR_DISK2_16SECTOR_FW 150
|
||||
#define IDR_APPLE2_JPLUS_ROM 151
|
||||
#define IDR_APPLE2_JPLUS_VIDEO_ROM 152
|
||||
#define IDR_BASE_64A_ROM 153
|
||||
#define IDR_BASE64A_VIDEO_ROM 154
|
||||
#define IDC_KEYB_BUFFER_ENABLE 1005
|
||||
#define IDC_SAVESTATE 1006
|
||||
#define IDC_SAVESTATE_ON_EXIT 1007
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define APPLEWIN_VERSION 1,29,8,0
|
||||
#define APPLEWIN_VERSION 1,29,14,0
|
||||
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
|
|
|
@ -26,9 +26,7 @@
|
|||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <crtdbg.h>
|
||||
#include "AY8910.h"
|
||||
|
||||
#include "Applewin.h" // For g_fh
|
||||
|
@ -991,7 +989,7 @@ sound_beeper( int is_tape, int on )
|
|||
#define SS_YAML_KEY_CHANGE "Change"
|
||||
#define SS_YAML_VALUE_CHANGE_FORMAT "%d, %d, 0x%1X, 0x%02X"
|
||||
|
||||
void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
|
||||
void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const std::string& suffix)
|
||||
{
|
||||
std::string unit = std::string(SS_YAML_KEY_AY8910) + suffix;
|
||||
YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", unit.c_str());
|
||||
|
@ -1046,7 +1044,7 @@ void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
|
|||
}
|
||||
}
|
||||
|
||||
bool CAY8910::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, std::string& suffix)
|
||||
bool CAY8910::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, const std::string& suffix)
|
||||
{
|
||||
std::string unit = std::string(SS_YAML_KEY_AY8910) + suffix;
|
||||
if (!yamlLoadHelper.GetSubMap(unit))
|
||||
|
@ -1201,7 +1199,7 @@ BYTE* AY8910_GetRegsPtr(UINT uChip)
|
|||
return g_AY8910[uChip].GetAYRegsPtr();
|
||||
}
|
||||
|
||||
UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix)
|
||||
UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, const std::string& suffix)
|
||||
{
|
||||
if (uChip >= MAX_8910)
|
||||
return 0;
|
||||
|
@ -1210,7 +1208,7 @@ UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string
|
|||
return 1;
|
||||
}
|
||||
|
||||
UINT AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix)
|
||||
UINT AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT uChip, const std::string& suffix)
|
||||
{
|
||||
if (uChip >= MAX_8910)
|
||||
return 0;
|
||||
|
|
|
@ -17,8 +17,8 @@ BYTE* AY8910_GetRegsPtr(UINT uChip);
|
|||
|
||||
void AY8910UpdateSetCycles();
|
||||
|
||||
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
|
||||
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
|
||||
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, const std::string& suffix);
|
||||
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, const std::string& suffix);
|
||||
|
||||
//-------------------------------------
|
||||
// FUSE stuff
|
||||
|
@ -46,8 +46,8 @@ public:
|
|||
void sound_frame( void );
|
||||
BYTE* GetAYRegsPtr( void ) { return &sound_ay_registers[0]; }
|
||||
static void SetCLK( double CLK ) { m_fCurrentCLK_AY8910 = CLK; }
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, std::string& suffix);
|
||||
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, std::string& suffix);
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const std::string& suffix);
|
||||
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, const std::string& suffix);
|
||||
|
||||
private:
|
||||
void init( void );
|
||||
|
|
|
@ -82,9 +82,12 @@ AppMode_e g_nAppMode = MODE_LOGO;
|
|||
static bool g_bLoadedSaveState = false;
|
||||
static bool g_bSysClkOK = false;
|
||||
|
||||
std::string g_sStartDir; // NB. AppleWin.exe maybe relative to this! (GH#663)
|
||||
std::string g_sProgramDir; // Directory of where AppleWin executable resides
|
||||
std::string g_sDebugDir; // TODO: Not currently used
|
||||
std::string g_sScreenShotDir; // TODO: Not currently used
|
||||
std::string g_sConfigFile; // INI file to use instead of Registry
|
||||
|
||||
bool g_bCapturePrintScreenKey = true;
|
||||
static bool g_bHookSystemKey = true;
|
||||
static bool g_bHookAltTab = false;
|
||||
|
@ -109,8 +112,10 @@ int g_nMemoryClearType = MIP_FF_FF_00_00; // Note: -1 = random MIP in Memory.c
|
|||
CardManager g_CardMgr;
|
||||
IPropertySheet& sg_PropertySheet = * new CPropertySheet;
|
||||
|
||||
HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $F800..$FFFF
|
||||
static bool g_bCustomRomF8Failed = false; // Set if custom ROM file failed
|
||||
HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom F8 ROM at $F800..$FFFF
|
||||
static bool g_bCustomRomF8Failed = false; // Set if custom F8 ROM file failed
|
||||
HANDLE g_hCustomRom = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $C000..$FFFF(16KiB) or $D000..$FFFF(12KiB)
|
||||
static bool g_bCustomRomFailed = false; // Set if custom ROM file failed
|
||||
|
||||
static bool g_bEnableSpeech = false;
|
||||
#ifdef USE_SPEECH_API
|
||||
|
@ -119,11 +124,51 @@ CSpeech g_Speech;
|
|||
|
||||
//===========================================================================
|
||||
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
static UINT64 g_timeTotal = 0;
|
||||
UINT64 g_timeCpu = 0;
|
||||
UINT64 g_timeVideo = 0; // part of timeCpu
|
||||
UINT64 g_timeMB_Timer = 0; // part of timeCpu
|
||||
UINT64 g_timeMB_NoTimer = 0;
|
||||
UINT64 g_timeSpeaker = 0;
|
||||
static UINT64 g_timeVideoRefresh = 0;
|
||||
|
||||
void LogPerfTimings(void)
|
||||
{
|
||||
if (g_timeTotal)
|
||||
{
|
||||
UINT64 cpu = g_timeCpu - g_timeVideo - g_timeMB_Timer;
|
||||
UINT64 video = g_timeVideo + g_timeVideoRefresh;
|
||||
UINT64 spkr = g_timeSpeaker;
|
||||
UINT64 mb = g_timeMB_Timer + g_timeMB_NoTimer;
|
||||
UINT64 audio = spkr + mb;
|
||||
UINT64 other = g_timeTotal - g_timeCpu - g_timeSpeaker - g_timeMB_NoTimer - g_timeVideoRefresh;
|
||||
|
||||
LogOutput("Perf breakdown:\n");
|
||||
LogOutput(". CPU %% = %6.2f\n", (double)cpu / (double)g_timeTotal * 100.0);
|
||||
LogOutput(". Video %% = %6.2f\n", (double)video / (double)g_timeTotal * 100.0);
|
||||
LogOutput("... NTSC %% = %6.2f\n", (double)g_timeVideo / (double)g_timeTotal * 100.0);
|
||||
LogOutput("... refresh %% = %6.2f\n", (double)g_timeVideoRefresh / (double)g_timeTotal * 100.0);
|
||||
LogOutput(". Audio %% = %6.2f\n", (double)audio / (double)g_timeTotal * 100.0);
|
||||
LogOutput("... Speaker %% = %6.2f\n", (double)spkr / (double)g_timeTotal * 100.0);
|
||||
LogOutput("... MB %% = %6.2f\n", (double)mb / (double)g_timeTotal * 100.0);
|
||||
LogOutput(". Other %% = %6.2f\n", (double)other / (double)g_timeTotal * 100.0);
|
||||
LogOutput(". TOTAL %% = %6.2f\n", (double)(cpu+video+audio+other) / (double)g_timeTotal * 100.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static DWORD dwLogKeyReadTickStart;
|
||||
static bool bLogKeyReadDone = false;
|
||||
|
||||
void LogFileTimeUntilFirstKeyReadReset(void)
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
LogPerfTimings();
|
||||
#endif
|
||||
|
||||
if (!g_fh)
|
||||
return;
|
||||
|
||||
|
@ -230,6 +275,10 @@ static bool g_uModeStepping_LastGetKey_ScrollLock = false;
|
|||
|
||||
static void ContinueExecution(void)
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
PerfMarker* pPerfMarkerTotal = new PerfMarker(g_timeTotal);
|
||||
#endif
|
||||
|
||||
_ASSERT(g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING);
|
||||
|
||||
const double fUsecPerSec = 1.e6;
|
||||
|
@ -348,6 +397,9 @@ static void ContinueExecution(void)
|
|||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
if (g_dwCyclesThisFrame >= dwClksPerFrame && !VideoGetVblBarEx(g_dwCyclesThisFrame))
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
PerfMarker perfMarkerVideoRefresh(g_timeVideoRefresh);
|
||||
#endif
|
||||
g_dwCyclesThisFrame -= dwClksPerFrame;
|
||||
|
||||
if (g_bFullSpeed)
|
||||
|
@ -356,6 +408,10 @@ static void ContinueExecution(void)
|
|||
VideoRefreshScreen(); // Just copy the output of our Apple framebuffer to the system Back Buffer
|
||||
}
|
||||
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
delete pPerfMarkerTotal; // Explicitly call dtor *before* SysClk_WaitTimer()
|
||||
#endif
|
||||
|
||||
if ((g_nAppMode == MODE_RUNNING && !g_bFullSpeed) || bModeStepping_WaitTimer)
|
||||
{
|
||||
SysClk_WaitTimer();
|
||||
|
@ -486,7 +542,8 @@ void EnterMessageLoop(void)
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
void GetProgramDirectory(void)
|
||||
|
||||
static void GetProgramDirectory(void)
|
||||
{
|
||||
TCHAR programDir[MAX_PATH];
|
||||
GetModuleFileName((HINSTANCE)0, programDir, MAX_PATH);
|
||||
|
@ -1086,19 +1143,27 @@ static std::string GetFullPath(LPCSTR szFileName)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Rel pathname
|
||||
char szCWD[_MAX_PATH] = {0};
|
||||
if (!GetCurrentDirectory(sizeof(szCWD), szCWD))
|
||||
return "";
|
||||
|
||||
strPathName = szCWD;
|
||||
strPathName.append("\\");
|
||||
// Rel pathname (GH#663)
|
||||
strPathName = g_sStartDir;
|
||||
strPathName.append(szFileName);
|
||||
}
|
||||
|
||||
return strPathName;
|
||||
}
|
||||
|
||||
static void SetCurrentDir(std::string pathname)
|
||||
{
|
||||
// Due to the order HDDs/disks are inserted, then s7 insertions take priority over s6 & s5; and d2 takes priority over d1:
|
||||
// . if -s6[dN] and -hN are specified, then g_sCurrentDir will be set to the HDD image's path
|
||||
// . if -s5[dN] and -s6[dN] are specified, then g_sCurrentDir will be set to the s6 image's path
|
||||
// . if -[sN]d1 and -[sN]d2 are specified, then g_sCurrentDir will be set to the d2 image's path
|
||||
// This is purely dependent on the current order of InsertFloppyDisks() & InsertHardDisks() - ie. very brittle!
|
||||
// . better to use -current-dir to be explicit
|
||||
std::size_t found = pathname.find_last_of("\\");
|
||||
std::string path = pathname.substr(0, found);
|
||||
SetCurrentImageDir(path);
|
||||
}
|
||||
|
||||
static bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName)
|
||||
{
|
||||
Disk2InterfaceCard& disk2Card = dynamic_cast<Disk2InterfaceCard&>(g_CardMgr.GetRef(slot));
|
||||
|
@ -1107,7 +1172,10 @@ static bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName)
|
|||
if (strPathName.empty()) return false;
|
||||
|
||||
ImageError_e Error = disk2Card.InsertDisk(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
|
||||
return Error == eIMAGE_ERROR_NONE;
|
||||
bool res = (Error == eIMAGE_ERROR_NONE);
|
||||
if (res)
|
||||
SetCurrentDir(strPathName);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName)
|
||||
|
@ -1116,7 +1184,10 @@ static bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName)
|
|||
if (strPathName.empty()) return false;
|
||||
|
||||
BOOL bRes = HD_Insert(nDrive, strPathName.c_str());
|
||||
return bRes ? true : false;
|
||||
bool res = (bRes == TRUE);
|
||||
if (res)
|
||||
SetCurrentDir(strPathName);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void InsertFloppyDisks(const UINT slot, LPSTR szImageName_drive[NUM_DRIVES], bool& bBoot)
|
||||
|
@ -1156,11 +1227,9 @@ static void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBo
|
|||
HD_SetEnabled(true);
|
||||
|
||||
DWORD dwTmp;
|
||||
if (REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp))
|
||||
{
|
||||
if (!dwTmp)
|
||||
REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 1); // Config: HDD Enabled
|
||||
}
|
||||
BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
|
||||
if (!res || !dwTmp)
|
||||
REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 1); // Config: HDD Enabled
|
||||
|
||||
//
|
||||
|
||||
|
@ -1189,11 +1258,9 @@ static void UnplugHardDiskControllerCard(void)
|
|||
HD_SetEnabled(false);
|
||||
|
||||
DWORD dwTmp;
|
||||
if (REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp))
|
||||
{
|
||||
if (dwTmp)
|
||||
REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 0); // Config: HDD Disabled
|
||||
}
|
||||
BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
|
||||
if (!res || dwTmp)
|
||||
REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 0); // Config: HDD Disabled
|
||||
}
|
||||
|
||||
static bool CheckOldAppleWinVersion(void)
|
||||
|
@ -1251,6 +1318,7 @@ struct CmdLine
|
|||
bSlot0LanguageCard = false;
|
||||
bSlot7EmptyOnExit = false;
|
||||
bSwapButtons0and1 = false;
|
||||
bRemoveNoSlotClock = false;
|
||||
bestWidth = 0;
|
||||
bestHeight = 0;
|
||||
szImageName_harddisk[HARDDISK_1] = NULL;
|
||||
|
@ -1265,6 +1333,9 @@ struct CmdLine
|
|||
newVideoRefreshRate = VR_NONE;
|
||||
clockMultiplier = 0.0; // 0 => not set from cmd-line
|
||||
model = A2TYPE_MAX;
|
||||
rgbCard = RGB_Videocard_e::Apple;
|
||||
rgbCardForegroundColor = 15;
|
||||
rgbCardBackgroundColor = 0;
|
||||
|
||||
for (UINT i = 0; i < NUM_SLOTS; i++)
|
||||
{
|
||||
|
@ -1283,6 +1354,7 @@ struct CmdLine
|
|||
bool bSlotEmpty[NUM_SLOTS];
|
||||
bool bSlot7EmptyOnExit;
|
||||
bool bSwapButtons0and1;
|
||||
bool bRemoveNoSlotClock;
|
||||
SS_CARDTYPE slotInsert[NUM_SLOTS];
|
||||
UINT bestWidth;
|
||||
UINT bestHeight;
|
||||
|
@ -1298,15 +1370,25 @@ struct CmdLine
|
|||
VideoRefreshRate_e newVideoRefreshRate;
|
||||
double clockMultiplier;
|
||||
eApple2Type model;
|
||||
RGB_Videocard_e rgbCard;
|
||||
int rgbCardForegroundColor;
|
||||
int rgbCardBackgroundColor;
|
||||
std::string strCurrentDir;
|
||||
};
|
||||
|
||||
static CmdLine g_cmdLine;
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
{
|
||||
char startDir[_MAX_PATH];
|
||||
GetCurrentDirectory(sizeof(startDir), startDir);
|
||||
g_sStartDir = startDir;
|
||||
if (*(g_sStartDir.end()-1) != '\\') g_sStartDir += '\\';
|
||||
|
||||
if (!ProcessCmdLine(lpCmdLine))
|
||||
return 0;
|
||||
|
||||
LogFileOutput("g_sStartDir = %s\n", g_sStartDir.c_str());
|
||||
GetAppleWinVersion();
|
||||
OneTimeInitialization(passinstance);
|
||||
|
||||
|
@ -1368,6 +1450,12 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
const std::string strCmdLine(lpCmdLine); // Keep a copy for log ouput
|
||||
std::string strUnsupported;
|
||||
|
||||
// If 1st param looks like an abs pathname then assume that an associated filetype has been double-clicked
|
||||
// NB. Handled by WM_DDE_INITIATE & WM_DDE_EXECUTE msgs
|
||||
if ((lpCmdLine[0] >= '\"' && lpCmdLine[1] >= 'A' && lpCmdLine[1] <= 'Z' && lpCmdLine[2] == ':') // always in quotes
|
||||
|| strncmp("\\\\?\\", lpCmdLine, 4) == 0)
|
||||
return true;
|
||||
|
||||
while (*lpCmdLine)
|
||||
{
|
||||
LPSTR lpNextArg = GetNextArg(lpCmdLine);
|
||||
|
@ -1380,6 +1468,17 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
{
|
||||
g_bRegisterFileTypes = false;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-conf") == 0)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
char buf[MAX_PATH];
|
||||
DWORD res = GetFullPathName(lpCmdLine, MAX_PATH, buf, NULL);
|
||||
if (res == 0)
|
||||
LogFileOutput("Failed to open configuration file: %s\n", lpCmdLine);
|
||||
else
|
||||
g_sConfigFile = buf;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-d1") == 0)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
|
@ -1432,15 +1531,15 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
g_cmdLine.szImageName_drive[slot][drive] = lpCmdLine;
|
||||
}
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-s7-empty-on-exit") == 0)
|
||||
{
|
||||
g_cmdLine.bSlot7EmptyOnExit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
|
||||
}
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-s7-empty-on-exit") == 0)
|
||||
{
|
||||
g_cmdLine.bSlot7EmptyOnExit = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-load-state") == 0)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
|
@ -1535,6 +1634,18 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
|
||||
g_bCustomRomF8Failed = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-rom") == 0) // Use custom 16K at [$C000..$FFFF] or 12K ROM at [$D000..$FFFF]
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
|
||||
if (g_hCustomRom != INVALID_HANDLE_VALUE) // Stop resource leak if -rom is specified twice!
|
||||
CloseHandle(g_hCustomRom);
|
||||
|
||||
g_hCustomRom = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
||||
if ((g_hCustomRom == INVALID_HANDLE_VALUE) || ((GetFileSize(g_hCustomRom, NULL) != 0x4000) && (GetFileSize(g_hCustomRom, NULL) != 0x3000)))
|
||||
g_bCustomRomFailed = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 2K (for II/II+). Use 4K,8K or 16K video ROM (for Enhanced //e)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
|
@ -1640,6 +1751,14 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_MONITOR_RGB;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-video-mode=rgb-videocard") == 0)
|
||||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_VIDEOCARD_RGB;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-video-mode=composite-monitor") == 0) // GH#763
|
||||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_MONITOR_NTSC;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-video-style=vertical-blend") == 0) // GH#616
|
||||
{
|
||||
g_cmdLine.newVideoStyleEnableMask = VS_COLOR_VERTICAL_BLEND;
|
||||
|
@ -1672,6 +1791,8 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
g_cmdLine.model = A2TYPE_APPLE2;
|
||||
else if (strcmp(lpCmdLine, "apple2p") == 0)
|
||||
g_cmdLine.model = A2TYPE_APPLE2PLUS;
|
||||
else if (strcmp(lpCmdLine, "apple2jp") == 0)
|
||||
g_cmdLine.model = A2TYPE_APPLE2JPLUS;
|
||||
else if (strcmp(lpCmdLine, "apple2e") == 0)
|
||||
g_cmdLine.model = A2TYPE_APPLE2E;
|
||||
else if (strcmp(lpCmdLine, "apple2ee") == 0)
|
||||
|
@ -1687,6 +1808,51 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
{
|
||||
g_cmdLine.newVideoRefreshRate = VR_60HZ;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-rgb-card-type") == 0)
|
||||
{
|
||||
// RGB video card valide types are: "apple", "sl7", "eve", "feline"
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
|
||||
if (strcmp(lpCmdLine, "apple") == 0)
|
||||
g_cmdLine.rgbCard = RGB_Videocard_e::Apple;
|
||||
else if (strcmp(lpCmdLine, "sl7") == 0)
|
||||
g_cmdLine.rgbCard = RGB_Videocard_e::Video7_SL7;
|
||||
else if (strcmp(lpCmdLine, "eve") == 0)
|
||||
g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_EVE;
|
||||
else if (strcmp(lpCmdLine, "feline") == 0)
|
||||
g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_Feline;
|
||||
else
|
||||
LogFileOutput("-rgb-card-type: unsupported type: %s\n", lpCmdLine);
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-rgb-card-foreground") == 0)
|
||||
{
|
||||
// Default hardware-defined Text foreground color, for some RGB cards only
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
g_cmdLine.rgbCardForegroundColor = atoi(lpCmdLine);
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-rgb-card-background") == 0)
|
||||
{
|
||||
// Default hardware-defined Text background color, for some RGB cards only
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
g_cmdLine.rgbCardBackgroundColor = atoi(lpCmdLine);
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-power-on") == 0)
|
||||
{
|
||||
g_cmdLine.bBoot = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-current-dir") == 0)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
g_cmdLine.strCurrentDir = lpCmdLine;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-no-nsc") == 0)
|
||||
{
|
||||
g_cmdLine.bRemoveNoSlotClock = true;
|
||||
}
|
||||
else // unsupported
|
||||
{
|
||||
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
|
||||
|
@ -1819,6 +1985,8 @@ static void RepeatInitialization(void)
|
|||
if (g_cmdLine.model != A2TYPE_MAX)
|
||||
SetApple2Type(g_cmdLine.model);
|
||||
|
||||
RGB_SetVideocard(g_cmdLine.rgbCard, g_cmdLine.rgbCardForegroundColor, g_cmdLine.rgbCardBackgroundColor);
|
||||
|
||||
if (g_cmdLine.newVideoType >= 0)
|
||||
{
|
||||
SetVideoType( (VideoType_e)g_cmdLine.newVideoType );
|
||||
|
@ -1877,7 +2045,12 @@ static void RepeatInitialization(void)
|
|||
FrameCreateWindow(); // g_hFrameWindow is now valid
|
||||
LogFileOutput("Main: FrameCreateWindow() - post\n");
|
||||
|
||||
// Init palette color
|
||||
VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
|
||||
|
||||
// Allow the 4 hardcoded slots to be configurated as empty
|
||||
// NB. this state is not persisted to the Registry/conf.ini (just as '-s7 empty' isn't)
|
||||
// TODO: support bSlotEmpty[] for slots: 0,4,5
|
||||
if (g_cmdLine.bSlotEmpty[SLOT1])
|
||||
g_CardMgr.Remove(SLOT1);
|
||||
if (g_cmdLine.bSlotEmpty[SLOT2])
|
||||
|
@ -1912,9 +2085,16 @@ static void RepeatInitialization(void)
|
|||
g_cmdLine.szImageName_harddisk[HARDDISK_1] = g_cmdLine.szImageName_harddisk[HARDDISK_2] = NULL; // Don't insert on a restart
|
||||
|
||||
if (g_cmdLine.bSlotEmpty[7])
|
||||
HD_SetEnabled(false);
|
||||
HD_SetEnabled(false); // Disable HDD controller, but don't persist this to Registry/conf.ini (consistent with other '-sn empty' cmds)
|
||||
}
|
||||
|
||||
// Set *after* InsertFloppyDisks() & InsertHardDisks(), which both update g_sCurrentDir
|
||||
if (!g_cmdLine.strCurrentDir.empty())
|
||||
SetCurrentImageDir(g_cmdLine.strCurrentDir);
|
||||
|
||||
if (g_cmdLine.bRemoveNoSlotClock)
|
||||
MemRemoveNoSlotClock();
|
||||
|
||||
MemInitialize();
|
||||
LogFileOutput("Main: MemInitialize()\n");
|
||||
|
||||
|
@ -1951,9 +2131,12 @@ static void RepeatInitialization(void)
|
|||
g_cmdLine.bShutdown = true;
|
||||
}
|
||||
|
||||
if (g_bCustomRomF8Failed)
|
||||
if (g_bCustomRomF8Failed || g_bCustomRomFailed || (g_hCustomRomF8 != INVALID_HANDLE_VALUE && g_hCustomRom != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
std::string msg = "Failed to load custom F8 rom (not found or not exactly 2KiB)\n";
|
||||
std::string msg = g_bCustomRomF8Failed ? "Failed to load custom F8 rom (not found or not exactly 2KiB)\n"
|
||||
: g_bCustomRomFailed ? "Failed to load custom rom (not found or not exactly 12KiB or 16KiB)\n"
|
||||
: "Unsupported -rom and -f8rom being used at the same time\n";
|
||||
|
||||
LogFileOutput("%s", msg.c_str());
|
||||
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
|
||||
g_cmdLine.bShutdown = true;
|
||||
|
@ -2058,6 +2241,9 @@ static void Shutdown(void)
|
|||
if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(g_hCustomRomF8);
|
||||
|
||||
if (g_hCustomRom != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(g_hCustomRom);
|
||||
|
||||
if (g_cmdLine.bSlot7EmptyOnExit)
|
||||
UnplugHardDiskControllerCard();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ extern int g_nMemoryClearType; // Cmd line switch: use specific MIP (
|
|||
|
||||
extern class CardManager g_CardMgr;
|
||||
|
||||
extern HANDLE g_hCustomRomF8; // NULL if no custom rom
|
||||
extern HANDLE g_hCustomRomF8; // INVALID_HANDLE_VALUE if no custom F8 rom
|
||||
extern HANDLE g_hCustomRom; // INVALID_HANDLE_VALUE if no custom rom
|
||||
|
||||
#ifdef USE_SPEECH_API
|
||||
class CSpeech;
|
||||
|
@ -62,3 +63,27 @@ extern CSpeech g_Speech;
|
|||
#endif
|
||||
|
||||
extern __interface IPropertySheet& sg_PropertySheet;
|
||||
|
||||
//
|
||||
|
||||
//#define LOG_PERF_TIMINGS
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
class PerfMarker
|
||||
{
|
||||
public:
|
||||
PerfMarker(UINT64& globalCounter)
|
||||
: counter(globalCounter)
|
||||
{
|
||||
QueryPerformanceCounter(&timeStart);
|
||||
}
|
||||
~PerfMarker()
|
||||
{
|
||||
QueryPerformanceCounter(&timeEnd);
|
||||
counter += (UINT64)timeEnd.QuadPart - (UINT64)timeStart.QuadPart;
|
||||
}
|
||||
private:
|
||||
UINT64& counter;
|
||||
LARGE_INTEGER timeStart;
|
||||
LARGE_INTEGER timeEnd;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
include(FindPkgConfig)
|
||||
|
||||
add_library(appleii SHARED
|
||||
linux/data.cpp
|
||||
|
||||
SaveState.cpp
|
||||
Speaker.cpp
|
||||
SoundCore.cpp
|
||||
AY8910.cpp
|
||||
Mockingboard.cpp
|
||||
Pravets.cpp
|
||||
Tape.cpp
|
||||
YamlHelper.cpp
|
||||
|
@ -27,6 +28,10 @@ add_library(appleii SHARED
|
|||
NTSC_CharSet.cpp
|
||||
CardManager.cpp
|
||||
Disk2CardManager.cpp
|
||||
SaveState.cpp # uses g_CardMgr in m_ConfigNew (reverse order)
|
||||
Riff.cpp
|
||||
|
||||
Configuration/PropertySheetHelper.cpp
|
||||
|
||||
linux/windows/memory.cpp
|
||||
linux/windows/handles.cpp
|
||||
|
@ -37,9 +42,15 @@ add_library(appleii SHARED
|
|||
linux/windows/stringcb.cpp
|
||||
linux/windows/strings.cpp
|
||||
linux/windows/misc.cpp
|
||||
linux/windows/winbase.cpp
|
||||
linux/windows/winuser.cpp
|
||||
linux/windows/dsound.cpp
|
||||
linux/windows/guiddef.cpp
|
||||
linux/windows/dmusicc.cpp
|
||||
linux/windows/winnls.cpp
|
||||
|
||||
linux/dummies.cpp
|
||||
linux/state.cpp
|
||||
|
||||
linux/data.cpp
|
||||
linux/benchmark.cpp
|
||||
linux/paddle.cpp
|
||||
linux/version.cpp
|
||||
|
@ -48,11 +59,11 @@ add_library(appleii SHARED
|
|||
|
||||
linux/duplicates/Debug.cpp
|
||||
linux/duplicates/Video.cpp
|
||||
linux/duplicates/Mockingboard.cpp
|
||||
linux/duplicates/Joystick.cpp
|
||||
linux/duplicates/Frame.cpp
|
||||
linux/duplicates/SerialComms.cpp
|
||||
linux/duplicates/Applewin.cpp
|
||||
linux/duplicates/IPropertySheet.cpp
|
||||
linux/duplicates/Applewin.cpp # defines g_CardMgr (reverse order)
|
||||
|
||||
Z80VICE/z80.cpp
|
||||
Z80VICE/z80mem.cpp
|
||||
|
@ -74,3 +85,6 @@ target_link_libraries(appleii PRIVATE
|
|||
${YAML_LIBRARIES}
|
||||
${MINIZIP_LIBRARIES}
|
||||
)
|
||||
|
||||
install(TARGETS appleii
|
||||
DESTINATION lib)
|
||||
|
|
104
source/CPU.cpp
104
source/CPU.cpp
|
@ -98,6 +98,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#endif
|
||||
#include "Video.h"
|
||||
#include "NTSC.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "z80emu.h"
|
||||
#include "Z80VICE/z80.h"
|
||||
|
@ -105,6 +106,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "YamlHelper.h"
|
||||
|
||||
#define LOG_IRQ_TAKEN_AND_RTI 0
|
||||
|
||||
// 6502 Accumulator Bit Flags
|
||||
#define AF_SIGN 0x80
|
||||
#define AF_OVERFLOW 0x40
|
||||
|
@ -211,13 +214,8 @@ void SetMouseCardInstalled(bool installed)
|
|||
//
|
||||
|
||||
#include "CPU/cpu_general.inl"
|
||||
|
||||
#include "CPU/cpu_instructions.inl"
|
||||
|
||||
// Break into debugger on invalid opcodes
|
||||
//#define INV IsDebugBreakOnInvalid(AM_1);
|
||||
#define INV
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* OPCODE TABLE
|
||||
|
@ -243,6 +241,10 @@ static __forceinline void DoIrqProfiling(DWORD uCycles)
|
|||
if(regs.ps & AF_INTERRUPT)
|
||||
return; // Still in Apple's ROM
|
||||
|
||||
#if LOG_IRQ_TAKEN_AND_RTI
|
||||
LogOutput("ISR-end\n\n");
|
||||
#endif
|
||||
|
||||
g_nCycleIrqEnd = g_nCumulativeCycles + uCycles;
|
||||
g_nCycleIrqTime = (UINT) (g_nCycleIrqEnd - g_nCycleIrqStart);
|
||||
|
||||
|
@ -268,18 +270,6 @@ static __forceinline void DoIrqProfiling(DWORD uCycles)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
BYTE CpuRead(USHORT addr, ULONG uExecutedCycles)
|
||||
{
|
||||
return READ;
|
||||
}
|
||||
|
||||
void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles)
|
||||
{
|
||||
WRITE(a);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#ifdef USE_SPEECH_API
|
||||
|
||||
const USHORT COUT = 0xFDED;
|
||||
|
@ -442,6 +432,9 @@ static __forceinline void IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
|||
regs.pc = * (WORD*) (mem+0xFFFE);
|
||||
UINT uExtraCycles = 0; // Needed for CYC(a) macro
|
||||
CYC(7)
|
||||
#if defined(_DEBUG) && LOG_IRQ_TAKEN_AND_RTI
|
||||
LogOutput("IRQ\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
g_irqOnLastOpcodeCycle = false;
|
||||
|
@ -477,18 +470,57 @@ void CpuAdjustIrqCheck(UINT uCyclesUntilInterrupt)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
#define READ _READ
|
||||
#define WRITE(value) _WRITE(value)
|
||||
#define HEATMAP_X(address)
|
||||
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#include "CPU/cpu65d02.h" // Debug CPU Memory Visualizer
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
|
||||
//-----------------
|
||||
|
||||
#define READ Heatmap_ReadByte(addr, uExecutedCycles)
|
||||
#define WRITE(value) Heatmap_WriteByte(addr, value, uExecutedCycles);
|
||||
|
||||
#define HEATMAP_X(address) Heatmap_X(address)
|
||||
|
||||
#include "CPU/cpu_heatmap.inl"
|
||||
|
||||
#define Cpu6502 Cpu6502_debug
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#define Cpu65C02 Cpu65C02_debug
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static DWORD InternalCpuExecute(const DWORD uTotalCycles, const bool bVideoUpdate)
|
||||
{
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
|
||||
else
|
||||
return Cpu65C02(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
|
||||
}
|
||||
else
|
||||
return Cpu65C02(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
|
||||
{
|
||||
_ASSERT(g_nAppMode == MODE_STEPPING || g_nAppMode == MODE_DEBUG);
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_debug(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
|
||||
else
|
||||
return Cpu65C02_debug(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -497,6 +529,31 @@ static DWORD InternalCpuExecute(const DWORD uTotalCycles, const bool bVideoUpdat
|
|||
|
||||
//===========================================================================
|
||||
|
||||
// Called by z80_RDMEM()
|
||||
BYTE CpuRead(USHORT addr, ULONG uExecutedCycles)
|
||||
{
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
return _READ;
|
||||
}
|
||||
|
||||
return Heatmap_ReadByte(addr, uExecutedCycles);
|
||||
}
|
||||
|
||||
// Called by z80_WRMEM()
|
||||
void CpuWrite(USHORT addr, BYTE value, ULONG uExecutedCycles)
|
||||
{
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
_WRITE(value);
|
||||
return;
|
||||
}
|
||||
|
||||
Heatmap_WriteByte(addr, value, uExecutedCycles);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void CpuDestroy ()
|
||||
{
|
||||
if (g_bCritSectionValid)
|
||||
|
@ -554,6 +611,11 @@ ULONG CpuGetCyclesThisVideoFrame(const ULONG nExecutedCycles)
|
|||
|
||||
DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate)
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
extern UINT64 g_timeCpu;
|
||||
PerfMarker perfMarker(g_timeCpu);
|
||||
#endif
|
||||
|
||||
g_nCyclesExecuted = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
|
|
@ -32,7 +32,7 @@ void CpuSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
|||
void CpuLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
|
||||
|
||||
BYTE CpuRead(USHORT addr, ULONG uExecutedCycles);
|
||||
void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles);
|
||||
void CpuWrite(USHORT addr, BYTE value, ULONG uExecutedCycles);
|
||||
|
||||
enum eCpuType {CPU_UNKNOWN=0, CPU_6502=1, CPU_65C02, CPU_Z80}; // Don't change! Persisted to Registry
|
||||
|
||||
|
|
|
@ -52,270 +52,269 @@ static DWORD Cpu6502(DWORD uTotalCycles, const bool bVideoUpdate)
|
|||
}
|
||||
else
|
||||
{
|
||||
HEATMAP_X( regs.pc );
|
||||
Fetch(iOpcode, uExecutedCycles);
|
||||
|
||||
//#define $ INV // INV = Invalid -> Debugger Break
|
||||
#define $
|
||||
switch (iOpcode)
|
||||
{
|
||||
case 0x00: BRK CYC(7) break;
|
||||
case 0x01: idx ORA CYC(6) break;
|
||||
case 0x02: $ HLT CYC(2) break;
|
||||
case 0x03: $ idx ASO CYC(8) break;
|
||||
case 0x04: $ ZPG NOP CYC(3) break;
|
||||
case 0x05: ZPG ORA CYC(3) break;
|
||||
case 0x06: ZPG ASLn CYC(5) break;
|
||||
case 0x07: $ ZPG ASO CYC(5) break;
|
||||
case 0x08: PHP CYC(3) break;
|
||||
case 0x09: IMM ORA CYC(2) break;
|
||||
case 0x0A: asl CYC(2) break;
|
||||
case 0x0B: $ IMM ANC CYC(2) break;
|
||||
case 0x0C: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0x0D: ABS ORA CYC(4) break;
|
||||
case 0x0E: ABS ASLn CYC(6) break;
|
||||
case 0x0F: $ ABS ASO CYC(6) break;
|
||||
case 0x10: REL BPL CYC(2) break;
|
||||
case 0x11: INDY_OPT ORA CYC(5) break;
|
||||
case 0x12: $ HLT CYC(2) break;
|
||||
case 0x13: $ INDY_CONST ASO CYC(8) break;
|
||||
case 0x14: $ zpx NOP CYC(4) break;
|
||||
case 0x15: zpx ORA CYC(4) break;
|
||||
case 0x16: zpx ASLn CYC(6) break;
|
||||
case 0x17: $ zpx ASO CYC(6) break;
|
||||
case 0x18: CLC CYC(2) break;
|
||||
case 0x19: ABSY_OPT ORA CYC(4) break;
|
||||
case 0x1A: $ NOP CYC(2) break;
|
||||
case 0x1B: $ ABSY_CONST ASO CYC(7) break;
|
||||
case 0x1C: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0x1D: ABSX_OPT ORA CYC(4) break;
|
||||
case 0x1E: ABSX_CONST ASLn CYC(7) break;
|
||||
case 0x1F: $ ABSX_CONST ASO CYC(7) break;
|
||||
case 0x20: ABS JSR CYC(6) break;
|
||||
case 0x21: idx AND CYC(6) break;
|
||||
case 0x22: $ HLT CYC(2) break;
|
||||
case 0x23: $ idx RLA CYC(8) break;
|
||||
case 0x24: ZPG BIT CYC(3) break;
|
||||
case 0x25: ZPG AND CYC(3) break;
|
||||
case 0x26: ZPG ROLn CYC(5) break;
|
||||
case 0x27: $ ZPG RLA CYC(5) break;
|
||||
case 0x28: PLP CYC(4) break;
|
||||
case 0x29: IMM AND CYC(2) break;
|
||||
case 0x2A: rol CYC(2) break;
|
||||
case 0x2B: $ IMM ANC CYC(2) break;
|
||||
case 0x2C: ABS BIT CYC(4) break;
|
||||
case 0x2D: ABS AND CYC(4) break;
|
||||
case 0x2E: ABS ROLn CYC(6) break;
|
||||
case 0x2F: $ ABS RLA CYC(6) break;
|
||||
case 0x30: REL BMI CYC(2) break;
|
||||
case 0x31: INDY_OPT AND CYC(5) break;
|
||||
case 0x32: $ HLT CYC(2) break;
|
||||
case 0x33: $ INDY_CONST RLA CYC(8) break;
|
||||
case 0x34: $ zpx NOP CYC(4) break;
|
||||
case 0x35: zpx AND CYC(4) break;
|
||||
case 0x36: zpx ROLn CYC(6) break;
|
||||
case 0x37: $ zpx RLA CYC(6) break;
|
||||
case 0x38: SEC CYC(2) break;
|
||||
case 0x39: ABSY_OPT AND CYC(4) break;
|
||||
case 0x3A: $ NOP CYC(2) break;
|
||||
case 0x3B: $ ABSY_CONST RLA CYC(7) break;
|
||||
case 0x3C: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0x3D: ABSX_OPT AND CYC(4) break;
|
||||
case 0x3E: ABSX_CONST ROLn CYC(6) break;
|
||||
case 0x3F: $ ABSX_CONST RLA CYC(7) break;
|
||||
case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
|
||||
case 0x41: idx EOR CYC(6) break;
|
||||
case 0x42: $ HLT CYC(2) break;
|
||||
case 0x43: $ idx LSE CYC(8) break;
|
||||
case 0x44: $ ZPG NOP CYC(3) break;
|
||||
case 0x45: ZPG EOR CYC(3) break;
|
||||
case 0x46: ZPG LSRn CYC(5) break;
|
||||
case 0x47: $ ZPG LSE CYC(5) break;
|
||||
case 0x48: PHA CYC(3) break;
|
||||
case 0x49: IMM EOR CYC(2) break;
|
||||
case 0x4A: lsr CYC(2) break;
|
||||
case 0x4B: $ IMM ALR CYC(2) break;
|
||||
case 0x4C: ABS JMP CYC(3) break;
|
||||
case 0x4D: ABS EOR CYC(4) break;
|
||||
case 0x4E: ABS LSRn CYC(6) break;
|
||||
case 0x4F: $ ABS LSE CYC(6) break;
|
||||
case 0x50: REL BVC CYC(2) break;
|
||||
case 0x51: INDY_OPT EOR CYC(5) break;
|
||||
case 0x52: $ HLT CYC(2) break;
|
||||
case 0x53: $ INDY_CONST LSE CYC(8) break;
|
||||
case 0x54: $ zpx NOP CYC(4) break;
|
||||
case 0x55: zpx EOR CYC(4) break;
|
||||
case 0x56: zpx LSRn CYC(6) break;
|
||||
case 0x57: $ zpx LSE CYC(6) break;
|
||||
case 0x58: CLI CYC(2) break;
|
||||
case 0x59: ABSY_OPT EOR CYC(4) break;
|
||||
case 0x5A: $ NOP CYC(2) break;
|
||||
case 0x5B: $ ABSY_CONST LSE CYC(7) break;
|
||||
case 0x5C: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0x5D: ABSX_OPT EOR CYC(4) break;
|
||||
case 0x5E: ABSX_CONST LSRn CYC(6) break;
|
||||
case 0x5F: $ ABSX_CONST LSE CYC(7) break;
|
||||
case 0x60: RTS CYC(6) break;
|
||||
case 0x61: idx ADCn CYC(6) break;
|
||||
case 0x62: $ HLT CYC(2) break;
|
||||
case 0x63: $ idx RRA CYC(8) break;
|
||||
case 0x64: $ ZPG NOP CYC(3) break;
|
||||
case 0x65: ZPG ADCn CYC(3) break;
|
||||
case 0x66: ZPG RORn CYC(5) break;
|
||||
case 0x67: $ ZPG RRA CYC(5) break;
|
||||
case 0x68: PLA CYC(4) break;
|
||||
case 0x69: IMM ADCn CYC(2) break;
|
||||
case 0x6A: ror CYC(2) break;
|
||||
case 0x6B: $ IMM ARR CYC(2) break;
|
||||
case 0x6C: IABS_NMOS JMP CYC(5) break; // GH#264
|
||||
case 0x6D: ABS ADCn CYC(4) break;
|
||||
case 0x6E: ABS RORn CYC(6) break;
|
||||
case 0x6F: $ ABS RRA CYC(6) break;
|
||||
case 0x70: REL BVS CYC(2) break;
|
||||
case 0x71: INDY_OPT ADCn CYC(5) break;
|
||||
case 0x72: $ HLT CYC(2) break;
|
||||
case 0x73: $ INDY_CONST RRA CYC(8) break;
|
||||
case 0x74: $ zpx NOP CYC(4) break;
|
||||
case 0x75: zpx ADCn CYC(4) break;
|
||||
case 0x76: zpx RORn CYC(6) break;
|
||||
case 0x77: $ zpx RRA CYC(6) break;
|
||||
case 0x78: SEI CYC(2) break;
|
||||
case 0x79: ABSY_OPT ADCn CYC(4) break;
|
||||
case 0x7A: $ NOP CYC(2) break;
|
||||
case 0x7B: $ ABSY_CONST RRA CYC(7) break;
|
||||
case 0x7C: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0x7D: ABSX_OPT ADCn CYC(4) break;
|
||||
case 0x7E: ABSX_CONST RORn CYC(6) break;
|
||||
case 0x7F: $ ABSX_CONST RRA CYC(7) break;
|
||||
case 0x80: $ IMM NOP CYC(2) break;
|
||||
case 0x81: idx STA CYC(6) break;
|
||||
case 0x82: $ IMM NOP CYC(2) break;
|
||||
case 0x83: $ idx AXS CYC(6) break;
|
||||
case 0x84: ZPG STY CYC(3) break;
|
||||
case 0x85: ZPG STA CYC(3) break;
|
||||
case 0x86: ZPG STX CYC(3) break;
|
||||
case 0x87: $ ZPG AXS CYC(3) break;
|
||||
case 0x88: DEY CYC(2) break;
|
||||
case 0x89: $ IMM NOP CYC(2) break;
|
||||
case 0x8A: TXA CYC(2) break;
|
||||
case 0x8B: $ IMM XAA CYC(2) break;
|
||||
case 0x8C: ABS STY CYC(4) break;
|
||||
case 0x8D: ABS STA CYC(4) break;
|
||||
case 0x8E: ABS STX CYC(4) break;
|
||||
case 0x8F: $ ABS AXS CYC(4) break;
|
||||
case 0x90: REL BCC CYC(2) break;
|
||||
case 0x91: INDY_CONST STA CYC(6) break;
|
||||
case 0x92: $ HLT CYC(2) break;
|
||||
case 0x93: $ INDY_CONST AXA CYC(6) break;
|
||||
case 0x94: zpx STY CYC(4) break;
|
||||
case 0x95: zpx STA CYC(4) break;
|
||||
case 0x96: zpy STX CYC(4) break;
|
||||
case 0x97: $ zpy AXS CYC(4) break;
|
||||
case 0x98: TYA CYC(2) break;
|
||||
case 0x99: ABSY_CONST STA CYC(5) break;
|
||||
case 0x9A: TXS CYC(2) break;
|
||||
case 0x9B: $ ABSY_CONST TAS CYC(5) break;
|
||||
case 0x9C: $ ABSX_CONST SAY CYC(5) break;
|
||||
case 0x9D: ABSX_CONST STA CYC(5) break;
|
||||
case 0x9E: $ ABSY_CONST XAS CYC(5) break;
|
||||
case 0x9F: $ ABSY_CONST AXA CYC(5) break;
|
||||
case 0xA0: IMM LDY CYC(2) break;
|
||||
case 0xA1: idx LDA CYC(6) break;
|
||||
case 0xA2: IMM LDX CYC(2) break;
|
||||
case 0xA3: $ idx LAX CYC(6) break;
|
||||
case 0xA4: ZPG LDY CYC(3) break;
|
||||
case 0xA5: ZPG LDA CYC(3) break;
|
||||
case 0xA6: ZPG LDX CYC(3) break;
|
||||
case 0xA7: $ ZPG LAX CYC(3) break;
|
||||
case 0xA8: TAY CYC(2) break;
|
||||
case 0xA9: IMM LDA CYC(2) break;
|
||||
case 0xAA: TAX CYC(2) break;
|
||||
case 0xAB: $ IMM OAL CYC(2) break;
|
||||
case 0xAC: ABS LDY CYC(4) break;
|
||||
case 0xAD: ABS LDA CYC(4) break;
|
||||
case 0xAE: ABS LDX CYC(4) break;
|
||||
case 0xAF: $ ABS LAX CYC(4) break;
|
||||
case 0xB0: REL BCS CYC(2) break;
|
||||
case 0xB1: INDY_OPT LDA CYC(5) break;
|
||||
case 0xB2: $ HLT CYC(2) break;
|
||||
case 0xB3: $ INDY_OPT LAX CYC(5) break;
|
||||
case 0xB4: zpx LDY CYC(4) break;
|
||||
case 0xB5: zpx LDA CYC(4) break;
|
||||
case 0xB6: zpy LDX CYC(4) break;
|
||||
case 0xB7: $ zpy LAX CYC(4) break;
|
||||
case 0xB8: CLV CYC(2) break;
|
||||
case 0xB9: ABSY_OPT LDA CYC(4) break;
|
||||
case 0xBA: TSX CYC(2) break;
|
||||
case 0xBB: $ ABSY_OPT LAS CYC(4) break;
|
||||
case 0xBC: ABSX_OPT LDY CYC(4) break;
|
||||
case 0xBD: ABSX_OPT LDA CYC(4) break;
|
||||
case 0xBE: ABSY_OPT LDX CYC(4) break;
|
||||
case 0xBF: $ ABSY_OPT LAX CYC(4) break;
|
||||
case 0xC0: IMM CPY CYC(2) break;
|
||||
case 0xC1: idx CMP CYC(6) break;
|
||||
case 0xC2: $ IMM NOP CYC(2) break;
|
||||
case 0xC3: $ idx DCM CYC(8) break;
|
||||
case 0xC4: ZPG CPY CYC(3) break;
|
||||
case 0xC5: ZPG CMP CYC(3) break;
|
||||
case 0xC6: ZPG DEC CYC(5) break;
|
||||
case 0xC7: $ ZPG DCM CYC(5) break;
|
||||
case 0xC8: INY CYC(2) break;
|
||||
case 0xC9: IMM CMP CYC(2) break;
|
||||
case 0xCA: DEX CYC(2) break;
|
||||
case 0xCB: $ IMM SAX CYC(2) break;
|
||||
case 0xCC: ABS CPY CYC(4) break;
|
||||
case 0xCD: ABS CMP CYC(4) break;
|
||||
case 0xCE: ABS DEC CYC(6) break;
|
||||
case 0xCF: $ ABS DCM CYC(6) break;
|
||||
case 0xD0: REL BNE CYC(2) break;
|
||||
case 0xD1: INDY_OPT CMP CYC(5) break;
|
||||
case 0xD2: $ HLT CYC(2) break;
|
||||
case 0xD3: $ INDY_CONST DCM CYC(8) break;
|
||||
case 0xD4: $ zpx NOP CYC(4) break;
|
||||
case 0xD5: zpx CMP CYC(4) break;
|
||||
case 0xD6: zpx DEC CYC(6) break;
|
||||
case 0xD7: $ zpx DCM CYC(6) break;
|
||||
case 0xD8: CLD CYC(2) break;
|
||||
case 0xD9: ABSY_OPT CMP CYC(4) break;
|
||||
case 0xDA: $ NOP CYC(2) break;
|
||||
case 0xDB: $ ABSY_CONST DCM CYC(7) break;
|
||||
case 0xDC: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0xDD: ABSX_OPT CMP CYC(4) break;
|
||||
case 0xDE: ABSX_CONST DEC CYC(7) break;
|
||||
case 0xDF: $ ABSX_CONST DCM CYC(7) break;
|
||||
case 0xE0: IMM CPX CYC(2) break;
|
||||
case 0xE1: idx SBCn CYC(6) break;
|
||||
case 0xE2: $ IMM NOP CYC(2) break;
|
||||
case 0xE3: $ idx INS CYC(8) break;
|
||||
case 0xE4: ZPG CPX CYC(3) break;
|
||||
case 0xE5: ZPG SBCn CYC(3) break;
|
||||
case 0xE6: ZPG INC CYC(5) break;
|
||||
case 0xE7: $ ZPG INS CYC(5) break;
|
||||
case 0xE8: INX CYC(2) break;
|
||||
case 0xE9: IMM SBCn CYC(2) break;
|
||||
case 0xEA: NOP CYC(2) break;
|
||||
case 0xEB: $ IMM SBCn CYC(2) break;
|
||||
case 0xEC: ABS CPX CYC(4) break;
|
||||
case 0xED: ABS SBCn CYC(4) break;
|
||||
case 0xEE: ABS INC CYC(6) break;
|
||||
case 0xEF: $ ABS INS CYC(6) break;
|
||||
case 0xF0: REL BEQ CYC(2) break;
|
||||
case 0xF1: INDY_OPT SBCn CYC(5) break;
|
||||
case 0xF2: $ HLT CYC(2) break;
|
||||
case 0xF3: $ INDY_CONST INS CYC(8) break;
|
||||
case 0xF4: $ zpx NOP CYC(4) break;
|
||||
case 0xF5: zpx SBCn CYC(4) break;
|
||||
case 0xF6: zpx INC CYC(6) break;
|
||||
case 0xF7: $ zpx INS CYC(6) break;
|
||||
case 0xF8: SED CYC(2) break;
|
||||
case 0xF9: ABSY_OPT SBCn CYC(4) break;
|
||||
case 0xFA: $ NOP CYC(2) break;
|
||||
case 0xFB: $ ABSY_CONST INS CYC(7) break;
|
||||
case 0xFC: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0xFD: ABSX_OPT SBCn CYC(4) break;
|
||||
case 0xFE: ABSX_CONST INC CYC(7) break;
|
||||
case 0xFF: $ ABSX_CONST INS CYC(7) break;
|
||||
// TODO-MP Optimization Note: ?? Move CYC(#) to array ??
|
||||
case 0x00: BRK 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
|
||||
case 0x04: ZPG NOP CYC(3) break; // invalid
|
||||
case 0x05: ZPG ORA CYC(3) break;
|
||||
case 0x06: ZPG ASLn CYC(5) break;
|
||||
case 0x07: ZPG ASO CYC(5) break; // invalid
|
||||
case 0x08: PHP CYC(3) break;
|
||||
case 0x09: IMM ORA CYC(2) break;
|
||||
case 0x0A: asl CYC(2) break;
|
||||
case 0x0B: IMM ANC CYC(2) break; // invalid
|
||||
case 0x0C: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0x0D: ABS ORA CYC(4) break;
|
||||
case 0x0E: ABS ASLn CYC(6) break;
|
||||
case 0x0F: ABS ASO CYC(6) break; // invalid
|
||||
case 0x10: REL BPL CYC(2) break;
|
||||
case 0x11: INDY_OPT ORA CYC(5) break;
|
||||
case 0x12: HLT CYC(2) break; // invalid
|
||||
case 0x13: INDY_CONST ASO CYC(8) break; // invalid
|
||||
case 0x14: zpx NOP CYC(4) break; // invalid
|
||||
case 0x15: zpx ORA CYC(4) break;
|
||||
case 0x16: zpx ASLn CYC(6) break;
|
||||
case 0x17: zpx ASO CYC(6) break; // invalid
|
||||
case 0x18: CLC CYC(2) break;
|
||||
case 0x19: ABSY_OPT ORA CYC(4) break;
|
||||
case 0x1A: NOP CYC(2) break; // invalid
|
||||
case 0x1B: ABSY_CONST ASO CYC(7) break; // invalid
|
||||
case 0x1C: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0x1D: ABSX_OPT ORA CYC(4) break;
|
||||
case 0x1E: ABSX_CONST ASLn CYC(7) break;
|
||||
case 0x1F: ABSX_CONST ASO CYC(7) break; // invalid
|
||||
case 0x20: ABS JSR CYC(6) break;
|
||||
case 0x21: idx AND CYC(6) break;
|
||||
case 0x22: HLT CYC(2) break; // invalid
|
||||
case 0x23: idx RLA CYC(8) break; // invalid
|
||||
case 0x24: ZPG BIT CYC(3) break;
|
||||
case 0x25: ZPG AND CYC(3) break;
|
||||
case 0x26: ZPG ROLn CYC(5) break;
|
||||
case 0x27: ZPG RLA CYC(5) break; // invalid
|
||||
case 0x28: PLP CYC(4) break;
|
||||
case 0x29: IMM AND CYC(2) break;
|
||||
case 0x2A: rol CYC(2) break;
|
||||
case 0x2B: IMM ANC CYC(2) break; // invalid
|
||||
case 0x2C: ABS BIT CYC(4) break;
|
||||
case 0x2D: ABS AND CYC(4) break;
|
||||
case 0x2E: ABS ROLn CYC(6) break;
|
||||
case 0x2F: ABS RLA CYC(6) break; // invalid
|
||||
case 0x30: REL BMI CYC(2) break;
|
||||
case 0x31: INDY_OPT AND CYC(5) break;
|
||||
case 0x32: HLT CYC(2) break; // invalid
|
||||
case 0x33: INDY_CONST RLA CYC(8) break; // invalid
|
||||
case 0x34: zpx NOP CYC(4) break; // invalid
|
||||
case 0x35: zpx AND CYC(4) break;
|
||||
case 0x36: zpx ROLn CYC(6) break;
|
||||
case 0x37: zpx RLA CYC(6) break; // invalid
|
||||
case 0x38: SEC CYC(2) break;
|
||||
case 0x39: ABSY_OPT AND CYC(4) break;
|
||||
case 0x3A: NOP CYC(2) break; // invalid
|
||||
case 0x3B: ABSY_CONST RLA CYC(7) break; // invalid
|
||||
case 0x3C: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0x3D: ABSX_OPT AND CYC(4) break;
|
||||
case 0x3E: ABSX_CONST ROLn CYC(7) break;
|
||||
case 0x3F: ABSX_CONST RLA CYC(7) break; // invalid
|
||||
case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
|
||||
case 0x41: idx EOR CYC(6) break;
|
||||
case 0x42: HLT CYC(2) break; // invalid
|
||||
case 0x43: idx LSE CYC(8) break; // invalid
|
||||
case 0x44: ZPG NOP CYC(3) break; // invalid
|
||||
case 0x45: ZPG EOR CYC(3) break;
|
||||
case 0x46: ZPG LSRn CYC(5) break;
|
||||
case 0x47: ZPG LSE CYC(5) break; // invalid
|
||||
case 0x48: PHA CYC(3) break;
|
||||
case 0x49: IMM EOR CYC(2) break;
|
||||
case 0x4A: lsr CYC(2) break;
|
||||
case 0x4B: IMM ALR CYC(2) break; // invalid
|
||||
case 0x4C: ABS JMP CYC(3) break;
|
||||
case 0x4D: ABS EOR CYC(4) break;
|
||||
case 0x4E: ABS LSRn CYC(6) break;
|
||||
case 0x4F: ABS LSE CYC(6) break; // invalid
|
||||
case 0x50: REL BVC CYC(2) break;
|
||||
case 0x51: INDY_OPT EOR CYC(5) break;
|
||||
case 0x52: HLT CYC(2) break; // invalid
|
||||
case 0x53: INDY_CONST LSE CYC(8) break; // invalid
|
||||
case 0x54: zpx NOP CYC(4) break; // invalid
|
||||
case 0x55: zpx EOR CYC(4) break;
|
||||
case 0x56: zpx LSRn CYC(6) break;
|
||||
case 0x57: zpx LSE CYC(6) break; // invalid
|
||||
case 0x58: CLI CYC(2) break;
|
||||
case 0x59: ABSY_OPT EOR CYC(4) break;
|
||||
case 0x5A: NOP CYC(2) break; // invalid
|
||||
case 0x5B: ABSY_CONST LSE CYC(7) break; // invalid
|
||||
case 0x5C: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0x5D: ABSX_OPT EOR CYC(4) break;
|
||||
case 0x5E: ABSX_CONST LSRn CYC(7) break;
|
||||
case 0x5F: ABSX_CONST LSE CYC(7) break; // invalid
|
||||
case 0x60: RTS CYC(6) break;
|
||||
case 0x61: idx ADCn CYC(6) break;
|
||||
case 0x62: HLT CYC(2) break; // invalid
|
||||
case 0x63: idx RRA CYC(8) break; // invalid
|
||||
case 0x64: ZPG NOP CYC(3) break; // invalid
|
||||
case 0x65: ZPG ADCn CYC(3) break;
|
||||
case 0x66: ZPG RORn CYC(5) break;
|
||||
case 0x67: ZPG RRA CYC(5) break; // invalid
|
||||
case 0x68: PLA CYC(4) break;
|
||||
case 0x69: IMM ADCn CYC(2) break;
|
||||
case 0x6A: ror CYC(2) break;
|
||||
case 0x6B: IMM ARR CYC(2) break; // invalid
|
||||
case 0x6C: IABS_NMOS JMP CYC(5) break; // GH#264
|
||||
case 0x6D: ABS ADCn CYC(4) break;
|
||||
case 0x6E: ABS RORn CYC(6) break;
|
||||
case 0x6F: ABS RRA CYC(6) break; // invalid
|
||||
case 0x70: REL BVS CYC(2) break;
|
||||
case 0x71: INDY_OPT ADCn CYC(5) break;
|
||||
case 0x72: HLT CYC(2) break; // invalid
|
||||
case 0x73: INDY_CONST RRA CYC(8) break; // invalid
|
||||
case 0x74: zpx NOP CYC(4) break; // invalid
|
||||
case 0x75: zpx ADCn CYC(4) break;
|
||||
case 0x76: zpx RORn CYC(6) break;
|
||||
case 0x77: zpx RRA CYC(6) break; // invalid
|
||||
case 0x78: SEI CYC(2) break;
|
||||
case 0x79: ABSY_OPT ADCn CYC(4) break;
|
||||
case 0x7A: NOP CYC(2) break; // invalid
|
||||
case 0x7B: ABSY_CONST RRA CYC(7) break; // invalid
|
||||
case 0x7C: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0x7D: ABSX_OPT ADCn CYC(4) break;
|
||||
case 0x7E: ABSX_CONST RORn CYC(7) break;
|
||||
case 0x7F: ABSX_CONST RRA CYC(7) break; // invalid
|
||||
case 0x80: IMM NOP CYC(2) break; // invalid
|
||||
case 0x81: idx STA CYC(6) break;
|
||||
case 0x82: IMM NOP CYC(2) break; // invalid
|
||||
case 0x83: idx AXS CYC(6) break; // invalid
|
||||
case 0x84: ZPG STY CYC(3) break;
|
||||
case 0x85: ZPG STA CYC(3) break;
|
||||
case 0x86: ZPG STX CYC(3) break;
|
||||
case 0x87: ZPG AXS CYC(3) break; // invalid
|
||||
case 0x88: DEY CYC(2) break;
|
||||
case 0x89: IMM NOP CYC(2) break; // invalid
|
||||
case 0x8A: TXA CYC(2) break;
|
||||
case 0x8B: IMM XAA CYC(2) break; // invalid
|
||||
case 0x8C: ABS STY CYC(4) break;
|
||||
case 0x8D: ABS STA CYC(4) break;
|
||||
case 0x8E: ABS STX CYC(4) break;
|
||||
case 0x8F: ABS AXS CYC(4) break; // invalid
|
||||
case 0x90: REL BCC CYC(2) break;
|
||||
case 0x91: INDY_CONST STA CYC(6) break;
|
||||
case 0x92: HLT CYC(2) break; // invalid
|
||||
case 0x93: INDY_CONST AXA CYC(6) break; // invalid
|
||||
case 0x94: zpx STY CYC(4) break;
|
||||
case 0x95: zpx STA CYC(4) break;
|
||||
case 0x96: zpy STX CYC(4) break;
|
||||
case 0x97: zpy AXS CYC(4) break; // invalid
|
||||
case 0x98: TYA CYC(2) break;
|
||||
case 0x99: ABSY_CONST STA CYC(5) break;
|
||||
case 0x9A: TXS CYC(2) break;
|
||||
case 0x9B: ABSY_CONST TAS CYC(5) break; // invalid
|
||||
case 0x9C: ABSX_CONST SAY CYC(5) break; // invalid
|
||||
case 0x9D: ABSX_CONST STA CYC(5) break;
|
||||
case 0x9E: ABSY_CONST XAS CYC(5) break; // invalid
|
||||
case 0x9F: ABSY_CONST AXA CYC(5) break; // invalid
|
||||
case 0xA0: IMM LDY CYC(2) break;
|
||||
case 0xA1: idx LDA CYC(6) break;
|
||||
case 0xA2: IMM LDX CYC(2) break;
|
||||
case 0xA3: idx LAX CYC(6) break; // invalid
|
||||
case 0xA4: ZPG LDY CYC(3) break;
|
||||
case 0xA5: ZPG LDA CYC(3) break;
|
||||
case 0xA6: ZPG LDX CYC(3) break;
|
||||
case 0xA7: ZPG LAX CYC(3) break; // invalid
|
||||
case 0xA8: TAY CYC(2) break;
|
||||
case 0xA9: IMM LDA CYC(2) break;
|
||||
case 0xAA: TAX CYC(2) break;
|
||||
case 0xAB: IMM OAL CYC(2) break; // invalid
|
||||
case 0xAC: ABS LDY CYC(4) break;
|
||||
case 0xAD: ABS LDA CYC(4) break;
|
||||
case 0xAE: ABS LDX CYC(4) break;
|
||||
case 0xAF: ABS LAX CYC(4) break; // invalid
|
||||
case 0xB0: REL BCS CYC(2) break;
|
||||
case 0xB1: INDY_OPT LDA CYC(5) break;
|
||||
case 0xB2: HLT CYC(2) break; // invalid
|
||||
case 0xB3: INDY_OPT LAX CYC(5) break; // invalid
|
||||
case 0xB4: zpx LDY CYC(4) break;
|
||||
case 0xB5: zpx LDA CYC(4) break;
|
||||
case 0xB6: zpy LDX CYC(4) break;
|
||||
case 0xB7: zpy LAX CYC(4) break; // invalid
|
||||
case 0xB8: CLV CYC(2) break;
|
||||
case 0xB9: ABSY_OPT LDA CYC(4) break;
|
||||
case 0xBA: TSX CYC(2) break;
|
||||
case 0xBB: ABSY_OPT LAS CYC(4) break; // invalid
|
||||
case 0xBC: ABSX_OPT LDY CYC(4) break;
|
||||
case 0xBD: ABSX_OPT LDA CYC(4) break;
|
||||
case 0xBE: ABSY_OPT LDX CYC(4) break;
|
||||
case 0xBF: ABSY_OPT LAX CYC(4) break; // invalid
|
||||
case 0xC0: IMM CPY CYC(2) break;
|
||||
case 0xC1: idx CMP CYC(6) break;
|
||||
case 0xC2: IMM NOP CYC(2) break; // invalid
|
||||
case 0xC3: idx DCM CYC(8) break; // invalid
|
||||
case 0xC4: ZPG CPY CYC(3) break;
|
||||
case 0xC5: ZPG CMP CYC(3) break;
|
||||
case 0xC6: ZPG DEC CYC(5) break;
|
||||
case 0xC7: ZPG DCM CYC(5) break; // invalid
|
||||
case 0xC8: INY CYC(2) break;
|
||||
case 0xC9: IMM CMP CYC(2) break;
|
||||
case 0xCA: DEX CYC(2) break;
|
||||
case 0xCB: IMM SAX CYC(2) break; // invalid
|
||||
case 0xCC: ABS CPY CYC(4) break;
|
||||
case 0xCD: ABS CMP CYC(4) break;
|
||||
case 0xCE: ABS DEC CYC(6) break;
|
||||
case 0xCF: ABS DCM CYC(6) break; // invalid
|
||||
case 0xD0: REL BNE CYC(2) break;
|
||||
case 0xD1: INDY_OPT CMP CYC(5) break;
|
||||
case 0xD2: HLT CYC(2) break; // invalid
|
||||
case 0xD3: INDY_CONST DCM CYC(8) break; // invalid
|
||||
case 0xD4: zpx NOP CYC(4) break; // invalid
|
||||
case 0xD5: zpx CMP CYC(4) break;
|
||||
case 0xD6: zpx DEC CYC(6) break;
|
||||
case 0xD7: zpx DCM CYC(6) break; // invalid
|
||||
case 0xD8: CLD CYC(2) break;
|
||||
case 0xD9: ABSY_OPT CMP CYC(4) break;
|
||||
case 0xDA: NOP CYC(2) break; // invalid
|
||||
case 0xDB: ABSY_CONST DCM CYC(7) break; // invalid
|
||||
case 0xDC: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0xDD: ABSX_OPT CMP CYC(4) break;
|
||||
case 0xDE: ABSX_CONST DEC CYC(7) break;
|
||||
case 0xDF: ABSX_CONST DCM CYC(7) break; // invalid
|
||||
case 0xE0: IMM CPX CYC(2) break;
|
||||
case 0xE1: idx SBCn CYC(6) break;
|
||||
case 0xE2: IMM NOP CYC(2) break; // invalid
|
||||
case 0xE3: idx INS CYC(8) break; // invalid
|
||||
case 0xE4: ZPG CPX CYC(3) break;
|
||||
case 0xE5: ZPG SBCn CYC(3) break;
|
||||
case 0xE6: ZPG INC CYC(5) break;
|
||||
case 0xE7: ZPG INS CYC(5) break; // invalid
|
||||
case 0xE8: INX CYC(2) break;
|
||||
case 0xE9: IMM SBCn CYC(2) break;
|
||||
case 0xEA: NOP CYC(2) break;
|
||||
case 0xEB: IMM SBCn CYC(2) break; // invalid
|
||||
case 0xEC: ABS CPX CYC(4) break;
|
||||
case 0xED: ABS SBCn CYC(4) break;
|
||||
case 0xEE: ABS INC CYC(6) break;
|
||||
case 0xEF: ABS INS CYC(6) break; // invalid
|
||||
case 0xF0: REL BEQ CYC(2) break;
|
||||
case 0xF1: INDY_OPT SBCn CYC(5) break;
|
||||
case 0xF2: HLT CYC(2) break; // invalid
|
||||
case 0xF3: INDY_CONST INS CYC(8) break; // invalid
|
||||
case 0xF4: zpx NOP CYC(4) break; // invalid
|
||||
case 0xF5: zpx SBCn CYC(4) break;
|
||||
case 0xF6: zpx INC CYC(6) break;
|
||||
case 0xF7: zpx INS CYC(6) break; // invalid
|
||||
case 0xF8: SED CYC(2) break;
|
||||
case 0xF9: ABSY_OPT SBCn CYC(4) break;
|
||||
case 0xFA: NOP CYC(2) break; // invalid
|
||||
case 0xFB: ABSY_CONST INS CYC(7) break; // invalid
|
||||
case 0xFC: ABSX_OPT NOP CYC(4) break; // invalid
|
||||
case 0xFD: ABSX_OPT SBCn CYC(4) break;
|
||||
case 0xFE: ABSX_CONST INC CYC(7) break;
|
||||
case 0xFF: ABSX_CONST INS CYC(7) break; // invalid
|
||||
}
|
||||
#undef $
|
||||
}
|
||||
|
||||
CheckInterruptSources(uExecutedCycles, bVideoUpdate);
|
||||
|
|
|
@ -25,9 +25,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
static DWORD Cpu65C02(DWORD uTotalCycles, const bool bVideoUpdate)
|
||||
{
|
||||
// Optimisation:
|
||||
// . Copy the global /regs/ vars to stack-based local vars
|
||||
// (Oliver Schmidt says this gives a performance gain, see email - The real deal: "1.10.5")
|
||||
WORD addr;
|
||||
BOOL flagc; // must always be 0 or 1, no other values allowed
|
||||
BOOL flagn; // must always be 0 or 0x80.
|
||||
|
@ -55,270 +52,269 @@ static DWORD Cpu65C02(DWORD uTotalCycles, const bool bVideoUpdate)
|
|||
}
|
||||
else
|
||||
{
|
||||
HEATMAP_X( regs.pc );
|
||||
Fetch(iOpcode, uExecutedCycles);
|
||||
|
||||
//#define $ INV // INV = Invalid -> Debugger Break
|
||||
#define $
|
||||
switch (iOpcode)
|
||||
{
|
||||
case 0x00: BRK CYC(7) break;
|
||||
case 0x01: idx ORA CYC(6) break;
|
||||
case 0x02: $ IMM NOP CYC(2) break;
|
||||
case 0x03: $ NOP CYC(1) break;
|
||||
case 0x04: ZPG TSB CYC(5) break;
|
||||
case 0x05: ZPG ORA CYC(3) break;
|
||||
case 0x06: ZPG ASLc CYC(5) break;
|
||||
case 0x07: $ NOP CYC(1) break;
|
||||
case 0x08: PHP CYC(3) break;
|
||||
case 0x09: IMM ORA CYC(2) break;
|
||||
case 0x0A: asl CYC(2) break;
|
||||
case 0x0B: $ NOP CYC(1) break;
|
||||
case 0x0C: ABS TSB CYC(6) break;
|
||||
case 0x0D: ABS ORA CYC(4) break;
|
||||
case 0x0E: ABS ASLc CYC(6) break;
|
||||
case 0x0F: $ NOP CYC(1) break;
|
||||
case 0x10: REL BPL CYC(2) break;
|
||||
case 0x11: INDY_OPT ORA CYC(5) break;
|
||||
case 0x12: izp ORA CYC(5) break;
|
||||
case 0x13: $ NOP CYC(1) break;
|
||||
case 0x14: ZPG TRB CYC(5) break;
|
||||
case 0x15: zpx ORA CYC(4) break;
|
||||
case 0x16: zpx ASLc CYC(6) break;
|
||||
case 0x17: $ NOP CYC(1) break;
|
||||
case 0x18: CLC CYC(2) break;
|
||||
case 0x19: ABSY_OPT ORA CYC(4) break;
|
||||
case 0x1A: INA CYC(2) break;
|
||||
case 0x1B: $ NOP CYC(1) break;
|
||||
case 0x1C: ABS TRB CYC(6) break;
|
||||
case 0x1D: ABSX_OPT ORA CYC(4) break;
|
||||
case 0x1E: ABSX_OPT ASLc CYC(6) break;
|
||||
case 0x1F: $ NOP CYC(1) break;
|
||||
case 0x20: ABS JSR CYC(6) break;
|
||||
case 0x21: idx AND CYC(6) break;
|
||||
case 0x22: $ IMM NOP CYC(2) break;
|
||||
case 0x23: $ NOP CYC(1) break;
|
||||
case 0x24: ZPG BIT CYC(3) break;
|
||||
case 0x25: ZPG AND CYC(3) break;
|
||||
case 0x26: ZPG ROLc CYC(5) break;
|
||||
case 0x27: $ NOP CYC(1) break;
|
||||
case 0x28: PLP CYC(4) break;
|
||||
case 0x29: IMM AND CYC(2) break;
|
||||
case 0x2A: rol CYC(2) break;
|
||||
case 0x2B: $ NOP CYC(1) break;
|
||||
case 0x2C: ABS BIT CYC(4) break;
|
||||
case 0x2D: ABS AND CYC(4) break;
|
||||
case 0x2E: ABS ROLc CYC(6) break;
|
||||
case 0x2F: $ NOP CYC(1) break;
|
||||
case 0x30: REL BMI CYC(2) break;
|
||||
case 0x31: INDY_OPT AND CYC(5) break;
|
||||
case 0x32: izp AND CYC(5) break;
|
||||
case 0x33: $ NOP CYC(1) break;
|
||||
case 0x34: zpx BIT CYC(4) break;
|
||||
case 0x35: zpx AND CYC(4) break;
|
||||
case 0x36: zpx ROLc CYC(6) break;
|
||||
case 0x37: $ NOP CYC(1) break;
|
||||
case 0x38: SEC CYC(2) break;
|
||||
case 0x39: ABSY_OPT AND CYC(4) break;
|
||||
case 0x3A: DEA CYC(2) break;
|
||||
case 0x3B: $ NOP CYC(1) break;
|
||||
case 0x3C: ABSX_OPT BIT CYC(4) break;
|
||||
case 0x3D: ABSX_OPT AND CYC(4) break;
|
||||
case 0x3E: ABSX_OPT ROLc CYC(6) break;
|
||||
case 0x3F: $ NOP CYC(1) break;
|
||||
case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
|
||||
case 0x41: idx EOR CYC(6) break;
|
||||
case 0x42: $ IMM NOP CYC(2) break;
|
||||
case 0x43: $ NOP CYC(1) break;
|
||||
case 0x44: $ ZPG NOP CYC(3) break;
|
||||
case 0x45: ZPG EOR CYC(3) break;
|
||||
case 0x46: ZPG LSRc CYC(5) break;
|
||||
case 0x47: $ NOP CYC(1) break;
|
||||
case 0x48: PHA CYC(3) break;
|
||||
case 0x49: IMM EOR CYC(2) break;
|
||||
case 0x4A: lsr CYC(2) break;
|
||||
case 0x4B: $ NOP CYC(1) break;
|
||||
case 0x4C: ABS JMP CYC(3) break;
|
||||
case 0x4D: ABS EOR CYC(4) break;
|
||||
case 0x4E: ABS LSRc CYC(6) break;
|
||||
case 0x4F: $ NOP CYC(1) break;
|
||||
case 0x50: REL BVC CYC(2) break;
|
||||
case 0x51: INDY_OPT EOR CYC(5) break;
|
||||
case 0x52: izp EOR CYC(5) break;
|
||||
case 0x53: $ NOP CYC(1) break;
|
||||
case 0x54: $ zpx NOP CYC(4) break;
|
||||
case 0x55: zpx EOR CYC(4) break;
|
||||
case 0x56: zpx LSRc CYC(6) break;
|
||||
case 0x57: $ NOP CYC(1) break;
|
||||
case 0x58: CLI CYC(2) break;
|
||||
case 0x59: ABSY_OPT EOR CYC(4) break;
|
||||
case 0x5A: PHY CYC(3) break;
|
||||
case 0x5B: $ NOP CYC(1) break;
|
||||
case 0x5C: $ ABS NOP CYC(8) break;
|
||||
case 0x5D: ABSX_OPT EOR CYC(4) break;
|
||||
case 0x5E: ABSX_OPT LSRc CYC(6) break;
|
||||
case 0x5F: $ NOP CYC(1) break;
|
||||
case 0x60: RTS CYC(6) break;
|
||||
case 0x61: idx ADCc CYC(6) break;
|
||||
case 0x62: $ IMM NOP CYC(2) break;
|
||||
case 0x63: $ NOP CYC(1) break;
|
||||
case 0x64: ZPG STZ CYC(3) break;
|
||||
case 0x65: ZPG ADCc CYC(3) break;
|
||||
case 0x66: ZPG RORc CYC(5) break;
|
||||
case 0x67: $ NOP CYC(1) break;
|
||||
case 0x68: PLA CYC(4) break;
|
||||
case 0x69: IMM ADCc CYC(2) break;
|
||||
case 0x6A: ror CYC(2) break;
|
||||
case 0x6B: $ NOP CYC(1) break;
|
||||
case 0x6C: IABS_CMOS JMP CYC(6) break;
|
||||
case 0x6D: ABS ADCc CYC(4) break;
|
||||
case 0x6E: ABS RORc CYC(6) break;
|
||||
case 0x6F: $ NOP CYC(1) break;
|
||||
case 0x70: REL BVS CYC(2) break;
|
||||
case 0x71: INDY_OPT ADCc CYC(5) break;
|
||||
case 0x72: izp ADCc CYC(5) break;
|
||||
case 0x73: $ NOP CYC(1) break;
|
||||
case 0x74: zpx STZ CYC(4) break;
|
||||
case 0x75: zpx ADCc CYC(4) break;
|
||||
case 0x76: zpx RORc CYC(6) break;
|
||||
case 0x77: $ NOP CYC(1) break;
|
||||
case 0x78: SEI CYC(2) break;
|
||||
case 0x79: ABSY_OPT ADCc CYC(4) break;
|
||||
case 0x7A: PLY CYC(4) break;
|
||||
case 0x7B: $ NOP CYC(1) break;
|
||||
case 0x7C: IABSX JMP CYC(6) break;
|
||||
case 0x7D: ABSX_OPT ADCc CYC(4) break;
|
||||
case 0x7E: ABSX_OPT RORc CYC(6) break;
|
||||
case 0x7F: $ NOP CYC(1) break;
|
||||
case 0x80: REL BRA CYC(2) break;
|
||||
case 0x81: idx STA CYC(6) break;
|
||||
case 0x82: $ IMM NOP CYC(2) break;
|
||||
case 0x83: $ NOP CYC(1) break;
|
||||
case 0x84: ZPG STY CYC(3) break;
|
||||
case 0x85: ZPG STA CYC(3) break;
|
||||
case 0x86: ZPG STX CYC(3) break;
|
||||
case 0x87: $ NOP CYC(1) break;
|
||||
case 0x88: DEY CYC(2) break;
|
||||
case 0x89: IMM BITI CYC(2) break;
|
||||
case 0x8A: TXA CYC(2) break;
|
||||
case 0x8B: $ NOP CYC(1) break;
|
||||
case 0x8C: ABS STY CYC(4) break;
|
||||
case 0x8D: ABS STA CYC(4) break;
|
||||
case 0x8E: ABS STX CYC(4) break;
|
||||
case 0x8F: $ NOP CYC(1) break;
|
||||
case 0x90: REL BCC CYC(2) break;
|
||||
case 0x91: INDY_CONST STA CYC(6) break;
|
||||
case 0x92: izp STA CYC(5) break;
|
||||
case 0x93: $ NOP CYC(1) break;
|
||||
case 0x94: zpx STY CYC(4) break;
|
||||
case 0x95: zpx STA CYC(4) break;
|
||||
case 0x96: zpy STX CYC(4) break;
|
||||
case 0x97: $ NOP CYC(1) break;
|
||||
case 0x98: TYA CYC(2) break;
|
||||
case 0x99: ABSY_CONST STA CYC(5) break;
|
||||
case 0x9A: TXS CYC(2) break;
|
||||
case 0x9B: $ NOP CYC(1) break;
|
||||
case 0x9C: ABS STZ CYC(4) break;
|
||||
case 0x9D: ABSX_CONST STA CYC(5) break;
|
||||
case 0x9E: ABSX_CONST STZ CYC(5) break;
|
||||
case 0x9F: $ NOP CYC(1) break;
|
||||
case 0xA0: IMM LDY CYC(2) break;
|
||||
case 0xA1: idx LDA CYC(6) break;
|
||||
case 0xA2: IMM LDX CYC(2) break;
|
||||
case 0xA3: $ NOP CYC(1) break;
|
||||
case 0xA4: ZPG LDY CYC(3) break;
|
||||
case 0xA5: ZPG LDA CYC(3) break;
|
||||
case 0xA6: ZPG LDX CYC(3) break;
|
||||
case 0xA7: $ NOP CYC(1) break;
|
||||
case 0xA8: TAY CYC(2) break;
|
||||
case 0xA9: IMM LDA CYC(2) break;
|
||||
case 0xAA: TAX CYC(2) break;
|
||||
case 0xAB: $ NOP CYC(1) break;
|
||||
case 0xAC: ABS LDY CYC(4) break;
|
||||
case 0xAD: ABS LDA CYC(4) break;
|
||||
case 0xAE: ABS LDX CYC(4) break;
|
||||
case 0xAF: $ NOP CYC(1) break;
|
||||
case 0xB0: REL BCS CYC(2) break;
|
||||
case 0xB1: INDY_OPT LDA CYC(5) break;
|
||||
case 0xB2: izp LDA CYC(5) break;
|
||||
case 0xB3: $ NOP CYC(1) break;
|
||||
case 0xB4: zpx LDY CYC(4) break;
|
||||
case 0xB5: zpx LDA CYC(4) break;
|
||||
case 0xB6: zpy LDX CYC(4) break;
|
||||
case 0xB7: $ NOP CYC(1) break;
|
||||
case 0xB8: CLV CYC(2) break;
|
||||
case 0xB9: ABSY_OPT LDA CYC(4) break;
|
||||
case 0xBA: TSX CYC(2) break;
|
||||
case 0xBB: $ NOP CYC(1) break;
|
||||
case 0xBC: ABSX_OPT LDY CYC(4) break;
|
||||
case 0xBD: ABSX_OPT LDA CYC(4) break;
|
||||
case 0xBE: ABSY_OPT LDX CYC(4) break;
|
||||
case 0xBF: $ NOP CYC(1) break;
|
||||
case 0xC0: IMM CPY CYC(2) break;
|
||||
case 0xC1: idx CMP CYC(6) break;
|
||||
case 0xC2: $ IMM NOP CYC(2) break;
|
||||
case 0xC3: $ NOP CYC(1) break;
|
||||
case 0xC4: ZPG CPY CYC(3) break;
|
||||
case 0xC5: ZPG CMP CYC(3) break;
|
||||
case 0xC6: ZPG DEC CYC(5) break;
|
||||
case 0xC7: $ NOP CYC(1) break;
|
||||
case 0xC8: INY CYC(2) break;
|
||||
case 0xC9: IMM CMP CYC(2) break;
|
||||
case 0xCA: DEX CYC(2) break;
|
||||
case 0xCB: $ NOP CYC(1) break;
|
||||
case 0xCC: ABS CPY CYC(4) break;
|
||||
case 0xCD: ABS CMP CYC(4) break;
|
||||
case 0xCE: ABS DEC CYC(6) break;
|
||||
case 0xCF: $ NOP CYC(1) break;
|
||||
case 0xD0: REL BNE CYC(2) break;
|
||||
case 0xD1: INDY_OPT CMP CYC(5) break;
|
||||
case 0xD2: izp CMP CYC(5) break;
|
||||
case 0xD3: $ NOP CYC(1) break;
|
||||
case 0xD4: $ zpx NOP CYC(4) break;
|
||||
case 0xD5: zpx CMP CYC(4) break;
|
||||
case 0xD6: zpx DEC CYC(6) break;
|
||||
case 0xD7: $ NOP CYC(1) break;
|
||||
case 0xD8: CLD CYC(2) break;
|
||||
case 0xD9: ABSY_OPT CMP CYC(4) break;
|
||||
case 0xDA: PHX CYC(3) break;
|
||||
case 0xDB: $ NOP CYC(1) break;
|
||||
case 0xDC: $ ABS LDD CYC(4) break;
|
||||
case 0xDD: ABSX_OPT CMP CYC(4) break;
|
||||
case 0xDE: ABSX_CONST DEC CYC(7) break;
|
||||
case 0xDF: $ NOP CYC(1) break;
|
||||
case 0xE0: IMM CPX CYC(2) break;
|
||||
case 0xE1: idx SBCc CYC(6) break;
|
||||
case 0xE2: $ IMM NOP CYC(2) break;
|
||||
case 0xE3: $ NOP CYC(1) break;
|
||||
case 0xE4: ZPG CPX CYC(3) break;
|
||||
case 0xE5: ZPG SBCc CYC(3) break;
|
||||
case 0xE6: ZPG INC CYC(5) break;
|
||||
case 0xE7: $ NOP CYC(1) break;
|
||||
case 0xE8: INX CYC(2) break;
|
||||
case 0xE9: IMM SBCc CYC(2) break;
|
||||
case 0xEA: NOP CYC(2) break;
|
||||
case 0xEB: $ NOP CYC(1) break;
|
||||
case 0xEC: ABS CPX CYC(4) break;
|
||||
case 0xED: ABS SBCc CYC(4) break;
|
||||
case 0xEE: ABS INC CYC(6) break;
|
||||
case 0xEF: $ NOP CYC(1) break;
|
||||
case 0xF0: REL BEQ CYC(2) break;
|
||||
case 0xF1: INDY_OPT SBCc CYC(5) break;
|
||||
case 0xF2: izp SBCc CYC(5) break;
|
||||
case 0xF3: $ NOP CYC(1) break;
|
||||
case 0xF4: $ zpx NOP CYC(4) break;
|
||||
case 0xF5: zpx SBCc CYC(4) break;
|
||||
case 0xF6: zpx INC CYC(6) break;
|
||||
case 0xF7: $ NOP CYC(1) break;
|
||||
case 0xF8: SED CYC(2) break;
|
||||
case 0xF9: ABSY_OPT SBCc CYC(4) break;
|
||||
case 0xFA: PLX CYC(4) break;
|
||||
case 0xFB: $ NOP CYC(1) break;
|
||||
case 0xFC: $ ABS LDD CYC(4) break;
|
||||
case 0xFD: ABSX_OPT SBCc CYC(4) break;
|
||||
case 0xFE: ABSX_CONST INC CYC(7) break;
|
||||
case 0xFF: $ NOP CYC(1) break;
|
||||
// TODO-MP Optimization Note: ?? Move CYC(#) to array ??
|
||||
case 0x00: BRK 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
|
||||
case 0x04: ZPG TSB CYC(5) break;
|
||||
case 0x05: ZPG ORA CYC(3) break;
|
||||
case 0x06: ZPG ASLc CYC(5) break;
|
||||
case 0x07: NOP CYC(1) break; // invalid
|
||||
case 0x08: PHP CYC(3) break;
|
||||
case 0x09: IMM ORA CYC(2) break;
|
||||
case 0x0A: asl CYC(2) break;
|
||||
case 0x0B: NOP CYC(1) break; // invalid
|
||||
case 0x0C: ABS TSB CYC(6) break;
|
||||
case 0x0D: ABS ORA CYC(4) break;
|
||||
case 0x0E: ABS ASLc CYC(6) break;
|
||||
case 0x0F: NOP CYC(1) break; // invalid
|
||||
case 0x10: REL BPL CYC(2) break;
|
||||
case 0x11: INDY_OPT ORA CYC(5) break;
|
||||
case 0x12: izp ORA CYC(5) break;
|
||||
case 0x13: NOP CYC(1) break; // invalid
|
||||
case 0x14: ZPG TRB CYC(5) break;
|
||||
case 0x15: zpx ORA CYC(4) break;
|
||||
case 0x16: zpx ASLc CYC(6) break;
|
||||
case 0x17: NOP CYC(1) break; // invalid
|
||||
case 0x18: CLC CYC(2) break;
|
||||
case 0x19: ABSY_OPT ORA CYC(4) break;
|
||||
case 0x1A: INA CYC(2) break;
|
||||
case 0x1B: NOP CYC(1) break; // invalid
|
||||
case 0x1C: ABS TRB CYC(6) break;
|
||||
case 0x1D: ABSX_OPT ORA CYC(4) break;
|
||||
case 0x1E: ABSX_OPT ASLc CYC(6) break;
|
||||
case 0x1F: NOP CYC(1) break; // invalid
|
||||
case 0x20: ABS JSR CYC(6) break;
|
||||
case 0x21: idx AND CYC(6) break;
|
||||
case 0x22: IMM NOP CYC(2) break; // invalid
|
||||
case 0x23: NOP CYC(1) break; // invalid
|
||||
case 0x24: ZPG BIT CYC(3) break;
|
||||
case 0x25: ZPG AND CYC(3) break;
|
||||
case 0x26: ZPG ROLc CYC(5) break;
|
||||
case 0x27: NOP CYC(1) break; // invalid
|
||||
case 0x28: PLP CYC(4) break;
|
||||
case 0x29: IMM AND CYC(2) break;
|
||||
case 0x2A: rol CYC(2) break;
|
||||
case 0x2B: NOP CYC(1) break; // invalid
|
||||
case 0x2C: ABS BIT CYC(4) break;
|
||||
case 0x2D: ABS AND CYC(4) break;
|
||||
case 0x2E: ABS ROLc CYC(6) break;
|
||||
case 0x2F: NOP CYC(1) break; // invalid
|
||||
case 0x30: REL BMI CYC(2) break;
|
||||
case 0x31: INDY_OPT AND CYC(5) break;
|
||||
case 0x32: izp AND CYC(5) break;
|
||||
case 0x33: NOP CYC(1) break; // invalid
|
||||
case 0x34: zpx BIT CYC(4) break;
|
||||
case 0x35: zpx AND CYC(4) break;
|
||||
case 0x36: zpx ROLc CYC(6) break;
|
||||
case 0x37: NOP CYC(1) break; // invalid
|
||||
case 0x38: SEC CYC(2) break;
|
||||
case 0x39: ABSY_OPT AND CYC(4) break;
|
||||
case 0x3A: DEA CYC(2) break;
|
||||
case 0x3B: NOP CYC(1) break; // invalid
|
||||
case 0x3C: ABSX_OPT BIT CYC(4) break;
|
||||
case 0x3D: ABSX_OPT AND CYC(4) break;
|
||||
case 0x3E: ABSX_OPT ROLc CYC(6) break;
|
||||
case 0x3F: NOP CYC(1) break; // invalid
|
||||
case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
|
||||
case 0x41: idx EOR CYC(6) break;
|
||||
case 0x42: IMM NOP CYC(2) break; // invalid
|
||||
case 0x43: NOP CYC(1) break; // invalid
|
||||
case 0x44: ZPG NOP CYC(3) break; // invalid
|
||||
case 0x45: ZPG EOR CYC(3) break;
|
||||
case 0x46: ZPG LSRc CYC(5) break;
|
||||
case 0x47: NOP CYC(1) break; // invalid
|
||||
case 0x48: PHA CYC(3) break;
|
||||
case 0x49: IMM EOR CYC(2) break;
|
||||
case 0x4A: lsr CYC(2) break;
|
||||
case 0x4B: NOP CYC(1) break; // invalid
|
||||
case 0x4C: ABS JMP CYC(3) break;
|
||||
case 0x4D: ABS EOR CYC(4) break;
|
||||
case 0x4E: ABS LSRc CYC(6) break;
|
||||
case 0x4F: NOP CYC(1) break; // invalid
|
||||
case 0x50: REL BVC CYC(2) break;
|
||||
case 0x51: INDY_OPT EOR CYC(5) break;
|
||||
case 0x52: izp EOR CYC(5) break;
|
||||
case 0x53: NOP CYC(1) break; // invalid
|
||||
case 0x54: zpx NOP CYC(4) break; // invalid
|
||||
case 0x55: zpx EOR CYC(4) break;
|
||||
case 0x56: zpx LSRc CYC(6) break;
|
||||
case 0x57: NOP CYC(1) break; // invalid
|
||||
case 0x58: CLI CYC(2) break;
|
||||
case 0x59: ABSY_OPT EOR CYC(4) break;
|
||||
case 0x5A: PHY CYC(3) break;
|
||||
case 0x5B: NOP CYC(1) break; // invalid
|
||||
case 0x5C: ABS NOP CYC(8) break; // invalid
|
||||
case 0x5D: ABSX_OPT EOR CYC(4) break;
|
||||
case 0x5E: ABSX_OPT LSRc CYC(6) break;
|
||||
case 0x5F: NOP CYC(1) break; // invalid
|
||||
case 0x60: RTS CYC(6) break;
|
||||
case 0x61: idx ADCc CYC(6) break;
|
||||
case 0x62: IMM NOP CYC(2) break; // invalid
|
||||
case 0x63: NOP CYC(1) break; // invalid
|
||||
case 0x64: ZPG STZ CYC(3) break;
|
||||
case 0x65: ZPG ADCc CYC(3) break;
|
||||
case 0x66: ZPG RORc CYC(5) break;
|
||||
case 0x67: NOP CYC(1) break; // invalid
|
||||
case 0x68: PLA CYC(4) break;
|
||||
case 0x69: IMM ADCc CYC(2) break;
|
||||
case 0x6A: ror CYC(2) break;
|
||||
case 0x6B: NOP CYC(1) break; // invalid
|
||||
case 0x6C: IABS_CMOS JMP CYC(6) break;
|
||||
case 0x6D: ABS ADCc CYC(4) break;
|
||||
case 0x6E: ABS RORc CYC(6) break;
|
||||
case 0x6F: NOP CYC(1) break; // invalid
|
||||
case 0x70: REL BVS CYC(2) break;
|
||||
case 0x71: INDY_OPT ADCc CYC(5) break;
|
||||
case 0x72: izp ADCc CYC(5) break;
|
||||
case 0x73: NOP CYC(1) break; // invalid
|
||||
case 0x74: zpx STZ CYC(4) break;
|
||||
case 0x75: zpx ADCc CYC(4) break;
|
||||
case 0x76: zpx RORc CYC(6) break;
|
||||
case 0x77: NOP CYC(1) break; // invalid
|
||||
case 0x78: SEI CYC(2) break;
|
||||
case 0x79: ABSY_OPT ADCc CYC(4) break;
|
||||
case 0x7A: PLY CYC(4) break;
|
||||
case 0x7B: NOP CYC(1) break; // invalid
|
||||
case 0x7C: IABSX JMP CYC(6) break;
|
||||
case 0x7D: ABSX_OPT ADCc CYC(4) break;
|
||||
case 0x7E: ABSX_OPT RORc CYC(6) break;
|
||||
case 0x7F: NOP CYC(1) break; // invalid
|
||||
case 0x80: REL BRA CYC(2) break;
|
||||
case 0x81: idx STA CYC(6) break;
|
||||
case 0x82: IMM NOP CYC(2) break; // invalid
|
||||
case 0x83: NOP CYC(1) break; // invalid
|
||||
case 0x84: ZPG STY CYC(3) break;
|
||||
case 0x85: ZPG STA CYC(3) break;
|
||||
case 0x86: ZPG STX CYC(3) break;
|
||||
case 0x87: NOP CYC(1) break; // invalid
|
||||
case 0x88: DEY CYC(2) break;
|
||||
case 0x89: IMM BITI CYC(2) break;
|
||||
case 0x8A: TXA CYC(2) break;
|
||||
case 0x8B: NOP CYC(1) break; // invalid
|
||||
case 0x8C: ABS STY CYC(4) break;
|
||||
case 0x8D: ABS STA CYC(4) break;
|
||||
case 0x8E: ABS STX CYC(4) break;
|
||||
case 0x8F: NOP CYC(1) break; // invalid
|
||||
case 0x90: REL BCC CYC(2) break;
|
||||
case 0x91: INDY_CONST STA CYC(6) break;
|
||||
case 0x92: izp STA CYC(5) break;
|
||||
case 0x93: NOP CYC(1) break; // invalid
|
||||
case 0x94: zpx STY CYC(4) break;
|
||||
case 0x95: zpx STA CYC(4) break;
|
||||
case 0x96: zpy STX CYC(4) break;
|
||||
case 0x97: NOP CYC(1) break; // invalid
|
||||
case 0x98: TYA CYC(2) break;
|
||||
case 0x99: ABSY_CONST STA CYC(5) break;
|
||||
case 0x9A: TXS CYC(2) break;
|
||||
case 0x9B: NOP CYC(1) break; // invalid
|
||||
case 0x9C: ABS STZ CYC(4) break;
|
||||
case 0x9D: ABSX_CONST STA CYC(5) break;
|
||||
case 0x9E: ABSX_CONST STZ CYC(5) break;
|
||||
case 0x9F: NOP CYC(1) break; // invalid
|
||||
case 0xA0: IMM LDY CYC(2) break;
|
||||
case 0xA1: idx LDA CYC(6) break;
|
||||
case 0xA2: IMM LDX CYC(2) break;
|
||||
case 0xA3: NOP CYC(1) break; // invalid
|
||||
case 0xA4: ZPG LDY CYC(3) break;
|
||||
case 0xA5: ZPG LDA CYC(3) break;
|
||||
case 0xA6: ZPG LDX CYC(3) break;
|
||||
case 0xA7: NOP CYC(1) break; // invalid
|
||||
case 0xA8: TAY CYC(2) break;
|
||||
case 0xA9: IMM LDA CYC(2) break;
|
||||
case 0xAA: TAX CYC(2) break;
|
||||
case 0xAB: NOP CYC(1) break; // invalid
|
||||
case 0xAC: ABS LDY CYC(4) break;
|
||||
case 0xAD: ABS LDA CYC(4) break;
|
||||
case 0xAE: ABS LDX CYC(4) break;
|
||||
case 0xAF: NOP CYC(1) break; // invalid
|
||||
case 0xB0: REL BCS CYC(2) break;
|
||||
case 0xB1: INDY_OPT LDA CYC(5) break;
|
||||
case 0xB2: izp LDA CYC(5) break;
|
||||
case 0xB3: NOP CYC(1) break; // invalid
|
||||
case 0xB4: zpx LDY CYC(4) break;
|
||||
case 0xB5: zpx LDA CYC(4) break;
|
||||
case 0xB6: zpy LDX CYC(4) break;
|
||||
case 0xB7: NOP CYC(1) break; // invalid
|
||||
case 0xB8: CLV CYC(2) break;
|
||||
case 0xB9: ABSY_OPT LDA CYC(4) break;
|
||||
case 0xBA: TSX CYC(2) break;
|
||||
case 0xBB: NOP CYC(1) break; // invalid
|
||||
case 0xBC: ABSX_OPT LDY CYC(4) break;
|
||||
case 0xBD: ABSX_OPT LDA CYC(4) break;
|
||||
case 0xBE: ABSY_OPT LDX CYC(4) break;
|
||||
case 0xBF: NOP CYC(1) break; // invalid
|
||||
case 0xC0: IMM CPY CYC(2) break;
|
||||
case 0xC1: idx CMP CYC(6) break;
|
||||
case 0xC2: IMM NOP CYC(2) break; // invalid
|
||||
case 0xC3: NOP CYC(1) break; // invalid
|
||||
case 0xC4: ZPG CPY CYC(3) break;
|
||||
case 0xC5: ZPG CMP CYC(3) break;
|
||||
case 0xC6: ZPG DEC CYC(5) break;
|
||||
case 0xC7: NOP CYC(1) break; // invalid
|
||||
case 0xC8: INY CYC(2) break;
|
||||
case 0xC9: IMM CMP CYC(2) break;
|
||||
case 0xCA: DEX CYC(2) break;
|
||||
case 0xCB: NOP CYC(1) break; // invalid
|
||||
case 0xCC: ABS CPY CYC(4) break;
|
||||
case 0xCD: ABS CMP CYC(4) break;
|
||||
case 0xCE: ABS DEC CYC(6) break;
|
||||
case 0xCF: NOP CYC(1) break; // invalid
|
||||
case 0xD0: REL BNE CYC(2) break;
|
||||
case 0xD1: INDY_OPT CMP CYC(5) break;
|
||||
case 0xD2: izp CMP CYC(5) break;
|
||||
case 0xD3: NOP CYC(1) break; // invalid
|
||||
case 0xD4: zpx NOP CYC(4) break; // invalid
|
||||
case 0xD5: zpx CMP CYC(4) break;
|
||||
case 0xD6: zpx DEC CYC(6) break;
|
||||
case 0xD7: NOP CYC(1) break; // invalid
|
||||
case 0xD8: CLD CYC(2) break;
|
||||
case 0xD9: ABSY_OPT CMP CYC(4) break;
|
||||
case 0xDA: PHX CYC(3) break;
|
||||
case 0xDB: NOP CYC(1) break; // invalid
|
||||
case 0xDC: ABS LDD CYC(4) break; // invalid
|
||||
case 0xDD: ABSX_OPT CMP CYC(4) break;
|
||||
case 0xDE: ABSX_CONST DEC CYC(7) break;
|
||||
case 0xDF: NOP CYC(1) break; // invalid
|
||||
case 0xE0: IMM CPX CYC(2) break;
|
||||
case 0xE1: idx SBCc CYC(6) break;
|
||||
case 0xE2: IMM NOP CYC(2) break; // invalid
|
||||
case 0xE3: NOP CYC(1) break; // invalid
|
||||
case 0xE4: ZPG CPX CYC(3) break;
|
||||
case 0xE5: ZPG SBCc CYC(3) break;
|
||||
case 0xE6: ZPG INC CYC(5) break;
|
||||
case 0xE7: NOP CYC(1) break; // invalid
|
||||
case 0xE8: INX CYC(2) break;
|
||||
case 0xE9: IMM SBCc CYC(2) break;
|
||||
case 0xEA: NOP CYC(2) break;
|
||||
case 0xEB: NOP CYC(1) break; // invalid
|
||||
case 0xEC: ABS CPX CYC(4) break;
|
||||
case 0xED: ABS SBCc CYC(4) break;
|
||||
case 0xEE: ABS INC CYC(6) break;
|
||||
case 0xEF: NOP CYC(1) break; // invalid
|
||||
case 0xF0: REL BEQ CYC(2) break;
|
||||
case 0xF1: INDY_OPT SBCc CYC(5) break;
|
||||
case 0xF2: izp SBCc CYC(5) break;
|
||||
case 0xF3: NOP CYC(1) break; // invalid
|
||||
case 0xF4: zpx NOP CYC(4) break; // invalid
|
||||
case 0xF5: zpx SBCc CYC(4) break;
|
||||
case 0xF6: zpx INC CYC(6) break;
|
||||
case 0xF7: NOP CYC(1) break; // invalid
|
||||
case 0xF8: SED CYC(2) break;
|
||||
case 0xF9: ABSY_OPT SBCc CYC(4) break;
|
||||
case 0xFA: PLX CYC(4) break;
|
||||
case 0xFB: NOP CYC(1) break; // invalid
|
||||
case 0xFC: ABS LDD CYC(4) break; // invalid
|
||||
case 0xFD: ABSX_OPT SBCc CYC(4) break;
|
||||
case 0xFE: ABSX_CONST INC CYC(7) break;
|
||||
case 0xFF: NOP CYC(1) break; // invalid
|
||||
}
|
||||
#undef $
|
||||
}
|
||||
|
||||
CheckInterruptSources(uExecutedCycles, bVideoUpdate);
|
||||
|
|
|
@ -1,426 +0,0 @@
|
|||
/*
|
||||
AppleWin : An Apple //e emulator for Windows
|
||||
|
||||
Copyright (C) 2010-2011, 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
|
||||
*/
|
||||
|
||||
typedef unsigned char u8; // TODO: change to <stdint.h> uint8_t
|
||||
typedef unsigned short u16; // TODO: change to <stdint.h> uint16_t
|
||||
|
||||
// return (x < 255) ? (x+1) : 255;
|
||||
inline u8 IncClamp8( u8 x )
|
||||
{
|
||||
u16 c = (~((x + 1) >> 8) & 1);
|
||||
u8 r = x + c;
|
||||
return r;
|
||||
}
|
||||
|
||||
// return (x > 0) ? (x-1) : 0;
|
||||
inline u8 DecClamp8( u8 x )
|
||||
{
|
||||
u16 c = (~((x - 1) >> 8) & 1);
|
||||
u8 r = x - c;
|
||||
return r;
|
||||
}
|
||||
|
||||
// TODO: Verify: RGBA or BGRA (.bmp format)
|
||||
// 0 A n/a
|
||||
// 1 B Exec
|
||||
// 2 G Read
|
||||
// 3 R Write
|
||||
//
|
||||
// 0xAARRGGBB
|
||||
// [0] B Exec
|
||||
// [1] G Load
|
||||
// [2] R Store
|
||||
// [3] A n/a
|
||||
// RGBA r = write, g = read, b = Program Counter
|
||||
const int HEATMAP_W_MASK = 0x00FF0000; // Red Store
|
||||
const int HEATMAP_R_MASK = 0x0000FF00; // Green Load
|
||||
const int HEATMAP_X_MASK = 0x000000FF; // Blue Exec
|
||||
|
||||
|
||||
// This is a memory heatmap
|
||||
// FF = accessed on this clock cycle
|
||||
// FE = accessed 1 clock cycles ago
|
||||
// FD = accessed 2 clock cycles ago
|
||||
// etc.
|
||||
// Displayed as 256x256 64K memory access
|
||||
int g_aMemoryHeatmap[ 65536 ]; // TODO: Change to <stdint.h> int32_t
|
||||
|
||||
#define HEATMAP_W(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_W_MASK
|
||||
#define HEATMAP_R(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_R_MASK
|
||||
#define HEATMAP_X(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_X_MASK
|
||||
|
||||
#undef READ
|
||||
#define READ ReadByte( addr, uExecutedCycles )
|
||||
|
||||
inline u8 ReadByte( u16 addr, int uExecutedCycles )
|
||||
{
|
||||
// TODO: We should have a single g_bDebuggerActive so we can have a single implementation across ][+ //e
|
||||
HEATMAP_R(addr);
|
||||
|
||||
return ((addr & 0xF000) == 0xC000)
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles)
|
||||
: *(mem+addr);
|
||||
}
|
||||
|
||||
#undef WRITE
|
||||
#define WRITE(a) \
|
||||
HEATMAP_W(addr); \
|
||||
{ \
|
||||
memdirty[addr >> 8] = 0xFF; \
|
||||
LPBYTE page = memwrite[addr >> 8]; \
|
||||
if (page) \
|
||||
*(page+(addr & 0xFF)) = (BYTE)(a); \
|
||||
else if ((addr & 0xF000) == 0xC000) \
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles); \
|
||||
}
|
||||
|
||||
#include "CPU/cpu_instructions.inl"
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Michael's Real-Time Debugger/Visualizer CPU
|
||||
// Based on Modified 65C02
|
||||
static DWORD Cpu65D02(DWORD uTotalCycles, const bool bVideoUpdate)
|
||||
{
|
||||
// Optimisation:
|
||||
// . Copy the global /regs/ vars to stack-based local vars
|
||||
// (Oliver Schmidt says this gives a performance gain, see email - The real deal: "1.10.5")
|
||||
WORD addr;
|
||||
BOOL flagc; // must always be 0 or 1, no other values allowed
|
||||
BOOL flagn; // must always be 0 or 0x80.
|
||||
BOOL flagv; // any value allowed
|
||||
BOOL flagz; // any value allowed
|
||||
WORD temp;
|
||||
WORD temp2;
|
||||
WORD val;
|
||||
AF_TO_EF
|
||||
ULONG uExecutedCycles = 0;
|
||||
WORD base;
|
||||
|
||||
do
|
||||
{
|
||||
UINT uExtraCycles = 0;
|
||||
BYTE iOpcode;
|
||||
|
||||
// NTSC_BEGIN
|
||||
ULONG uPreviousCycles = uExecutedCycles;
|
||||
// NTSC_END
|
||||
|
||||
if (GetActiveCpu() == CPU_Z80)
|
||||
{
|
||||
const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles)
|
||||
}
|
||||
else
|
||||
|
||||
HEATMAP_X( regs.pc );
|
||||
|
||||
Fetch(iOpcode, uExecutedCycles);
|
||||
|
||||
// INV = Invalid -> Debugger Break
|
||||
// MSVC C PreProcessor is BROKEN... #define @ INV
|
||||
//#define # INV
|
||||
//#define @ Read()
|
||||
//#define $ Store()
|
||||
//#define $ INV // INV = Invalid -> Debugger Break
|
||||
#define $
|
||||
|
||||
switch (iOpcode)
|
||||
{
|
||||
// TODO Optimization Note: ?? Move CYC(#) to array ??
|
||||
|
||||
// Version 2 opcode: $ AM Instruction // $=DebugBreak AM=AddressingMode
|
||||
//! ! ! ! ! ! // Tab-Stops
|
||||
case 0x00: BRK CYC(7) break;
|
||||
case 0x01: idx ORA CYC(6) break;
|
||||
case 0x02: $ IMM NOP CYC(2) break;
|
||||
case 0x03: $ NOP CYC(2) break;
|
||||
case 0x04: ZPG TSB CYC(5) break;
|
||||
case 0x05: ZPG ORA CYC(3) break;
|
||||
case 0x06: ZPG ASLc CYC(5) break;
|
||||
case 0x07: $ NOP CYC(2) break;
|
||||
case 0x08: PHP CYC(3) break;
|
||||
case 0x09: IMM ORA CYC(2) break;
|
||||
case 0x0A: asl CYC(2) break;
|
||||
case 0x0B: $ NOP CYC(2) break;
|
||||
case 0x0C: ABS TSB CYC(6) break;
|
||||
case 0x0D: ABS ORA CYC(4) break;
|
||||
case 0x0E: ABS ASLc CYC(6) break;
|
||||
case 0x0F: $ NOP CYC(2) break;
|
||||
case 0x10: REL BPL CYC(2) break;
|
||||
case 0x11: INDY_OPT ORA CYC(5) break;
|
||||
case 0x12: izp ORA CYC(5) break;
|
||||
case 0x13: $ NOP CYC(2) break;
|
||||
case 0x14: ZPG TRB CYC(5) break;
|
||||
case 0x15: zpx ORA CYC(4) break;
|
||||
case 0x16: zpx ASLc CYC(6) break;
|
||||
case 0x17: $ NOP CYC(2) break;
|
||||
case 0x18: CLC CYC(2) break;
|
||||
case 0x19: ABSY_OPT ORA CYC(4) break;
|
||||
case 0x1A: INA CYC(2) break;
|
||||
case 0x1B: $ NOP CYC(2) break;
|
||||
case 0x1C: ABS TRB CYC(6) break;
|
||||
case 0x1D: ABSX_OPT ORA CYC(4) break;
|
||||
case 0x1E: ABSX_OPT ASLc CYC(6) break;
|
||||
case 0x1F: $ NOP CYC(2) break;
|
||||
case 0x20: ABS JSR CYC(6) break;
|
||||
case 0x21: idx AND CYC(6) break;
|
||||
case 0x22: $ IMM NOP CYC(2) break;
|
||||
case 0x23: $ NOP CYC(2) break;
|
||||
case 0x24: ZPG BIT CYC(3) break;
|
||||
case 0x25: ZPG AND CYC(3) break;
|
||||
case 0x26: ZPG ROLc CYC(5) break;
|
||||
case 0x27: $ NOP CYC(2) break;
|
||||
case 0x28: PLP CYC(4) break;
|
||||
case 0x29: IMM AND CYC(2) break;
|
||||
case 0x2A: rol CYC(2) break;
|
||||
case 0x2B: $ NOP CYC(2) break;
|
||||
case 0x2C: ABS BIT CYC(4) break;
|
||||
case 0x2D: ABS AND CYC(2) break;
|
||||
case 0x2E: ABS ROLc CYC(6) break;
|
||||
case 0x2F: $ NOP CYC(2) break;
|
||||
case 0x30: REL BMI CYC(2) break;
|
||||
case 0x31: INDY_OPT AND CYC(5) break;
|
||||
case 0x32: izp AND CYC(5) break;
|
||||
case 0x33: $ NOP CYC(2) break;
|
||||
case 0x34: zpx BIT CYC(4) break;
|
||||
case 0x35: zpx AND CYC(4) break;
|
||||
case 0x36: zpx ROLc CYC(6) break;
|
||||
case 0x37: $ NOP CYC(2) break;
|
||||
case 0x38: SEC CYC(2) break;
|
||||
case 0x39: ABSY_OPT AND CYC(4) break;
|
||||
case 0x3A: DEA CYC(2) break;
|
||||
case 0x3B: $ NOP CYC(2) break;
|
||||
case 0x3C: ABSX_OPT BIT CYC(4) break;
|
||||
case 0x3D: ABSX_OPT AND CYC(4) break;
|
||||
case 0x3E: ABSX_OPT ROLc CYC(6) break;
|
||||
case 0x3F: $ NOP CYC(2) break;
|
||||
case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
|
||||
case 0x41: idx EOR CYC(6) break;
|
||||
case 0x42: $ IMM NOP CYC(2) break;
|
||||
case 0x43: $ NOP CYC(2) break;
|
||||
case 0x44: $ ZPG NOP CYC(3) break;
|
||||
case 0x45: ZPG EOR CYC(3) break;
|
||||
case 0x46: ZPG LSRc CYC(5) break;
|
||||
case 0x47: $ NOP CYC(2) break;
|
||||
case 0x48: PHA CYC(3) break;
|
||||
case 0x49: IMM EOR CYC(2) break;
|
||||
case 0x4A: lsr CYC(2) break;
|
||||
case 0x4B: $ NOP CYC(2) break;
|
||||
case 0x4C: ABS JMP CYC(3) break;
|
||||
case 0x4D: ABS EOR CYC(4) break;
|
||||
case 0x4E: ABS LSRc CYC(6) break;
|
||||
case 0x4F: $ NOP CYC(2) break;
|
||||
case 0x50: REL BVC CYC(2) break;
|
||||
case 0x51: INDY_OPT EOR CYC(5) break;
|
||||
case 0x52: izp EOR CYC(5) break;
|
||||
case 0x53: $ NOP CYC(2) break;
|
||||
case 0x54: $ zpx NOP CYC(4) break;
|
||||
case 0x55: zpx EOR CYC(4) break;
|
||||
case 0x56: zpx LSRc CYC(6) break;
|
||||
case 0x57: $ NOP CYC(2) break;
|
||||
case 0x58: CLI CYC(2) break;
|
||||
case 0x59: ABSY_OPT EOR CYC(4) break;
|
||||
case 0x5A: PHY CYC(3) break;
|
||||
case 0x5B: $ NOP CYC(2) break;
|
||||
case 0x5C: $ ABSX_OPT NOP CYC(8) break;
|
||||
case 0x5D: ABSX_OPT EOR CYC(4) break;
|
||||
case 0x5E: ABSX_OPT LSRc CYC(6) break;
|
||||
case 0x5F: $ NOP CYC(2) break;
|
||||
case 0x60: RTS CYC(6) break;
|
||||
case 0x61: idx ADCc CYC(6) break;
|
||||
case 0x62: $ IMM NOP CYC(2) break;
|
||||
case 0x63: $ NOP CYC(2) break;
|
||||
case 0x64: ZPG STZ CYC(3) break;
|
||||
case 0x65: ZPG ADCc CYC(3) break;
|
||||
case 0x66: ZPG RORc CYC(5) break;
|
||||
case 0x67: $ NOP CYC(2) break;
|
||||
case 0x68: PLA CYC(4) break;
|
||||
case 0x69: IMM ADCc CYC(2) break;
|
||||
case 0x6A: ror CYC(2) break;
|
||||
case 0x6B: $ NOP CYC(2) break;
|
||||
case 0x6C: IABS_CMOS JMP CYC(6) break;
|
||||
case 0x6D: ABS ADCc CYC(4) break;
|
||||
case 0x6E: ABS RORc CYC(6) break;
|
||||
case 0x6F: $ NOP CYC(2) break;
|
||||
case 0x70: REL BVS CYC(2) break;
|
||||
case 0x71: INDY_OPT ADCc CYC(5) break;
|
||||
case 0x72: izp ADCc CYC(5) break;
|
||||
case 0x73: $ NOP CYC(2) break;
|
||||
case 0x74: zpx STZ CYC(4) break;
|
||||
case 0x75: zpx ADCc CYC(4) break;
|
||||
case 0x76: zpx RORc CYC(6) break;
|
||||
case 0x77: $ NOP CYC(2) break;
|
||||
case 0x78: SEI CYC(2) break;
|
||||
case 0x79: ABSY_OPT ADCc CYC(4) break;
|
||||
case 0x7A: PLY CYC(4) break;
|
||||
case 0x7B: $ NOP CYC(2) break;
|
||||
case 0x7C: IABSX JMP CYC(6) break;
|
||||
case 0x7D: ABSX_OPT ADCc CYC(4) break;
|
||||
case 0x7E: ABSX_OPT RORc CYC(6) break;
|
||||
case 0x7F: $ NOP CYC(2) break;
|
||||
case 0x80: REL BRA CYC(2) break;
|
||||
case 0x81: idx STA CYC(6) break;
|
||||
case 0x82: $ IMM NOP CYC(2) break;
|
||||
case 0x83: $ NOP CYC(2) break;
|
||||
case 0x84: ZPG STY CYC(3) break;
|
||||
case 0x85: ZPG STA CYC(3) break;
|
||||
case 0x86: ZPG STX CYC(3) break;
|
||||
case 0x87: $ NOP CYC(2) break;
|
||||
case 0x88: DEY CYC(2) break;
|
||||
case 0x89: IMM BITI CYC(2) break;
|
||||
case 0x8A: TXA CYC(2) break;
|
||||
case 0x8B: $ NOP CYC(2) break;
|
||||
case 0x8C: ABS STY CYC(4) break;
|
||||
case 0x8D: ABS STA CYC(4) break;
|
||||
case 0x8E: ABS STX CYC(4) break;
|
||||
case 0x8F: $ NOP CYC(2) break;
|
||||
case 0x90: REL BCC CYC(2) break;
|
||||
case 0x91: INDY_CONST STA CYC(6) break;
|
||||
case 0x92: izp STA CYC(5) break;
|
||||
case 0x93: $ NOP CYC(2) break;
|
||||
case 0x94: zpx STY CYC(4) break;
|
||||
case 0x95: zpx STA CYC(4) break;
|
||||
case 0x96: zpy STX CYC(4) break;
|
||||
case 0x97: $ NOP CYC(2) break;
|
||||
case 0x98: TYA CYC(2) break;
|
||||
case 0x99: ABSY_CONST STA CYC(5) break;
|
||||
case 0x9A: TXS CYC(2) break;
|
||||
case 0x9B: $ NOP CYC(2) break;
|
||||
case 0x9C: ABS STZ CYC(4) break;
|
||||
case 0x9D: ABSX_CONST STA CYC(5) break;
|
||||
case 0x9E: ABSX_CONST STZ CYC(5) break;
|
||||
case 0x9F: $ NOP CYC(2) break;
|
||||
case 0xA0: IMM LDY CYC(2) break;
|
||||
case 0xA1: idx LDA CYC(6) break;
|
||||
case 0xA2: IMM LDX CYC(2) break;
|
||||
case 0xA3: $ NOP CYC(2) break;
|
||||
case 0xA4: ZPG LDY CYC(3) break;
|
||||
case 0xA5: ZPG LDA CYC(3) break;
|
||||
case 0xA6: ZPG LDX CYC(3) break;
|
||||
case 0xA7: $ NOP CYC(2) break;
|
||||
case 0xA8: TAY CYC(2) break;
|
||||
case 0xA9: IMM LDA CYC(2) break;
|
||||
case 0xAA: TAX CYC(2) break;
|
||||
case 0xAB: $ NOP CYC(2) break;
|
||||
case 0xAC: ABS LDY CYC(4) break;
|
||||
case 0xAD: ABS LDA CYC(4) break;
|
||||
case 0xAE: ABS LDX CYC(4) break;
|
||||
case 0xAF: $ NOP CYC(2) break;
|
||||
case 0xB0: REL BCS CYC(2) break;
|
||||
case 0xB1: INDY_OPT LDA CYC(5) break;
|
||||
case 0xB2: izp LDA CYC(5) break;
|
||||
case 0xB3: $ NOP CYC(2) break;
|
||||
case 0xB4: zpx LDY CYC(4) break;
|
||||
case 0xB5: zpx LDA CYC(4) break;
|
||||
case 0xB6: zpy LDX CYC(4) break;
|
||||
case 0xB7: $ NOP CYC(2) break;
|
||||
case 0xB8: CLV CYC(2) break;
|
||||
case 0xB9: ABSY_OPT LDA CYC(4) break;
|
||||
case 0xBA: TSX CYC(2) break;
|
||||
case 0xBB: $ NOP CYC(2) break;
|
||||
case 0xBC: ABSX_OPT LDY CYC(4) break;
|
||||
case 0xBD: ABSX_OPT LDA CYC(4) break;
|
||||
case 0xBE: ABSY_OPT LDX CYC(4) break;
|
||||
case 0xBF: $ NOP CYC(2) break;
|
||||
case 0xC0: IMM CPY CYC(2) break;
|
||||
case 0xC1: idx CMP CYC(6) break;
|
||||
case 0xC2: $ IMM NOP CYC(2) break;
|
||||
case 0xC3: $ NOP CYC(2) break;
|
||||
case 0xC4: ZPG CPY CYC(3) break;
|
||||
case 0xC5: ZPG CMP CYC(3) break;
|
||||
case 0xC6: ZPG DEC CYC(5) break;
|
||||
case 0xC7: $ NOP CYC(2) break;
|
||||
case 0xC8: INY CYC(2) break;
|
||||
case 0xC9: IMM CMP CYC(2) break;
|
||||
case 0xCA: DEX CYC(2) break;
|
||||
case 0xCB: $ NOP CYC(2) break;
|
||||
case 0xCC: ABS CPY CYC(4) break;
|
||||
case 0xCD: ABS CMP CYC(4) break;
|
||||
case 0xCE: ABS DEC CYC(6) break;
|
||||
case 0xCF: $ NOP CYC(2) break;
|
||||
case 0xD0: REL BNE CYC(2) break;
|
||||
case 0xD1: INDY_OPT CMP CYC(5) break;
|
||||
case 0xD2: izp CMP CYC(5) break;
|
||||
case 0xD3: $ NOP CYC(2) break;
|
||||
case 0xD4: $ zpx NOP CYC(4) break;
|
||||
case 0xD5: zpx CMP CYC(4) break;
|
||||
case 0xD6: zpx DEC CYC(6) break;
|
||||
case 0xD7: $ NOP CYC(2) break;
|
||||
case 0xD8: CLD CYC(2) break;
|
||||
case 0xD9: ABSY_OPT CMP CYC(4) break;
|
||||
case 0xDA: PHX CYC(3) break;
|
||||
case 0xDB: $ NOP CYC(2) break;
|
||||
case 0xDC: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0xDD: ABSX_OPT CMP CYC(4) break;
|
||||
case 0xDE: ABSX_CONST DEC CYC(7) break;
|
||||
case 0xDF: $ NOP CYC(2) break;
|
||||
case 0xE0: IMM CPX CYC(2) break;
|
||||
case 0xE1: idx SBCc CYC(6) break;
|
||||
case 0xE2: $ IMM NOP CYC(2) break;
|
||||
case 0xE3: $ NOP CYC(2) break;
|
||||
case 0xE4: ZPG CPX CYC(3) break;
|
||||
case 0xE5: ZPG SBCc CYC(3) break;
|
||||
case 0xE6: ZPG INC CYC(5) break;
|
||||
case 0xE7: $ NOP CYC(2) break;
|
||||
case 0xE8: INX CYC(2) break;
|
||||
case 0xE9: IMM SBCc CYC(2) break;
|
||||
case 0xEA: NOP CYC(2) break;
|
||||
case 0xEB: $ NOP CYC(2) break;
|
||||
case 0xEC: ABS CPX CYC(4) break;
|
||||
case 0xED: ABS SBCc CYC(4) break;
|
||||
case 0xEE: ABS INC CYC(6) break;
|
||||
case 0xEF: $ NOP CYC(2) break;
|
||||
case 0xF0: REL BEQ CYC(2) break;
|
||||
case 0xF1: INDY_OPT SBCc CYC(5) break;
|
||||
case 0xF2: izp SBCc CYC(5) break;
|
||||
case 0xF3: $ NOP CYC(2) break;
|
||||
case 0xF4: $ zpx NOP CYC(4) break;
|
||||
case 0xF5: zpx SBCc CYC(4) break;
|
||||
case 0xF6: zpx INC CYC(6) break;
|
||||
case 0xF7: $ NOP CYC(2) break;
|
||||
case 0xF8: SED CYC(2) break;
|
||||
case 0xF9: ABSY_OPT SBCc CYC(4) break;
|
||||
case 0xFA: PLX CYC(4) break;
|
||||
case 0xFB: $ NOP CYC(2) break;
|
||||
case 0xFC: $ ABSX_OPT NOP CYC(4) break;
|
||||
case 0xFD: ABSX_OPT SBCc CYC(4) break;
|
||||
case 0xFE: ABSX_CONST INC CYC(7) break;
|
||||
case 0xFF: $ NOP CYC(2) break;
|
||||
}
|
||||
#undef $
|
||||
|
||||
CheckInterruptSources(uExecutedCycles, bVideoUpdate);
|
||||
NMI(uExecutedCycles, flagc, flagn, flagv, flagz);
|
||||
IRQ(uExecutedCycles, flagc, flagn, flagv, flagz);
|
||||
|
||||
// NTSC_BEGIN
|
||||
if (bVideoUpdate)
|
||||
{
|
||||
ULONG uElapsedCycles = uExecutedCycles - uPreviousCycles;
|
||||
NTSC_VideoUpdateCycles( uElapsedCycles );
|
||||
}
|
||||
// NTSC_END
|
||||
|
||||
} while (uExecutedCycles < uTotalCycles);
|
||||
|
||||
EF_TO_AF // Emulator Flags to Apple Flags
|
||||
|
||||
return uExecutedCycles;
|
||||
}
|
|
@ -54,7 +54,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#define PUSH(a) *(mem+regs.sp--) = (a); \
|
||||
if (regs.sp < 0x100) \
|
||||
regs.sp = 0x1FF;
|
||||
#define READ ( \
|
||||
#define _READ ( \
|
||||
((addr & 0xF000) == 0xC000) \
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
|
||||
: *(mem+addr) \
|
||||
|
@ -64,7 +64,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
flagz = !((a) & 0xFF); \
|
||||
}
|
||||
#define SETZ(a) flagz = !((a) & 0xFF);
|
||||
#define WRITE(a) { \
|
||||
#define _WRITE(a) { \
|
||||
memdirty[addr >> 8] = 0xFF; \
|
||||
LPBYTE page = memwrite[addr >> 8]; \
|
||||
if (page) \
|
||||
|
|
60
source/CPU/cpu_heatmap.inl
Normal file
60
source/CPU/cpu_heatmap.inl
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
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-2020, 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
|
||||
*/
|
||||
|
||||
/* Description: 6502/65C02 emulation
|
||||
*
|
||||
* Author: Various
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* RAM ACCESS MACROS (built-in debugger mode)
|
||||
*
|
||||
***/
|
||||
|
||||
inline void Heatmap_R(uint16_t address)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
inline void Heatmap_W(uint16_t address)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
inline void Heatmap_X(uint16_t address)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
inline uint8_t Heatmap_ReadByte(uint16_t addr, int uExecutedCycles)
|
||||
{
|
||||
Heatmap_R(addr);
|
||||
return _READ;
|
||||
}
|
||||
|
||||
inline void Heatmap_WriteByte(uint16_t addr, uint16_t value, int uExecutedCycles)
|
||||
{
|
||||
Heatmap_W(addr);
|
||||
_WRITE(value);
|
||||
}
|
|
@ -46,12 +46,12 @@ void CardManager::Insert(UINT slot, SS_CARDTYPE type)
|
|||
switch (type)
|
||||
{
|
||||
case CT_Disk2:
|
||||
m_slot[slot] = new Disk2InterfaceCard;
|
||||
m_slot[slot] = new Disk2InterfaceCard(slot);
|
||||
break;
|
||||
case CT_SSC:
|
||||
_ASSERT(m_pSSC == NULL);
|
||||
if (m_pSSC) break; // Only support one SSC
|
||||
m_slot[slot] = m_pSSC = new CSuperSerialCard;
|
||||
m_slot[slot] = m_pSSC = new CSuperSerialCard(slot);
|
||||
break;
|
||||
case CT_MockingboardC:
|
||||
m_slot[slot] = new DummyCard(type);
|
||||
|
|
|
@ -48,14 +48,15 @@ enum AppMode_e
|
|||
// TODO: Move to StringTable.h
|
||||
#define TITLE_APPLE_2 TEXT("Apple ][ Emulator")
|
||||
#define TITLE_APPLE_2_PLUS TEXT("Apple ][+ Emulator")
|
||||
#define TITLE_APPLE_2_JPLUS TEXT("Apple ][ J-Plus Emulator")
|
||||
#define TITLE_APPLE_2E TEXT("Apple //e Emulator")
|
||||
#define TITLE_APPLE_2E_ENHANCED TEXT("Enhanced Apple //e Emulator")
|
||||
#define TITLE_APPLE_2C TEXT("Apple //e Emulator")
|
||||
#define TITLE_APPLE_2D TEXT("Apple )(d Virtual Debug Hardware")
|
||||
#define TITLE_PRAVETS_82 TEXT("Pravets 82 Emulator")
|
||||
#define TITLE_PRAVETS_8M TEXT("Pravets 8M Emulator")
|
||||
#define TITLE_PRAVETS_8A TEXT("Pravets 8A Emulator")
|
||||
#define TITLE_TK3000_2E TEXT("TK3000 //e Emulator")
|
||||
#define TITLE_BASE64A TEXT("Base64A Emulator")
|
||||
|
||||
#define TITLE_PAUSED TEXT("* PAUSED *")
|
||||
#define TITLE_STEPPING TEXT("Stepping")
|
||||
|
@ -152,15 +153,13 @@ enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE};
|
|||
//e 10
|
||||
//e+ 11
|
||||
//c 20
|
||||
//d 40
|
||||
*/
|
||||
#define APPLE2E_MASK 0x10
|
||||
#define APPLE2C_MASK 0x20
|
||||
#define APPLE2D_MASK 0x40
|
||||
#define APPLECLONE_MASK 0x100
|
||||
|
||||
#define IS_APPLE2 ((g_Apple2Type & (APPLE2E_MASK|APPLE2C_MASK)) == 0)
|
||||
#define IS_APPLE2E() (g_Apple2Type & APPLE2E_MASK)
|
||||
//#define IS_APPLE2E() (g_Apple2Type & APPLE2E_MASK) // unused
|
||||
#define IS_APPLE2C() (g_Apple2Type & APPLE2C_MASK)
|
||||
#define IS_CLONE() (g_Apple2Type & APPLECLONE_MASK)
|
||||
|
||||
|
@ -168,16 +167,17 @@ enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE};
|
|||
enum eApple2Type {
|
||||
A2TYPE_APPLE2=0,
|
||||
A2TYPE_APPLE2PLUS,
|
||||
A2TYPE_APPLE2JPLUS,
|
||||
A2TYPE_APPLE2E=APPLE2E_MASK,
|
||||
A2TYPE_APPLE2EENHANCED,
|
||||
A2TYPE_UNDEFINED,
|
||||
A2TYPE_APPLE2C=APPLE2C_MASK,
|
||||
A2TYPE_APPLE2D=APPLE2D_MASK,
|
||||
|
||||
// ][ clones start here:
|
||||
A2TYPE_CLONE=APPLECLONE_MASK,
|
||||
A2TYPE_PRAVETS8M, // Apple ][ clone
|
||||
A2TYPE_PRAVETS82, // Apple ][ clone
|
||||
A2TYPE_BASE64A, // Apple ][ clone
|
||||
// (Gap for more Apple ][ clones)
|
||||
A2TYPE_CLONE_A2_MAX,
|
||||
|
||||
|
@ -196,21 +196,31 @@ inline bool IsApple2Original(eApple2Type type) // Apple ][
|
|||
return type == A2TYPE_APPLE2;
|
||||
}
|
||||
|
||||
inline bool IsApple2Plus(eApple2Type type) // Apple ][,][+
|
||||
inline bool IsApple2Plus(eApple2Type type) // Apple ][,][+,][J-Plus
|
||||
{
|
||||
return ((type & (APPLE2E_MASK|APPLE2C_MASK)) == 0) && !(type & APPLECLONE_MASK);
|
||||
}
|
||||
|
||||
inline bool IsApple2JPlus(eApple2Type type) // Apple ][J-Plus
|
||||
{
|
||||
return type == A2TYPE_APPLE2JPLUS;
|
||||
}
|
||||
|
||||
inline bool IsClone(eApple2Type type)
|
||||
{
|
||||
return (type & APPLECLONE_MASK) != 0;
|
||||
}
|
||||
|
||||
inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+ or clone ][,][+
|
||||
inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+,][J-Plus or clone ][,][+
|
||||
{
|
||||
return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
|
||||
}
|
||||
|
||||
inline bool IsAppleIIeOrAbove(eApple2Type type) // Apple //e,Enhanced//e,//c or clone //e,Enhanced//e
|
||||
{
|
||||
return !IsApple2PlusOrClone(type);
|
||||
}
|
||||
|
||||
extern eApple2Type g_Apple2Type;
|
||||
inline bool IsEnhancedIIE(void)
|
||||
{
|
||||
|
@ -222,6 +232,11 @@ inline bool IsEnhancedIIEorIIC(void)
|
|||
return ( (g_Apple2Type == A2TYPE_APPLE2EENHANCED) || (g_Apple2Type == A2TYPE_TK30002E) || IS_APPLE2C() );
|
||||
}
|
||||
|
||||
inline bool IsCopamBase64A(eApple2Type type) // Copam Base64A
|
||||
{
|
||||
return type == A2TYPE_BASE64A;
|
||||
}
|
||||
|
||||
enum eBUTTON {BUTTON0=0, BUTTON1};
|
||||
|
||||
enum eBUTTONSTATE {BUTTON_UP=0, BUTTON_DOWN};
|
||||
|
|
|
@ -33,12 +33,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
CPageAdvanced* CPageAdvanced::ms_this = 0; // reinit'd in ctor
|
||||
|
||||
enum CLONECHOICE {MENUITEM_CLONEMIN, MENUITEM_PRAVETS82=MENUITEM_CLONEMIN, MENUITEM_PRAVETS8M, MENUITEM_PRAVETS8A, MENUITEM_TK30002E, MENUITEM_CLONEMAX};
|
||||
enum CLONECHOICE {MENUITEM_CLONEMIN, MENUITEM_PRAVETS82=MENUITEM_CLONEMIN, MENUITEM_PRAVETS8M, MENUITEM_PRAVETS8A, MENUITEM_TK30002E, MENUITEM_BASE64A, MENUITEM_CLONEMAX};
|
||||
const TCHAR CPageAdvanced::m_CloneChoices[] =
|
||||
TEXT("Pravets 82\0") // Bulgarian
|
||||
TEXT("Pravets 8M\0") // Bulgarian
|
||||
TEXT("Pravets 8A\0") // Bulgarian
|
||||
TEXT("TK3000 //e\0"); // Brazilian
|
||||
TEXT("TK3000 //e\0") // Brazilian
|
||||
TEXT("Base 64A\0"); // Taiwanese
|
||||
|
||||
|
||||
BOOL CALLBACK CPageAdvanced::DlgProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
|
@ -223,6 +225,7 @@ eApple2Type CPageAdvanced::GetCloneType(DWORD NewMenuItem)
|
|||
case MENUITEM_PRAVETS8M: return A2TYPE_PRAVETS8M;
|
||||
case MENUITEM_PRAVETS8A: return A2TYPE_PRAVETS8A;
|
||||
case MENUITEM_TK30002E: return A2TYPE_TK30002E;
|
||||
case MENUITEM_BASE64A: return A2TYPE_BASE64A;
|
||||
default: return A2TYPE_PRAVETS82;
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +253,7 @@ int CPageAdvanced::GetCloneMenuItem(void)
|
|||
case A2TYPE_PRAVETS8M: nMenuItem = MENUITEM_PRAVETS8M; break;
|
||||
case A2TYPE_PRAVETS8A: nMenuItem = MENUITEM_PRAVETS8A; break;
|
||||
case A2TYPE_TK30002E: nMenuItem = MENUITEM_TK30002E; break;
|
||||
case A2TYPE_BASE64A: nMenuItem = MENUITEM_BASE64A; break;
|
||||
default: // New clone needs adding here?
|
||||
_ASSERT(0);
|
||||
}
|
||||
|
|
|
@ -34,10 +34,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
CPageConfig* CPageConfig::ms_this = 0; // reinit'd in ctor
|
||||
|
||||
enum APPLEIICHOICE {MENUITEM_IIORIGINAL, MENUITEM_IIPLUS, MENUITEM_IIE, MENUITEM_ENHANCEDIIE, MENUITEM_CLONE};
|
||||
enum APPLEIICHOICE {MENUITEM_IIORIGINAL, MENUITEM_IIPLUS, MENUITEM_IIJPLUS, MENUITEM_IIE, MENUITEM_ENHANCEDIIE, MENUITEM_CLONE};
|
||||
const TCHAR CPageConfig::m_ComputerChoices[] =
|
||||
TEXT("Apple ][ (Original)\0")
|
||||
TEXT("Apple ][+\0")
|
||||
TEXT("Apple ][ J-Plus\0")
|
||||
TEXT("Apple //e\0")
|
||||
TEXT("Enhanced Apple //e\0")
|
||||
TEXT("Clone\0");
|
||||
|
@ -182,12 +183,14 @@ BOOL CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
|
|||
{
|
||||
case A2TYPE_APPLE2: nCurrentChoice = MENUITEM_IIORIGINAL; break;
|
||||
case A2TYPE_APPLE2PLUS: nCurrentChoice = MENUITEM_IIPLUS; break;
|
||||
case A2TYPE_APPLE2JPLUS: nCurrentChoice = MENUITEM_IIJPLUS; break;
|
||||
case A2TYPE_APPLE2E: nCurrentChoice = MENUITEM_IIE; break;
|
||||
case A2TYPE_APPLE2EENHANCED:nCurrentChoice = MENUITEM_ENHANCEDIIE; break;
|
||||
case A2TYPE_PRAVETS82: nCurrentChoice = MENUITEM_CLONE; break;
|
||||
case A2TYPE_PRAVETS8M: nCurrentChoice = MENUITEM_CLONE; break;
|
||||
case A2TYPE_PRAVETS8A: nCurrentChoice = MENUITEM_CLONE; break;
|
||||
case A2TYPE_TK30002E: nCurrentChoice = MENUITEM_CLONE; break;
|
||||
case A2TYPE_BASE64A: nCurrentChoice = MENUITEM_CLONE; break;
|
||||
default: _ASSERT(0); break;
|
||||
}
|
||||
|
||||
|
@ -380,6 +383,7 @@ eApple2Type CPageConfig::GetApple2Type(DWORD NewMenuItem)
|
|||
{
|
||||
case MENUITEM_IIORIGINAL: return A2TYPE_APPLE2;
|
||||
case MENUITEM_IIPLUS: return A2TYPE_APPLE2PLUS;
|
||||
case MENUITEM_IIJPLUS: return A2TYPE_APPLE2JPLUS;
|
||||
case MENUITEM_IIE: return A2TYPE_APPLE2E;
|
||||
case MENUITEM_ENHANCEDIIE: return A2TYPE_APPLE2EENHANCED;
|
||||
case MENUITEM_CLONE: return A2TYPE_CLONE;
|
||||
|
|
|
@ -50,7 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#define ALLOW_INPUT_LOWERCASE 1
|
||||
|
||||
// See /docs/Debugger_Changelog.txt for full details
|
||||
const int DEBUGGER_VERSION = MAKE_VERSION(2,9,0,15);
|
||||
const int DEBUGGER_VERSION = MAKE_VERSION(2,9,1,0);
|
||||
|
||||
|
||||
// Public _________________________________________________________________________________________
|
||||
|
@ -440,10 +440,10 @@ bool DebugGetVideoMode(UINT* pVideoMode)
|
|||
|
||||
// File _______________________________________________________________________
|
||||
|
||||
int _GetFileSize( FILE *hFile )
|
||||
size_t _GetFileSize( FILE *hFile )
|
||||
{
|
||||
fseek( hFile, 0, SEEK_END );
|
||||
int nFileBytes = ftell( hFile );
|
||||
size_t nFileBytes = ftell( hFile );
|
||||
fseek( hFile, 0, SEEK_SET );
|
||||
|
||||
return nFileBytes;
|
||||
|
@ -484,13 +484,17 @@ bool _Bookmark_Del( const WORD nAddress )
|
|||
{
|
||||
// g_aBookmarks.at( iBookmark ) = NO_6502_TARGET;
|
||||
g_aBookmarks[ iBookmark ].bSet = false;
|
||||
g_nBookmarks--;
|
||||
bDeleted = true;
|
||||
}
|
||||
}
|
||||
return bDeleted;
|
||||
}
|
||||
|
||||
bool Bookmark_Find( const WORD nAddress )
|
||||
// Returns:
|
||||
// 0 if address does not have a bookmark set
|
||||
// N+1 if there is an existing bookmark that has this address
|
||||
int Bookmark_Find( const WORD nAddress )
|
||||
{
|
||||
// Ugh, linear search
|
||||
// int nSize = g_aBookmarks.size();
|
||||
|
@ -500,10 +504,10 @@ bool Bookmark_Find( const WORD nAddress )
|
|||
if (g_aBookmarks[ iBookmark ].nAddress == nAddress)
|
||||
{
|
||||
if (g_aBookmarks[ iBookmark ].bSet)
|
||||
return true;
|
||||
return iBookmark + 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -534,6 +538,8 @@ void _Bookmark_Reset()
|
|||
{
|
||||
g_aBookmarks[ iBookmark ].bSet = false;
|
||||
}
|
||||
|
||||
g_nBookmarks = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -598,15 +604,26 @@ Update_t CmdBookmarkAdd (int nArgs )
|
|||
ConsoleDisplayPush( sText );
|
||||
return ConsoleUpdate();
|
||||
}
|
||||
|
||||
if ((iBookmark < MAX_BOOKMARKS) && (g_nBookmarks < MAX_BOOKMARKS))
|
||||
|
||||
// 2.9.0.16 Fixed: Replacing an existing bookmark incorrectly increased the total bookmark count.
|
||||
int nOldBookmark = Bookmark_Find( nAddress );
|
||||
if (nOldBookmark)
|
||||
{
|
||||
g_aBookmarks[iBookmark].bSet = true;
|
||||
g_aBookmarks[iBookmark].nAddress = nAddress;
|
||||
bAdded = true;
|
||||
g_nBookmarks++;
|
||||
iBookmark++;
|
||||
_Bookmark_Del( nAddress );
|
||||
}
|
||||
|
||||
// 2.9.0.17 Fixed: If all bookmarks were used then setting a new one wouldn't update an existing one to the new address.
|
||||
if (g_aBookmarks[ iBookmark ].bSet)
|
||||
{
|
||||
g_aBookmarks[ iBookmark ].nAddress = nAddress;
|
||||
bAdded = true;
|
||||
}
|
||||
else
|
||||
if (g_nBookmarks < MAX_BOOKMARKS)
|
||||
{
|
||||
bAdded = _Bookmark_Add( iBookmark, nAddress );
|
||||
iBookmark++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bAdded)
|
||||
|
@ -632,11 +649,7 @@ Update_t CmdBookmarkClear (int nArgs)
|
|||
{
|
||||
if (! _tcscmp(g_aArgs[nArgs].sArg, g_aParameters[ PARAM_WILDSTAR ].m_sName))
|
||||
{
|
||||
for (iBookmark = 0; iBookmark < MAX_BOOKMARKS; iBookmark++ )
|
||||
{
|
||||
if (g_aBookmarks[ iBookmark ].bSet)
|
||||
g_aBookmarks[ iBookmark ].bSet = false;
|
||||
}
|
||||
_Bookmark_Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -688,8 +701,6 @@ Update_t CmdBookmarkList (int nArgs)
|
|||
//===========================================================================
|
||||
Update_t CmdBookmarkLoad (int nArgs)
|
||||
{
|
||||
char sFilePath[ MAX_PATH ] = "";
|
||||
|
||||
if (nArgs == 1)
|
||||
{
|
||||
// strcpy( sMiniFileName, pFileName );
|
||||
|
@ -978,7 +989,7 @@ Update_t CmdBreakInvalid (int nArgs) // Breakpoint IFF Full-speed!
|
|||
return UPDATE_CONSOLE_DISPLAY;
|
||||
|
||||
_Help:
|
||||
return HelpLastCommand();
|
||||
return HelpLastCommand();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1444,8 +1455,6 @@ Update_t CmdBreakpointAddPC (int nArgs)
|
|||
g_aArgs[1].nValue = g_nDisasmCurAddress;
|
||||
}
|
||||
|
||||
bool bHaveCmp = false;
|
||||
|
||||
// int iParamSrc;
|
||||
int iParamCmp;
|
||||
|
||||
|
@ -1463,12 +1472,12 @@ Update_t CmdBreakpointAddPC (int nArgs)
|
|||
{
|
||||
switch (iParamCmp)
|
||||
{
|
||||
case PARAM_BP_LESS_EQUAL : iCmp = BP_OP_LESS_EQUAL ; bHaveCmp = true; break;
|
||||
case PARAM_BP_LESS_THAN : iCmp = BP_OP_LESS_THAN ; bHaveCmp = true; break;
|
||||
case PARAM_BP_EQUAL : iCmp = BP_OP_EQUAL ; bHaveCmp = true; break;
|
||||
case PARAM_BP_NOT_EQUAL : iCmp = BP_OP_NOT_EQUAL ; bHaveCmp = true; break;
|
||||
case PARAM_BP_GREATER_THAN : iCmp = BP_OP_GREATER_THAN ; bHaveCmp = true; break;
|
||||
case PARAM_BP_GREATER_EQUAL: iCmp = BP_OP_GREATER_EQUAL; bHaveCmp = true; break;
|
||||
case PARAM_BP_LESS_EQUAL : iCmp = BP_OP_LESS_EQUAL ; break;
|
||||
case PARAM_BP_LESS_THAN : iCmp = BP_OP_LESS_THAN ; break;
|
||||
case PARAM_BP_EQUAL : iCmp = BP_OP_EQUAL ; break;
|
||||
case PARAM_BP_NOT_EQUAL : iCmp = BP_OP_NOT_EQUAL ; break;
|
||||
case PARAM_BP_GREATER_THAN : iCmp = BP_OP_GREATER_THAN ; break;
|
||||
case PARAM_BP_GREATER_EQUAL: iCmp = BP_OP_GREATER_EQUAL; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1803,8 +1812,6 @@ Update_t CmdBreakpointSave (int nArgs)
|
|||
//===========================================================================
|
||||
Update_t _CmdAssemble( WORD nAddress, int iArg, int nArgs )
|
||||
{
|
||||
bool bHaveLabel = false;
|
||||
|
||||
// if AlphaNumeric
|
||||
ArgToken_e iTokenSrc = NO_TOKEN;
|
||||
ParserFindToken( g_pConsoleInput, g_aTokens, NUM_TOKENS, &iTokenSrc );
|
||||
|
@ -1812,8 +1819,6 @@ Update_t _CmdAssemble( WORD nAddress, int iArg, int nArgs )
|
|||
if (iTokenSrc == NO_TOKEN) // is TOKEN_ALPHANUMERIC
|
||||
if (g_pConsoleInput[0] != CHAR_SPACE)
|
||||
{
|
||||
bHaveLabel = true;
|
||||
|
||||
// Symbol
|
||||
char *pSymbolName = g_aArgs[ iArg ].sArg; // pArg->sArg;
|
||||
SymbolUpdate( SYMBOLS_ASSEMBLY, pSymbolName, nAddress, false, true ); // bool bRemoveSymbol, bool bUpdateSymbol )
|
||||
|
@ -3659,9 +3664,9 @@ Update_t CmdCursorPageUp4K (int nArgs)
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
Update_t CmdCursorSetPC( int nArgs) // TODO rename
|
||||
Update_t CmdCursorSetPC(int)
|
||||
{
|
||||
regs.pc = nArgs; // HACK:
|
||||
regs.pc = g_nDisasmCurAddress; // set PC to current cursor address
|
||||
return UPDATE_DISASM;
|
||||
}
|
||||
|
||||
|
@ -3768,7 +3773,8 @@ Update_t CmdDisk ( int nArgs)
|
|||
goto _Help;
|
||||
|
||||
char buffer[200] = "";
|
||||
ConsoleBufferPushFormat(buffer, "D%d at T$%s, phase $%s, offset $%X, mask $%02X, extraCycles %.2f, %s",
|
||||
ConsoleBufferPushFormat(buffer, "FW%2d: D%d at T$%s, phase $%s, offset $%X, mask $%02X, extraCycles %.2f, %s",
|
||||
diskCard.GetCurrentFirmware(),
|
||||
diskCard.GetCurrentDrive() + 1,
|
||||
diskCard.GetCurrentTrackString().c_str(),
|
||||
diskCard.GetCurrentPhaseString().c_str(),
|
||||
|
@ -4491,7 +4497,7 @@ Update_t CmdMemoryLoad (int nArgs)
|
|||
FILE *hFile = fopen( sLoadSaveFilePath.c_str(), "rb" );
|
||||
if (hFile)
|
||||
{
|
||||
int nFileBytes = _GetFileSize( hFile );
|
||||
size_t nFileBytes = _GetFileSize( hFile );
|
||||
|
||||
if (nFileBytes > _6502_MEM_END)
|
||||
nFileBytes = _6502_MEM_END + 1; // Bank-switched RAM/ROM is only 16-bit
|
||||
|
@ -5364,7 +5370,7 @@ Update_t CmdNTSC (int nArgs)
|
|||
*pDst++ = pTmp[3];
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
// we duplicate phase 0 a total of 4 times
|
||||
const size_t nBytesPerScanLine = 4096 * nBPP;
|
||||
for( int iPhase = 1; iPhase < 4; iPhase++ )
|
||||
|
@ -5925,11 +5931,6 @@ Update_t _CmdMemorySearch (int nArgs, bool bTextIsAscii = true )
|
|||
return ConsoleDisplayError( TEXT("Error: Missing address seperator (comma or colon)" ) );
|
||||
|
||||
int iArgFirstByte = 4;
|
||||
|
||||
// S start,len #
|
||||
int nMinLen = nArgs - (iArgFirstByte - 1);
|
||||
|
||||
bool bHaveWildCards = false;
|
||||
int iArg;
|
||||
|
||||
MemorySearchValues_t vMemorySearchValues;
|
||||
|
@ -6226,8 +6227,6 @@ Update_t CmdOutputCalc (int nArgs)
|
|||
//===========================================================================
|
||||
Update_t CmdOutputEcho (int nArgs)
|
||||
{
|
||||
TCHAR sText[ CONSOLE_WIDTH ] = TEXT("");
|
||||
|
||||
if (g_aArgs[1].bType & TYPE_QUOTED_2)
|
||||
{
|
||||
ConsoleDisplayPush( g_aArgs[1].sArg );
|
||||
|
@ -6520,7 +6519,6 @@ Update_t CmdOutputRun (int nArgs)
|
|||
|
||||
if (script.Read( sFileName ))
|
||||
{
|
||||
int iLine = 0;
|
||||
int nLine = script.GetNumLines();
|
||||
|
||||
Update_t bUpdateDisplay = UPDATE_NOTHING;
|
||||
|
@ -6639,10 +6637,6 @@ bool ParseAssemblyListing( bool bBytesToMemory, bool bAddSymbols )
|
|||
|
||||
const DWORD INVALID_ADDRESS = _6502_MEM_END + 1;
|
||||
|
||||
bool bPrevSymbol = false;
|
||||
bool bFourBytes = false;
|
||||
BYTE nByte4 = 0;
|
||||
|
||||
int nLines = g_AssemblerSourceBuffer.GetNumLines();
|
||||
for( int iLine = 0; iLine < nLines; iLine++ )
|
||||
{
|
||||
|
@ -6895,11 +6889,16 @@ Update_t CmdCyclesInfo(int nArgs)
|
|||
else
|
||||
{
|
||||
if (strcmp(g_aArgs[1].sArg, "abs") == 0)
|
||||
g_videoScannerDisplayInfo.isAbsCycle = true;
|
||||
g_videoScannerDisplayInfo.cycleMode = VideoScannerDisplayInfo::abs;
|
||||
else if (strcmp(g_aArgs[1].sArg, "rel") == 0)
|
||||
g_videoScannerDisplayInfo.isAbsCycle = false;
|
||||
g_videoScannerDisplayInfo.cycleMode = VideoScannerDisplayInfo::rel;
|
||||
else if (strcmp(g_aArgs[1].sArg, "part") == 0)
|
||||
g_videoScannerDisplayInfo.cycleMode = VideoScannerDisplayInfo::part;
|
||||
else
|
||||
return Help_Arg_1(CMD_CYCLES_INFO);
|
||||
|
||||
if (g_videoScannerDisplayInfo.cycleMode == VideoScannerDisplayInfo::part)
|
||||
CmdCyclesReset(0);
|
||||
}
|
||||
|
||||
TCHAR sText[CONSOLE_WIDTH];
|
||||
|
@ -6909,6 +6908,12 @@ Update_t CmdCyclesInfo(int nArgs)
|
|||
return UPDATE_ALL;
|
||||
}
|
||||
|
||||
Update_t CmdCyclesReset(int /*nArgs*/)
|
||||
{
|
||||
g_videoScannerDisplayInfo.savedCumulativeCycles = g_nCumulativeCycles;
|
||||
return UPDATE_ALL;
|
||||
}
|
||||
|
||||
// View ___________________________________________________________________________________________
|
||||
|
||||
// See: CmdWindowViewOutput (int nArgs)
|
||||
|
@ -8129,16 +8134,26 @@ Update_t ExecuteCommand (int nArgs)
|
|||
//===========================================================================
|
||||
void OutputTraceLine ()
|
||||
{
|
||||
if (!g_hTraceFile)
|
||||
return;
|
||||
|
||||
DisasmLine_t line;
|
||||
GetDisassemblyLine( regs.pc, line );
|
||||
|
||||
char sDisassembly[ CONSOLE_WIDTH ]; // DrawDisassemblyLine( 0,regs.pc, sDisassembly); // Get Disasm String
|
||||
FormatDisassemblyLine( line, sDisassembly, CONSOLE_WIDTH );
|
||||
|
||||
char sFlags[ _6502_NUM_FLAGS + 1 ]; DrawFlags( 0, regs.ps, sFlags ); // Get Flags String
|
||||
|
||||
if (!g_hTraceFile)
|
||||
return;
|
||||
char sFlags[] = "........";
|
||||
WORD nRegFlags = regs.ps;
|
||||
int nFlag = _6502_NUM_FLAGS;
|
||||
while (nFlag--)
|
||||
{
|
||||
int iFlag = (_6502_NUM_FLAGS - nFlag - 1);
|
||||
bool bSet = (nRegFlags & 1);
|
||||
if (bSet)
|
||||
sFlags[nFlag] = g_aBreakpointSource[BP_SRC_FLAG_C + iFlag][0];
|
||||
nRegFlags >>= 1;
|
||||
}
|
||||
|
||||
if (g_bTraceHeader)
|
||||
{
|
||||
|
@ -8153,8 +8168,8 @@ void OutputTraceLine ()
|
|||
else
|
||||
{
|
||||
fprintf( g_hTraceFile,
|
||||
// "00 00 00 0000 -------- 0000:90 90 90 NOP"
|
||||
"A: X: Y: SP: Flags Addr:Opcode Mnemonic\n");
|
||||
// "00000000 00 00 00 0000 -------- 0000:90 90 90 NOP"
|
||||
"Cycles A: X: Y: SP: Flags Addr:Opcode Mnemonic\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8189,8 +8204,10 @@ void OutputTraceLine ()
|
|||
}
|
||||
else
|
||||
{
|
||||
const UINT cycles = (UINT)g_nCumulativeCycles;
|
||||
fprintf( g_hTraceFile,
|
||||
"%02X %02X %02X %04X %s %s\n",
|
||||
"%08X %02X %02X %02X %04X %s %s\n",
|
||||
cycles,
|
||||
(unsigned)regs.a,
|
||||
(unsigned)regs.x,
|
||||
(unsigned)regs.y,
|
||||
|
@ -8806,11 +8823,7 @@ void DebugDestroy ()
|
|||
}
|
||||
// TODO: DataDisassembly_Clear()
|
||||
|
||||
DeleteObject( g_hConsoleBrushFG );
|
||||
DeleteObject( g_hConsoleBrushBG );
|
||||
|
||||
DeleteDC( g_hConsoleFontDC );
|
||||
DeleteObject( g_hConsoleFontBitmap );
|
||||
ReleaseConsoleFontDC();
|
||||
}
|
||||
|
||||
|
||||
|
@ -8853,67 +8866,13 @@ void DebugInitialize ()
|
|||
#endif
|
||||
|
||||
// Must select a bitmap into the temp DC !
|
||||
HDC hTmpDC = CreateCompatibleDC( FrameGetDC() );
|
||||
// HDC hTmpDC = CreateCompatibleDC( FrameGetDC() );
|
||||
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
|
||||
g_hConsoleFontDC = CreateCompatibleDC( FrameGetDC() );
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
|
||||
#if APPLE_FONT_NEW
|
||||
// Pre-scaled bitmap
|
||||
g_hConsoleFontBitmap = LoadBitmap(g_hInstance,TEXT("IDB_DEBUG_FONT_7x8"));
|
||||
SelectObject( g_hConsoleFontDC, g_hConsoleFontBitmap );
|
||||
#else
|
||||
// Scale at run-time
|
||||
|
||||
// Black = Transparent
|
||||
// White = Opaque
|
||||
HBITMAP hTmpBitamp = LoadBitmap(g_hInstance,TEXT("CHARSET40"));
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
|
||||
SelectObject( hTmpDC ,hTmpBitamp);
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
|
||||
g_hConsoleFontBrush = GetStockBrush( WHITE_BRUSH );
|
||||
SelectObject(g_hConsoleFontDC, g_hConsoleFontBrush );
|
||||
|
||||
// SelectObject(hTmpDC, g_hDebugFontBrush );
|
||||
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
|
||||
g_hConsoleFontBitmap = CreateCompatibleBitmap(
|
||||
hTmpDC,
|
||||
APPLE_FONT_X_REGIONSIZE/2, APPLE_FONT_Y_REGIONSIZE/2
|
||||
);
|
||||
#if _DEBUG
|
||||
nError = GetLastError();
|
||||
#endif
|
||||
SelectObject( g_hConsoleFontDC, g_hConsoleFontBitmap );
|
||||
|
||||
StretchBlt(
|
||||
g_hConsoleFontDC, // HDC hdcDest, // handle to destination DC
|
||||
0, 0, // int nXOriginDest, int nYOriginDest, // y-coord of destination upper-left corner
|
||||
APPLE_FONT_X_REGIONSIZE/2, APPLE_FONT_Y_REGIONSIZE/2, // int nWidthDest, int nHeightDest,
|
||||
hTmpDC, // HDC hdcSrc, // handle to source DC
|
||||
0, APPLE_FONT_Y_APPLE_80COL, // int nXOriginSrc, int nYOriginSrc,
|
||||
APPLE_FONT_X_REGIONSIZE, APPLE_FONT_Y_REGIONSIZE, // int nWidthSrc, int nHeightSrc,
|
||||
SRCCOPY // DWORD dwRop // raster operation code
|
||||
);
|
||||
|
||||
DeleteObject( hTmpBitamp );
|
||||
DeleteObject( hTmpDC );
|
||||
#endif
|
||||
GetConsoleFontDC(); // Load font
|
||||
|
||||
ZeroMemory( g_aConsoleDisplay, sizeof( g_aConsoleDisplay ) ); // CONSOLE_WIDTH * CONSOLE_HEIGHT );
|
||||
ConsoleInputReset();
|
||||
|
@ -9609,7 +9568,7 @@ void DebuggerProcessKey( int keycode )
|
|||
|
||||
case VK_RIGHT:
|
||||
if (KeybGetCtrlStatus())
|
||||
bUpdateDisplay |= CmdCursorSetPC( g_nDisasmCurAddress );
|
||||
bUpdateDisplay |= CmdCursorSetPC(0/*unused*/);
|
||||
else
|
||||
if (KeybGetShiftStatus())
|
||||
bUpdateDisplay |= CmdCursorJumpPC( CURSOR_ALIGN_TOP );
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
// Prototypes _______________________________________________________________
|
||||
|
||||
// Bookmarks
|
||||
bool Bookmark_Find( const WORD nAddress );
|
||||
int Bookmark_Find( const WORD nAddress );
|
||||
|
||||
// Breakpoints
|
||||
int CheckBreakpointsIO ();
|
||||
|
|
|
@ -787,8 +787,6 @@ bool _6502_GetTargetAddress ( const WORD & nAddress, WORD & nTarget_ )
|
|||
iOpcode = _6502_GetOpmodeOpbyte( nAddress, iOpmode, nOpbytes );
|
||||
|
||||
// Composite string that has the target nAddress
|
||||
// WORD nTarget = 0;
|
||||
int nTargetOffset_ = 0;
|
||||
|
||||
if ((iOpmode != AM_IMPLIED) &&
|
||||
(iOpmode != AM_1) &&
|
||||
|
@ -796,10 +794,10 @@ bool _6502_GetTargetAddress ( const WORD & nAddress, WORD & nTarget_ )
|
|||
(iOpmode != AM_3))
|
||||
{
|
||||
int nTargetPartial;
|
||||
int nTargetPartial2;
|
||||
int nTargetPointer;
|
||||
WORD nTargetValue = 0; // de-ref
|
||||
int nTargetBytes;
|
||||
_6502_GetTargets( nAddress, &nTargetPartial, &nTargetPointer, &nTargetBytes, false );
|
||||
_6502_GetTargets( nAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, &nTargetBytes, false );
|
||||
|
||||
// if (nTargetPointer == NO_6502_TARGET)
|
||||
// {
|
||||
|
@ -870,9 +868,8 @@ int AssemblerHashMnemonic ( const TCHAR * pMnemonic )
|
|||
const int NUM_MSK_BITS = 5; // 4 -> 5 prime
|
||||
const Hash_t BIT_MSK_HIGH = ((1 << NUM_MSK_BITS) - 1) << NUM_LOW_BITS;
|
||||
|
||||
int nLen = strlen( pMnemonic );
|
||||
|
||||
#if DEBUG_ASSEMBLER
|
||||
int nLen = strlen( pMnemonic );
|
||||
static int nMaxLen = 0;
|
||||
if (nMaxLen < nLen) {
|
||||
nMaxLen = nLen;
|
||||
|
@ -961,7 +958,7 @@ void _CmdAssembleHashDump ()
|
|||
|
||||
std::sort( vHashes.begin(), vHashes.end(), HashOpcode_t() );
|
||||
|
||||
Hash_t nPrevHash = vHashes.at( 0 ).m_nValue;
|
||||
// Hash_t nPrevHash = vHashes.at( 0 ).m_nValue;
|
||||
Hash_t nThisHash = 0;
|
||||
|
||||
for( iOpcode = 0; iOpcode < NUM_OPCODES; iOpcode++ )
|
||||
|
@ -1097,7 +1094,7 @@ bool AssemblerGetArgs( int iArg, int nArgs, WORD nBaseAddress )
|
|||
while (iArg < g_nArgRaw)
|
||||
{
|
||||
int iToken = pArg->eToken;
|
||||
int iType = pArg->bType;
|
||||
// int iType = pArg->bType;
|
||||
|
||||
if (iToken == TOKEN_HASH)
|
||||
{
|
||||
|
|
|
@ -123,6 +123,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
{TEXT("PAGEDOWN4K" ) , CmdCursorPageDown4K , CMD_CURSOR_PAGE_DOWN_4K , "Scroll down 4096 bytes" }, // Ctrl
|
||||
// Cycles info
|
||||
{TEXT("CYCLES") , CmdCyclesInfo , CMD_CYCLES_INFO, "Cycles display configuration" },
|
||||
{TEXT("RCC") , CmdCyclesReset , CMD_CYCLES_RESET, "Reset cycles counter" },
|
||||
// Disassembler Data
|
||||
{TEXT("Z") , CmdDisasmDataDefByte1 , CMD_DISASM_DATA , "Treat byte [range] as data" },
|
||||
{TEXT("X") , CmdDisasmDataDefCode , CMD_DISASM_CODE , "Treat byte [range] as code" },
|
||||
|
|
|
@ -354,7 +354,6 @@ void ConsoleBufferToDisplay ()
|
|||
//===========================================================================
|
||||
void ConsoleConvertFromText ( conchar_t * sText, const char * pText )
|
||||
{
|
||||
int x = 0;
|
||||
const char *pSrc = pText;
|
||||
conchar_t *pDst = sText;
|
||||
while (pSrc && *pSrc)
|
||||
|
@ -523,13 +522,6 @@ void ConsoleInputReset ()
|
|||
g_aConsoleInput[0] = g_sConsolePrompt[0];
|
||||
g_nConsolePromptLen = 1;
|
||||
|
||||
// int nLen = strlen( g_aConsoleInput );
|
||||
#if CONSOLE_INPUT_CHAR16
|
||||
int nLen = ConsoleLineLength( g_aConsoleInput );
|
||||
#else
|
||||
int nLen = strlen( g_aConsoleInput );
|
||||
#endif
|
||||
|
||||
g_pConsoleInput = &g_aConsoleInput[ g_nConsolePromptLen ];
|
||||
g_nConsoleInputChars = 0;
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ 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)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,8 @@ 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-2014, Tom Charlesworth, Michael Pohoreski
|
||||
Copyright (C) 2006-2019, Tom Charlesworth, Michael Pohoreski
|
||||
Copyright (C) 2020, Tom Charlesworth, Michael Pohoreski, Cyril Lambin
|
||||
|
||||
AppleWin is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,7 +24,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
/* Description: Debugger
|
||||
*
|
||||
* Author: Copyright (C) 2006-2010 Michael Pohoreski
|
||||
* Author: Copyright (C) 2006-2020 Michael Pohoreski, (C) 2020 Cyril Lambin
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
@ -79,13 +80,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
// Display - Win32
|
||||
static HDC g_hDebuggerMemDC = NULL;
|
||||
static HBITMAP g_hDebuggerMemBM = NULL;
|
||||
static LPBITMAPINFO g_pDebuggerMemFramebufferinfo = NULL;
|
||||
static bgra_t* g_pDebuggerMemFramebits = NULL;
|
||||
|
||||
HDC g_hConsoleFontDC = NULL;
|
||||
HBRUSH g_hConsoleFontBrush = NULL;
|
||||
HBITMAP g_hConsoleFontBitmap = NULL;
|
||||
static HDC g_hConsoleFontDC = NULL;
|
||||
static HBITMAP g_hConsoleFontBitmap = NULL;
|
||||
static LPBITMAPINFO g_hConsoleFontFramebufferinfo = NULL;
|
||||
static bgra_t* g_hConsoleFontFramebits;
|
||||
|
||||
HBRUSH g_hConsoleBrushFG = NULL;
|
||||
HBRUSH g_hConsoleBrushBG = NULL;
|
||||
char g_cConsoleBrushFG_r;
|
||||
char g_cConsoleBrushFG_g;
|
||||
char g_cConsoleBrushFG_b;
|
||||
char g_cConsoleBrushBG_r;
|
||||
char g_cConsoleBrushBG_g;
|
||||
char g_cConsoleBrushBG_b;
|
||||
|
||||
static HBRUSH g_hConsoleBrushFG = NULL;
|
||||
static HBRUSH g_hConsoleBrushBG = NULL;
|
||||
|
||||
// NOTE: Keep in sync ConsoleColors_e g_anConsoleColor !
|
||||
COLORREF g_anConsoleColor[ NUM_CONSOLE_COLORS ] =
|
||||
|
@ -164,7 +175,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
const int DISPLAY_MINIMEM_COLUMN = INFO_COL_3;
|
||||
const int DISPLAY_VIDEO_SCANNER_COLUMN = INFO_COL_3;
|
||||
#else
|
||||
const int DISPLAY_CPU_INFO_LEFT_COLUMN = SCREENSPLIT1 // TC: SCREENSPLIT1 is not defined anywhere in the .sln!
|
||||
const int DISPLAY_CPU_INFO_LEFT_COLUMN = SCREENSPLIT1; // TC: SCREENSPLIT1 is not defined anywhere in the .sln!
|
||||
|
||||
const int DISPLAY_REGS_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
||||
const int DISPLAY_FLAG_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
||||
|
@ -214,6 +225,7 @@ static char ColorizeSpecialChar( char * sText, BYTE nData, const MemoryView_e iV
|
|||
void DrawSubWindow_Symbols (Update_t bUpdate);
|
||||
void DrawSubWindow_ZeroPage (Update_t bUpdate);
|
||||
|
||||
|
||||
void DrawWindowBottom ( Update_t bUpdate, int iWindow );
|
||||
|
||||
char* FormatCharCopy( char *pDst, const char *pSrc, const int nLen );
|
||||
|
@ -541,7 +553,31 @@ HDC GetDebuggerMemDC(void)
|
|||
{
|
||||
HDC hFrameDC = FrameGetDC();
|
||||
g_hDebuggerMemDC = CreateCompatibleDC(hFrameDC);
|
||||
g_hDebuggerMemBM = CreateCompatibleBitmap(hFrameDC, GetFrameBufferWidth(), GetFrameBufferHeight());
|
||||
|
||||
// CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER
|
||||
g_pDebuggerMemFramebufferinfo = (LPBITMAPINFO)VirtualAlloc(
|
||||
NULL,
|
||||
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD),
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
ZeroMemory(g_pDebuggerMemFramebufferinfo, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biWidth = 560;
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biHeight = 384;
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biPlanes = 1;
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biBitCount = 32;
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biCompression = BI_RGB;
|
||||
g_pDebuggerMemFramebufferinfo->bmiHeader.biClrUsed = 0;
|
||||
|
||||
|
||||
// CREATE THE FRAME BUFFER DIB SECTION
|
||||
g_hDebuggerMemBM = CreateDIBSection(
|
||||
hFrameDC,
|
||||
g_pDebuggerMemFramebufferinfo,
|
||||
DIB_RGB_COLORS,
|
||||
(LPVOID*)&g_pDebuggerMemFramebits, 0, 0
|
||||
);
|
||||
SelectObject(g_hDebuggerMemDC, g_hDebuggerMemBM);
|
||||
}
|
||||
|
||||
|
@ -557,10 +593,87 @@ void ReleaseDebuggerMemDC(void)
|
|||
g_hDebuggerMemBM = NULL;
|
||||
DeleteDC(g_hDebuggerMemDC);
|
||||
g_hDebuggerMemDC = NULL;
|
||||
|
||||
FrameReleaseDC();
|
||||
|
||||
VirtualFree(g_pDebuggerMemFramebufferinfo, 0, MEM_RELEASE);
|
||||
g_pDebuggerMemFramebufferinfo = NULL;
|
||||
g_pDebuggerMemFramebits = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HDC GetConsoleFontDC(void)
|
||||
{
|
||||
if (!g_hConsoleFontDC)
|
||||
{
|
||||
HDC hFrameDC = FrameGetDC();
|
||||
g_hConsoleFontDC = CreateCompatibleDC(hFrameDC);
|
||||
|
||||
// CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER
|
||||
g_hConsoleFontFramebufferinfo = (LPBITMAPINFO)VirtualAlloc(
|
||||
NULL,
|
||||
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD),
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
ZeroMemory(g_hConsoleFontFramebufferinfo, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biWidth = CONSOLE_FONT_BITMAP_WIDTH;
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biHeight = CONSOLE_FONT_BITMAP_HEIGHT;
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biPlanes = 1;
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biBitCount = 32;
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biCompression = BI_RGB;
|
||||
g_hConsoleFontFramebufferinfo->bmiHeader.biClrUsed = 0;
|
||||
|
||||
|
||||
// CREATE THE FRAME BUFFER DIB SECTION
|
||||
g_hConsoleFontBitmap = CreateDIBSection(
|
||||
hFrameDC,
|
||||
g_hConsoleFontFramebufferinfo,
|
||||
DIB_RGB_COLORS,
|
||||
(LPVOID*)&g_hConsoleFontFramebits, 0, 0
|
||||
);
|
||||
SelectObject(g_hConsoleFontDC, g_hConsoleFontBitmap);
|
||||
|
||||
// DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER
|
||||
HDC tmpDC = CreateCompatibleDC(hFrameDC);
|
||||
// Pre-scaled bitmap
|
||||
HBITMAP tmpFont = LoadBitmap(g_hInstance, TEXT("IDB_DEBUG_FONT_7x8")); // Bitmap must be 112x128 as defined above
|
||||
SelectObject(tmpDC, tmpFont);
|
||||
BitBlt(g_hConsoleFontDC, 0, 0, CONSOLE_FONT_BITMAP_WIDTH, CONSOLE_FONT_BITMAP_HEIGHT,
|
||||
tmpDC, 0, 0,
|
||||
SRCCOPY);
|
||||
DeleteDC(tmpDC);
|
||||
DeleteObject(tmpFont);
|
||||
|
||||
}
|
||||
|
||||
_ASSERT(g_hConsoleFontDC);
|
||||
return g_hConsoleFontDC;
|
||||
}
|
||||
|
||||
void ReleaseConsoleFontDC(void)
|
||||
{
|
||||
if (g_hConsoleFontDC)
|
||||
{
|
||||
DeleteDC( g_hConsoleFontDC );
|
||||
g_hConsoleFontDC = NULL;
|
||||
DeleteObject( g_hConsoleFontBitmap );
|
||||
g_hConsoleFontBitmap = NULL;
|
||||
|
||||
VirtualFree(g_hConsoleFontFramebufferinfo, 0, MEM_RELEASE);
|
||||
g_hConsoleFontFramebufferinfo = NULL;
|
||||
g_hConsoleFontFramebits = NULL;
|
||||
}
|
||||
|
||||
DeleteObject( g_hConsoleBrushFG );
|
||||
g_hConsoleBrushFG = NULL;
|
||||
DeleteObject( g_hConsoleBrushBG );
|
||||
g_hConsoleBrushBG = NULL;
|
||||
}
|
||||
|
||||
|
||||
void StretchBltMemToFrameDC(void)
|
||||
{
|
||||
int nViewportCX, nViewportCY;
|
||||
|
@ -594,7 +707,12 @@ void DebuggerSetColorFG( COLORREF nRGB )
|
|||
g_hConsoleBrushFG = NULL;
|
||||
}
|
||||
|
||||
g_hConsoleBrushFG = CreateSolidBrush( nRGB );
|
||||
g_hConsoleBrushFG = CreateSolidBrush(nRGB);
|
||||
|
||||
g_cConsoleBrushFG_r = nRGB & 0xFF;
|
||||
g_cConsoleBrushFG_g = (nRGB>>8) & 0xFF;
|
||||
g_cConsoleBrushFG_b = (nRGB>>16) & 0xFF;
|
||||
|
||||
#else
|
||||
SetTextColor( GetDebuggerMemDC(), nRGB );
|
||||
#endif
|
||||
|
@ -615,6 +733,12 @@ void DebuggerSetColorBG( COLORREF nRGB, bool bTransparent )
|
|||
{
|
||||
g_hConsoleBrushBG = CreateSolidBrush( nRGB );
|
||||
}
|
||||
|
||||
// Transparency seems to be never used...
|
||||
g_cConsoleBrushBG_r = nRGB & 0xFF;
|
||||
g_cConsoleBrushBG_g = (nRGB >> 8) & 0xFF;
|
||||
g_cConsoleBrushBG_b = (nRGB >> 16) & 0xFF;
|
||||
|
||||
#else
|
||||
SetBkColor( GetDebuggerMemDC(), nRGB );
|
||||
#endif
|
||||
|
@ -622,31 +746,28 @@ void DebuggerSetColorBG( COLORREF nRGB, bool bTransparent )
|
|||
|
||||
// @param glyph Specifies a native glyph from the 16x16 chars Apple Font Texture.
|
||||
//===========================================================================
|
||||
void PrintGlyph( const int x, const int y, const char glyph )
|
||||
static void PrintGlyph( const int xDst, const int yDst, const int glyph )
|
||||
{
|
||||
HDC hDstDC = GetDebuggerMemDC();
|
||||
|
||||
int xDst = x;
|
||||
int yDst = y;
|
||||
|
||||
// 16x8 chars in bitmap
|
||||
int xSrc = (glyph & 0x0F) * CONSOLE_FONT_GRID_X;
|
||||
int ySrc = (glyph >> 4) * CONSOLE_FONT_GRID_Y;
|
||||
int xSrc = (glyph % CONSOLE_FONT_NUM_CHARS_PER_ROW) * CONSOLE_FONT_GRID_X;
|
||||
int ySrc = (glyph / CONSOLE_FONT_NUM_CHARS_PER_ROW) * CONSOLE_FONT_GRID_Y;
|
||||
_ASSERT(ySrc < CONSOLE_FONT_BITMAP_HEIGHT);
|
||||
|
||||
// BUG #239 - (Debugger) Save debugger "text screen" to clipboard / file
|
||||
// if( g_bDebuggerVirtualTextCapture )
|
||||
//
|
||||
{
|
||||
#if _DEBUG
|
||||
if ((x < 0) || (y < 0))
|
||||
if ((xDst < 0) || (yDst < 0))
|
||||
MessageBox( g_hFrameWindow, "X or Y out of bounds!", "PrintGlyph()", MB_OK );
|
||||
#endif
|
||||
int col = x / CONSOLE_FONT_WIDTH ;
|
||||
int row = y / CONSOLE_FONT_HEIGHT;
|
||||
int col = xDst / CONSOLE_FONT_WIDTH ;
|
||||
int row = yDst / CONSOLE_FONT_HEIGHT;
|
||||
|
||||
// if( !g_bDebuggerCopyInfoPane )
|
||||
// if( col < 50
|
||||
if (x > DISPLAY_DISASM_RIGHT) // INFO_COL_2 // DISPLAY_CPU_INFO_LEFT_COLUMN
|
||||
if (xDst > DISPLAY_DISASM_RIGHT) // INFO_COL_2 // DISPLAY_CPU_INFO_LEFT_COLUMN
|
||||
col++;
|
||||
|
||||
if ((col < DEBUG_VIRTUAL_TEXT_WIDTH)
|
||||
|
@ -654,74 +775,21 @@ void PrintGlyph( const int x, const int y, const char glyph )
|
|||
g_aDebuggerVirtualTextScreen[ row ][ col ] = glyph;
|
||||
}
|
||||
|
||||
#if !DEBUG_FONT_NO_BACKGROUND_CHAR
|
||||
// Background color
|
||||
if (g_hConsoleBrushBG)
|
||||
// Manual print of character. A lot faster than BitBlt, which must be avoided.
|
||||
int index_src = (CONSOLE_FONT_BITMAP_HEIGHT - 1 - ySrc) * CONSOLE_FONT_NUM_CHARS_PER_ROW * CONSOLE_FONT_GRID_X + xSrc; // font bitmap
|
||||
int index_dst = (DISPLAY_HEIGHT - 1 - yDst) * DEBUG_VIRTUAL_TEXT_WIDTH * CONSOLE_FONT_GRID_X + xDst; // debugger bitmap
|
||||
for (int yy = 0; yy < CONSOLE_FONT_GRID_Y; yy++)
|
||||
{
|
||||
SelectObject( hDstDC, g_hConsoleBrushBG );
|
||||
|
||||
// Draw Background (solid pattern)
|
||||
BitBlt(
|
||||
hDstDC, // hdcDest
|
||||
xDst, yDst, // nXDest, nYDest
|
||||
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT, // nWidth, nHeight
|
||||
g_hConsoleFontDC, // hdcSrc
|
||||
0, CONSOLE_FONT_GRID_Y * 2, // nXSrc, nYSrc // FontTexture[2][0] = Solid (Filled) Space
|
||||
PATCOPY // dwRop
|
||||
);
|
||||
for (int xx = 0; xx < CONSOLE_FONT_GRID_X; xx++)
|
||||
{
|
||||
char fontpx = g_hConsoleFontFramebits[index_src + xx].g; // Should be same for R/G/B anyway (greyscale)
|
||||
g_pDebuggerMemFramebits[index_dst + xx].r = (g_cConsoleBrushBG_r & ~fontpx) | (g_cConsoleBrushFG_r & fontpx);
|
||||
g_pDebuggerMemFramebits[index_dst + xx].g = (g_cConsoleBrushBG_g & ~fontpx) | (g_cConsoleBrushFG_g & fontpx);
|
||||
g_pDebuggerMemFramebits[index_dst + xx].b = (g_cConsoleBrushBG_b & ~fontpx) | (g_cConsoleBrushFG_b & fontpx);
|
||||
}
|
||||
index_src -= CONSOLE_FONT_NUM_CHARS_PER_ROW * CONSOLE_FONT_GRID_X;
|
||||
index_dst -= DEBUG_VIRTUAL_TEXT_WIDTH * CONSOLE_FONT_GRID_X;
|
||||
}
|
||||
#endif
|
||||
|
||||
// SelectObject( hDstDC, GetStockBrush( WHITE_BRUSH ) );
|
||||
|
||||
// http://kkow.net/etep/docs/rop.html
|
||||
// P 1 1 1 1 0 0 0 0 (Pen/Pattern)
|
||||
// S 1 1 0 0 1 1 0 0 (Source)
|
||||
// D 1 0 1 0 1 0 1 0 (Destination)
|
||||
// =================
|
||||
// 0 0 1 0 0 0 1 0 0x22 DSna
|
||||
// 1 1 1 0 1 0 1 0 0xEA DPSao
|
||||
|
||||
// Black = Transparent (DC Background)
|
||||
// White = Opaque (DC Text color)
|
||||
|
||||
#if DEBUG_FONT_ROP
|
||||
SelectObject( hDstDC, g_hConsoleBrushFG );
|
||||
BitBlt(
|
||||
hDstDC,
|
||||
xDst, yDst,
|
||||
DEBUG_FONT_WIDTH, DEBUG_FONT_HEIGHT,
|
||||
g_hDebugFontDC,
|
||||
xSrc, ySrc,
|
||||
aROP4[ iRop4 ]
|
||||
);
|
||||
#else
|
||||
// Use inverted source as mask (AND)
|
||||
// D & ~S -> DSna
|
||||
BitBlt(
|
||||
hDstDC,
|
||||
xDst, yDst,
|
||||
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT,
|
||||
g_hConsoleFontDC,
|
||||
xSrc, ySrc,
|
||||
DSna
|
||||
);
|
||||
|
||||
SelectObject( hDstDC, g_hConsoleBrushFG );
|
||||
|
||||
// Use Source as mask to make color Pattern mask (AND), then apply to dest (OR)
|
||||
// D | (P & S) -> DPSao
|
||||
BitBlt(
|
||||
hDstDC,
|
||||
xDst, yDst,
|
||||
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT,
|
||||
g_hConsoleFontDC,
|
||||
xSrc, ySrc,
|
||||
DPSao
|
||||
);
|
||||
#endif
|
||||
|
||||
SelectObject( hDstDC, GetStockObject(NULL_BRUSH) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -814,7 +882,7 @@ int PrintText ( const char * pText, RECT & rRect )
|
|||
int nLen = strlen( pText );
|
||||
|
||||
#if !DEBUG_FONT_NO_BACKGROUND_TEXT
|
||||
FillRect( GetDebuggerMemDC(), &rRect, g_hConsoleBrushBG );
|
||||
FillBackground(rRect.left, rRect.top, rRect.right, rRect.bottom);
|
||||
#endif
|
||||
|
||||
DebuggerPrint( rRect.left, rRect.top, pText );
|
||||
|
@ -825,12 +893,37 @@ int PrintText ( const char * pText, RECT & rRect )
|
|||
void PrintTextColor ( const conchar_t *pText, RECT & rRect )
|
||||
{
|
||||
#if !DEBUG_FONT_NO_BACKGROUND_TEXT
|
||||
FillRect( GetDebuggerMemDC(), &rRect, g_hConsoleBrushBG );
|
||||
FillBackground(rRect.left, rRect.top, rRect.right, rRect.bottom);
|
||||
#endif
|
||||
|
||||
DebuggerPrintColor( rRect.left, rRect.top, pText );
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void FillBackground(long left, long top, long right, long bottom)
|
||||
{
|
||||
long index_dst = (384-bottom) * 80 * CONSOLE_FONT_GRID_X;
|
||||
|
||||
for (long x = left; x < right; x++)
|
||||
{
|
||||
g_pDebuggerMemFramebits[index_dst + x].r = g_cConsoleBrushBG_r;
|
||||
g_pDebuggerMemFramebits[index_dst + x].g = g_cConsoleBrushBG_g;
|
||||
g_pDebuggerMemFramebits[index_dst + x].b = g_cConsoleBrushBG_b;
|
||||
}
|
||||
|
||||
if (top != bottom)
|
||||
{
|
||||
bgra_t* src = g_pDebuggerMemFramebits + (index_dst + left);
|
||||
bgra_t* dst = src + (80 * CONSOLE_FONT_GRID_X);
|
||||
size_t size = (right - left) * sizeof(bgra_t);
|
||||
for (int i = 0; i < bottom - top - 1; i++)
|
||||
{
|
||||
memcpy((void*)dst, (void*)src, size);
|
||||
dst += 80 * CONSOLE_FONT_GRID_X ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the horizontal cursor
|
||||
//===========================================================================
|
||||
int PrintTextCursorX ( const char * pText, RECT & rRect )
|
||||
|
@ -968,7 +1061,6 @@ char ColorizeSpecialChar( char * sText, BYTE nData, const MemoryView_e iView,
|
|||
const int iCtrlBackground /*= BG_INFO_CHAR*/, const int iCtrlForeground /*= FG_INFO_CHAR_LO*/ )
|
||||
{
|
||||
bool bHighBit = false;
|
||||
bool bAsciBit = false;
|
||||
bool bCtrlBit = false;
|
||||
|
||||
int iTextBG = iAsciBackground;
|
||||
|
@ -1061,7 +1153,6 @@ void DrawBreakpoints ( int line )
|
|||
rect.right = DISPLAY_WIDTH;
|
||||
rect.bottom = rect.top + g_nFontHeight;
|
||||
|
||||
const int MAX_BP_LEN = 16;
|
||||
char sText[16] = "Breakpoints"; // TODO: Move to BP1
|
||||
|
||||
#if DISPLAY_BREAKPOINT_TITLE
|
||||
|
@ -1406,7 +1497,7 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|||
(iOpmode != AM_3))
|
||||
{
|
||||
// Assume target address starts after the opcode ...
|
||||
// BUT in the Assembler Directve / Data Disassembler case for define addr/word
|
||||
// BUT in the Assembler Directive / Data Disassembler case for define addr/word
|
||||
// the opcode literally IS the target address!
|
||||
if( pData )
|
||||
{
|
||||
|
@ -1670,10 +1761,10 @@ void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|||
void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
||||
{
|
||||
char *pDst = line_.sTarget;
|
||||
const char *pSrc = 0;
|
||||
const char *pSrc = 0;
|
||||
DWORD nStartAddress = line_.pDisasmData->nStartAddress;
|
||||
DWORD nEndAddress = line_.pDisasmData->nEndAddress ;
|
||||
int nDataLen = nEndAddress - nStartAddress + 1 ;
|
||||
// int nDataLen = nEndAddress - nStartAddress + 1 ;
|
||||
int nDisplayLen = nEndAddress - nBaseAddress + 1 ; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
|
||||
int len = nDisplayLen;
|
||||
|
||||
|
@ -1827,7 +1918,7 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
||||
return 0;
|
||||
|
||||
int iOpcode;
|
||||
// int iOpcode;
|
||||
int iOpmode;
|
||||
int nOpbyte;
|
||||
DisasmLine_t line;
|
||||
|
@ -1838,7 +1929,7 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
int bDisasmFormatFlags = GetDisassemblyLine( nBaseAddress, line );
|
||||
const DisasmData_t *pData = line.pDisasmData;
|
||||
|
||||
iOpcode = line.iOpcode;
|
||||
// iOpcode = line.iOpcode;
|
||||
iOpmode = line.iOpmode;
|
||||
nOpbyte = line.nOpbyte;
|
||||
|
||||
|
@ -1891,7 +1982,6 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
aTabs[ TS_IMMEDIATE ] -= 1;
|
||||
}
|
||||
#endif
|
||||
const int OPCODE_TO_LABEL_SPACE = static_cast<int>( aTabs[ TS_INSTRUCTION ] - aTabs[ TS_LABEL ] );
|
||||
|
||||
int iTab = 0;
|
||||
int nSpacer = 11; // 9
|
||||
|
@ -1917,12 +2007,6 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
aTabs[ iTab ] *= nDefaultFontWidth;
|
||||
}
|
||||
|
||||
#if USE_APPLE_FONT
|
||||
const int DISASM_SYMBOL_LEN = 12;
|
||||
#else
|
||||
const int DISASM_SYMBOL_LEN = 9;
|
||||
#endif
|
||||
|
||||
int nFontHeight = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nLineHeight; // _nFontHeight; // g_nFontHeight
|
||||
|
||||
RECT linerect;
|
||||
|
@ -1935,7 +2019,7 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
bool bBreakpointEnable;
|
||||
GetBreakpointInfo( nBaseAddress, bBreakpointActive, bBreakpointEnable );
|
||||
bool bAddressAtPC = (nBaseAddress == regs.pc);
|
||||
bool bAddressIsBookmark = Bookmark_Find( nBaseAddress );
|
||||
int bAddressIsBookmark = Bookmark_Find( nBaseAddress );
|
||||
|
||||
DebugColors_e iBackground = BG_DISASM_1;
|
||||
DebugColors_e iForeground = FG_DISASM_MNEMONIC; // FG_DISASM_TEXT;
|
||||
|
@ -2005,16 +2089,8 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
}
|
||||
}
|
||||
|
||||
if (bAddressIsBookmark)
|
||||
{
|
||||
DebuggerSetColorBG( DebuggerGetColor( BG_DISASM_BOOKMARK ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_BOOKMARK ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
||||
}
|
||||
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
||||
|
||||
// Address
|
||||
if (! bCursorLine)
|
||||
|
@ -2030,18 +2106,31 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
PrintTextCursorX( (LPCTSTR) line.sAddress, linerect );
|
||||
}
|
||||
|
||||
if (bAddressIsBookmark)
|
||||
{
|
||||
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
||||
}
|
||||
|
||||
// Address Seperator
|
||||
if (! bCursorLine)
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
||||
|
||||
if (g_bConfigDisasmAddressColon)
|
||||
PrintTextCursorX( ":", linerect );
|
||||
{
|
||||
if (bAddressIsBookmark)
|
||||
{
|
||||
DebuggerSetColorBG( DebuggerGetColor( BG_DISASM_BOOKMARK ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_BOOKMARK ) );
|
||||
|
||||
// Can't use PrintTextCursorX() as that clamps chars > 0x7F to Mouse Text
|
||||
// char bookmark_text[2] = { 0x7F + bAddressIsBookmark, 0 };
|
||||
// PrintTextCursorX( bookmark_text, linerect );
|
||||
FillRect( GetDebuggerMemDC(), &linerect, g_hConsoleBrushBG );
|
||||
PrintGlyph( linerect.left, linerect.top, 0x7F + bAddressIsBookmark ); // Glyphs 0x80 .. 0x89 = Unicode U+24EA, U+2460 .. U+2468
|
||||
linerect.left += g_aFontConfig[ FONT_DISASM_DEFAULT ]._nFontWidthAvg;
|
||||
|
||||
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
||||
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
||||
}
|
||||
else
|
||||
PrintTextCursorX( ":", linerect );
|
||||
}
|
||||
else
|
||||
PrintTextCursorX( " ", linerect ); // bugfix, not showing "addr:" doesn't alternate color lines
|
||||
|
||||
|
@ -2335,9 +2424,8 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|||
}
|
||||
|
||||
|
||||
// Optionally copy the flags to pText_
|
||||
//===========================================================================
|
||||
void DrawFlags ( int line, WORD nRegFlags, LPTSTR pFlagNames_)
|
||||
static void DrawFlags ( int line, WORD nRegFlags )
|
||||
{
|
||||
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
||||
return;
|
||||
|
@ -2426,19 +2514,8 @@ void DrawFlags ( int line, WORD nRegFlags, LPTSTR pFlagNames_)
|
|||
rect.top -= g_nFontHeight;
|
||||
rect.bottom -= g_nFontHeight;
|
||||
|
||||
if (pFlagNames_)
|
||||
{
|
||||
if (!bSet)
|
||||
sFlagNames[nFlag] = '.';
|
||||
else
|
||||
sFlagNames[nFlag] = g_aBreakpointSource[ BP_SRC_FLAG_C + iFlag ][0];
|
||||
}
|
||||
|
||||
nRegFlags >>= 1;
|
||||
}
|
||||
|
||||
if (pFlagNames_)
|
||||
strcpy(pFlagNames_,sFlagNames);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -2477,7 +2554,6 @@ void DrawMemory ( int line, int iMemDump )
|
|||
|
||||
const int MAX_MEM_VIEW_TXT = 16;
|
||||
char sText[ MAX_MEM_VIEW_TXT * 2 ];
|
||||
char sData[ MAX_MEM_VIEW_TXT * 2 ];
|
||||
|
||||
char sType [ 6 ] = "Mem";
|
||||
char sAddress[ 8 ] = "";
|
||||
|
@ -2524,8 +2600,6 @@ void DrawMemory ( int line, int iMemDump )
|
|||
rect.top = rect2.top;
|
||||
rect.bottom = rect2.bottom;
|
||||
|
||||
sData[0] = 0;
|
||||
|
||||
WORD iAddress = nAddr;
|
||||
|
||||
int nLines = g_nDisplayMemoryLines;
|
||||
|
@ -2562,9 +2636,6 @@ void DrawMemory ( int line, int iMemDump )
|
|||
|
||||
for (int iCol = 0; iCol < nCols; iCol++)
|
||||
{
|
||||
bool bHiBit = false;
|
||||
bool bLoBit = false;
|
||||
|
||||
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
||||
DebuggerSetColorFG( DebuggerGetColor( iForeground ));
|
||||
|
||||
|
@ -2596,8 +2667,6 @@ void DrawMemory ( int line, int iMemDump )
|
|||
BYTE nData = (unsigned)*(LPBYTE)(mem+iAddress);
|
||||
sText[0] = 0;
|
||||
|
||||
char c = nData;
|
||||
|
||||
if (iView == MEM_VIEW_HEX)
|
||||
{
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
|
@ -2626,7 +2695,6 @@ void DrawMemory ( int line, int iMemDump )
|
|||
|
||||
rect.top += g_nFontHeight;
|
||||
rect.bottom += g_nFontHeight;
|
||||
sData[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2727,7 +2795,7 @@ void DrawRegisters ( int line )
|
|||
DrawRegister( line++, sReg[ BP_SRC_REG_X ] , 1, regs.x , PARAM_REG_X );
|
||||
DrawRegister( line++, sReg[ BP_SRC_REG_Y ] , 1, regs.y , PARAM_REG_Y );
|
||||
DrawRegister( line++, sReg[ BP_SRC_REG_PC] , 2, regs.pc, PARAM_REG_PC );
|
||||
DrawFlags ( line , regs.ps, NULL);
|
||||
DrawFlags ( line , regs.ps);
|
||||
line += 2;
|
||||
DrawRegister( line++, sReg[ BP_SRC_REG_S ] , 2, regs.sp, PARAM_REG_SP );
|
||||
}
|
||||
|
@ -2771,7 +2839,6 @@ void _DrawSoftSwitchAddress( RECT & rect, int nAddress, int bg_default = BG_INFO
|
|||
void _DrawSoftSwitch( RECT & rect, int nAddress, bool bSet, char *sPrefix, char *sOn, char *sOff, const char *sSuffix = NULL, int bg_default = BG_INFO )
|
||||
{
|
||||
RECT temp = rect;
|
||||
char sText[ 4 ] = "";
|
||||
|
||||
_DrawSoftSwitchAddress( temp, nAddress, bg_default );
|
||||
|
||||
|
@ -3017,10 +3084,9 @@ void DrawSoftSwitches( int iSoftSwitch )
|
|||
|
||||
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
||||
|
||||
char sText[16] = "";
|
||||
|
||||
#if SOFTSWITCH_OLD
|
||||
char sText[16] = "";
|
||||
// $C050 / $C051 = TEXTOFF/TEXTON = SW.TXTCLR/SW.TXTSET
|
||||
// GR / TEXT
|
||||
// GRAPH/TEXT
|
||||
|
@ -3325,7 +3391,6 @@ void DrawWatches (int line)
|
|||
PrintTextCursorX( ":", rect2 );
|
||||
|
||||
BYTE nTarget8 = 0;
|
||||
BYTE nValue8 = 0;
|
||||
|
||||
nTarget8 = (unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress);
|
||||
sprintf(sText,"%02X", nTarget8 );
|
||||
|
@ -3631,7 +3696,7 @@ void DrawSubWindow_Data (Update_t bUpdate)
|
|||
|
||||
rect.left = X_CHAR;
|
||||
|
||||
// Seperator
|
||||
// Separator
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
||||
PrintTextCursorX( " | ", rect );
|
||||
|
||||
|
@ -3647,12 +3712,12 @@ void DrawSubWindow_Data (Update_t bUpdate)
|
|||
for (iByte = 0; iByte < nMaxOpcodes; iByte++ )
|
||||
{
|
||||
BYTE nImmediate = (unsigned)*(LPBYTE)(mem + iAddress);
|
||||
int iTextBackground = iBackground;
|
||||
/*int iTextBackground = iBackground;
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
{
|
||||
iTextBackground = BG_INFO_IO_BYTE;
|
||||
}
|
||||
|
||||
*/
|
||||
ColorizeSpecialChar( sImmediate, (BYTE) nImmediate, eView, iBackground );
|
||||
PrintTextCursorX( (LPCSTR) sImmediate, rect );
|
||||
|
||||
|
@ -3784,8 +3849,15 @@ void DrawVideoScannerInfo (int line)
|
|||
PrintText("cycles:", rect);
|
||||
rect.left += nameWidth * nFontWidth;
|
||||
|
||||
UINT cycles = 0;
|
||||
if (g_videoScannerDisplayInfo.cycleMode == VideoScannerDisplayInfo::abs)
|
||||
cycles = (UINT)g_nCumulativeCycles;
|
||||
else if (g_videoScannerDisplayInfo.cycleMode == VideoScannerDisplayInfo::rel)
|
||||
cycles = g_videoScannerDisplayInfo.cycleDelta;
|
||||
else // "part"
|
||||
cycles = (UINT)g_videoScannerDisplayInfo.lastCumulativeCycles - (UINT)g_videoScannerDisplayInfo.savedCumulativeCycles;
|
||||
|
||||
char sValue[10];
|
||||
const UINT cycles = g_videoScannerDisplayInfo.isAbsCycle ? (UINT)g_nCumulativeCycles : g_videoScannerDisplayInfo.cycleDelta;
|
||||
sprintf_s(sValue, sizeof(sValue), "%08X", cycles);
|
||||
PrintText(sValue, rect);
|
||||
}
|
||||
|
@ -3882,7 +3954,6 @@ void DrawSubWindow_Source2 (Update_t bUpdate)
|
|||
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_SOURCE ));
|
||||
|
||||
int iSource = g_iSourceDisplayStart;
|
||||
int nLines = g_nDisasmWinHeight;
|
||||
|
||||
int y = g_nDisasmWinHeight;
|
||||
|
@ -4037,7 +4108,7 @@ void DrawWindowBackground_Info( int g_iWindowThis )
|
|||
{
|
||||
RECT rect;
|
||||
rect.top = 0;
|
||||
rect.left = DISPLAY_DISASM_RIGHT;
|
||||
rect.left = DISPLAY_DISASM_RIGHT;
|
||||
rect.right = DISPLAY_WIDTH;
|
||||
int nTop = GetConsoleTopPixels( g_nConsoleDisplayLines - 1 );
|
||||
rect.bottom = nTop;
|
||||
|
|
|
@ -7,19 +7,9 @@
|
|||
#define DEBUG_APPLE_FONT 0
|
||||
|
||||
// Win32 Debugger Font
|
||||
// 1 = Use Debugger_Font.BMP (7x8)
|
||||
// 0 = Use CHARSET40.bmp (fg & bg colors aren't proper)
|
||||
#define APPLE_FONT_NEW 1
|
||||
|
||||
#if APPLE_FONT_NEW
|
||||
#define APPLE_FONT_BITMAP_PADDED 0
|
||||
#else
|
||||
#define APPLE_FONT_BITMAP_PADDED 1
|
||||
#endif
|
||||
|
||||
enum ConsoleFontSize_e
|
||||
{
|
||||
#if APPLE_FONT_NEW
|
||||
// Grid Alignment
|
||||
CONSOLE_FONT_GRID_X = 7,
|
||||
CONSOLE_FONT_GRID_Y = 8,
|
||||
|
@ -27,23 +17,14 @@
|
|||
// Font Char Width/Height in pixels
|
||||
CONSOLE_FONT_WIDTH = 7,
|
||||
CONSOLE_FONT_HEIGHT = 8,
|
||||
#else
|
||||
CONSOLE_FONT_GRID_X = 8,
|
||||
CONSOLE_FONT_GRID_Y = 8,
|
||||
|
||||
// Font Char Width/Height in pixels
|
||||
CONSOLE_FONT_WIDTH = 7,
|
||||
CONSOLE_FONT_HEIGHT = 8,
|
||||
#endif
|
||||
CONSOLE_FONT_NUM_CHARS_PER_ROW = 16,
|
||||
CONSOLE_FONT_NUM_ROWS = 16,
|
||||
|
||||
CONSOLE_FONT_BITMAP_WIDTH = CONSOLE_FONT_WIDTH * CONSOLE_FONT_NUM_CHARS_PER_ROW, // 112 pixels
|
||||
CONSOLE_FONT_BITMAP_HEIGHT = CONSOLE_FONT_HEIGHT * CONSOLE_FONT_NUM_ROWS, // 128 pixels
|
||||
};
|
||||
|
||||
extern HBRUSH g_hConsoleBrushFG;
|
||||
extern HBRUSH g_hConsoleBrushBG;
|
||||
|
||||
extern HDC g_hConsoleFontDC;
|
||||
extern HBRUSH g_hConsoleFontBrush;
|
||||
extern HBITMAP g_hConsoleFontBitmap;
|
||||
|
||||
enum
|
||||
{
|
||||
DISPLAY_HEIGHT = 384,
|
||||
|
@ -57,7 +38,8 @@
|
|||
void DebuggerSetColorFG( COLORREF nRGB );
|
||||
void DebuggerSetColorBG( COLORREF nRGB, bool bTransparent = false );
|
||||
|
||||
void PrintGlyph ( const int x, const int y, const int iChar );
|
||||
void FillBackground(long left, long top, long right, long bottom);
|
||||
|
||||
int PrintText ( const char * pText, RECT & rRect );
|
||||
int PrintTextCursorX( const char * pText, RECT & rRect );
|
||||
int PrintTextCursorY( const char * pText, RECT & rRect );
|
||||
|
@ -81,13 +63,13 @@
|
|||
void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ );
|
||||
void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ );
|
||||
|
||||
void DrawFlags ( int line, WORD nRegFlags, LPTSTR pFlagNames_);
|
||||
|
||||
//
|
||||
|
||||
extern HDC GetDebuggerMemDC(void);
|
||||
extern void ReleaseDebuggerMemDC(void);
|
||||
extern void StretchBltMemToFrameDC(void);
|
||||
extern HDC GetConsoleFontDC(void);
|
||||
extern void ReleaseConsoleFontDC(void);
|
||||
|
||||
enum DebugVirtualTextScreen_e
|
||||
{
|
||||
|
@ -102,15 +84,17 @@
|
|||
class VideoScannerDisplayInfo
|
||||
{
|
||||
public:
|
||||
VideoScannerDisplayInfo(void) : isDecimal(false), isHorzReal(false), isAbsCycle(false),
|
||||
lastCumulativeCycles(0), cycleDelta(0) {}
|
||||
void Reset(void) { lastCumulativeCycles = g_nCumulativeCycles; cycleDelta = 0; }
|
||||
VideoScannerDisplayInfo(void) : isDecimal(false), isHorzReal(false), cycleMode(rel),
|
||||
lastCumulativeCycles(0), savedCumulativeCycles(0), cycleDelta(0) {}
|
||||
void Reset(void) { lastCumulativeCycles = savedCumulativeCycles = g_nCumulativeCycles; cycleDelta = 0; }
|
||||
|
||||
bool isDecimal;
|
||||
bool isHorzReal;
|
||||
bool isAbsCycle;
|
||||
enum CYCLE_MODE {abs=0, rel, part};
|
||||
CYCLE_MODE cycleMode;
|
||||
|
||||
unsigned __int64 lastCumulativeCycles;
|
||||
unsigned __int64 savedCumulativeCycles;
|
||||
UINT cycleDelta;
|
||||
};
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ bool TestStringCat ( 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); // 2.5.6.25 BUGFIX
|
||||
if (bOverflow)
|
||||
|
@ -390,7 +389,6 @@ bool Colorize( char * pDst, const char * pSrc )
|
|||
const char sExamples[] = "Examples:";
|
||||
const int nExamples = sizeof( sExamples ) - 1;
|
||||
|
||||
int nLen = 0;
|
||||
while (*pSrc)
|
||||
{
|
||||
if (strncmp( sUsage, pSrc, nUsage) == 0)
|
||||
|
@ -1408,11 +1406,17 @@ Update_t CmdHelpSpecific (int nArgs)
|
|||
break;
|
||||
// Cycles
|
||||
case CMD_CYCLES_INFO:
|
||||
ConsoleColorizePrint(sText, " Usage: <abs|rel>");
|
||||
ConsoleColorizePrint(sText, " Usage: <abs|rel|part>");
|
||||
ConsoleBufferPush(" Where:");
|
||||
ConsoleBufferPush(" <abs|rel> changes cycle output to absolute/relative");
|
||||
ConsoleBufferPush(" abs = absolute number of cycles since power-on");
|
||||
ConsoleBufferPush(" rel = number of cycles since last step or breakpoint");
|
||||
ConsoleBufferPush(" part= number of cycles relative to current instruction");
|
||||
break;
|
||||
case CMD_CYCLES_RESET:
|
||||
ConsoleBufferPush(" Use in conjunctioned with 'cycles part' to reset to current instruction");
|
||||
break;
|
||||
// Video-Scanner
|
||||
|
||||
case CMD_VIDEO_SCANNER_INFO:
|
||||
ConsoleColorizePrint(sText, " Usage: <dec|hex|real|apple>");
|
||||
ConsoleBufferPush(" Where:");
|
||||
|
@ -1524,10 +1528,6 @@ Update_t CmdHelpList (int nArgs)
|
|||
|
||||
char sText[ nBuf ] = "";
|
||||
|
||||
int nLenLine = strlen( sText );
|
||||
int y = 0;
|
||||
int nLinesScrolled = 0;
|
||||
|
||||
int nMaxWidth = g_nConsoleDisplayWidth - 1;
|
||||
int iCommand;
|
||||
|
||||
|
@ -1541,7 +1541,6 @@ Update_t CmdHelpList (int nArgs)
|
|||
}
|
||||
std::sort( g_vSortedCommands.begin(), g_vSortedCommands.end(), commands_functor_compare() );
|
||||
}
|
||||
int nCommands = g_vSortedCommands.size();
|
||||
|
||||
int nLen = 0;
|
||||
// Colorize( sText, "Commands: " );
|
||||
|
|
|
@ -418,7 +418,6 @@ void ArgsRawParse ( void )
|
|||
WORD nAddressArg;
|
||||
WORD nAddressSymbol;
|
||||
WORD nAddressValue;
|
||||
int nParamLen = 0;
|
||||
|
||||
while (iArg <= nArg)
|
||||
{
|
||||
|
@ -869,8 +868,6 @@ const TCHAR * FindTokenOrAlphaNumeric ( const TCHAR *pSrc, const TokenTable_t *a
|
|||
//===========================================================================
|
||||
void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDstSize, int nTabStop )
|
||||
{
|
||||
int nLen = _tcslen( pText );
|
||||
|
||||
int TAB_SPACING = 8;
|
||||
int TAB_SPACING_1 = 16;
|
||||
int TAB_SPACING_2 = 21;
|
||||
|
@ -881,7 +878,6 @@ void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDst
|
|||
LPCTSTR pSrc = pText;
|
||||
LPTSTR pDst = pDeTabified_;
|
||||
|
||||
int iTab = 0; // number of tabs seen
|
||||
int nTab = 0; // gap left to next tab
|
||||
int nGap = 0; // actual gap
|
||||
int nCur = 0; // current cursor position
|
||||
|
|
|
@ -377,6 +377,7 @@
|
|||
, CMD_CURSOR_PAGE_DOWN_4K // Down to nearest 4K boundary
|
||||
// Cycles info
|
||||
, CMD_CYCLES_INFO
|
||||
, CMD_CYCLES_RESET
|
||||
// Disassembler Data
|
||||
, CMD_DISASM_DATA
|
||||
, CMD_DISASM_CODE
|
||||
|
@ -666,7 +667,8 @@
|
|||
Update_t CmdCursorPageUp4K (int nArgs);
|
||||
|
||||
// Cycles info
|
||||
Update_t CmdCyclesInfo (int nArgs);
|
||||
Update_t CmdCyclesInfo (int nArgs);
|
||||
Update_t CmdCyclesReset (int nArgs);
|
||||
|
||||
// Disk
|
||||
Update_t CmdDisk (int nArgs);
|
||||
|
|
342
source/Disk.cpp
342
source/Disk.cpp
|
@ -53,17 +53,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
// . if false && I/O ReadWrite($C0EC) && drive is spinning, then advance the track buffer's nibble index (to simulate spinning).
|
||||
// Also m_enhanceDisk is persisted to the save-state, so it's an attribute of the DiskII interface card.
|
||||
|
||||
Disk2InterfaceCard::Disk2InterfaceCard(void) :
|
||||
Card(CT_Disk2)
|
||||
Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
|
||||
Card(CT_Disk2),
|
||||
m_slot(slot)
|
||||
{
|
||||
ResetSwitches();
|
||||
|
||||
m_floppyLatch = 0;
|
||||
m_saveDiskImage = true; // Save the DiskImage name to Registry
|
||||
m_slot = 0;
|
||||
m_diskLastCycle = 0;
|
||||
m_diskLastReadLatchCycle = 0;
|
||||
m_enhanceDisk = true;
|
||||
m_is13SectorFirmware = false;
|
||||
|
||||
ResetLogicStateSequencer();
|
||||
|
||||
|
@ -228,33 +229,6 @@ void Disk2InterfaceCard::CheckSpinning(const ULONG uExecutedCycles)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
Disk_Status_e Disk2InterfaceCard::GetDriveLightStatus(const int drive)
|
||||
{
|
||||
if (IsDriveValid( drive ))
|
||||
{
|
||||
FloppyDrive* pDrive = &m_floppyDrive[ drive ];
|
||||
|
||||
if (pDrive->m_spinning)
|
||||
{
|
||||
if (pDrive->m_disk.m_bWriteProtected)
|
||||
return DISK_STATUS_PROT;
|
||||
|
||||
if (pDrive->m_writelight)
|
||||
return DISK_STATUS_WRITE;
|
||||
else
|
||||
return DISK_STATUS_READ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DISK_STATUS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
return DISK_STATUS_OFF;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
bool Disk2InterfaceCard::IsDriveValid(const int drive)
|
||||
{
|
||||
return (drive >= 0 && drive < NUM_DRIVES);
|
||||
|
@ -282,6 +256,12 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
|
|||
if (ImagePhaseToTrack(pFloppy->m_imagehandle, pDrive->m_phasePrecise, false) >= ImageGetNumTracks(pFloppy->m_imagehandle))
|
||||
{
|
||||
_ASSERT(0); // What can cause this? Add a comment to replace this assert.
|
||||
// Boot with DOS 3.3 Master in D1
|
||||
// Create a blank disk in D2
|
||||
// INIT HELLO,D2
|
||||
// RUN HELLO
|
||||
// F2 to reboot DOS 3.3 Master
|
||||
// RUN HELLO,D2
|
||||
pFloppy->m_trackimagedata = false;
|
||||
return;
|
||||
}
|
||||
|
@ -589,6 +569,31 @@ const std::string & Disk2InterfaceCard::DiskGetFullPathName(const int drive)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
Disk_Status_e Disk2InterfaceCard::GetDriveLightStatus(const int drive)
|
||||
{
|
||||
if (IsDriveValid( drive ))
|
||||
{
|
||||
FloppyDrive* pDrive = &m_floppyDrive[ drive ];
|
||||
|
||||
if (pDrive->m_spinning)
|
||||
{
|
||||
if (pDrive->m_disk.m_bWriteProtected)
|
||||
return DISK_STATUS_PROT;
|
||||
|
||||
if (pDrive->m_writelight)
|
||||
return DISK_STATUS_WRITE;
|
||||
else
|
||||
return DISK_STATUS_READ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DISK_STATUS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
return DISK_STATUS_OFF;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::GetLightStatus(Disk_Status_e *pDisk1Status, Disk_Status_e *pDisk2Status)
|
||||
{
|
||||
if (pDisk1Status)
|
||||
|
@ -613,8 +618,8 @@ ImageError_e Disk2InterfaceCard::InsertDisk(const int drive, LPCTSTR pszImageFil
|
|||
pFloppy->clear();
|
||||
|
||||
const DWORD dwAttributes = GetFileAttributes(pszImageFilename);
|
||||
if(dwAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
pFloppy->m_bWriteProtected = false; // Assume this is a new file to create
|
||||
if (dwAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
pFloppy->m_bWriteProtected = false; // Assume this is a new file to create (so it must be write-enabled to allow it to be formatted)
|
||||
else
|
||||
pFloppy->m_bWriteProtected = bForceWriteProtected ? true : (dwAttributes & FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
|
@ -656,6 +661,9 @@ ImageError_e Disk2InterfaceCard::InsertDisk(const int drive, LPCTSTR pszImageFil
|
|||
{
|
||||
GetImageTitle(pszImageFilename, pFloppy->m_imagename, pFloppy->m_fullname);
|
||||
Video_ResetScreenshotCounter(pFloppy->m_imagename);
|
||||
|
||||
if (g_nAppMode == MODE_LOGO)
|
||||
InitFirmware(GetCxRomPeripheral());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -729,17 +737,6 @@ void Disk2InterfaceCard::NotifyInvalidImage(const int drive, LPCTSTR pszImageFil
|
|||
pszImageFilename);
|
||||
break;
|
||||
|
||||
case eIMAGE_ERROR_UNSUPPORTED_MULTI_ZIP:
|
||||
StringCbPrintf(
|
||||
szBuffer,
|
||||
MAX_PATH + 128,
|
||||
TEXT("Unable to use the file %s\nbecause the ")
|
||||
TEXT("first file (%s) in this multi-zip archive is not recognized.\n")
|
||||
TEXT("Try unzipping and using the disk images directly.\n"),
|
||||
pszImageFilename,
|
||||
m_floppyDrive[drive].m_disk.m_strFilenameInZip.c_str());
|
||||
break;
|
||||
|
||||
case eIMAGE_ERROR_GZ:
|
||||
case eIMAGE_ERROR_ZIP:
|
||||
StringCbPrintf(
|
||||
|
@ -984,24 +981,18 @@ void Disk2InterfaceCard::ResetLogicStateSequencer(void)
|
|||
m_shiftReg = 0;
|
||||
m_latchDelay = 0;
|
||||
m_resetSequencer = true;
|
||||
m_writeStarted = false;
|
||||
m_dbgLatchDelayedCnt = 0;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::UpdateBitStreamPositionAndDiskCycle(const ULONG uExecutedCycles)
|
||||
UINT Disk2InterfaceCard::GetBitCellDelta(const ULONG uExecutedCycles)
|
||||
{
|
||||
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
||||
|
||||
CpuCalcCycles(uExecutedCycles);
|
||||
const UINT bitCellDelta = GetBitCellDelta(ImageGetOptimalBitTiming(floppy.m_imagehandle));
|
||||
UpdateBitStreamPosition(floppy, bitCellDelta);
|
||||
|
||||
m_diskLastCycle = g_nCumulativeCycles;
|
||||
}
|
||||
|
||||
UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
||||
{
|
||||
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
||||
|
||||
const BYTE optimalBitTiming = ImageGetOptimalBitTiming(floppy.m_imagehandle);
|
||||
|
||||
// NB. m_extraCycles is needed to retain accuracy:
|
||||
// . Read latch #1: 0-> 9: cycleDelta= 9, bitCellDelta=2, extraCycles=1
|
||||
// . Read latch #2: 9->20: cycleDelta=11, bitCellDelta=2, extraCycles=3
|
||||
|
@ -1010,9 +1001,9 @@ UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
|||
#if 0
|
||||
if (optimalBitTiming == 32)
|
||||
{
|
||||
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - m_diskLastCycle) + (BYTE) m_extraCycles;
|
||||
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - m_diskLastCycle) + (BYTE) floppy.m_extraCycles;
|
||||
bitCellDelta = cycleDelta / 4; // DIV 4 for 4us per bit-cell
|
||||
m_extraCycles = cycleDelta & 3; // MOD 4 : remainder carried forward for next time
|
||||
floppy.m_extraCycles = cycleDelta & 3; // MOD 4 : remainder carried forward for next time
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1022,13 +1013,17 @@ UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
|||
bitCellDelta = (UINT) floor( cycleDelta / bitTime );
|
||||
floppy.m_extraCycles = (double)cycleDelta - ((double)bitCellDelta * bitTime);
|
||||
}
|
||||
|
||||
// NB. actual m_diskLastCycle for the last bitCell is minus floppy.m_extraCycles
|
||||
// - but don't need this value; and it's correctly accounted for in this function.
|
||||
m_diskLastCycle = g_nCumulativeCycles;
|
||||
|
||||
return bitCellDelta;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG bitCellDelta)
|
||||
{
|
||||
_ASSERT(floppy.m_bitCount); // Should never happen - ReadTrack() will handle this
|
||||
if (floppy.m_bitCount == 0)
|
||||
if (floppy.m_bitCount == 0) // Repro: Boot DOS3.3(WOZ), eject+reinsert disk, CALL-151, C0E9 N C0ED ; motor-on & LoadWriteProtect()
|
||||
return;
|
||||
|
||||
floppy.m_bitOffset += bitCellDelta;
|
||||
|
@ -1036,6 +1031,8 @@ void Disk2InterfaceCard::UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG
|
|||
floppy.m_bitOffset %= floppy.m_bitCount;
|
||||
|
||||
UpdateBitStreamOffsets(floppy);
|
||||
|
||||
m_resetSequencer = false;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
|
||||
|
@ -1045,8 +1042,28 @@ void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
|
|||
floppy.m_bitMask = 1 << remainder;
|
||||
}
|
||||
|
||||
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles)
|
||||
__forceinline void Disk2InterfaceCard::IncBitStream(FloppyDisk& floppy)
|
||||
{
|
||||
floppy.m_bitMask >>= 1;
|
||||
if (!floppy.m_bitMask)
|
||||
{
|
||||
floppy.m_bitMask = 1 << 7;
|
||||
floppy.m_byte++;
|
||||
}
|
||||
|
||||
floppy.m_bitOffset++;
|
||||
if (floppy.m_bitOffset == floppy.m_bitCount)
|
||||
{
|
||||
floppy.m_bitMask = 1 << 7;
|
||||
floppy.m_bitOffset = 0;
|
||||
floppy.m_byte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles)
|
||||
{
|
||||
_ASSERT(m_seqFunc.function != dataShiftWrite);
|
||||
|
||||
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||
FloppyDisk& floppy = drive.m_disk;
|
||||
|
||||
|
@ -1067,14 +1084,11 @@ void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYT
|
|||
if (!drive.m_spinning) // GH#599
|
||||
return;
|
||||
|
||||
CpuCalcCycles(uExecutedCycles);
|
||||
|
||||
// Skipping forward a large amount of bitcells means the bitstream will very likely be out-of-sync.
|
||||
// The first 1-bit will produce a latch nibble, and this 1-bit is unlikely to be the nibble's high bit.
|
||||
// So we need to ensure we run enough bits through the sequencer to re-sync.
|
||||
// NB. For Planetfall 13 bitcells(NG) / 14 bitcells(OK)
|
||||
const UINT significantBitCells = 50; // 5x 10-bit sync FF nibbles
|
||||
UINT bitCellDelta = GetBitCellDelta(ImageGetOptimalBitTiming(floppy.m_imagehandle));
|
||||
UINT bitCellDelta = GetBitCellDelta(uExecutedCycles);
|
||||
|
||||
UINT bitCellRemainder;
|
||||
if (bitCellDelta <= significantBitCells)
|
||||
|
@ -1092,20 +1106,21 @@ void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYT
|
|||
drive.m_headWindow = 0;
|
||||
}
|
||||
|
||||
// NB. actual m_diskLastCycle for the last bitCell is minus floppy.m_extraCycles
|
||||
// - but don't need this value; and it's correctly accounted for in GetBitCellDelta()
|
||||
m_diskLastCycle = g_nCumulativeCycles;
|
||||
|
||||
if (!bWrite)
|
||||
{
|
||||
if (m_seqFunc.function != readSequencing)
|
||||
{
|
||||
_ASSERT(m_seqFunc.function == checkWriteProtAndInitWrite);
|
||||
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||
return;
|
||||
}
|
||||
|
||||
DataLatchReadWOZ(pc, addr, bitCellRemainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataLatchWriteWOZ(pc, addr, d, bitCellRemainder);
|
||||
_ASSERT(m_seqFunc.function == dataLoadWrite);
|
||||
DataLoadWriteWOZ(pc, addr, bitCellRemainder);
|
||||
}
|
||||
|
||||
// Show track status (GH#201) - NB. Prevent flooding of forcing UI to redraw!!!
|
||||
|
@ -1147,20 +1162,7 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||
BYTE outputBit = (drive.m_headWindow & 0xf) ? (drive.m_headWindow >> 1) & 1
|
||||
: (rand() < (RAND_MAX / 10 * 3)) ? 1 : 0; // ~30% chance of a 1 bit (Ref: WOZ-2.0)
|
||||
|
||||
floppy.m_bitMask >>= 1;
|
||||
if (!floppy.m_bitMask)
|
||||
{
|
||||
floppy.m_bitMask = 1 << 7;
|
||||
floppy.m_byte++;
|
||||
}
|
||||
|
||||
floppy.m_bitOffset++;
|
||||
if (floppy.m_bitOffset == floppy.m_bitCount)
|
||||
{
|
||||
floppy.m_bitMask = 1 << 7;
|
||||
floppy.m_bitOffset = 0;
|
||||
floppy.m_byte = 0;
|
||||
}
|
||||
IncBitStream(floppy);
|
||||
|
||||
if (m_resetSequencer)
|
||||
{
|
||||
|
@ -1238,17 +1240,64 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||
#endif
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::DataLatchWriteWOZ(WORD pc, WORD addr, BYTE d, UINT bitCellRemainder)
|
||||
void Disk2InterfaceCard::DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder)
|
||||
{
|
||||
_ASSERT(m_seqFunc.writeMode);
|
||||
_ASSERT(m_seqFunc.function == dataLoadWrite);
|
||||
|
||||
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||
FloppyDisk& floppy = drive.m_disk;
|
||||
|
||||
if (!floppy.m_bWriteProtected)
|
||||
if (floppy.m_bWriteProtected)
|
||||
{
|
||||
//TODO
|
||||
_ASSERT(0); // Must be a bug in the 6502 code for this to occur!
|
||||
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_writeStarted)
|
||||
UpdateBitStreamPosition(floppy, bitCellRemainder); // skip over bitCells before switching to write mode
|
||||
|
||||
m_writeStarted = true;
|
||||
#if LOG_DISK_WOZ_LOADWRITE
|
||||
LOG_DISK("load shiftReg with %02X (was: %02X)\n", m_floppyLatch, m_shiftReg);
|
||||
#endif
|
||||
m_shiftReg = m_floppyLatch;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles)
|
||||
{
|
||||
_ASSERT(m_seqFunc.function == dataShiftWrite);
|
||||
|
||||
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||
FloppyDisk& floppy = drive.m_disk;
|
||||
|
||||
const UINT bitCellRemainder = GetBitCellDelta(uExecutedCycles);
|
||||
|
||||
if (floppy.m_bWriteProtected)
|
||||
{
|
||||
_ASSERT(0); // Must be a bug in the 6502 code for this to occur!
|
||||
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||
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
|
||||
|
||||
for (UINT i = 0; i < bitCellRemainder; i++)
|
||||
{
|
||||
BYTE outputBit = m_shiftReg & 0x80;
|
||||
m_shiftReg <<= 1;
|
||||
|
||||
BYTE n = floppy.m_trackimage[floppy.m_byte];
|
||||
n &= ~floppy.m_bitMask;
|
||||
if (outputBit) n |= floppy.m_bitMask;
|
||||
floppy.m_trackimage[floppy.m_byte] = n;
|
||||
|
||||
IncBitStream(floppy);
|
||||
}
|
||||
|
||||
floppy.m_trackimagedirty = true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1316,19 +1365,18 @@ void Disk2InterfaceCard::DumpSectorWOZ(FloppyDisk floppy) // pass a copy of m_fl
|
|||
// Dump nibbles from current position bitstream wraps to same position
|
||||
void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_floppy
|
||||
{
|
||||
#ifdef LOG_DISK_NIBBLES_READ
|
||||
FormatTrack formatTrack;
|
||||
#endif
|
||||
FormatTrack formatTrack(true);
|
||||
|
||||
BYTE shiftReg = 0;
|
||||
UINT zeroCount = 0;
|
||||
UINT nibbleCount = 0;
|
||||
|
||||
floppy.m_bitMask = 1 << 7;
|
||||
floppy.m_bitOffset = 0;
|
||||
floppy.m_byte = 0;
|
||||
const UINT startBitOffset = 0;
|
||||
floppy.m_bitOffset = startBitOffset;
|
||||
|
||||
const UINT startBitOffset = floppy.m_bitOffset;
|
||||
floppy.m_byte = floppy.m_bitOffset / 8;
|
||||
const UINT remainder = 7 - (floppy.m_bitOffset & 7);
|
||||
floppy.m_bitMask = 1 << remainder;
|
||||
|
||||
bool newLine = true;
|
||||
|
||||
|
@ -1381,19 +1429,36 @@ void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_flo
|
|||
if (zeroCount == 0) StringCbPrintf(str, sizeof(str), " %02X", shiftReg);
|
||||
else StringCbPrintf(str, sizeof(str), "(%c)%02X", syncBits, shiftReg);
|
||||
OutputDebugString(str);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef LOG_DISK_NIBBLES_READ
|
||||
formatTrack.DecodeLatchNibbleRead(shiftReg);
|
||||
#endif
|
||||
|
||||
shiftReg = 0;
|
||||
zeroCount = 0;
|
||||
}
|
||||
|
||||
// Output any remaining "read D5AAxx detected"
|
||||
if (nibbleCount % 32)
|
||||
{
|
||||
std::string strReadDetected = formatTrack.GetReadD5AAxxDetectedString();
|
||||
if (!strReadDetected.empty())
|
||||
{
|
||||
OutputDebugString("\t; ");
|
||||
OutputDebugString(strReadDetected.c_str());
|
||||
}
|
||||
OutputDebugString("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1421,6 +1486,9 @@ void Disk2InterfaceCard::Reset(const bool bIsPowerCycle)
|
|||
|
||||
FrameRefreshStatus(DRAW_LEDS, false);
|
||||
}
|
||||
|
||||
InitFirmware(GetCxRomPeripheral());
|
||||
FrameRefreshStatus(DRAW_TITLE, false);
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::ResetSwitches(void)
|
||||
|
@ -1485,7 +1553,9 @@ bool Disk2InterfaceCard::UserSelectNewDiskImage(const int drive, LPCSTR pszFilen
|
|||
|
||||
void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG uExecutedCycles)
|
||||
{
|
||||
// NB. m_seqFunc.function == checkWriteProtAndInitWrite or shiftWrite (both OK)
|
||||
// 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)
|
||||
|
@ -1500,20 +1570,28 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE
|
|||
// 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)
|
||||
// . A read or write will shift 'write protect' in QA.
|
||||
if (m_floppyDrive[m_currDrive].m_disk.m_bWriteProtected)
|
||||
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
||||
if (floppy.m_bWriteProtected)
|
||||
m_floppyLatch |= 0x80;
|
||||
else
|
||||
m_floppyLatch &= 0x7F;
|
||||
|
||||
if (ImageIsWOZ(m_floppyDrive[m_currDrive].m_disk.m_imagehandle))
|
||||
if (m_writeStarted) // Prevent ResetLogicStateSequencer() from resetting m_writeStarted
|
||||
return;
|
||||
|
||||
if (ImageIsWOZ(floppy.m_imagehandle))
|
||||
{
|
||||
#if LOG_DISK_NIBBLES_READ
|
||||
CpuCalcCycles(uExecutedCycles);
|
||||
LOG_DISK("%08X: reset LSS: ~PC=%04X\r\n", (UINT32)g_nCumulativeCycles, regs.pc);
|
||||
#endif
|
||||
|
||||
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)
|
||||
// m_latchDelay = 7; // TODO: Treat like a regular $C0EC latch load?
|
||||
UpdateBitStreamPositionAndDiskCycle(uExecutedCycles); // Fix E7-copy protection
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1639,28 +1717,51 @@ bool Disk2InterfaceCard::DriveSwap(void)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
// TODO: LoadRom_Disk_Floppy()
|
||||
void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
|
||||
bool Disk2InterfaceCard::GetFirmware(LPCSTR lpName, BYTE* pDst)
|
||||
{
|
||||
const UINT DISK2_FW_SIZE = APPLE_SLOT_SIZE;
|
||||
|
||||
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_DISK2_FW), "FIRMWARE");
|
||||
HRSRC hResInfo = FindResource(NULL, lpName, "FIRMWARE");
|
||||
if(hResInfo == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
DWORD dwResSize = SizeofResource(NULL, hResInfo);
|
||||
if(dwResSize != DISK2_FW_SIZE)
|
||||
return;
|
||||
return false;
|
||||
|
||||
HGLOBAL hResData = LoadResource(NULL, hResInfo);
|
||||
if(hResData == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
BYTE* pData = (BYTE*) LockResource(hResData); // NB. Don't need to unlock resource
|
||||
if(pData == NULL)
|
||||
if (!pData)
|
||||
return false;
|
||||
|
||||
memcpy(pDst, pData, DISK2_FW_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::InitFirmware(LPBYTE pCxRomPeripheral)
|
||||
{
|
||||
if (pCxRomPeripheral == NULL)
|
||||
return;
|
||||
|
||||
memcpy(pCxRomPeripheral + uSlot*APPLE_SLOT_SIZE, pData, DISK2_FW_SIZE);
|
||||
ImageInfo* pImage = m_floppyDrive[DRIVE_1].m_disk.m_imagehandle;
|
||||
|
||||
m_is13SectorFirmware = ImageIsBootSectorFormatSector13(pImage);
|
||||
|
||||
if (m_is13SectorFirmware)
|
||||
memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, m_13SectorFirmware, DISK2_FW_SIZE);
|
||||
else
|
||||
memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, m_16SectorFirmware, DISK2_FW_SIZE);
|
||||
}
|
||||
|
||||
// TODO: LoadRom_Disk_Floppy()
|
||||
void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
|
||||
{
|
||||
bool res = GetFirmware(MAKEINTRESOURCE(IDR_DISK2_13SECTOR_FW), m_13SectorFirmware);
|
||||
_ASSERT(res);
|
||||
|
||||
res = GetFirmware(MAKEINTRESOURCE(IDR_DISK2_16SECTOR_FW), m_16SectorFirmware);
|
||||
_ASSERT(res);
|
||||
|
||||
// Note: We used to disable the track stepping delay in the Disk II controller firmware by
|
||||
// patching $C64C with $A9,$00,$EA. Now not doing this since:
|
||||
|
@ -1669,9 +1770,12 @@ void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
|
|||
// . Patching the firmware breaks the ADC checksum used by "The CIA Files" (Tricky Dick)
|
||||
// . In this case we can patch to compensate for an ADC or EOR checksum but not both (nickw)
|
||||
|
||||
_ASSERT(m_slot == uSlot);
|
||||
RegisterIoHandler(uSlot, &Disk2InterfaceCard::IORead, &Disk2InterfaceCard::IOWrite, NULL, NULL, this, NULL);
|
||||
|
||||
m_slot = uSlot;
|
||||
|
||||
InitFirmware(pCxRomPeripheral);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1688,6 +1792,9 @@ void Disk2InterfaceCard::SetSequencerFunction(WORD addr)
|
|||
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)
|
||||
}
|
||||
|
||||
if (!m_seqFunc.writeMode)
|
||||
m_writeStarted = false;
|
||||
}
|
||||
|
||||
BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
|
||||
|
@ -1698,6 +1805,9 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
||||
bool isWOZ = ImageIsWOZ(pImage);
|
||||
|
||||
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);
|
||||
|
||||
switch (addr & 0xF)
|
||||
|
@ -1723,8 +1833,8 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||
// only even addresses return the latch (UTAIIe Table 9.1)
|
||||
if (!(addr & 1))
|
||||
{
|
||||
if (isWOZ)
|
||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, d, nExecutedCycles);
|
||||
if (isWOZ && pCard->m_seqFunc.function != dataShiftWrite)
|
||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, nExecutedCycles);
|
||||
|
||||
return pCard->m_floppyLatch;
|
||||
}
|
||||
|
@ -1740,6 +1850,9 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
||||
bool isWOZ = ImageIsWOZ(pImage);
|
||||
|
||||
if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite)
|
||||
pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write
|
||||
|
||||
pCard->SetSequencerFunction(addr);
|
||||
|
||||
switch (addr & 0xF)
|
||||
|
@ -1763,13 +1876,12 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||
}
|
||||
|
||||
// any address writes the latch via sequencer LD command (74LS323 datasheet)
|
||||
// if (pCard->m_seqFunc.writeMode /* && m_seqFunc.loadMode */)
|
||||
if (pCard->m_seqFunc.function == dataLoadWrite)
|
||||
{
|
||||
pCard->m_floppyLatch = d;
|
||||
|
||||
if (isWOZ)
|
||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, d, nExecutedCycles);
|
||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, nExecutedCycles);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
class Disk2InterfaceCard : public Card
|
||||
{
|
||||
public:
|
||||
Disk2InterfaceCard(void);
|
||||
Disk2InterfaceCard(UINT slot);
|
||||
virtual ~Disk2InterfaceCard(void);
|
||||
|
||||
virtual void Init(void) {};
|
||||
|
@ -144,6 +144,7 @@ public:
|
|||
void NotifyInvalidImage(const int drive, LPCTSTR pszImageFilename, const ImageError_e Error);
|
||||
bool GetProtect(const int drive);
|
||||
void SetProtect(const int drive, const bool bWriteProtect);
|
||||
UINT GetCurrentFirmware(void) { return m_is13SectorFirmware ? 13 : 16; }
|
||||
int GetCurrentDrive(void);
|
||||
int GetCurrentTrack(void);
|
||||
float GetCurrentPhase(void);
|
||||
|
@ -185,15 +186,18 @@ private:
|
|||
void WriteTrack(const int drive);
|
||||
const std::string & DiskGetFullPathName(const int drive);
|
||||
void ResetLogicStateSequencer(void);
|
||||
void UpdateBitStreamPositionAndDiskCycle(const ULONG uExecutedCycles);
|
||||
UINT GetBitCellDelta(const BYTE optimalBitTiming);
|
||||
UINT GetBitCellDelta(const ULONG uExecutedCycles);
|
||||
void UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG bitCellDelta);
|
||||
void UpdateBitStreamOffsets(FloppyDisk& floppy);
|
||||
__forceinline void IncBitStream(FloppyDisk& floppy);
|
||||
void DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
||||
void DataLatchWriteWOZ(WORD pc, WORD addr, BYTE d, UINT bitCellRemainder);
|
||||
void DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
||||
void DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles);
|
||||
void SetSequencerFunction(WORD addr);
|
||||
void DumpSectorWOZ(FloppyDisk floppy);
|
||||
void DumpTrackWOZ(FloppyDisk floppy);
|
||||
bool GetFirmware(LPCSTR lpName, BYTE* pDst);
|
||||
void InitFirmware(LPBYTE pCxRomPeripheral);
|
||||
|
||||
void SaveSnapshotFloppy(YamlSaveHelper& yamlSaveHelper, UINT unit);
|
||||
void SaveSnapshotDriveUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
|
||||
|
@ -206,7 +210,7 @@ private:
|
|||
void __stdcall ControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
||||
void __stdcall Enable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
||||
void __stdcall ReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||
void __stdcall DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||
void __stdcall DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles);
|
||||
void __stdcall LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG);
|
||||
void __stdcall SetReadMode(WORD, WORD, BYTE, BYTE, ULONG);
|
||||
void __stdcall SetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles);
|
||||
|
@ -217,6 +221,11 @@ private:
|
|||
|
||||
//
|
||||
|
||||
static const UINT DISK2_FW_SIZE = 256;
|
||||
BYTE m_13SectorFirmware[DISK2_FW_SIZE];
|
||||
BYTE m_16SectorFirmware[DISK2_FW_SIZE];
|
||||
bool m_is13SectorFirmware;
|
||||
|
||||
WORD m_currDrive;
|
||||
FloppyDrive m_floppyDrive[NUM_DRIVES];
|
||||
BYTE m_floppyLatch;
|
||||
|
@ -240,8 +249,9 @@ private:
|
|||
BYTE m_shiftReg;
|
||||
int m_latchDelay;
|
||||
bool m_resetSequencer;
|
||||
bool m_writeStarted;
|
||||
|
||||
enum SEQFUNC {readSequencing=0, checkWriteProtAndInitWrite, dataShiftWrite, dataLoadWrite}; // UTAIIe 9-14
|
||||
enum SEQFUNC {readSequencing=0, dataShiftWrite, checkWriteProtAndInitWrite, dataLoadWrite}; // UTAIIe 9-14
|
||||
union SEQUENCER_FUNCTION
|
||||
{
|
||||
struct
|
||||
|
|
|
@ -118,3 +118,17 @@ void Disk2CardManager::Destroy(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Disk2CardManager::IsAnyFirmware13Sector(void)
|
||||
{
|
||||
for (UINT i = 0; i < NUM_SLOTS; i++)
|
||||
{
|
||||
if (g_CardMgr.QuerySlot(i) == CT_Disk2)
|
||||
{
|
||||
// If any Disk2 card has 13-sector firmware then return true
|
||||
if (dynamic_cast<Disk2InterfaceCard&>(g_CardMgr.GetRef(i)).GetCurrentFirmware() == 13)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,4 +13,5 @@ public:
|
|||
void SetEnhanceDisk(bool enhanceDisk);
|
||||
void LoadLastDiskImage(void);
|
||||
void Destroy(void);
|
||||
bool IsAnyFirmware13Sector(void);
|
||||
};
|
||||
|
|
|
@ -268,7 +268,13 @@ void FormatTrack::DecodeLatchNibble(BYTE floppylatch, bool bIsWrite, bool bIsSyn
|
|||
if (!bIsWrite)
|
||||
{
|
||||
BYTE addrPrologue = m_bAddressPrologueIsDOS3_2 ? (BYTE)kADDR_PROLOGUE_DOS3_2 : (BYTE)kADDR_PROLOGUE_DOS3_3;
|
||||
LOG_DISK("read D5AA%02X detected - Vol:%02X Trk:%02X Sec:%02X Chk:%02X %s\r\n", addrPrologue, m_VolTrkSecChk[0], m_VolTrkSecChk[1], m_VolTrkSecChk[2], m_VolTrkSecChk[3], chk?"":"(bad)");
|
||||
char str[100];
|
||||
sprintf_s(str, sizeof(str), "read D5AA%02X detected - Vol:%02X Trk:%02X Sec:%02X Chk:%02X %s", addrPrologue, m_VolTrkSecChk[0], m_VolTrkSecChk[1], m_VolTrkSecChk[2], m_VolTrkSecChk[3], chk?"":"(bad)");
|
||||
m_strReadD5AAxxDetected = str;
|
||||
if (!m_bSuppressReadD5AAxxDetected)
|
||||
{
|
||||
LOG_DISK("%s\r\n", str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if LOG_DISK_NIBBLES_WRITE
|
||||
|
|
|
@ -26,8 +26,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
class FormatTrack // Monitor for formatting of track
|
||||
{
|
||||
public:
|
||||
FormatTrack(void)
|
||||
FormatTrack(bool bSuppressOutput=false)
|
||||
{
|
||||
m_bSuppressReadD5AAxxDetected = bSuppressOutput;
|
||||
Reset();
|
||||
};
|
||||
|
||||
|
@ -39,6 +40,7 @@ public:
|
|||
void DriveSwitchedToWriteMode(UINT uTrackIndex);
|
||||
void DecodeLatchNibbleRead(BYTE floppylatch);
|
||||
void DecodeLatchNibbleWrite(BYTE floppylatch, UINT uSpinNibbleCount, const class FloppyDisk* const pFloppy, bool bIsSyncFF);
|
||||
std::string GetReadD5AAxxDetectedString(void) { std::string tmp = m_strReadD5AAxxDetected; m_strReadD5AAxxDetected = ""; return tmp; }
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void LoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
|
@ -60,6 +62,9 @@ private:
|
|||
BYTE m_VolTrkSecChk4and4[8];
|
||||
UINT m_4and4idx;
|
||||
|
||||
std::string m_strReadD5AAxxDetected;
|
||||
bool m_bSuppressReadD5AAxxDetected;
|
||||
|
||||
#if LOG_DISK_NIBBLES_WRITE_TRACK_GAPS
|
||||
UINT m_DbgGap1Size;
|
||||
UINT m_DbgGap2Size;
|
||||
|
|
|
@ -63,7 +63,7 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||
ImageError_e Err = pImageInfo->pImageHelper->Open(pszImageFilename.c_str(), pImageInfo, bCreateIfNecessary, strFilenameInZip);
|
||||
if (Err != eIMAGE_ERROR_NONE)
|
||||
{
|
||||
ImageClose(*ppImageInfo, true);
|
||||
ImageClose(*ppImageInfo);
|
||||
*ppImageInfo = NULL;
|
||||
return Err;
|
||||
}
|
||||
|
@ -81,10 +81,7 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||
if (!bExpectFloppy)
|
||||
return eIMAGE_ERROR_UNSUPPORTED;
|
||||
|
||||
pImageInfo->uNumTracks = sg_DiskImageHelper.GetNumTracksInImage(pImageInfo->pImageType);
|
||||
|
||||
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
|
||||
pImageInfo->ValidTrack[uTrack] = (pImageInfo->uImageSize > 0) ? 1 : 0;
|
||||
_ASSERT(pImageInfo->uNumTracks);
|
||||
|
||||
*pWriteProtected = pImageInfo->bWriteProtected;
|
||||
|
||||
|
@ -93,25 +90,9 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void ImageClose(ImageInfo* const pImageInfo, const bool bOpenError /*=false*/)
|
||||
void ImageClose(ImageInfo* const pImageInfo)
|
||||
{
|
||||
bool bDeleteFile = false;
|
||||
|
||||
if (!bOpenError)
|
||||
{
|
||||
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
|
||||
{
|
||||
if (!pImageInfo->ValidTrack[uTrack])
|
||||
{
|
||||
// TODO: Comment using info from this URL:
|
||||
// http://groups.google.de/group/comp.emulators.apple2/msg/7a1b9317e7905152
|
||||
bDeleteFile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pImageInfo->pImageHelper->Close(pImageInfo, bDeleteFile);
|
||||
pImageInfo->pImageHelper->Close(pImageInfo);
|
||||
|
||||
delete pImageInfo;
|
||||
}
|
||||
|
@ -162,7 +143,7 @@ void ImageReadTrack( ImageInfo* const pImageInfo,
|
|||
|
||||
const UINT track = pImageInfo->pImageType->PhaseToTrack(phase);
|
||||
|
||||
if (pImageInfo->pImageType->AllowRW() && pImageInfo->ValidTrack[track])
|
||||
if (pImageInfo->pImageType->AllowRW())
|
||||
{
|
||||
pImageInfo->pImageType->Read(pImageInfo, phase, pTrackImageBuffer, pNibbles, pBitCount, enhanceDisk);
|
||||
}
|
||||
|
@ -190,7 +171,14 @@ void ImageWriteTrack( ImageInfo* const pImageInfo,
|
|||
if (pImageInfo->pImageType->AllowRW() && !pImageInfo->bWriteProtected)
|
||||
{
|
||||
pImageInfo->pImageType->Write(pImageInfo, phase, pTrackImageBuffer, nNibbles);
|
||||
pImageInfo->ValidTrack[track] = 1;
|
||||
|
||||
eImageType imageType = pImageInfo->pImageType->GetType();
|
||||
if (imageType == eImageWOZ1 || imageType == eImageWOZ2)
|
||||
{
|
||||
DWORD dummy;
|
||||
bool res = sg_DiskImageHelper.WOZUpdateInfo(pImageInfo, dummy);
|
||||
_ASSERT(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +222,7 @@ bool ImageIsWriteProtected(ImageInfo* const pImageInfo)
|
|||
|
||||
bool ImageIsMultiFileZip(ImageInfo* const pImageInfo)
|
||||
{
|
||||
return pImageInfo ? (pImageInfo->uNumEntriesInZip > 1) : false;
|
||||
return pImageInfo ? (pImageInfo->uNumValidImagesInZip > 1) : false;
|
||||
}
|
||||
|
||||
const std::string & ImageGetPathname(ImageInfo* const pImageInfo)
|
||||
|
@ -258,6 +246,11 @@ BYTE ImageGetOptimalBitTiming(ImageInfo* const pImageInfo)
|
|||
return pImageInfo ? pImageInfo->optimalBitTiming : 32;
|
||||
}
|
||||
|
||||
bool ImageIsBootSectorFormatSector13(ImageInfo* const pImageInfo)
|
||||
{
|
||||
return pImageInfo ? pImageInfo->bootSectorFormat == CWOZHelper::bootSector13 : false;
|
||||
}
|
||||
|
||||
UINT ImagePhaseToTrack(ImageInfo* const pImageInfo, const float phase, const bool limit/*=true*/)
|
||||
{
|
||||
if (!pImageInfo)
|
||||
|
|
|
@ -51,7 +51,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
eIMAGE_ERROR_GZ,
|
||||
eIMAGE_ERROR_ZIP,
|
||||
eIMAGE_ERROR_REJECTED_MULTI_ZIP,
|
||||
eIMAGE_ERROR_UNSUPPORTED_MULTI_ZIP,
|
||||
eIMAGE_ERROR_UNABLE_TO_OPEN,
|
||||
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
|
||||
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
|
||||
|
@ -66,7 +65,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
struct ImageInfo;
|
||||
|
||||
ImageError_e ImageOpen(const std::string & pszImageFilename, ImageInfo** ppImageInfo, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
|
||||
void ImageClose(ImageInfo* const pImageInfo, const bool bOpenError=false);
|
||||
void ImageClose(ImageInfo* const pImageInfo);
|
||||
BOOL ImageBoot(ImageInfo* const pImageInfo);
|
||||
void ImageDestroy(void);
|
||||
void ImageInitialize(void);
|
||||
|
@ -85,5 +84,6 @@ bool ImageIsWOZ(ImageInfo* const pImageInfo);
|
|||
BYTE ImageGetOptimalBitTiming(ImageInfo* const pImageInfo);
|
||||
UINT ImagePhaseToTrack(ImageInfo* const pImageInfo, const float phase, const bool limit=true);
|
||||
UINT ImageGetMaxNibblesPerTrack(ImageInfo* const pImageInfo);
|
||||
bool ImageIsBootSectorFormatSector13(ImageInfo* const pImageInfo);
|
||||
|
||||
void GetImageTitle(LPCTSTR pPathname, std::string & pImageName, std::string & pFullName);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,12 +31,13 @@ struct ImageInfo
|
|||
std::string szFilenameInZip;
|
||||
zip_fileinfo zipFileInfo;
|
||||
UINT uNumEntriesInZip;
|
||||
UINT uNumValidImagesInZip;
|
||||
// Floppy only
|
||||
BYTE ValidTrack[TRACKS_MAX];
|
||||
UINT uNumTracks;
|
||||
BYTE* pImageBuffer;
|
||||
BYTE* pTrackMap; // WOZ only
|
||||
BYTE* pWOZTrackMap; // WOZ only (points into pImageBuffer)
|
||||
BYTE optimalBitTiming; // WOZ only
|
||||
BYTE bootSectorFormat; // WOZ only
|
||||
UINT maxNibblesPerTrack;
|
||||
|
||||
ImageInfo();
|
||||
|
@ -73,6 +74,7 @@ public:
|
|||
virtual const char* GetCreateExtensions(void) = 0;
|
||||
virtual const char* GetRejectExtensions(void) = 0;
|
||||
|
||||
bool WriteImageHeader(ImageInfo* pImageInfo, LPBYTE pHdr, const UINT hdrSize);
|
||||
void SetVolumeNumber(const BYTE uVolumeNumber) { m_uVolumeNumber = uVolumeNumber; }
|
||||
bool IsValidImageSize(const DWORD uImageSize);
|
||||
|
||||
|
@ -88,6 +90,7 @@ protected:
|
|||
bool WriteTrack(ImageInfo* pImageInfo, const int nTrack, LPBYTE pTrackBuffer, const UINT uTrackSize);
|
||||
bool ReadBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
||||
bool WriteBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
||||
bool WriteImageData(ImageInfo* pImageInfo, LPBYTE pSrcBuffer, const UINT uSrcSize, const long offset);
|
||||
|
||||
LPBYTE Code62(int sector);
|
||||
void Decode62(LPBYTE imageptr);
|
||||
|
@ -134,6 +137,10 @@ private:
|
|||
#pragma pack(push)
|
||||
#pragma pack(1) // Ensure Header2IMG & WOZ structs are packed
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4200) // Allow zero-sized array in struct
|
||||
|
||||
|
||||
class C2IMGHelper : public CHdrHelper
|
||||
{
|
||||
public:
|
||||
|
@ -200,10 +207,16 @@ public:
|
|||
virtual ~CWOZHelper(void) {}
|
||||
virtual eDetectResult DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD& dwOffset) { _ASSERT(0); return eMismatch; }
|
||||
virtual UINT GetMaxHdrSize(void) { return sizeof(WOZHeader); }
|
||||
eDetectResult ProcessChunks(const LPBYTE pImage, const DWORD dwImageSize, DWORD& dwOffset, BYTE*& pTrackMap);
|
||||
eDetectResult ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset);
|
||||
bool IsWriteProtected(void) { return m_pInfo->v1.writeProtected == 1; }
|
||||
BYTE GetOptimalBitTiming(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->optimalBitTiming : CWOZHelper::InfoChunkv2::optimalBitTiming5_25; }
|
||||
UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->largestTrack*CWOZHelper::BLOCK_SIZE : CWOZHelper::WOZ1_TRACK_SIZE; }
|
||||
BYTE GetOptimalBitTiming(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->optimalBitTiming : InfoChunkv2::optimalBitTiming5_25; }
|
||||
UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->largestTrack*CWOZHelper::BLOCK_SIZE : WOZ1_TRACK_SIZE; }
|
||||
BYTE GetBootSectorFormat(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->bootSectorFormat : bootUnknown; }
|
||||
void InvalidateInfo(void) { m_pInfo = NULL; }
|
||||
BYTE* CreateEmptyDisk(DWORD& size);
|
||||
#if _DEBUG
|
||||
BYTE* CreateEmptyDiskv1(DWORD& size);
|
||||
#endif
|
||||
|
||||
static const UINT32 ID1_WOZ1 = '1ZOW'; // 'WOZ1'
|
||||
static const UINT32 ID1_WOZ2 = '2ZOW'; // 'WOZ2'
|
||||
|
@ -217,10 +230,29 @@ public:
|
|||
};
|
||||
|
||||
static const UINT32 MAX_TRACKS_5_25 = 40;
|
||||
static const UINT32 MAX_QUARTER_TRACKS_5_25 = MAX_TRACKS_5_25 * 4;
|
||||
static const UINT32 WOZ1_TRACK_SIZE = 6656; // 0x1A00
|
||||
static const UINT32 WOZ1_TRK_OFFSET = 6646;
|
||||
static const UINT32 EMPTY_TRACK_SIZE = 6400;
|
||||
static const UINT32 EMPTY_TRACK_SIZE = 6400; // $C.5 blocks
|
||||
static const UINT32 BLOCK_SIZE = 512;
|
||||
static const BYTE TMAP_TRACK_EMPTY = 0xFF;
|
||||
static const UINT16 TRK_DEFAULT_BLOCK_COUNT_5_25 = 13; // $D is default for TRKv2.blockCount
|
||||
|
||||
static const BYTE bootUnknown = 0;
|
||||
static const BYTE bootSector16 = 1;
|
||||
static const BYTE bootSector13 = 2;
|
||||
static const BYTE bootSectorBoth = 3;
|
||||
|
||||
struct WOZChunkHdr
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 size;
|
||||
};
|
||||
|
||||
struct Tmap
|
||||
{
|
||||
BYTE tmap[MAX_QUARTER_TRACKS_5_25];
|
||||
};
|
||||
|
||||
struct TRKv1
|
||||
{
|
||||
|
@ -239,17 +271,22 @@ public:
|
|||
UINT32 bitCount;
|
||||
};
|
||||
|
||||
struct Trks
|
||||
{
|
||||
TRKv2 trks[MAX_QUARTER_TRACKS_5_25];
|
||||
BYTE bits[0]; // bits[] starts at offset 3 x BLOCK_SIZE = 1536
|
||||
};
|
||||
|
||||
private:
|
||||
static const UINT32 INFO_CHUNK_ID = 'OFNI'; // 'INFO'
|
||||
static const UINT32 TMAP_CHUNK_ID = 'PAMT'; // 'TMAP'
|
||||
static const UINT32 TRKS_CHUNK_ID = 'SKRT'; // 'TRKS'
|
||||
static const UINT32 WRIT_CHUNK_ID = 'TIRW'; // 'WRIT' - WOZv2
|
||||
static const UINT32 META_CHUNK_ID = 'ATEM'; // 'META'
|
||||
static const UINT32 INFO_CHUNK_SIZE = 60; // Fixed size for both WOZv1 & WOZv2
|
||||
|
||||
struct InfoChunk
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 size;
|
||||
BYTE version;
|
||||
BYTE diskType;
|
||||
BYTE writeProtected; // 1 = Floppy is write protected
|
||||
|
@ -273,17 +310,44 @@ private:
|
|||
UINT16 requiredRAM; // in K (1024 bytes)
|
||||
UINT16 largestTrack; // in blocks (512 bytes)
|
||||
|
||||
static const BYTE bootUnknown = 0;
|
||||
static const BYTE bootSector16 = 1;
|
||||
static const BYTE bootSector13 = 2;
|
||||
static const BYTE bootSectorBoth = 3;
|
||||
|
||||
static const BYTE optimalBitTiming5_25 = 32;
|
||||
};
|
||||
|
||||
InfoChunkv2* m_pInfo;
|
||||
InfoChunkv2* m_pInfo; // NB. image-specific - only valid during Detect(), which calls InvalidateInfo() when done
|
||||
|
||||
//
|
||||
|
||||
struct WOZEmptyImage525 // 5.25"
|
||||
{
|
||||
WOZHeader hdr;
|
||||
|
||||
WOZChunkHdr infoHdr;
|
||||
InfoChunkv2 info;
|
||||
BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunkv2)];
|
||||
|
||||
WOZChunkHdr tmapHdr;
|
||||
Tmap tmap;
|
||||
|
||||
WOZChunkHdr trksHdr;
|
||||
Trks trks;
|
||||
};
|
||||
|
||||
struct WOZv1EmptyImage525 // 5.25"
|
||||
{
|
||||
WOZHeader hdr;
|
||||
|
||||
WOZChunkHdr infoHdr;
|
||||
InfoChunk info;
|
||||
BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunk)];
|
||||
|
||||
WOZChunkHdr tmapHdr;
|
||||
Tmap tmap;
|
||||
|
||||
WOZChunkHdr trksHdr;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
#pragma pack(pop)
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -304,7 +368,8 @@ public:
|
|||
}
|
||||
|
||||
ImageError_e Open(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary, std::string& strFilenameInZip);
|
||||
void Close(ImageInfo* pImageInfo, const bool bDeleteFile);
|
||||
void Close(ImageInfo* pImageInfo);
|
||||
bool WOZUpdateInfo(ImageInfo* pImageInfo, DWORD& dwOffset);
|
||||
|
||||
virtual CImageBase* Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, ImageInfo* pImageInfo) = 0;
|
||||
virtual CImageBase* GetImageForCreation(const TCHAR* pszExt, DWORD* pCreateImageSize) = 0;
|
||||
|
@ -317,7 +382,7 @@ protected:
|
|||
ImageError_e CheckNormalFile(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary);
|
||||
void GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
||||
void GetCharLowerExt2(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
||||
void SetImageInfo(ImageInfo* pImageInfo, FileType_e eFileGZip, DWORD dwOffset, CImageBase* pImageType, DWORD dwSize);
|
||||
void SetImageInfo(ImageInfo* pImageInfo, FileType_e fileType, DWORD dwOffset, CImageBase* pImageType, DWORD dwSize);
|
||||
|
||||
UINT GetNumImages(void) { return m_vecImageTypes.size(); };
|
||||
CImageBase* GetImage(UINT uIndex) { _ASSERT(uIndex<GetNumImages()); return m_vecImageTypes[uIndex]; }
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#define LOG_DISK_NIBBLES_WRITE 1
|
||||
#define LOG_DISK_NIBBLES_WRITE_TRACK_GAPS 1 // Gap1, Gap2 & Gap3 info when writing a track
|
||||
#define LOG_DISK_NIBBLES_USE_RUNTIME_VAR 1
|
||||
#define LOG_DISK_WOZ_LOADWRITE 1
|
||||
#define LOG_DISK_WOZ_SHIFTWRITE 1
|
||||
|
||||
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
|
||||
#if (LOG_DISK_ENABLED)
|
||||
|
|
|
@ -169,6 +169,7 @@ static int g_win_fullscreen_offsetx = 0;
|
|||
static int g_win_fullscreen_offsety = 0;
|
||||
|
||||
static bool g_bFrameActive = false;
|
||||
static bool g_windowMinimized = false;
|
||||
|
||||
static std::string driveTooltip;
|
||||
|
||||
|
@ -256,12 +257,14 @@ static void GetAppleWindowTitle()
|
|||
default:
|
||||
case A2TYPE_APPLE2: g_pAppTitle = TITLE_APPLE_2 ; break;
|
||||
case A2TYPE_APPLE2PLUS: g_pAppTitle = TITLE_APPLE_2_PLUS ; break;
|
||||
case A2TYPE_APPLE2JPLUS: g_pAppTitle = TITLE_APPLE_2_JPLUS ; break;
|
||||
case A2TYPE_APPLE2E: g_pAppTitle = TITLE_APPLE_2E ; break;
|
||||
case A2TYPE_APPLE2EENHANCED: g_pAppTitle = TITLE_APPLE_2E_ENHANCED; break;
|
||||
case A2TYPE_PRAVETS82: g_pAppTitle = TITLE_PRAVETS_82 ; break;
|
||||
case A2TYPE_PRAVETS8M: g_pAppTitle = TITLE_PRAVETS_8M ; break;
|
||||
case A2TYPE_PRAVETS8A: g_pAppTitle = TITLE_PRAVETS_8A ; break;
|
||||
case A2TYPE_TK30002E: g_pAppTitle = TITLE_TK3000_2E ; break;
|
||||
case A2TYPE_BASE64A: g_pAppTitle = TITLE_BASE64A ; break;
|
||||
}
|
||||
|
||||
#if _DEBUG
|
||||
|
@ -274,10 +277,12 @@ static void GetAppleWindowTitle()
|
|||
g_pAppTitle += " - ";
|
||||
|
||||
if( IsVideoStyle(VS_HALF_SCANLINES) )
|
||||
{
|
||||
g_pAppTitle += " 50% ";
|
||||
}
|
||||
g_pAppTitle += g_apVideoModeDesc[ g_eVideoType ];
|
||||
|
||||
g_pAppTitle += VideoGetAppWindowTitle();
|
||||
|
||||
if (g_CardMgr.GetDisk2CardMgr().IsAnyFirmware13Sector())
|
||||
g_pAppTitle += " (S6-13) ";
|
||||
|
||||
if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
|
||||
g_pAppTitle += TEXT(" (custom rom)");
|
||||
|
@ -384,6 +389,9 @@ static void CreateGdiObjects(void)
|
|||
case A2TYPE_TK30002E:
|
||||
buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN3000E_BUTTON"));
|
||||
break;
|
||||
case A2TYPE_BASE64A:
|
||||
buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNBASE64A_BUTTON"));
|
||||
break;
|
||||
default:
|
||||
buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN_BUTTON"));
|
||||
break;
|
||||
|
@ -765,6 +773,9 @@ void FrameDrawDiskStatus( HDC passdc )
|
|||
if (g_nAppMode == MODE_LOGO)
|
||||
return;
|
||||
|
||||
if (g_windowMinimized) // Prevent DC leaks when app window is minimised (GH#820)
|
||||
return;
|
||||
|
||||
// We use the actual drive since probing from memory doesn't tell us anything we don't already know.
|
||||
// DOS3.3 ProDOS
|
||||
// Drive $B7EA $BE3D
|
||||
|
@ -1090,6 +1101,21 @@ LRESULT CALLBACK FrameWndProc (
|
|||
g_bAppActive = (wparam ? TRUE : FALSE);
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
switch(wparam)
|
||||
{
|
||||
case SIZE_RESTORED:
|
||||
case SIZE_MAXIMIZED:
|
||||
g_windowMinimized = false;
|
||||
break;
|
||||
case SIZE_MINIMIZED:
|
||||
g_windowMinimized = true;
|
||||
break;
|
||||
default: // SIZE_MAXSHOW, SIZE_MAXHIDE
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
LogFileOutput("WM_CLOSE\n");
|
||||
if (g_bIsFullScreen && g_bRestart)
|
||||
|
@ -1286,7 +1312,7 @@ LRESULT CALLBACK FrameWndProc (
|
|||
case WM_KEYDOWN:
|
||||
KeybUpdateCtrlShiftStatus();
|
||||
|
||||
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
|
||||
// Processing is done in WM_KEYUP for: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
|
||||
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == -1))
|
||||
{
|
||||
SetUsingCursor(FALSE);
|
||||
|
@ -1347,7 +1373,7 @@ LRESULT CALLBACK FrameWndProc (
|
|||
}
|
||||
else if (wparam == VK_F10)
|
||||
{
|
||||
if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED)
|
||||
if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED || g_Apple2Type == A2TYPE_BASE64A)
|
||||
{
|
||||
SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch
|
||||
NTSC_VideoInitAppleType();
|
||||
|
@ -1420,7 +1446,6 @@ LRESULT CALLBACK FrameWndProc (
|
|||
LogOutput("WM_KEYDOWN: %08X (scanCode=%04X)\n", wparam, (lparam>>16)&0xfff);
|
||||
#endif
|
||||
if (!IsJoyKey &&
|
||||
!KeybGetAltStatus() && // GH#749 - AltGr also fakes CTRL being pressed!
|
||||
(g_nAppMode != MODE_LOGO)) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
|
||||
{
|
||||
// GH#678 Alternate key(s) to toggle max speed
|
||||
|
@ -1428,7 +1453,9 @@ LRESULT CALLBACK FrameWndProc (
|
|||
// . Ctrl-1: Speed = 1 MHz
|
||||
// . Ctrl-3: Speed = Full-Speed
|
||||
bool keyHandled = false;
|
||||
if( KeybGetCtrlStatus() && wparam >= '0' && wparam <= '9' )
|
||||
if( KeybGetCtrlStatus() &&
|
||||
!KeybGetAltStatus() && // GH#749 - AltGr also fakes CTRL being pressed!
|
||||
wparam >= '0' && wparam <= '9' )
|
||||
{
|
||||
switch (wparam)
|
||||
{
|
||||
|
@ -1487,7 +1514,6 @@ LRESULT CALLBACK FrameWndProc (
|
|||
break;
|
||||
|
||||
case WM_KEYUP:
|
||||
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
|
||||
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
|
||||
{
|
||||
buttondown = -1;
|
||||
|
@ -1495,7 +1521,23 @@ LRESULT CALLBACK FrameWndProc (
|
|||
EraseButton(wparam-VK_F1);
|
||||
else
|
||||
DrawButton((HDC)0,wparam-VK_F1);
|
||||
ProcessButtonClick(wparam-VK_F1, true);
|
||||
|
||||
const int iButton = wparam-VK_F1;
|
||||
if (KeybGetCtrlStatus() && (wparam == VK_F3 || wparam == VK_F4)) // Ctrl+F3/F4 for drive pop-up menu (GH#817)
|
||||
{
|
||||
POINT pt; // location of mouse click
|
||||
pt.x = buttonx + BUTTONCX/2;
|
||||
pt.y = buttony + BUTTONCY/2 + iButton * BUTTONCY;
|
||||
const int iDrive = wparam - VK_F3;
|
||||
ProcessDiskPopupMenu( window, pt, iDrive );
|
||||
|
||||
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
|
||||
DrawButton((HDC)0, iButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessButtonClick(iButton, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1766,7 +1808,6 @@ LRESULT CALLBACK FrameWndProc (
|
|||
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
// Right Click on Drive Icon -- eject Disk
|
||||
if ((buttonover == -1) && (message == WM_RBUTTONUP)) // HACK: BUTTON_NONE
|
||||
{
|
||||
int x = LOWORD(lparam);
|
||||
|
@ -1776,18 +1817,10 @@ LRESULT CALLBACK FrameWndProc (
|
|||
(y >= buttony) &&
|
||||
(y <= buttony+BUTTONS*BUTTONCY))
|
||||
{
|
||||
int iButton = (y-buttony-1)/BUTTONCY;
|
||||
int iDrive = iButton - BTN_DRIVE1;
|
||||
const int iButton = (y-buttony-1)/BUTTONCY;
|
||||
const int iDrive = iButton - BTN_DRIVE1;
|
||||
if ((iButton == BTN_DRIVE1) || (iButton == BTN_DRIVE2))
|
||||
{
|
||||
/*
|
||||
if (KeybGetShiftStatus())
|
||||
DiskProtect( iDrive, true );
|
||||
else
|
||||
if (KeybGetCtrlStatus())
|
||||
DiskProtect( iDrive, false );
|
||||
else
|
||||
*/
|
||||
{
|
||||
RECT rect; // client area
|
||||
POINT pt; // location of mouse click
|
||||
|
@ -1807,7 +1840,7 @@ LRESULT CALLBACK FrameWndProc (
|
|||
}
|
||||
|
||||
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
|
||||
DrawButton((HDC)0,iButton);
|
||||
DrawButton((HDC)0, iButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2294,7 +2327,7 @@ void ResetMachineState ()
|
|||
HD_Reset();
|
||||
g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
|
||||
|
||||
MemReset(); // calls CpuInitialize()
|
||||
MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
|
||||
PravetsReset();
|
||||
if (g_CardMgr.QuerySlot(SLOT6) == CT_Disk2)
|
||||
dynamic_cast<Disk2InterfaceCard&>(g_CardMgr.GetRef(SLOT6)).Boot();
|
||||
|
@ -2337,6 +2370,13 @@ void CtrlReset()
|
|||
VideoResetState(); // Switch Alternate char set off
|
||||
}
|
||||
|
||||
if (IsAppleIIeOrAbove(GetApple2Type()) || IsCopamBase64A(GetApple2Type()))
|
||||
{
|
||||
// For A][ & A][+, reset doesn't reset the annunciators (UTAIIe:I-5)
|
||||
// Base 64A: on RESET does reset to ROM page 0 (GH#807)
|
||||
MemAnnunciatorReset();
|
||||
}
|
||||
|
||||
PravetsReset();
|
||||
g_CardMgr.GetDisk2CardMgr().Reset();
|
||||
HD_Reset();
|
||||
|
|
|
@ -650,6 +650,10 @@ BYTE __stdcall JoyReadPosition(WORD programcounter, WORD address, BYTE, BYTE, UL
|
|||
|
||||
BOOL nPdlCntrActive = g_nCumulativeCycles <= (g_nJoyCntrResetCycle + (unsigned __int64) ((double)nPdlPos * PDL_CNTR_INTERVAL));
|
||||
|
||||
// If no joystick connected, then this is always active (GH#778)
|
||||
if (joyinfo[joytype[nJoyNum]] == DEVICE_NONE)
|
||||
nPdlCntrActive = TRUE;
|
||||
|
||||
return MemReadFloatingBus(nPdlCntrActive, nExecutedCycles);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#define SW_INTCXROM (memmode & MF_INTCXROM)
|
||||
#define SW_WRITERAM (memmode & MF_WRITERAM)
|
||||
#define SW_IOUDIS (memmode & MF_IOUDIS)
|
||||
#define SW_ALTROM0 (memmode & MF_ALTROM0) // For Copam Base64A
|
||||
#define SW_ALTROM1 (memmode & MF_ALTROM1) // For Copam Base64A
|
||||
|
||||
/*
|
||||
MEMORY MANAGEMENT SOFT SWITCHES
|
||||
|
@ -210,7 +212,9 @@ static LPBYTE g_pMemMainLanguageCard = NULL;
|
|||
static DWORD memmode = LanguageCardUnit::kMemModeInitialState;
|
||||
static BOOL modechanging = 0; // An Optimisation: means delay calling UpdatePaging() for 1 instruction
|
||||
|
||||
static CNoSlotClock g_NoSlotClock;
|
||||
static UINT memrompages = 1;
|
||||
|
||||
static CNoSlotClock* g_NoSlotClock = new CNoSlotClock;
|
||||
static LanguageCardUnit* g_pLanguageCard = NULL; // For all Apple II, //e and above
|
||||
|
||||
#ifdef RAMWORKS
|
||||
|
@ -233,6 +237,15 @@ static SS_CARDTYPE g_MemTypeAppleIIPlus = CT_LanguageCard; // Keep a copy so it'
|
|||
static SS_CARDTYPE g_MemTypeAppleIIe = CT_Extended80Col; // Keep a copy so it's not lost if machine type changes, eg: A//e -> A][ -> A//e
|
||||
static UINT g_uSaturnBanksFromCmdLine = 0;
|
||||
|
||||
|
||||
const UINT CxRomSize = 4 * 1024;
|
||||
const UINT Apple2RomSize = 12 * 1024;
|
||||
const UINT Apple2eRomSize = Apple2RomSize + CxRomSize;
|
||||
//const UINT Pravets82RomSize = 12*1024;
|
||||
//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize;
|
||||
const UINT MaxRomPages = 4; // For Copam Base64A
|
||||
const UINT Base64ARomSize = MaxRomPages * Apple2RomSize;
|
||||
|
||||
// Called from MemLoadSnapshot()
|
||||
void ResetDefaultMachineMemTypes(void)
|
||||
{
|
||||
|
@ -372,6 +385,11 @@ LanguageCardUnit* GetLanguageCard(void)
|
|||
return g_pLanguageCard;
|
||||
}
|
||||
|
||||
LPBYTE GetCxRomPeripheral(void)
|
||||
{
|
||||
return pCxRomPeripheral; // Can be NULL if at MODE_LOGO
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static BYTE __stdcall IORead_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
|
||||
|
@ -480,8 +498,11 @@ static BYTE __stdcall IORead_C05x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
|
|||
case 0xC: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xD: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xE: // fall through...
|
||||
case 0xF: return (!SW_IOUDIS) ? VideoSetMode(pc, addr, bWrite, d, nExecutedCycles)
|
||||
: IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xF: if (IsApple2PlusOrClone(GetApple2Type()))
|
||||
IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
else
|
||||
return (!SW_IOUDIS) ? VideoSetMode(pc, addr, bWrite, d, nExecutedCycles)
|
||||
: IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -506,8 +527,11 @@ static BYTE __stdcall IOWrite_C05x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON
|
|||
case 0xC: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xD: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xE: // fall through...
|
||||
case 0xF: return (!SW_IOUDIS) ? VideoSetMode(pc, addr, bWrite, d, nExecutedCycles)
|
||||
: IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
case 0xF: if (IsApple2PlusOrClone(GetApple2Type()))
|
||||
IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
else
|
||||
return (!SW_IOUDIS) ? VideoSetMode(pc, addr, bWrite, d, nExecutedCycles)
|
||||
: IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -681,9 +705,13 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT
|
|||
g_Annunciator[(address>>1) & 3] = (address&1) ? true : false;
|
||||
|
||||
if (address >= 0xC058 && address <= 0xC05B)
|
||||
{
|
||||
JoyportControl(address & 0x3); // AN0 and AN1 control
|
||||
}
|
||||
|
||||
if (address >= 0xC058 && address <= 0xC05B && IsCopamBase64A(GetApple2Type()))
|
||||
MemSetPaging(programcounter, address, write, value, nExecutedCycles);
|
||||
|
||||
if (address >= 0xC05C && address <= 0xC05D && IsApple2JPlus(GetApple2Type()))
|
||||
NTSC_VideoInitAppleType(); // AN2 switches between Katakana & ASCII video rom chars (GH#773)
|
||||
|
||||
if (!write)
|
||||
return MemReadFloatingBus(nExecutedCycles);
|
||||
|
@ -818,17 +846,17 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
|||
}
|
||||
}
|
||||
|
||||
if (IsPotentialNoSlotClockAccess(address))
|
||||
if (g_NoSlotClock && IsPotentialNoSlotClockAccess(address))
|
||||
{
|
||||
if (!write)
|
||||
{
|
||||
int data = 0;
|
||||
if (g_NoSlotClock.Read(address, data))
|
||||
if (g_NoSlotClock->Read(address, data))
|
||||
return (BYTE) data;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_NoSlotClock.Write(address);
|
||||
g_NoSlotClock->Write(address);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1118,12 +1146,17 @@ static void UpdatePaging(BOOL initialize)
|
|||
: pCxRomInternal+uRomOffset; // C800..CFFF - Internal ROM
|
||||
}
|
||||
|
||||
const int selectedrompage = (SW_ALTROM0 ? 1 : 0) | (SW_ALTROM1 ? 2 : 0);
|
||||
#ifdef _DEBUG
|
||||
if (selectedrompage) { _ASSERT(IsCopamBase64A(GetApple2Type())); }
|
||||
#endif
|
||||
const int romoffset = (selectedrompage % memrompages) * Apple2RomSize; // Only Copam Base64A has a non-zero romoffset
|
||||
for (loop = 0xD0; loop < 0xE0; loop++)
|
||||
{
|
||||
int bankoffset = (SW_BANK2 ? 0 : 0x1000);
|
||||
const int bankoffset = (SW_BANK2 ? 0 : 0x1000);
|
||||
memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8)-bankoffset
|
||||
: g_pMemMainLanguageCard+((loop-0xC0)<<8)-bankoffset
|
||||
: memrom+((loop-0xD0) * 0x100);
|
||||
: memrom+((loop-0xD0) * 0x100)+romoffset;
|
||||
|
||||
memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8)
|
||||
: SW_ALTZP ? memaux+(loop << 8)-bankoffset
|
||||
|
@ -1135,7 +1168,7 @@ static void UpdatePaging(BOOL initialize)
|
|||
{
|
||||
memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8)
|
||||
: g_pMemMainLanguageCard+((loop-0xC0)<<8)
|
||||
: memrom+((loop-0xD0) * 0x100);
|
||||
: memrom+((loop-0xD0) * 0x100)+romoffset;
|
||||
|
||||
memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8)
|
||||
: SW_ALTZP ? memaux+(loop << 8)
|
||||
|
@ -1415,19 +1448,13 @@ bool MemIsAddrCodeMemory(const USHORT addr)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
const UINT CxRomSize = 4*1024;
|
||||
const UINT Apple2RomSize = 12*1024;
|
||||
const UINT Apple2eRomSize = Apple2RomSize+CxRomSize;
|
||||
//const UINT Pravets82RomSize = 12*1024;
|
||||
//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize;
|
||||
|
||||
void MemInitialize()
|
||||
{
|
||||
// ALLOCATE MEMORY FOR THE APPLE MEMORY IMAGE AND ASSOCIATED DATA STRUCTURES
|
||||
memaux = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
|
||||
memmain = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
|
||||
memdirty = (LPBYTE)VirtualAlloc(NULL,0x100 ,MEM_COMMIT,PAGE_READWRITE);
|
||||
memrom = (LPBYTE)VirtualAlloc(NULL,0x5000 ,MEM_COMMIT,PAGE_READWRITE);
|
||||
memrom = (LPBYTE)VirtualAlloc(NULL,0x3000 * MaxRomPages ,MEM_COMMIT,PAGE_READWRITE);
|
||||
memimage = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_RESERVE,PAGE_NOACCESS);
|
||||
|
||||
pCxRomInternal = (LPBYTE) VirtualAlloc(NULL, CxRomSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
@ -1486,6 +1513,7 @@ void MemInitialize()
|
|||
CreateLanguageCard();
|
||||
|
||||
MemInitializeROM();
|
||||
MemInitializeCustomROM();
|
||||
MemInitializeCustomF8ROM();
|
||||
MemInitializeIO();
|
||||
MemReset();
|
||||
|
@ -1500,12 +1528,14 @@ void MemInitializeROM(void)
|
|||
{
|
||||
case A2TYPE_APPLE2: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break;
|
||||
case A2TYPE_APPLE2PLUS: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2_PLUS_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break;
|
||||
case A2TYPE_APPLE2JPLUS: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2_JPLUS_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break;
|
||||
case A2TYPE_APPLE2E: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2E_ROM ), "ROM"); ROM_SIZE = Apple2eRomSize; break;
|
||||
case A2TYPE_APPLE2EENHANCED:hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2E_ENHANCED_ROM), "ROM"); ROM_SIZE = Apple2eRomSize; break;
|
||||
case A2TYPE_PRAVETS82: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PRAVETS_82_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break;
|
||||
case A2TYPE_PRAVETS8M: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PRAVETS_8M_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break;
|
||||
case A2TYPE_PRAVETS8A: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PRAVETS_8C_ROM ), "ROM"); ROM_SIZE = Apple2eRomSize; break;
|
||||
case A2TYPE_TK30002E: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_TK3000_2E_ROM ), "ROM"); ROM_SIZE = Apple2eRomSize; break;
|
||||
case A2TYPE_BASE64A: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_BASE_64A_ROM ), "ROM"); ROM_SIZE = Base64ARomSize; break;
|
||||
}
|
||||
|
||||
if (hResInfo == NULL)
|
||||
|
@ -1515,12 +1545,14 @@ void MemInitializeROM(void)
|
|||
{
|
||||
case A2TYPE_APPLE2: _tcscpy(sRomFileName, TEXT("APPLE2.ROM" )); break;
|
||||
case A2TYPE_APPLE2PLUS: _tcscpy(sRomFileName, TEXT("APPLE2_PLUS.ROM" )); break;
|
||||
case A2TYPE_APPLE2JPLUS: _tcscpy(sRomFileName, TEXT("APPLE2_JPLUS.ROM" )); break;
|
||||
case A2TYPE_APPLE2E: _tcscpy(sRomFileName, TEXT("APPLE2E.ROM" )); break;
|
||||
case A2TYPE_APPLE2EENHANCED:_tcscpy(sRomFileName, TEXT("APPLE2E_ENHANCED.ROM")); break;
|
||||
case A2TYPE_PRAVETS82: _tcscpy(sRomFileName, TEXT("PRAVETS82.ROM" )); break;
|
||||
case A2TYPE_PRAVETS8M: _tcscpy(sRomFileName, TEXT("PRAVETS8M.ROM" )); break;
|
||||
case A2TYPE_PRAVETS8A: _tcscpy(sRomFileName, TEXT("PRAVETS8C.ROM" )); break;
|
||||
case A2TYPE_TK30002E: _tcscpy(sRomFileName, TEXT("TK3000e.ROM" )); break;
|
||||
case A2TYPE_BASE64A: _tcscpy(sRomFileName, TEXT("BASE64A.ROM" )); break;
|
||||
default:
|
||||
{
|
||||
_tcscpy(sRomFileName, TEXT("Unknown type!"));
|
||||
|
@ -1564,8 +1596,9 @@ void MemInitializeROM(void)
|
|||
ROM_SIZE -= CxRomSize;
|
||||
}
|
||||
|
||||
_ASSERT(ROM_SIZE == Apple2RomSize);
|
||||
memcpy(memrom, pData, Apple2RomSize); // ROM at $D000...$FFFF
|
||||
memrompages = MAX(MaxRomPages, ROM_SIZE / Apple2RomSize);
|
||||
_ASSERT(ROM_SIZE % Apple2RomSize == 0);
|
||||
memcpy(memrom, pData, ROM_SIZE); // ROM at $D000...$FFFF, one or several pages
|
||||
}
|
||||
|
||||
void MemInitializeCustomF8ROM(void)
|
||||
|
@ -1603,15 +1636,14 @@ void MemInitializeCustomF8ROM(void)
|
|||
|
||||
if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
BYTE OldRom[Apple2RomSize]; // NB. 12KB on stack
|
||||
memcpy(OldRom, memrom, Apple2RomSize);
|
||||
std::vector<BYTE> oldRom(memrom, memrom+Apple2RomSize); // range ctor: [first,last)
|
||||
|
||||
SetFilePointer(g_hCustomRomF8, 0, NULL, FILE_BEGIN);
|
||||
DWORD uNumBytesRead;
|
||||
BOOL bRes = ReadFile(g_hCustomRomF8, memrom+F8RomOffset, F8RomSize, &uNumBytesRead, NULL);
|
||||
if (uNumBytesRead != F8RomSize)
|
||||
{
|
||||
memcpy(memrom, OldRom, Apple2RomSize); // ROM at $D000...$FFFF
|
||||
memcpy(memrom, &oldRom[0], Apple2RomSize); // ROM at $D000...$FFFF
|
||||
bRes = FALSE;
|
||||
}
|
||||
|
||||
|
@ -1640,6 +1672,48 @@ void MemInitializeCustomF8ROM(void)
|
|||
}
|
||||
}
|
||||
|
||||
void MemInitializeCustomROM(void)
|
||||
{
|
||||
if (g_hCustomRom == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
SetFilePointer(g_hCustomRom, 0, NULL, FILE_BEGIN);
|
||||
DWORD uNumBytesRead;
|
||||
BOOL bRes = TRUE;
|
||||
|
||||
if (GetFileSize(g_hCustomRom, NULL) == Apple2eRomSize)
|
||||
{
|
||||
std::vector<BYTE> oldRomC0(pCxRomInternal, pCxRomInternal+CxRomSize); // range ctor: [first,last)
|
||||
bRes = ReadFile(g_hCustomRom, pCxRomInternal, CxRomSize, &uNumBytesRead, NULL);
|
||||
if (uNumBytesRead != CxRomSize)
|
||||
{
|
||||
memcpy(pCxRomInternal, &oldRomC0[0], CxRomSize); // ROM at $C000...$CFFF
|
||||
bRes = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bRes)
|
||||
{
|
||||
std::vector<BYTE> oldRom(memrom, memrom+Apple2RomSize); // range ctor: [first,last)
|
||||
bRes = ReadFile(g_hCustomRom, memrom, Apple2RomSize, &uNumBytesRead, NULL);
|
||||
if (uNumBytesRead != Apple2RomSize)
|
||||
{
|
||||
memcpy(memrom, &oldRom[0], Apple2RomSize); // ROM at $D000...$FFFF
|
||||
bRes = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// NB. If succeeded, then keep g_hCustomRom handle open - so that any next restart can load it again
|
||||
|
||||
if (!bRes)
|
||||
{
|
||||
MessageBox( g_hFrameWindow, "Failed to read custom rom", TEXT("AppleWin Error"), MB_OK );
|
||||
CloseHandle(g_hCustomRom);
|
||||
g_hCustomRom = INVALID_HANDLE_VALUE;
|
||||
// Failed, so use default rom...
|
||||
}
|
||||
}
|
||||
|
||||
// Called by:
|
||||
// . MemInitialize()
|
||||
// . Snapshot_LoadState_v2()
|
||||
|
@ -1705,19 +1779,17 @@ void MemInitializeIO(void)
|
|||
|
||||
if (g_CardMgr.QuerySlot(SLOT7) == CT_GenericHDD)
|
||||
HD_Load_Rom(pCxRomPeripheral, SLOT7); // $C700 : HDD f/w
|
||||
|
||||
//
|
||||
|
||||
// Finally remove the cards' ROMs at $Csnn if internal ROM is enabled
|
||||
// . required when restoring saved-state
|
||||
if (SW_INTCXROM)
|
||||
IoHandlerCardsOut();
|
||||
}
|
||||
|
||||
// Called by:
|
||||
// . Snapshot_LoadState_v2()
|
||||
void MemInitializeCardExpansionRomFromSnapshot(void)
|
||||
void MemInitializeCardSlotAndExpansionRomFromSnapshot(void)
|
||||
{
|
||||
// Remove all the cards' ROMs at $Csnn if internal ROM is enabled
|
||||
if (IsAppleIIeOrAbove(GetApple2Type()) && SW_INTCXROM)
|
||||
IoHandlerCardsOut();
|
||||
|
||||
// Potentially init a card's expansion ROM
|
||||
const UINT uSlot = g_uPeripheralRomSlot;
|
||||
|
||||
if (ExpansionRom[uSlot] == NULL)
|
||||
|
@ -1737,7 +1809,7 @@ inline DWORD getRandomTime()
|
|||
//===========================================================================
|
||||
|
||||
// Called by:
|
||||
// . MemInitialize()
|
||||
// . MemInitialize() eg. on AppleWin start & restart (eg. h/w config changes)
|
||||
// . ResetMachineState() eg. Power-cycle ('Apple-Go' button)
|
||||
// . Snapshot_LoadState_v2()
|
||||
void MemReset()
|
||||
|
@ -1884,7 +1956,8 @@ void MemReset()
|
|||
mem = memimage;
|
||||
|
||||
// INITIALIZE PAGING, FILLING IN THE 64K MEMORY IMAGE
|
||||
ResetPaging(1); // Initialize=1
|
||||
ResetPaging(TRUE); // Initialize=1, init memmode
|
||||
MemAnnunciatorReset();
|
||||
|
||||
// INITIALIZE & RESET THE CPU
|
||||
// . Do this after ROM has been copied back to mem[], so that PC is correctly init'ed from 6502's reset vector
|
||||
|
@ -1892,6 +1965,9 @@ void MemReset()
|
|||
//Sets Caps Lock = false (Pravets 8A/C only)
|
||||
|
||||
z80_reset(); // NB. Also called above in CpuInitialize()
|
||||
|
||||
if (g_NoSlotClock)
|
||||
g_NoSlotClock->Reset(); // NB. Power-cycle, but not RESET signal
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1986,6 +2062,17 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
|||
}
|
||||
}
|
||||
|
||||
if (IsCopamBase64A(GetApple2Type()))
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x58: SetMemMode(memmode & ~MF_ALTROM0); break;
|
||||
case 0x59: SetMemMode(memmode | MF_ALTROM0); break;
|
||||
case 0x5A: SetMemMode(memmode & ~MF_ALTROM1); break;
|
||||
case 0x5B: SetMemMode(memmode | MF_ALTROM1); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MemOptimizeForModeChanging(programcounter, address))
|
||||
return write ? 0 : MemReadFloatingBus(nExecutedCycles);
|
||||
|
||||
|
@ -2034,7 +2121,7 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
|||
|
||||
bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
{
|
||||
if (IS_APPLE2E())
|
||||
if (IsAppleIIeOrAbove(GetApple2Type()))
|
||||
{
|
||||
// IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
|
||||
// ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
|
||||
|
@ -2071,6 +2158,18 @@ LPVOID MemGetSlotParameters(UINT uSlot)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void MemAnnunciatorReset(void)
|
||||
{
|
||||
for (UINT i=0; i<kNumAnnunciators; i++)
|
||||
g_Annunciator[i] = 0;
|
||||
|
||||
if (IsCopamBase64A(GetApple2Type()))
|
||||
{
|
||||
SetMemMode(memmode & ~(MF_ALTROM0|MF_ALTROM1));
|
||||
UpdatePaging(FALSE); // Initialize=FALSE
|
||||
}
|
||||
}
|
||||
|
||||
bool MemGetAnnunciator(UINT annunciator)
|
||||
{
|
||||
return g_Annunciator[annunciator];
|
||||
|
@ -2078,6 +2177,26 @@ bool MemGetAnnunciator(UINT annunciator)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
bool MemHasNoSlotClock(void)
|
||||
{
|
||||
return g_NoSlotClock != NULL;
|
||||
}
|
||||
|
||||
void MemInsertNoSlotClock(void)
|
||||
{
|
||||
if (!MemHasNoSlotClock())
|
||||
g_NoSlotClock = new CNoSlotClock;
|
||||
g_NoSlotClock->Reset();
|
||||
}
|
||||
|
||||
void MemRemoveNoSlotClock(void)
|
||||
{
|
||||
delete g_NoSlotClock;
|
||||
g_NoSlotClock = NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// NB. Don't need to save 'modechanging', as this is just an optimisation to save calling UpdatePaging() twice.
|
||||
// . If we were to save the state when 'modechanging' is set, then on restoring the state, the 6502 code will immediately update the read memory mode.
|
||||
// . This will work correctly.
|
||||
|
@ -2394,3 +2513,17 @@ bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NoSlotClockSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
{
|
||||
if (g_NoSlotClock)
|
||||
g_NoSlotClock->SaveSnapshot(yamlSaveHelper);
|
||||
}
|
||||
|
||||
void NoSlotClockLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
|
||||
{
|
||||
if (!g_NoSlotClock)
|
||||
g_NoSlotClock = new CNoSlotClock;
|
||||
|
||||
g_NoSlotClock->LoadSnapshot(yamlLoadHelper);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define MF_INTCXROM 0x00000200
|
||||
#define MF_WRITERAM 0x00000400 // Language Card RAM is Write Enabled
|
||||
#define MF_IOUDIS 0x00000800 // Disable IOU access for addresses $C058 to $C05F; enable access to DHIRES switch (0=on) (Enhanced //e only)
|
||||
#define MF_ALTROM0 0x00001000 // Use alternate ROM for $D000 to $FFFF. Two bits for up to 4 pages
|
||||
#define MF_ALTROM1 0x00002000 // Use alternate ROM, second bit to have four pages
|
||||
#define MF_IMAGEMASK 0x000003F7
|
||||
#define MF_LANGCARD_MASK (MF_WRITERAM|MF_HIGHRAM|MF_BANK2)
|
||||
|
||||
|
@ -72,21 +74,28 @@ bool MemOptimizeForModeChanging(WORD programcounter, WORD address);
|
|||
bool MemIsAddrCodeMemory(const USHORT addr);
|
||||
void MemInitialize ();
|
||||
void MemInitializeROM(void);
|
||||
void MemInitializeCustomROM(void);
|
||||
void MemInitializeCustomF8ROM(void);
|
||||
void MemInitializeIO(void);
|
||||
void MemInitializeCardExpansionRomFromSnapshot(void);
|
||||
void MemInitializeCardSlotAndExpansionRomFromSnapshot(void);
|
||||
BYTE MemReadFloatingBus(const ULONG uExecutedCycles);
|
||||
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles);
|
||||
void MemReset ();
|
||||
void MemResetPaging ();
|
||||
void MemUpdatePaging(BOOL initialize);
|
||||
LPVOID MemGetSlotParameters (UINT uSlot);
|
||||
void MemAnnunciatorReset(void);
|
||||
bool MemGetAnnunciator(UINT annunciator);
|
||||
bool MemHasNoSlotClock(void);
|
||||
void MemInsertNoSlotClock(void);
|
||||
void MemRemoveNoSlotClock(void);
|
||||
std::string MemGetSnapshotUnitAuxSlotName(void);
|
||||
void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion);
|
||||
void MemSaveSnapshotAux(class YamlSaveHelper& yamlSaveHelper);
|
||||
bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion);
|
||||
void NoSlotClockSaveSnapshot(YamlSaveHelper& yamlSaveHelper);
|
||||
void NoSlotClockLoadSnapshot(YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
|
||||
|
||||
|
@ -103,3 +112,5 @@ UINT GetRamWorksActiveBank(void);
|
|||
void SetSaturnMemorySize(UINT banks);
|
||||
void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain=false);
|
||||
class LanguageCardUnit* GetLanguageCard(void);
|
||||
|
||||
LPBYTE GetCxRomPeripheral(void);
|
||||
|
|
|
@ -87,11 +87,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Mockingboard.h"
|
||||
#include "SoundCore.h"
|
||||
#include "YamlHelper.h"
|
||||
#include "Riff.h"
|
||||
|
||||
#include "AY8910.h"
|
||||
#include "SSI263Phonemes.h"
|
||||
|
||||
#define LOG_SSI263 0
|
||||
#define LOG_SSI263B 0 // Alternate SSI263 logging (use in conjunction with CPU.cpp's LOG_IRQ_TAKEN_AND_RTI)
|
||||
|
||||
|
||||
#define SY6522_DEVICE_A 0
|
||||
|
@ -187,7 +189,8 @@ static bool g_bMBAvailable = false;
|
|||
|
||||
static SS_CARDTYPE g_SoundcardType = CT_Empty; // Use CT_Empty to mean: no soundcard
|
||||
static bool g_bPhasorEnable = false;
|
||||
static BYTE g_nPhasorMode = 0; // 0=Mockingboard emulation, 1=Phasor native
|
||||
enum PHASOR_MODE {PH_Mockingboard=0, PH_UNDEF1, PH_UNDEF2, PH_UNDEF3, PH_UNDEF4, PH_Phasor/*=5*/, PH_UNDEF6, PH_EchoPlus/*=7*/};
|
||||
static PHASOR_MODE g_phasorMode = PH_Mockingboard;
|
||||
static UINT g_PhasorClockScaleFactor = 1; // for save-state only
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -363,8 +366,7 @@ static void UpdateIFR(SY6522_AY8910* pMB, BYTE clr_ifr, BYTE set_ifr=0)
|
|||
// NB. Mockingboard generates IRQ on both 6522s:
|
||||
// . SSI263's IRQ (A/!R) is routed via the 2nd 6522 (at $Cx80) and must generate a 6502 IRQ (not NMI)
|
||||
// . SC-01's IRQ (A/!R) is also routed via a (2nd?) 6522
|
||||
// Phasor's SSI263 appears to be wired directly to the 6502's IRQ (ie. not via a 6522)
|
||||
// . I assume Phasor's 6522s just generate 6502 IRQs (not NMIs)
|
||||
// Phasor's SSI263 IRQ (A/!R) line is *also* wired directly to the 6502's IRQ (as well as the 6522's CA1)
|
||||
|
||||
if (bIRQ)
|
||||
CpuIrqAssert(IS_6522);
|
||||
|
@ -394,7 +396,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
|
||||
if(g_bPhasorEnable)
|
||||
{
|
||||
int nAY_CS = (g_nPhasorMode & 1) ? (~(nValue >> 3) & 3) : 1;
|
||||
int nAY_CS = (g_phasorMode == PH_Phasor) ? (~(nValue >> 3) & 3) : 1;
|
||||
|
||||
if(nAY_CS & 1)
|
||||
AY8910_Write(nDevice, nReg, nValue, 0);
|
||||
|
@ -446,7 +448,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
// Clear Timer2 Interrupt Flag.
|
||||
UpdateIFR(pMB, IxR_TIMER2);
|
||||
|
||||
pMB->sy6522.TIMER2_LATCH.h = nValue;
|
||||
pMB->sy6522.TIMER2_LATCH.h = nValue; // NB. Real 6522 doesn't have TIMER2_LATCH.h
|
||||
pMB->sy6522.TIMER2_COUNTER.w = pMB->sy6522.TIMER2_LATCH.w;
|
||||
|
||||
StartTimer2(pMB);
|
||||
|
@ -471,29 +473,14 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
// Clear those bits which are set in the lower 7 bits.
|
||||
nValue ^= 0x7F;
|
||||
pMB->sy6522.IER &= nValue;
|
||||
UpdateIFR(pMB, 0);
|
||||
|
||||
// Check if active timer has been disabled:
|
||||
if (((pMB->sy6522.IER & IxR_TIMER1) == 0) && pMB->bTimer1Active)
|
||||
StopTimer1(pMB);
|
||||
|
||||
if (((pMB->sy6522.IER & IxR_TIMER2) == 0) && pMB->bTimer2Active)
|
||||
StopTimer2(pMB);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set those bits which are set in the lower 7 bits.
|
||||
nValue &= 0x7F;
|
||||
pMB->sy6522.IER |= nValue;
|
||||
UpdateIFR(pMB, 0);
|
||||
|
||||
// Check if a timer interrupt has been enabled (regardless of if there's an active timer or not): GH#567
|
||||
if (pMB->sy6522.IER & IxR_TIMER1)
|
||||
StartTimer1(pMB);
|
||||
|
||||
if (pMB->sy6522.IER & IxR_TIMER2)
|
||||
StartTimer2(pMB);
|
||||
}
|
||||
UpdateIFR(pMB, 0);
|
||||
break;
|
||||
case 0x0f: // ORA_NO_HS
|
||||
break;
|
||||
|
@ -569,7 +556,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg)
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SSI263_Play(unsigned int nPhoneme);
|
||||
static void SSI263_Play(unsigned int nPhoneme);
|
||||
|
||||
#if 0
|
||||
typedef struct
|
||||
|
@ -605,52 +592,77 @@ const BYTE CONTROL_MASK = 0x80;
|
|||
const BYTE ARTICULATION_MASK = 0x70;
|
||||
const BYTE AMPLITUDE_MASK = 0x0F;
|
||||
|
||||
static BYTE SSI263_Read(BYTE nDevice, BYTE nReg)
|
||||
#if LOG_SSI263B
|
||||
static int ssiRegs[5]={-1,-1,-1,-1,-1};
|
||||
|
||||
void SSI_Output(void)
|
||||
{
|
||||
LogOutput("SSI: ");
|
||||
for (int i=0; i<=4; i++)
|
||||
{
|
||||
char r[3]="--";
|
||||
if (ssiRegs[i]>=0) sprintf(r,"%02X",ssiRegs[i]);
|
||||
LogOutput("%s ", r);
|
||||
ssiRegs[i] = -1;
|
||||
}
|
||||
LogOutput("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static BYTE SSI263_Read(BYTE nDevice, ULONG nExecutedCycles)
|
||||
{
|
||||
SY6522_AY8910* pMB = &g_MB[nDevice];
|
||||
|
||||
// Regardless of register, just return inverted A/!R in bit7
|
||||
// . A/!R is low for IRQ
|
||||
|
||||
return pMB->SpeechChip.CurrentMode << 7;
|
||||
return MemReadFloatingBus(pMB->SpeechChip.CurrentMode & 1, nExecutedCycles);
|
||||
}
|
||||
|
||||
static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
||||
{
|
||||
SY6522_AY8910* pMB = &g_MB[nDevice];
|
||||
|
||||
#if LOG_SSI263B
|
||||
_ASSERT(nReg < 5);
|
||||
if (nReg>4) nReg=4;
|
||||
if (ssiRegs[nReg]>=0) SSI_Output(); // overwriting a reg
|
||||
ssiRegs[nReg] = nValue;
|
||||
#endif
|
||||
|
||||
switch(nReg)
|
||||
{
|
||||
case SSI_DURPHON:
|
||||
#if LOG_SSI263
|
||||
if(g_fh) fprintf(g_fh, "DUR = 0x%02X, PHON = 0x%02X\n\n", nValue>>6, nValue&PHONEME_MASK);
|
||||
LogOutput("DUR = %d, PHON = 0x%02X\n", nValue>>6, nValue&PHONEME_MASK);
|
||||
#endif
|
||||
#if LOG_SSI263B
|
||||
SSI_Output();
|
||||
#endif
|
||||
|
||||
// Datasheet is not clear, but a write to DURPHON must clear the IRQ
|
||||
if(g_bPhasorEnable)
|
||||
{
|
||||
CpuIrqDeassert(IS_SPEECH);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateIFR(pMB, IxR_PERIPHERAL);
|
||||
}
|
||||
// Notes:
|
||||
// . Phasor's text-to-speech playback has no CTL H->L
|
||||
// - ISR just writes CTL=0 (and new ART+AMP values), and writes DUR=x (and new PHON)
|
||||
// - since no CTL H->L, then DUR value doesn't take affect (so continue using previous)
|
||||
// - so the write to DURPHON must clear the IRQ
|
||||
// . Does a write of CTL=0 clear IRQ? (ie. CTL 0->0)
|
||||
// . Does a write of CTL=1 clear IRQ? (ie. CTL 0->1)
|
||||
// - SSI263 datasheet says: "Setting the Control bit (CTL) to a logic one puts the device into Power Down mode..."
|
||||
// . Does phoneme output only happen when CTL=0? (Otherwise device is in PD mode)
|
||||
|
||||
// SSI263 datasheet is not clear, but a write to DURPHON must clear the IRQ.
|
||||
// NB. For Mockingboard, A/!R is ack'ed by 6522's PCR handshake.
|
||||
if (g_bPhasorEnable && g_phasorMode == PH_Phasor)
|
||||
CpuIrqDeassert(IS_SPEECH);
|
||||
|
||||
pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin
|
||||
|
||||
pMB->SpeechChip.DurationPhoneme = nValue;
|
||||
|
||||
g_nSSI263Device = nDevice;
|
||||
|
||||
// Phoneme output not dependent on CONTROL bit
|
||||
if(g_bPhasorEnable)
|
||||
{
|
||||
if(nValue || (g_nCurrentActivePhoneme<0))
|
||||
SSI263_Play(nValue & PHONEME_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
SSI263_Play(nValue & PHONEME_MASK);
|
||||
}
|
||||
SSI263_Play(nValue & PHONEME_MASK);
|
||||
break;
|
||||
case SSI_INFLECT:
|
||||
#if LOG_SSI263
|
||||
|
@ -658,6 +670,7 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
#endif
|
||||
pMB->SpeechChip.Inflection = nValue;
|
||||
break;
|
||||
|
||||
case SSI_RATEINF:
|
||||
#if LOG_SSI263
|
||||
if(g_fh) fprintf(g_fh, "RATE = 0x%02X, INF = 0x%02X\n", nValue>>4, nValue&0x0F);
|
||||
|
@ -667,19 +680,44 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
case SSI_CTTRAMP:
|
||||
#if LOG_SSI263
|
||||
if(g_fh) fprintf(g_fh, "CTRL = %d, ART = 0x%02X, AMP=0x%02X\n", nValue>>7, (nValue&ARTICULATION_MASK)>>4, nValue&LITUDE_MASK);
|
||||
//
|
||||
{
|
||||
bool H2L = (pMB->SpeechChip.CtrlArtAmp & CONTROL_MASK) && !(nValue & CONTROL_MASK);
|
||||
char newMode[20];
|
||||
sprintf_s(newMode, sizeof(newMode), "(new mode=%d)", pMB->SpeechChip.DurationPhoneme>>6);
|
||||
LogOutput("CTRL = %d->%d, ART = 0x%02X, AMP=0x%02X %s\n", pMB->SpeechChip.CtrlArtAmp>>7, nValue>>7, (nValue&ARTICULATION_MASK)>>4, nValue&LITUDE_MASK, H2L?newMode:"");
|
||||
}
|
||||
#endif
|
||||
#if LOG_SSI263B
|
||||
if ( ((pMB->SpeechChip.CtrlArtAmp & CONTROL_MASK) && !(nValue & CONTROL_MASK)) || ((nValue&0xF) == 0x0) ) // H->L or amp=0
|
||||
SSI_Output();
|
||||
#endif
|
||||
if((pMB->SpeechChip.CtrlArtAmp & CONTROL_MASK) && !(nValue & CONTROL_MASK)) // H->L
|
||||
{
|
||||
pMB->SpeechChip.CurrentMode = pMB->SpeechChip.DurationPhoneme & DURATION_MODE_MASK;
|
||||
if (pMB->SpeechChip.CurrentMode == MODE_IRQ_DISABLED)
|
||||
{
|
||||
// "Disables A/!R output only; does not change previous A/!R response" (SSI263 datasheet)
|
||||
// CpuIrqDeassert(IS_SPEECH);
|
||||
}
|
||||
}
|
||||
|
||||
pMB->SpeechChip.CtrlArtAmp = nValue;
|
||||
|
||||
// "Setting the Control bit (CTL) to a logic one puts the device into Power Down mode..." (SSI263 datasheet)
|
||||
if (pMB->SpeechChip.CtrlArtAmp & CONTROL_MASK)
|
||||
{
|
||||
// CpuIrqDeassert(IS_SPEECH);
|
||||
// pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin
|
||||
}
|
||||
break;
|
||||
case SSI_FILFREQ:
|
||||
case SSI_FILFREQ: // RegAddr.b2=1 (b1 & b0 are: don't care)
|
||||
default:
|
||||
#if LOG_SSI263
|
||||
if(g_fh) fprintf(g_fh, "FFREQ = 0x%02X\n", nValue);
|
||||
#endif
|
||||
pMB->SpeechChip.FilterFreq = nValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,7 +815,7 @@ static UINT64 g_uLastMBUpdateCycle = 0;
|
|||
// Called by:
|
||||
// . MB_UpdateCycles() - when g_nMBTimerDevice == {0,1,2,3}
|
||||
// . MB_PeriodicUpdate() - when g_nMBTimerDevice == kTIMERDEVICE_INVALID
|
||||
static void MB_Update(void)
|
||||
static void MB_UpdateInt(void)
|
||||
{
|
||||
if (!MockingboardVoice.bActive)
|
||||
return;
|
||||
|
@ -984,8 +1022,59 @@ static void MB_Update(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void MB_Update(void)
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
extern UINT64 g_timeMB_NoTimer;
|
||||
extern UINT64 g_timeMB_Timer;
|
||||
PerfMarker perfMarker(g_nMBTimerDevice == kTIMERDEVICE_INVALID ? g_timeMB_NoTimer : g_timeMB_Timer);
|
||||
#endif
|
||||
|
||||
MB_UpdateInt();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Called by SSI263Thread(), MB_LoadSnapshot & Phasor_LoadSnapshot
|
||||
// Pre: g_bVotraxPhoneme, g_bPhasorEnable, g_phasorMode
|
||||
static void SetSpeechIRQ(SY6522_AY8910* pMB)
|
||||
{
|
||||
if (!g_bVotraxPhoneme)
|
||||
{
|
||||
// Always set SSI263's D7 pin regardless of SSI263 mode (DR1:0), including MODE_IRQ_DISABLED
|
||||
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
|
||||
|
||||
if ((pMB->SpeechChip.CurrentMode & DURATION_MODE_MASK) != MODE_IRQ_DISABLED)
|
||||
{
|
||||
if (!g_bPhasorEnable || (g_bPhasorEnable && g_phasorMode == PH_Mockingboard))
|
||||
{
|
||||
if ((pMB->sy6522.PCR & 1) == 0) // CA1 Latch/Input = 0 (Negative active edge)
|
||||
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
|
||||
if (pMB->sy6522.PCR == 0x0C) // CA2 Control = b#110 (Low output)
|
||||
pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin (cleared by 6522's PCR CA1/CA2 handshake)
|
||||
|
||||
// NB. Don't set CTL=1, as Mockingboard(SMS) speech doesn't work (it sets MODE_IRQ_DISABLED mode during ISR)
|
||||
//pMB->SpeechChip.CtrlArtAmp |= CONTROL_MASK; // 6522's CA2 sets Power Down mode (pin 18), which sets Control bit
|
||||
}
|
||||
else if (g_bPhasorEnable && g_phasorMode == PH_Phasor) // Phasor's SSI263 IRQ (A/!R) line is *also* wired directly to the 6502's IRQ (as well as the 6522's CA1)
|
||||
{
|
||||
CpuIrqAssert(IS_SPEECH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (g_bVotraxPhoneme && pMB->sy6522.PCR == 0xB0)
|
||||
{
|
||||
// !A/R: Time-out of old phoneme (signal goes from low to high)
|
||||
|
||||
UpdateIFR(pMB, 0, IxR_VOTRAX);
|
||||
|
||||
g_bVotraxPhoneme = false;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI SSI263Thread(LPVOID lpParameter)
|
||||
{
|
||||
while(1)
|
||||
|
@ -1016,41 +1105,15 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter)
|
|||
//if(g_fh) fprintf(g_fh, "IRQ: Phoneme complete (0x%02X)\n\n", g_nCurrentActivePhoneme);
|
||||
#endif
|
||||
|
||||
if (g_nCurrentActivePhoneme < 0)
|
||||
continue; // On CTRL+RESET or power-cycle (during phoneme playback): ResetState() is called, which set g_nCurrentActivePhoneme=-1
|
||||
|
||||
SSI263Voice[g_nCurrentActivePhoneme].bActive = false;
|
||||
g_nCurrentActivePhoneme = -1;
|
||||
|
||||
// Phoneme complete, so generate IRQ if necessary
|
||||
SY6522_AY8910* pMB = &g_MB[g_nSSI263Device];
|
||||
|
||||
if(g_bPhasorEnable)
|
||||
{
|
||||
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED))
|
||||
{
|
||||
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
|
||||
|
||||
// Phasor's SSI263.IRQ line appears to be wired directly to IRQ (Bypassing the 6522)
|
||||
CpuIrqAssert(IS_SPEECH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C))
|
||||
{
|
||||
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
|
||||
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(g_bVotraxPhoneme && (pMB->sy6522.PCR == 0xB0))
|
||||
{
|
||||
// !A/R: Time-out of old phoneme (signal goes from low to high)
|
||||
|
||||
UpdateIFR(pMB, 0, IxR_VOTRAX);
|
||||
|
||||
g_bVotraxPhoneme = false;
|
||||
}
|
||||
SetSpeechIRQ(pMB);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1219,13 +1282,13 @@ static bool MB_DSInit()
|
|||
FALSE, // bManualReset (FALSE = auto-reset)
|
||||
FALSE, // bInitialState (FALSE = non-signaled)
|
||||
NULL); // lpName
|
||||
LogFileOutput("MB_DSInit: CreateEvent(), g_hSSI263Event[0]=0x%08X\n", (UINT32)g_hSSI263Event[0]);
|
||||
LogFileOutput("MB_DSInit: CreateEvent(), g_hSSI263Event[0]=0x%08X\n", g_hSSI263Event[0]);
|
||||
|
||||
g_hSSI263Event[1] = CreateEvent(NULL, // lpEventAttributes
|
||||
FALSE, // bManualReset (FALSE = auto-reset)
|
||||
FALSE, // bInitialState (FALSE = non-signaled)
|
||||
NULL); // lpName
|
||||
LogFileOutput("MB_DSInit: CreateEvent(), g_hSSI263Event[1]=0x%08X\n", (UINT32)g_hSSI263Event[1]);
|
||||
LogFileOutput("MB_DSInit: CreateEvent(), g_hSSI263Event[1]=0x%08X\n", g_hSSI263Event[1]);
|
||||
|
||||
if((g_hSSI263Event[0] == NULL) || (g_hSSI263Event[1] == NULL))
|
||||
{
|
||||
|
@ -1327,7 +1390,7 @@ static bool MB_DSInit()
|
|||
NULL, // lpParameter
|
||||
0, // dwCreationFlags : 0 = Run immediately
|
||||
&dwThreadId); // lpThreadId
|
||||
LogFileOutput("MB_DSInit: CreateThread(), g_hThread=0x%08X\n", (UINT32)g_hThread);
|
||||
LogFileOutput("MB_DSInit: CreateThread(), g_hThread=0x%08X\n", g_hThread);
|
||||
|
||||
BOOL bRes2 = SetThreadPriority(g_hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
LogFileOutput("MB_DSInit: SetThreadPriority(), bRes=%d\n", bRes2 ? 1 : 0);
|
||||
|
@ -1448,7 +1511,7 @@ void MB_Initialize()
|
|||
g_bCritSectionValid = true;
|
||||
}
|
||||
|
||||
void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType);
|
||||
static void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType);
|
||||
|
||||
// NB. Mockingboard voice is *already* muted because showing 'Select Load State file' dialog
|
||||
// . and voice will be demuted when dialog is closed
|
||||
|
@ -1505,7 +1568,7 @@ static void ResetState()
|
|||
g_bMB_RegAccessedFlag = false;
|
||||
g_bMB_Active = false;
|
||||
|
||||
g_nPhasorMode = 0;
|
||||
g_phasorMode = PH_Mockingboard;
|
||||
g_PhasorClockScaleFactor = 1;
|
||||
|
||||
g_uLastMBUpdateCycle = 0;
|
||||
|
@ -1534,6 +1597,8 @@ void MB_Reset() // CTRL+RESET or power-cycle
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Echo+ mode - Phasor's 2nd 6522 is mapped to every 16-byte offset in $Cnxx (Echo+ has a single 6522 controlling two AY-3-8913's)
|
||||
|
||||
static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles)
|
||||
{
|
||||
if (g_bFullSpeed)
|
||||
|
@ -1561,11 +1626,13 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
|
|||
if(nMB != 0) // Slot4 only
|
||||
return MemReadFloatingBus(nExecutedCycles);
|
||||
|
||||
int CS;
|
||||
if(g_nPhasorMode & 1)
|
||||
CS = ( ( nAddr & 0x80 ) >> 6 ) | ( ( nAddr & 0x10 ) >> 4 ); // 0, 1, 2 or 3
|
||||
else // Mockingboard Mode
|
||||
int CS = 0;
|
||||
if (g_phasorMode == PH_Mockingboard)
|
||||
CS = ( ( nAddr & 0x80 ) >> 7 ) + 1; // 1 or 2
|
||||
else if (g_phasorMode == PH_Phasor)
|
||||
CS = ( ( nAddr & 0x80 ) >> 6 ) | ( ( nAddr & 0x10 ) >> 4 ); // 0, 1, 2 or 3
|
||||
else if (g_phasorMode == PH_EchoPlus)
|
||||
CS = 2;
|
||||
|
||||
BYTE nRes = 0;
|
||||
|
||||
|
@ -1577,23 +1644,21 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
|
|||
|
||||
bool bAccessedDevice = (CS & 3) ? true : false;
|
||||
|
||||
if((nOffset >= SSI263_Offset) && (nOffset <= (SSI263_Offset+0x05)))
|
||||
if ((g_phasorMode == PH_Phasor) && ((nAddr & 0xD0) == 0x40)) // $Cn4x and $Cn6x (Mockingboard mode: SSI263.bit7 not readable)
|
||||
{
|
||||
nRes |= SSI263_Read(nMB, nAddr&0xf);
|
||||
_ASSERT(!bAccessedDevice);
|
||||
nRes = SSI263_Read(nMB*2+1, nExecutedCycles); // SSI263 only drives bit7
|
||||
bAccessedDevice = true;
|
||||
}
|
||||
|
||||
return bAccessedDevice ? nRes : MemReadFloatingBus(nExecutedCycles);
|
||||
}
|
||||
|
||||
if(nOffset <= (SY6522A_Offset+0x0F))
|
||||
// NB. Mockingboard: SSI263.bit7 not readable (TODO: check this with real h/w)
|
||||
if (nOffset < SY6522B_Offset)
|
||||
return SY6522_Read(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_A, nAddr&0xf);
|
||||
else if((nOffset >= SY6522B_Offset) && (nOffset <= (SY6522B_Offset+0x0F)))
|
||||
return SY6522_Read(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_B, nAddr&0xf);
|
||||
else if((nOffset >= SSI263_Offset) && (nOffset <= (SSI263_Offset+0x05)))
|
||||
return SSI263_Read(nMB, nAddr&0xf);
|
||||
else
|
||||
return MemReadFloatingBus(nExecutedCycles);
|
||||
return SY6522_Read(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_B, nAddr&0xf);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1617,6 +1682,36 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
|
|||
}
|
||||
#endif
|
||||
|
||||
// Support 6502/65C02 false-reads of 6522 (GH#52)
|
||||
if ( ((mem[(PC-2)&0xffff] == 0x91) && GetMainCpu() == CPU_6502) || // sta (zp),y - 6502 only (no-PX variant only) (UTAIIe:4-23)
|
||||
(mem[(PC-3)&0xffff] == 0x99) || // sta abs16,y - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
(mem[(PC-3)&0xffff] == 0x9D) ) // sta abs16,x - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
{
|
||||
WORD base;
|
||||
WORD addr16;
|
||||
if (mem[(PC-2)&0xffff] == 0x91)
|
||||
{
|
||||
BYTE zp = mem[(PC-1)&0xffff];
|
||||
base = (mem[zp] | (mem[(zp+1)&0xff]<<8));
|
||||
addr16 = base + regs.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = mem[(PC-2)&0xffff] | (mem[(PC-1)&0xffff]<<8);
|
||||
addr16 = base + ((mem[(PC-3)&0xffff] == 0x99) ? regs.y : regs.x);
|
||||
}
|
||||
|
||||
if (((base ^ addr16) >> 8) == 0) // Only the no-PX variant does the false read (to the same I/O SELECT page)
|
||||
{
|
||||
_ASSERT(addr16 == nAddr);
|
||||
if (addr16 == nAddr) // Check we've reverse looked-up the 6502 opcode correctly
|
||||
{
|
||||
if ( ((nAddr&0xf) == 4) || ((nAddr&0xf) == 8) ) // Only reading 6522 reg-4 or reg-8 actually has an effect
|
||||
MB_Read(PC, nAddr, 0, 0, nExecutedCycles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BYTE nMB = (nAddr>>8)&0xf - SLOT4;
|
||||
BYTE nOffset = nAddr&0xff;
|
||||
|
||||
|
@ -1627,10 +1722,12 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
|
|||
|
||||
int CS;
|
||||
|
||||
if(g_nPhasorMode & 1)
|
||||
CS = ( ( nAddr & 0x80 ) >> 6 ) | ( ( nAddr & 0x10 ) >> 4 ); // 0, 1, 2 or 3
|
||||
else // Mockingboard Mode
|
||||
if (g_phasorMode == PH_Mockingboard)
|
||||
CS = ( ( nAddr & 0x80 ) >> 7 ) + 1; // 1 or 2
|
||||
else if (g_phasorMode == PH_Phasor)
|
||||
CS = ( ( nAddr & 0x80 ) >> 6 ) | ( ( nAddr & 0x10 ) >> 4 ); // 0, 1, 2 or 3
|
||||
else if (g_phasorMode == PH_EchoPlus)
|
||||
CS = 2;
|
||||
|
||||
if(CS & 1)
|
||||
SY6522_Write(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_A, nAddr&0xf, nValue);
|
||||
|
@ -1638,33 +1735,64 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
|
|||
if(CS & 2)
|
||||
SY6522_Write(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_B, nAddr&0xf, nValue);
|
||||
|
||||
if((nOffset >= SSI263_Offset) && (nOffset <= (SSI263_Offset+0x05)))
|
||||
SSI263_Write(nMB*2+1, nAddr&0xf, nValue); // Second 6522 is used for speech chip
|
||||
int CS_SSI263 = (g_phasorMode == PH_Mockingboard) ? (nAddr & 0xE0) == 0x40 // Mockingboard: $Cn4x
|
||||
: (g_phasorMode == PH_Phasor) ? (nAddr & 0xC0) == 0x40 // Phasor: $Cn4x and $Cn6x
|
||||
: 0; // Echo+
|
||||
|
||||
if (CS_SSI263)
|
||||
{
|
||||
// NB. Mockingboard mode: writes to $Cn4x/SSI263 also get written to 1st 6522 (have confirmed on real Phasor h/w)
|
||||
_ASSERT( (g_phasorMode == PH_Mockingboard && (CS==0 || CS==1)) || (g_phasorMode == PH_Phasor && (CS==0)) );
|
||||
SSI263_Write(nMB*2+1, nAddr&0x7, nValue); // Second 6522 is used for speech chip
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(nOffset <= (SY6522A_Offset+0x0F))
|
||||
if (nOffset < SY6522B_Offset)
|
||||
SY6522_Write(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_A, nAddr&0xf, nValue);
|
||||
else if((nOffset >= SY6522B_Offset) && (nOffset <= (SY6522B_Offset+0x0F)))
|
||||
else
|
||||
SY6522_Write(nMB*NUM_DEVS_PER_MB + SY6522_DEVICE_B, nAddr&0xf, nValue);
|
||||
else if((nOffset >= SSI263_Offset) && (nOffset <= (SSI263_Offset+0x05)))
|
||||
SSI263_Write(nMB*2+1, nAddr&0xf, nValue); // Second 6522 is used for speech chip
|
||||
|
||||
if ((nOffset >= SSI263_Offset) && (nOffset <= (SSI263_Offset+0x07)))
|
||||
SSI263_Write(nMB*2+1, nAddr&0x7, nValue); // Second 6522 is used for speech chip -- TODO confirm with real MB h/w that writes go to 1st 6522
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Phasor's DEVICE SELECT' logic:
|
||||
// . if addr.[b3]==1, then clear the card's mode bits b2:b0
|
||||
// . if any of addr.[b2:b0] are a logic 1, then set these bits in the card's mode
|
||||
//
|
||||
// Example DEVICE SELECT' accesses for Phasor in slot-4: (from empirical observations on real Phasor h/w)
|
||||
// 1)
|
||||
// . RESET -> Mockingboard mode (b#000)
|
||||
// . $C0C5 -> Phasor mode (b#101)
|
||||
// 2)
|
||||
// . RESET -> Mockingboard mode (b#000)
|
||||
// . $C0C1, then $C0C4 (or $C0C4, then $C0C1) -> Phasor mode (b#101)
|
||||
// . $C0C2 -> Echo+ mode (b#111)
|
||||
// . $C0C5 -> remaing in Echo+ mode (b#111)
|
||||
// So $C0C5 seemingly results in 2 different modes.
|
||||
//
|
||||
|
||||
static BYTE __stdcall PhasorIO(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles)
|
||||
{
|
||||
if(!g_bPhasorEnable)
|
||||
if (!g_bPhasorEnable)
|
||||
return MemReadFloatingBus(nExecutedCycles);
|
||||
|
||||
if(g_nPhasorMode < 2)
|
||||
g_nPhasorMode = nAddr & 1;
|
||||
UINT bits = (UINT) g_phasorMode;
|
||||
if (nAddr & 8)
|
||||
bits = 0;
|
||||
bits |= (nAddr & 7);
|
||||
g_phasorMode = (PHASOR_MODE) bits;
|
||||
|
||||
g_PhasorClockScaleFactor = (nAddr & 4) ? 2 : 1;
|
||||
if (g_phasorMode == PH_Mockingboard || g_phasorMode == PH_EchoPlus)
|
||||
g_PhasorClockScaleFactor = 1;
|
||||
else if (g_phasorMode == PH_Phasor)
|
||||
g_PhasorClockScaleFactor = 2;
|
||||
|
||||
AY8910_InitClock((int)(Get6502BaseClock() * g_PhasorClockScaleFactor));
|
||||
|
||||
|
@ -1800,7 +1928,7 @@ void MB_PeriodicUpdate(UINT executedCycles)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, const USHORT nClocks, bool* pTimerUnderflow=NULL)
|
||||
static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, const USHORT nClocks)
|
||||
{
|
||||
if (nClocks == 0)
|
||||
return false;
|
||||
|
@ -1822,9 +1950,6 @@ static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay,
|
|||
|
||||
if (oldTimer >= 0 && timer < 0) // Underflow occurs for 0x0000 -> 0xFFFF
|
||||
{
|
||||
if (pTimerUnderflow)
|
||||
*pTimerUnderflow = true; // Just for Willy Byte!
|
||||
|
||||
if (timer <= -2) // TIMER = 0xFFFE (or less)
|
||||
timerIrq = true;
|
||||
else // TIMER = 0xFFFF
|
||||
|
@ -1860,40 +1985,26 @@ bool MB_UpdateCycles(ULONG uExecutedCycles)
|
|||
{
|
||||
SY6522_AY8910* pMB = &g_MB[i];
|
||||
|
||||
bool bTimer1Underflow = false; // Just for Willy Byte!
|
||||
bool bTimer1Irq = false;
|
||||
bool bTimer1IrqOnLastCycle = false;
|
||||
|
||||
if (isOpcode)
|
||||
{
|
||||
bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks-1, &bTimer1Underflow);
|
||||
bTimer1IrqOnLastCycle = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, 1, &bTimer1Underflow);
|
||||
bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks-1);
|
||||
bTimer1IrqOnLastCycle = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, 1);
|
||||
bTimer1Irq = bTimer1Irq || bTimer1IrqOnLastCycle;
|
||||
}
|
||||
else
|
||||
{
|
||||
bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks, &bTimer1Underflow);
|
||||
bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks);
|
||||
}
|
||||
|
||||
const bool bTimer2Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER2_COUNTER.w, pMB->sy6522.timer2IrqDelay, nClocks);
|
||||
|
||||
if (!pMB->bTimer1Active && bTimer1Underflow)
|
||||
{
|
||||
if ( (g_nMBTimerDevice == kTIMERDEVICE_INVALID) // StopTimer1() has been called
|
||||
&& (pMB->sy6522.IFR & IxR_TIMER1) // Counter underflowed
|
||||
&& ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode
|
||||
{
|
||||
// Fix for Willy Byte - need to confirm that 6522 really does this!
|
||||
// . It never accesses IER/IFR/TIMER1 regs to clear IRQ
|
||||
// . NB. Willy Byte doesn't work with Phasor.
|
||||
UpdateIFR(pMB, IxR_TIMER1); // Deassert the TIMER IRQ
|
||||
}
|
||||
}
|
||||
|
||||
if (pMB->bTimer1Active && bTimer1Irq)
|
||||
{
|
||||
UpdateIFR(pMB, 0, IxR_TIMER1);
|
||||
bIrqOnLastOpcodeCycle = true;
|
||||
bIrqOnLastOpcodeCycle = bTimer1IrqOnLastCycle;
|
||||
|
||||
MB_Update();
|
||||
|
||||
|
@ -1901,7 +2012,6 @@ bool MB_UpdateCycles(ULONG uExecutedCycles)
|
|||
{
|
||||
// One-shot mode
|
||||
// - Phasor's playback code uses one-shot mode
|
||||
// - Willy Byte sets to one-shot to stop the timer IRQ
|
||||
StopTimer1(pMB);
|
||||
}
|
||||
else
|
||||
|
@ -1934,22 +2044,8 @@ bool MB_UpdateCycles(ULONG uExecutedCycles)
|
|||
{
|
||||
UpdateIFR(pMB, 0, IxR_TIMER2);
|
||||
|
||||
if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT)
|
||||
{
|
||||
StopTimer2(pMB);
|
||||
}
|
||||
else
|
||||
{
|
||||
pMB->sy6522.TIMER2_COUNTER.w += pMB->sy6522.TIMER2_LATCH.w;
|
||||
if (pMB->sy6522.TIMER2_COUNTER.w > pMB->sy6522.TIMER2_LATCH.w)
|
||||
{
|
||||
if (pMB->sy6522.TIMER2_LATCH.w)
|
||||
pMB->sy6522.TIMER2_COUNTER.w %= pMB->sy6522.TIMER2_LATCH.w;
|
||||
else
|
||||
pMB->sy6522.TIMER2_COUNTER.w = 0;
|
||||
}
|
||||
StartTimer2(pMB);
|
||||
}
|
||||
// TIMER2 only runs in one-shot mode
|
||||
StopTimer2(pMB);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1979,7 +2075,7 @@ void MB_SetVolume(DWORD dwVolume, DWORD dwVolumeMax)
|
|||
|
||||
MockingboardVoice.nVolume = NewVolume(dwVolume, dwVolumeMax);
|
||||
|
||||
if(MockingboardVoice.bActive)
|
||||
if (MockingboardVoice.bActive && !MockingboardVoice.bMute)
|
||||
MockingboardVoice.lpDSBvoice->SetVolume(MockingboardVoice.nVolume);
|
||||
}
|
||||
|
||||
|
@ -2021,7 +2117,10 @@ void MB_GetSnapshot_v1(SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot)
|
|||
// 3: Added: Unit state - GH#320
|
||||
// 4: Added: 6522 timerIrqDelay - GH#652
|
||||
// 5: Added: Unit state-B (Phasor only) - GH#659
|
||||
const UINT kUNIT_VERSION = 5;
|
||||
// 6: Changed SS_YAML_KEY_PHASOR_MODE from (0,1) to (0,5,7)
|
||||
// Added SS_YAML_KEY_VOTRAX_PHONEME
|
||||
// Removed: redundant SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR
|
||||
const UINT kUNIT_VERSION = 6;
|
||||
|
||||
const UINT NUM_MB_UNITS = 2;
|
||||
const UINT NUM_PHASOR_UNITS = 2;
|
||||
|
@ -2060,9 +2159,11 @@ const UINT NUM_PHASOR_UNITS = 2;
|
|||
#define SS_YAML_KEY_SY6522_TIMER2_IRQ_DELAY "Timer2 IRQ Delay"
|
||||
|
||||
#define SS_YAML_KEY_PHASOR_UNIT "Unit"
|
||||
#define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor"
|
||||
#define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor" // Redundant from v6
|
||||
#define SS_YAML_KEY_PHASOR_MODE "Mode"
|
||||
|
||||
#define SS_YAML_KEY_VOTRAX_PHONEME "Votrax Phoneme"
|
||||
|
||||
std::string MB_GetSnapshotCardName(void)
|
||||
{
|
||||
static const std::string name("Mockingboard C");
|
||||
|
@ -2119,6 +2220,8 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
|
|||
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, g_bVotraxPhoneme);
|
||||
|
||||
for(UINT i=0; i<NUM_MB_UNITS; i++)
|
||||
{
|
||||
YamlSaveHelper::Label unit(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_MB_UNIT, i);
|
||||
|
@ -2194,6 +2297,8 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
|
|||
if (version < 1 || version > kUNIT_VERSION)
|
||||
throw std::string("Card: wrong version");
|
||||
|
||||
g_bVotraxPhoneme = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
|
||||
|
||||
AY8910UpdateSetCycles();
|
||||
|
||||
const UINT nMbCardNum = slot - SLOT4;
|
||||
|
@ -2245,19 +2350,15 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
|
|||
StartTimer1(pMB); // Attempt to start timer
|
||||
}
|
||||
|
||||
// Crude - currently only support a single speech chip
|
||||
// FIX THIS:
|
||||
// . Speech chip could be Votrax instead
|
||||
// . Is this IRQ compatible with Phasor?
|
||||
if(pMB->SpeechChip.DurationPhoneme)
|
||||
// FIXME: currently only support a single speech chip
|
||||
// NB. g_bVotraxPhoneme is never true, as the phoneme playback completes in SSI263Thread() before this point in the save-state.
|
||||
// NB. SpeechChip.DurationPhoneme will mostly be non-zero during speech playback, as this is the SSI263 register, not whether the phonene is active.
|
||||
// FIXME: So possible race-condition between saving-state & SSI263Thread()
|
||||
if (pMB->SpeechChip.DurationPhoneme || g_bVotraxPhoneme)
|
||||
{
|
||||
g_nSSI263Device = nDeviceNum;
|
||||
|
||||
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL))
|
||||
{
|
||||
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
|
||||
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
|
||||
}
|
||||
g_bPhasorEnable = false;
|
||||
SetSpeechIRQ(pMB);
|
||||
}
|
||||
|
||||
nDeviceNum++;
|
||||
|
@ -2283,8 +2384,8 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
|
|||
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR, g_PhasorClockScaleFactor);
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_MODE, g_nPhasorMode);
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_MODE, g_phasorMode);
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, g_bVotraxPhoneme);
|
||||
|
||||
for(UINT i=0; i<NUM_PHASOR_UNITS; i++)
|
||||
{
|
||||
|
@ -2317,8 +2418,21 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
|
|||
if (version < 1 || version > kUNIT_VERSION)
|
||||
throw std::string("Card: wrong version");
|
||||
|
||||
g_PhasorClockScaleFactor = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR);
|
||||
g_nPhasorMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_MODE);
|
||||
if (version < 6)
|
||||
yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR); // Consume redundant data
|
||||
|
||||
UINT phasorMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_MODE);
|
||||
if (version < 6)
|
||||
{
|
||||
if (phasorMode == 0)
|
||||
phasorMode = PH_Mockingboard;
|
||||
else
|
||||
phasorMode = PH_Phasor;
|
||||
}
|
||||
g_phasorMode = (PHASOR_MODE) phasorMode;
|
||||
g_PhasorClockScaleFactor = (g_phasorMode == PH_Phasor) ? 2 : 1;
|
||||
|
||||
g_bVotraxPhoneme = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
|
||||
|
||||
AY8910UpdateSetCycles();
|
||||
|
||||
|
@ -2373,19 +2487,12 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
|
|||
StartTimer1(pMB); // Attempt to start timer
|
||||
}
|
||||
|
||||
// Crude - currently only support a single speech chip
|
||||
// FIX THIS:
|
||||
// . Speech chip could be Votrax instead
|
||||
// . Is this IRQ compatible with Phasor?
|
||||
if(pMB->SpeechChip.DurationPhoneme)
|
||||
// FIXME: currently only support a single speech chip
|
||||
if (pMB->SpeechChip.DurationPhoneme || g_bVotraxPhoneme)
|
||||
{
|
||||
g_nSSI263Device = nDeviceNum;
|
||||
|
||||
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL))
|
||||
{
|
||||
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
|
||||
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
|
||||
}
|
||||
g_bPhasorEnable = true;
|
||||
SetSpeechIRQ(pMB);
|
||||
}
|
||||
|
||||
nDeviceNum += 2;
|
||||
|
|
|
@ -181,6 +181,7 @@ void CMouseInterface::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
|
|||
{
|
||||
// m_bActive = true;
|
||||
m_bEnabled = true;
|
||||
_ASSERT(m_uSlot == uSlot);
|
||||
SetSlotRom(); // Pre: m_bActive == true
|
||||
RegisterIoHandler(uSlot, &CMouseInterface::IORead, &CMouseInterface::IOWrite, NULL, NULL, this, NULL);
|
||||
}
|
||||
|
|
363
source/NTSC.cpp
363
source/NTSC.cpp
|
@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Applewin.h"
|
||||
#include "CPU.h" // CpuGetCyclesThisVideoFrame()
|
||||
#include "Frame.h"
|
||||
#include "Memory.h" // MemGetMainPtr() MemGetAuxPtr()
|
||||
#include "Memory.h" // MemGetMainPtr(), MemGetAuxPtr(), MemGetAnnunciator()
|
||||
#include "Video.h" // g_pFramebufferbits
|
||||
#include "RGBMonitor.h"
|
||||
|
||||
|
@ -441,6 +441,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
static void updateScreenSingleLores40( long cycles6502 );
|
||||
static void updateScreenText40 ( long cycles6502 );
|
||||
static void updateScreenText80 ( long cycles6502 );
|
||||
static void updateScreenText40RGB ( long cycles6502 );
|
||||
static void updateScreenText80RGB ( long cycles6502 );
|
||||
static void updateScreenDoubleHires80Simplified(long cycles6502);
|
||||
static void updateScreenDoubleHires80RGB(long cycles6502);
|
||||
|
||||
//===========================================================================
|
||||
static void set_csbits()
|
||||
|
@ -450,13 +454,15 @@ static void set_csbits()
|
|||
{
|
||||
case A2TYPE_APPLE2: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
|
||||
case A2TYPE_APPLE2PLUS: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
|
||||
case A2TYPE_APPLE2JPLUS: csbits = &csbits_a2j[MemGetAnnunciator(2) ? 1 : 0]; g_nVideoCharSet = 0; break;
|
||||
case A2TYPE_APPLE2E: csbits = Get2e_csbits(); break;
|
||||
case A2TYPE_APPLE2EENHANCED:csbits = Get2e_csbits(); break;
|
||||
case A2TYPE_PRAVETS82: csbits = &csbits_pravets82[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
|
||||
case A2TYPE_PRAVETS8M: csbits = &csbits_pravets8M[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
|
||||
case A2TYPE_PRAVETS8A: csbits = &csbits_pravets8C[0]; break; // Apple //e clone
|
||||
case A2TYPE_TK30002E: csbits = &csbits_enhanced2e[0]; break; // Enhanced Apple //e clone
|
||||
default: csbits = &csbits_enhanced2e[0]; break;
|
||||
case A2TYPE_BASE64A: csbits = &csbits_base64a[GetVideoRomRockerSwitch() ? 0 : 1]; g_nVideoCharSet = 0; break; // Apple ][ clone
|
||||
default: _ASSERT(0); csbits = &csbits_enhanced2e[0]; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,7 +695,7 @@ void update7MonoPixels( uint16_t bits )
|
|||
|
||||
// NB. g_nLastColumnPixelNTSC = bits.b13 will be superseded by these parent funcs which use bits.b14:
|
||||
// . updateScreenDoubleHires80(), updateScreenDoubleLores80(), updateScreenText80()
|
||||
inline void updatePixels( uint16_t bits )
|
||||
inline void updatePixels(uint16_t bits)
|
||||
{
|
||||
if (!GetColorBurst())
|
||||
{
|
||||
|
@ -806,6 +812,9 @@ inline void updateVideoScannerHorzEOL()
|
|||
//===========================================================================
|
||||
inline void updateVideoScannerAddress()
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && GetVideoRefreshRate() == VR_50HZ) // GH#763
|
||||
g_nColorBurstPixels = 0; // instantaneously kill color-burst!
|
||||
|
||||
g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY ? g_pScanLines[2*g_nVideoClockVert] : g_pScanLines[0];
|
||||
|
||||
// Adjust, as these video styles have 2x 14M pixels of pre-render
|
||||
|
@ -821,8 +830,9 @@ inline void updateVideoScannerAddress()
|
|||
if (((g_pFuncUpdateGraphicsScreen == updateScreenDoubleHires80) ||
|
||||
(g_pFuncUpdateGraphicsScreen == updateScreenDoubleLores80) ||
|
||||
(g_pFuncUpdateGraphicsScreen == updateScreenText80) ||
|
||||
(g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && g_pFuncUpdateTextScreen == updateScreenText80))
|
||||
&& (g_eVideoType != VT_COLOR_MONITOR_RGB)) // Fix for "Ansi Story" (Turn the disk over) - Top row of TEXT80 is shifted by 1 pixel
|
||||
(g_pFuncUpdateGraphicsScreen == updateScreenText80RGB) ||
|
||||
(g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && (g_pFuncUpdateTextScreen == updateScreenText80 || g_pFuncUpdateGraphicsScreen == updateScreenText80RGB)))
|
||||
&& (g_eVideoType != VT_COLOR_MONITOR_RGB) && (g_eVideoType != VT_COLOR_VIDEOCARD_RGB)) // Fix for "Ansi Story" (Turn the disk over) - Top row of TEXT80 is shifted by 1 pixel
|
||||
{
|
||||
g_pVideoAddress -= 1;
|
||||
}
|
||||
|
@ -1141,24 +1151,28 @@ void updateMonochromeTables( uint16_t r, uint16_t g, uint16_t b )
|
|||
static void updatePixelBnWMonitorSingleScanline (uint16_t compositeSignal)
|
||||
{
|
||||
updateFramebufferMonitorSingleScanline(compositeSignal, g_aBnWMonitorCustom);
|
||||
updateColorPhase(); // Maintain color-phase, as could be switching graphics/text video modes mid-scanline
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updatePixelBnWMonitorDoubleScanline (uint16_t compositeSignal)
|
||||
{
|
||||
updateFramebufferMonitorDoubleScanline(compositeSignal, g_aBnWMonitorCustom);
|
||||
updateColorPhase(); // Maintain color-phase, as could be switching graphics/text video modes mid-scanline
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updatePixelBnWColorTVSingleScanline (uint16_t compositeSignal)
|
||||
{
|
||||
updateFramebufferTVSingleScanline(compositeSignal, g_aBnWColorTVCustom);
|
||||
updateColorPhase(); // Maintain color-phase, as could be switching graphics/text video modes mid-scanline
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updatePixelBnWColorTVDoubleScanline (uint16_t compositeSignal)
|
||||
{
|
||||
updateFramebufferTVDoubleScanline(compositeSignal, g_aBnWColorTVCustom);
|
||||
updateColorPhase(); // Maintain color-phase, as could be switching graphics/text video modes mid-scanline
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1223,7 +1237,41 @@ void updateScreenDoubleHires40 (long cycles6502) // wsUpdateVideoHires0
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
void updateScreenDoubleHires80Simplified(long cycles6502) // wsUpdateVideoDblHires
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen(cycles6502);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
g_nColorBurstPixels = 1024;
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
uint8_t a = *MemGetAuxPtr(addr);
|
||||
uint8_t m = *MemGetMainPtr(addr);
|
||||
|
||||
UpdateDHiResCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true, true);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void updateScreenDoubleHires80RGB (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
|
@ -1258,31 +1306,16 @@ void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblH
|
|||
int width = UpdateDHiRes160Cell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += width;
|
||||
}
|
||||
else if (RGB_Is560Mode() || (RGB_IsMixMode() && !((a | m) & 0x80)))
|
||||
else if (RGB_Is560Mode())// || (RGB_IsMixMode() && !((a | m) & 0x80)))
|
||||
{
|
||||
update7MonoPixels(a);
|
||||
update7MonoPixels(m);
|
||||
}
|
||||
else if (!RGB_IsMixMode() || (RGB_IsMixMode() && (a & m & 0x80)))
|
||||
else
|
||||
{
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true, true);
|
||||
UpdateDHiResCellRGB(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, RGB_IsMixMode(), RGB_IsMixModeInvertBit7());
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
else // RGB_IsMixMode() && ((a ^ m) & 0x80)
|
||||
{
|
||||
if (a & 0x80) // RGB color, then monochrome
|
||||
{
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true ,false);
|
||||
g_pVideoAddress += 7;
|
||||
update7MonoPixels(m);
|
||||
}
|
||||
else // monochrome, then RGB color
|
||||
{
|
||||
update7MonoPixels(a);
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, false, true);
|
||||
g_pVideoAddress += 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
|
@ -1473,6 +1506,65 @@ static void updateScreenSingleHires40Simplified (long cycles6502)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updateScreenSingleHires40Duochrome(long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen(cycles6502);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
g_nColorBurstPixels = 1024;
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
|
||||
UpdateHiResDuochromeCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updateScreenSingleHires40RGB(long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen(cycles6502);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
g_nColorBurstPixels = 1024;
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
|
||||
UpdateHiResRGBCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void updateScreenSingleHires40 (long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
|
@ -1599,13 +1691,46 @@ void updateScreenText40 (long cycles6502)
|
|||
bits ^= g_nTextFlashMask;
|
||||
|
||||
updatePixels( bits );
|
||||
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOL();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void updateScreenText40RGB(long cycles6502)
|
||||
{
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressTXT();
|
||||
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
if (g_nColorBurstPixels > 0)
|
||||
g_nColorBurstPixels -= 1;
|
||||
}
|
||||
else if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
uint8_t m = pMain[0];
|
||||
uint8_t c = getCharSetBits(m);
|
||||
|
||||
if (0 == g_nVideoCharSet && 0x40 == (m & 0xC0)) // Flash only if mousetext not active
|
||||
c ^= g_nTextFlashMask;
|
||||
|
||||
UpdateText40ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, c, m);
|
||||
g_pVideoAddress += 14;
|
||||
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void updateScreenText80 (long cycles6502)
|
||||
{
|
||||
|
@ -1638,8 +1763,10 @@ void updateScreenText80 (long cycles6502)
|
|||
aux ^= g_nTextFlashMask;
|
||||
|
||||
uint16_t bits = (main << 7) | (aux & 0x7f);
|
||||
if (g_eVideoType != VT_COLOR_MONITOR_RGB) // No extra 14M bit needed for VT_COLOR_MONITOR_RGB
|
||||
if ((g_eVideoType != VT_COLOR_MONITOR_RGB) // No extra 14M bit needed for VT_COLOR_MONITOR_RGB
|
||||
&& (g_eVideoType != VT_COLOR_VIDEOCARD_RGB))
|
||||
bits = (bits << 1) | g_nLastColumnPixelNTSC; // GH#555: Align TEXT80 chars with DHGR
|
||||
|
||||
updatePixels( bits );
|
||||
g_nLastColumnPixelNTSC = (bits >> 14) & 1;
|
||||
}
|
||||
|
@ -1648,6 +1775,51 @@ void updateScreenText80 (long cycles6502)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void updateScreenText80RGB(long cycles6502)
|
||||
{
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressTXT();
|
||||
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
if (g_nColorBurstPixels > 0)
|
||||
g_nColorBurstPixels -= 1;
|
||||
}
|
||||
else if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
|
||||
uint8_t m = pMain[0];
|
||||
uint8_t a = pAux[0];
|
||||
|
||||
uint16_t main = getCharSetBits(m);
|
||||
uint16_t aux = getCharSetBits(a);
|
||||
|
||||
if ((0 == g_nVideoCharSet) && 0x40 == (m & 0xC0)) // Flash only if mousetext not active
|
||||
main ^= g_nTextFlashMask;
|
||||
|
||||
if ((0 == g_nVideoCharSet) && 0x40 == (a & 0xC0)) // Flash only if mousetext not active
|
||||
aux ^= g_nTextFlashMask;
|
||||
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)aux, a);
|
||||
g_pVideoAddress += 7;
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)main, m);
|
||||
g_pVideoAddress += 7;
|
||||
|
||||
uint16_t bits = (main << 7) | (aux & 0x7f);
|
||||
|
||||
g_nLastColumnPixelNTSC = (bits >> 14) & 1;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOL();
|
||||
}
|
||||
}
|
||||
|
||||
// Functions (Public) _____________________________________________________________________________
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1726,7 +1898,14 @@ uint16_t NTSC_VideoGetScannerAddressForDebugger(void)
|
|||
//===========================================================================
|
||||
void NTSC_SetVideoTextMode( int cols )
|
||||
{
|
||||
if( cols == 40 )
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
{
|
||||
if (cols == 40)
|
||||
g_pFuncUpdateTextScreen = updateScreenText40RGB;
|
||||
else
|
||||
g_pFuncUpdateTextScreen = updateScreenText80RGB;
|
||||
}
|
||||
else if( cols == 40 )
|
||||
g_pFuncUpdateTextScreen = updateScreenText40;
|
||||
else
|
||||
g_pFuncUpdateTextScreen = updateScreenText80;
|
||||
|
@ -1744,9 +1923,12 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
g_nVideoMixed = uVideoModeFlags & VF_MIXED;
|
||||
g_nVideoCharSet = VideoGetSWAltCharSet() ? 1 : 0;
|
||||
|
||||
RGB_DisableTextFB();
|
||||
|
||||
g_nTextPage = 1;
|
||||
g_nHiresPage = 1;
|
||||
if (uVideoModeFlags & VF_PAGE2)
|
||||
|
@ -1760,10 +1942,99 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
}
|
||||
}
|
||||
|
||||
if (uVideoModeFlags & VF_TEXT)
|
||||
if (GetVideoRefreshRate() == VR_50HZ && g_pVideoAddress) // GH#763 / NB. g_pVideoAddress==NULL when called via VideoResetState()
|
||||
{
|
||||
if (uVideoModeFlags & VF_TEXT)
|
||||
{
|
||||
g_nColorBurstPixels = 0; // (For mid-line video mode change) Instantaneously kill color-burst! (not correct as TV's can take many lines)
|
||||
|
||||
// Switching mid-line from graphics to TEXT
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_NTSC &&
|
||||
g_pFuncUpdateGraphicsScreen != updateScreenText40 && g_pFuncUpdateGraphicsScreen != updateScreenText40RGB
|
||||
&& g_pFuncUpdateGraphicsScreen != updateScreenText80 && g_pFuncUpdateGraphicsScreen != updateScreenText80RGB)
|
||||
{
|
||||
*(uint32_t*)&g_pVideoAddress[0] = 0; // blank out any stale pixel data, eg. ANSI STORY (at end credits)
|
||||
*(uint32_t*)&g_pVideoAddress[1] = 0;
|
||||
g_pVideoAddress += 2; // eg. FT's TRIBU demo & ANSI STORY (at "turn the disk over!")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_nColorBurstPixels = 1024; // (For mid-line video mode change)
|
||||
|
||||
// Switching mid-line from TEXT to graphics
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_NTSC &&
|
||||
(g_pFuncUpdateGraphicsScreen == updateScreenText40 || g_pFuncUpdateGraphicsScreen == updateScreenText40RGB
|
||||
|| g_pFuncUpdateGraphicsScreen == updateScreenText80 || g_pFuncUpdateGraphicsScreen == updateScreenText80RGB))
|
||||
{
|
||||
g_pVideoAddress -= 2; // eg. FT's TRIBU demo & ANSI STORY (at "turn the disk over!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Video7_SL7 extra RGB modes handling
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB
|
||||
&& RGB_GetVideocard() == RGB_Videocard_e::Video7_SL7
|
||||
// Exclude following modes (fallback through regular NTSC rendering with RGB text)
|
||||
// VF_DHIRES = 1 -> regular Apple IIe modes
|
||||
// VF_DHIRES = 0 and VF_TEXT=0, VF_DHIRES=1, VF_80COL=1 -> DHIRES modes, setup by F1/F2
|
||||
&& !(!(uVideoModeFlags & VF_DHIRES) ||
|
||||
((uVideoModeFlags & VF_DHIRES) && !(uVideoModeFlags & VF_TEXT) && (uVideoModeFlags & VF_DHIRES) && (uVideoModeFlags & VF_80COL))
|
||||
)
|
||||
)
|
||||
{
|
||||
RGB_EnableTextFB(); // F/B text only shows in 40col mode anyway
|
||||
|
||||
// ----- Video-7 SL7 extra modes ----- (from the videocard manual)
|
||||
// AN3 TEXT HIRES 80COL
|
||||
// 0 1 ? 0 F/B Text
|
||||
// 0 1 ? 1 80 col Text
|
||||
// 0 0 0 0 LoRes (mixed with F/B Text)
|
||||
// 0 0 0 1 DLoRes (mixed with 80 col. Text)
|
||||
// 0 0 1 0 F/B HiRes (mixed with F/B Text)
|
||||
if (uVideoModeFlags & VF_TEXT)
|
||||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
// 80 col text
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40RGB;
|
||||
}
|
||||
}
|
||||
else if (uVideoModeFlags & VF_HIRES)
|
||||
{
|
||||
// F/B HiRes
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40Duochrome;
|
||||
g_pFuncUpdateTextScreen = updateScreenText40RGB;
|
||||
}
|
||||
else if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
// DLoRes
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80Simplified;
|
||||
g_pFuncUpdateTextScreen = updateScreenText80RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
// LoRes + F/B Text
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40Simplified;
|
||||
g_pFuncUpdateTextScreen = updateScreenText40RGB;
|
||||
}
|
||||
}
|
||||
// Regular NTSC modes
|
||||
else if (uVideoModeFlags & VF_TEXT)
|
||||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80;
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80;
|
||||
}
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40;
|
||||
}
|
||||
|
@ -1775,6 +2046,8 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80Simplified;
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80;
|
||||
}
|
||||
|
@ -1787,6 +2060,8 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40Simplified;
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40;
|
||||
}
|
||||
|
@ -1797,7 +2072,7 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if ((g_eVideoType == VT_COLOR_MONITOR_RGB) || (g_eVideoType == VT_COLOR_VIDEOCARD_RGB))
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80;
|
||||
|
@ -1809,7 +2084,7 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
}
|
||||
else
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if ((g_eVideoType == VT_COLOR_MONITOR_RGB) || (g_eVideoType == VT_COLOR_VIDEOCARD_RGB))
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40;
|
||||
|
@ -1819,9 +2094,10 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void NTSC_SetVideoStyle() // (int v, int s)
|
||||
void NTSC_SetVideoStyle(void)
|
||||
{
|
||||
int half = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
const bool half = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
const VideoRefreshRate_e refresh = GetVideoRefreshRate();
|
||||
uint8_t r, g, b;
|
||||
|
||||
switch ( g_eVideoType )
|
||||
|
@ -1836,7 +2112,8 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
g_pFuncUpdateBnWPixel = updatePixelBnWColorTVSingleScanline;
|
||||
g_pFuncUpdateHuePixel = updatePixelHueColorTVSingleScanline;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateBnWPixel = updatePixelBnWColorTVDoubleScanline;
|
||||
g_pFuncUpdateHuePixel = updatePixelHueColorTVDoubleScanline;
|
||||
}
|
||||
|
@ -1853,7 +2130,8 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
g_pFuncUpdateBnWPixel = updatePixelBnWMonitorSingleScanline;
|
||||
g_pFuncUpdateHuePixel = updatePixelHueMonitorSingleScanline;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateBnWPixel = updatePixelBnWMonitorDoubleScanline;
|
||||
g_pFuncUpdateHuePixel = updatePixelHueMonitorDoubleScanline;
|
||||
}
|
||||
|
@ -1865,12 +2143,9 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
b = 0xFF;
|
||||
updateMonochromeTables( r, g, b ); // Custom Monochrome color
|
||||
if (half)
|
||||
{
|
||||
g_pFuncUpdateBnWPixel = g_pFuncUpdateHuePixel = updatePixelBnWColorTVSingleScanline;
|
||||
}
|
||||
else {
|
||||
else
|
||||
g_pFuncUpdateBnWPixel = g_pFuncUpdateHuePixel = updatePixelBnWColorTVDoubleScanline;
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_MONO_AMBER:
|
||||
|
@ -1886,6 +2161,7 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
goto _mono;
|
||||
|
||||
case VT_COLOR_MONITOR_RGB:
|
||||
case VT_COLOR_VIDEOCARD_RGB:
|
||||
case VT_MONO_WHITE:
|
||||
r = 0xFF;
|
||||
g = 0xFF;
|
||||
|
@ -1904,13 +2180,9 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
_mono:
|
||||
updateMonochromeTables( r, g, b ); // Custom Monochrome color
|
||||
if (half)
|
||||
{
|
||||
g_pFuncUpdateBnWPixel = g_pFuncUpdateHuePixel = updatePixelBnWMonitorSingleScanline;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateBnWPixel = g_pFuncUpdateHuePixel = updatePixelBnWMonitorDoubleScanline;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2090,6 +2362,11 @@ static void VideoUpdateCycles( int cyclesLeftToUpdate )
|
|||
//===========================================================================
|
||||
void NTSC_VideoUpdateCycles( UINT cycles6502 )
|
||||
{
|
||||
#ifdef LOG_PERF_TIMINGS
|
||||
extern UINT64 g_timeVideo;
|
||||
PerfMarker perfMarker(g_timeVideo);
|
||||
#endif
|
||||
|
||||
_ASSERT(cycles6502 && cycles6502 < g_videoScanner6502Cycles); // Use NTSC_VideoRedrawWholeScreen() instead
|
||||
|
||||
if (g_bDelayVideoMode)
|
||||
|
|
|
@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "StdAfx.h"
|
||||
#include "Applewin.h"
|
||||
#include "../resource/resource.h"
|
||||
#include "Video.h"
|
||||
|
||||
#include "NTSC_CharSet.h"
|
||||
|
@ -29,9 +30,12 @@ unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
|
|||
static unsigned char csbits_2e_pal[2][256][8]; // PAL Original or Enhanced //e (2764 8K video ROM - low 4K) via rocker switch under keyboard
|
||||
unsigned char csbits_2e[2][256][8]; // Original //e (no mousetext)
|
||||
unsigned char csbits_a2[1][256][8]; // ][ and ][+
|
||||
unsigned char csbits_a2j[2][256][8]; // ][J-Plus
|
||||
unsigned char csbits_pravets82[1][256][8]; // Pravets 82
|
||||
unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M
|
||||
unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C
|
||||
unsigned char csbits_base64a[2][256][8]; // Base 64A
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
@ -105,7 +109,7 @@ static void get_csbits(csbits_t csbits, const char* resourceName, const UINT cy0
|
|||
// FLASH toggles every 16 VBLs, so alternates between selecting NORMAL control/special and INVERSE control/special
|
||||
//
|
||||
|
||||
void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
|
||||
static void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
|
||||
{
|
||||
int RA = 0; // rom address
|
||||
int i = 0;
|
||||
|
@ -154,7 +158,7 @@ void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
|
|||
}
|
||||
}
|
||||
|
||||
void userVideoRomForIIe(void)
|
||||
static void userVideoRomForIIe(void)
|
||||
{
|
||||
const BYTE* pVideoRom;
|
||||
UINT size = GetVideoRom(pVideoRom); // 2K or 4K or 8K
|
||||
|
@ -177,32 +181,63 @@ void userVideoRomForIIe(void)
|
|||
|
||||
//-------------------------------------
|
||||
|
||||
void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom)
|
||||
{
|
||||
int RA = 0; // rom address
|
||||
static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const eApple2Type type = A2TYPE_APPLE2, const int AN2=0);
|
||||
|
||||
for (int i=0; i<256; i++, RA+=8)
|
||||
static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const eApple2Type type /*= A2TYPE_APPLE2*/, const int AN2/*=0*/)
|
||||
{
|
||||
for (int i=0; i<256; i++)
|
||||
{
|
||||
int RA = i*8; // rom address
|
||||
|
||||
if (type == A2TYPE_APPLE2JPLUS)
|
||||
{
|
||||
// AN2=0: $00-3F, $00-3F; $80-BF, $80-BF => KKAA (Repeat Katakana)
|
||||
// AN2=1: $40-7F, $40-7F; $C0-FF, $C0-FF => AAAA (Repeat ASCII)
|
||||
RA &= ~(1<<(6+3));
|
||||
RA |= (AN2<<(6+3)); // AN2 controls A9 (UTAII 8-12, Fig 8.7)
|
||||
}
|
||||
|
||||
for (int y=0; y<8; y++)
|
||||
{
|
||||
BYTE n = pVideoRom[RA+y];
|
||||
|
||||
// UTAII:8-30 "Bit 7 of your EPROM fonts will control flashing in the lower 1024 bytes of the EPROM"
|
||||
// UTAII:8-31 "If you leave O7 (EPROM Output7) reset in these patterns, the resulting characters will be inversions..."
|
||||
if (!(n & 0x80) && RA < 1024)
|
||||
n = n ^ 0x7f;
|
||||
// Apple II J-Plus: simplest logic is just invert if reading low 1K of video ROM
|
||||
// Base64A: Bit 0 instead of bit 7
|
||||
if (RA < 1024)
|
||||
{
|
||||
if (type == A2TYPE_BASE64A)
|
||||
{
|
||||
if (!(n & 0x01))
|
||||
n = n ^ 0xfe;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(n & 0x80) || (type == A2TYPE_APPLE2JPLUS))
|
||||
n = n ^ 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
// UTAII:8-30 "TEXT ROM pattern is ... reversed"
|
||||
BYTE d = 0;
|
||||
for (BYTE j=0; j<7; j++, n >>= 1) // Just bits [0..6]
|
||||
d = (d << 1) | (n & 1);
|
||||
if (type == A2TYPE_BASE64A)
|
||||
{
|
||||
// On the Base 64A bits are ordered 1345672.
|
||||
d = (n >> 2) | ((n & 2) >> 1) | ((n & 4) << 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UTAII:8-30 "TEXT ROM pattern is ... reversed"
|
||||
for (BYTE j = 0; j < 7; j++, n >>= 1) // Just bits [0..6]
|
||||
d = (d << 1) | (n & 1);
|
||||
}
|
||||
|
||||
csbits[0][i][y] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void userVideoRomForIIPlus(void)
|
||||
static void userVideoRomForIIPlus(void)
|
||||
{
|
||||
const BYTE* pVideoRom;
|
||||
UINT size = GetVideoRom(pVideoRom); // 2K or 4K or 8K
|
||||
|
@ -212,6 +247,53 @@ void userVideoRomForIIPlus(void)
|
|||
userVideoRom2K(&csbits_a2[0], pVideoRom);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
static void VideoRomForIIJPlus(void)
|
||||
{
|
||||
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2_JPLUS_VIDEO_ROM), "ROM");
|
||||
if (hResInfo == NULL)
|
||||
return;
|
||||
|
||||
DWORD dwResSize = SizeofResource(NULL, hResInfo);
|
||||
if(dwResSize != kVideoRomSize2K)
|
||||
return;
|
||||
|
||||
HGLOBAL hResData = LoadResource(NULL, hResInfo);
|
||||
if(hResData == NULL)
|
||||
return;
|
||||
|
||||
BYTE* pVideoRom = (BYTE*) LockResource(hResData); // NB. Don't need to unlock resource
|
||||
if (pVideoRom == NULL)
|
||||
return;
|
||||
|
||||
userVideoRom2K(&csbits_a2j[0], pVideoRom, A2TYPE_APPLE2JPLUS, 0);
|
||||
userVideoRom2K(&csbits_a2j[1], pVideoRom, A2TYPE_APPLE2JPLUS, 1);
|
||||
}
|
||||
|
||||
static void VideoRomForBase64A(void)
|
||||
{
|
||||
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_BASE64A_VIDEO_ROM), "ROM");
|
||||
if (hResInfo == NULL)
|
||||
return;
|
||||
|
||||
DWORD dwResSize = SizeofResource(NULL, hResInfo);
|
||||
if (dwResSize != kVideoRomSize4K)
|
||||
return;
|
||||
|
||||
HGLOBAL hResData = LoadResource(NULL, hResInfo);
|
||||
if (hResData == NULL)
|
||||
return;
|
||||
|
||||
BYTE* pVideoRom = (BYTE*)LockResource(hResData); // NB. Don't need to unlock resource
|
||||
if (pVideoRom == NULL)
|
||||
return;
|
||||
|
||||
userVideoRom2K(&csbits_base64a[0], pVideoRom, A2TYPE_BASE64A, 0);
|
||||
userVideoRom2K(&csbits_base64a[1], pVideoRom + kVideoRomSize2K, A2TYPE_BASE64A, 0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void make_csbits(void)
|
||||
|
@ -228,6 +310,9 @@ void make_csbits(void)
|
|||
memcpy(csbits_2e, csbits_enhanced2e, sizeof(csbits_enhanced2e));
|
||||
memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8);
|
||||
|
||||
VideoRomForIIJPlus(); // GH#773
|
||||
VideoRomForBase64A(); // GH#806
|
||||
|
||||
// Try to use any user-provided video ROM for Original/Enhanced //e
|
||||
userVideoRomForIIe();
|
||||
|
||||
|
|
|
@ -4,9 +4,12 @@ typedef unsigned char (*csbits_t)[256][8];
|
|||
|
||||
extern unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
|
||||
extern unsigned char csbits_a2[1][256][8]; // ][ and ][+
|
||||
extern unsigned char csbits_a2j[2][256][8]; // ][J-Plus
|
||||
extern unsigned char csbits_pravets82[1][256][8]; // Pravets 82
|
||||
extern unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M
|
||||
extern unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C
|
||||
extern unsigned char csbits_base64a[2][256][8]; // Base64A
|
||||
|
||||
|
||||
void make_csbits(void);
|
||||
csbits_t Get2e_csbits(void);
|
||||
|
|
|
@ -41,6 +41,7 @@ All the other drivers and utilities available to me don't define the DOW mapping
|
|||
|
||||
#include "StdAfx.h"
|
||||
#include "NoSlotClock.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
CNoSlotClock::CNoSlotClock()
|
||||
:
|
||||
|
@ -166,6 +167,45 @@ void CNoSlotClock::PopulateClockRegister()
|
|||
m_ClockRegister.WriteNibble(year / 10);
|
||||
}
|
||||
|
||||
#define SS_YAML_KEY_CLOCK_REGISTER_ENABLED "Clock Register Enabled"
|
||||
#define SS_YAML_KEY_WRITE_ENABLED "Write Enabled"
|
||||
#define SS_YAML_KEY_CLOCK_REGISTER_MASK "Clock Register Mask"
|
||||
#define SS_YAML_KEY_CLOCK_REGISTER "Clock Register"
|
||||
#define SS_YAML_KEY_COMPARISON_REGISTER_MASK "Comparison Register Mask"
|
||||
#define SS_YAML_KEY_COMPARISON_REGISTER "Comparison Register"
|
||||
|
||||
std::string CNoSlotClock::GetSnapshotStructName(void)
|
||||
{
|
||||
static const std::string name("No Slot Clock");
|
||||
return name;
|
||||
}
|
||||
|
||||
void CNoSlotClock::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
{
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", GetSnapshotStructName().c_str());
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_CLOCK_REGISTER_ENABLED, m_bClockRegisterEnabled);
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_WRITE_ENABLED, m_bWriteEnabled);
|
||||
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CLOCK_REGISTER_MASK, m_ClockRegister.m_Mask);
|
||||
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CLOCK_REGISTER, m_ClockRegister.m_Register);
|
||||
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_COMPARISON_REGISTER_MASK, m_ComparisonRegister.m_Mask);
|
||||
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_COMPARISON_REGISTER, m_ComparisonRegister.m_Register);
|
||||
}
|
||||
|
||||
void CNoSlotClock::LoadSnapshot(YamlLoadHelper& yamlLoadHelper)
|
||||
{
|
||||
if (!yamlLoadHelper.GetSubMap(GetSnapshotStructName()))
|
||||
return;
|
||||
|
||||
m_bClockRegisterEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_CLOCK_REGISTER_ENABLED);
|
||||
m_bWriteEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_WRITE_ENABLED);
|
||||
m_ClockRegister.m_Mask = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CLOCK_REGISTER_MASK);
|
||||
m_ClockRegister.m_Register = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CLOCK_REGISTER);
|
||||
m_ComparisonRegister.m_Mask = yamlLoadHelper.LoadUint64(SS_YAML_KEY_COMPARISON_REGISTER_MASK);
|
||||
m_ComparisonRegister.m_Register = yamlLoadHelper.LoadUint64(SS_YAML_KEY_COMPARISON_REGISTER);
|
||||
|
||||
yamlLoadHelper.PopMap();
|
||||
}
|
||||
|
||||
CNoSlotClock::RingRegister64::RingRegister64()
|
||||
{
|
||||
Reset();
|
||||
|
|
|
@ -57,6 +57,9 @@ public:
|
|||
bool ClockRead(int& data);
|
||||
void ClockWrite(int address);
|
||||
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void LoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
bool m_bClockRegisterEnabled;
|
||||
bool m_bWriteEnabled;
|
||||
RingRegister64 m_ClockRegister;
|
||||
|
@ -64,6 +67,7 @@ public:
|
|||
|
||||
private:
|
||||
void PopulateClockRegister();
|
||||
std::string GetSnapshotStructName(void);
|
||||
|
||||
static const UINT64 kClockInitSequence = 0x5CA33AC55CA33AC5;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,14 @@
|
|||
#include "RGBMonitor.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
|
||||
// RGB videocards types
|
||||
|
||||
static RGB_Videocard_e g_RGBVideocard = RGB_Videocard_e::Apple;
|
||||
static int g_nTextFBMode = 0; // F/B Text
|
||||
static int g_nRegularTextFG = 15; // Default TEXT color
|
||||
static int g_nRegularTextBG = 0; // Default TEXT background color
|
||||
|
||||
const int HIRES_COLUMN_SUBUNIT_SIZE = 16;
|
||||
const int HIRES_COLUMN_UNIT_SIZE = (HIRES_COLUMN_SUBUNIT_SIZE)*2;
|
||||
const int HIRES_NUMBER_COLUMNS = (1<<5); // 5 bits
|
||||
|
@ -109,7 +117,9 @@ const BYTE DoubleHiresPalIndex[16] = {
|
|||
|
||||
#define SETRGBCOLOR(r,g,b) {b,g,r,0xFF}
|
||||
|
||||
static RGBQUAD PalIndex2RGB[] =
|
||||
static RGBQUAD* g_pPaletteRGB;
|
||||
|
||||
static RGBQUAD PaletteRGB_NTSC[] =
|
||||
{
|
||||
// hires
|
||||
#if DO_OPT_PALETTE
|
||||
|
@ -120,6 +130,7 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00), // For TV emulation HGR Video Mode
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
#else
|
||||
// Note: this is a placeholder. This palette is overwritten by VideoInitializeOriginal()
|
||||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00), // For TV emulation HGR Video Mode
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
SETRGBCOLOR(/*BLUE, */ 0x0D,0xA1,0xFF), // FC Linards Tweaked 0x00,0x00,0xFF -> 0x0D,0xA1,0xFF
|
||||
|
@ -137,6 +148,7 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*HGR_PINK, */ 0xFF,0x32,0xB5), // 0xD0,0x40,0xA0 -> 0xFF,0x32,0xB5
|
||||
|
||||
// lores & dhires
|
||||
// Note: this is a placeholder. This palette is overwritten by VideoInitializeOriginal()
|
||||
SETRGBCOLOR(/*BLACK,*/ 0x00,0x00,0x00), // 0
|
||||
SETRGBCOLOR(/*DEEP_RED,*/ 0x9D,0x09,0x66), // 0xD0,0x00,0x30 -> Linards Tweaked 0x9D,0x09,0x66
|
||||
SETRGBCOLOR(/*DARK_BLUE,*/ 0x2A,0x2A,0xE5), // 4 // Linards Tweaked 0x00,0x00,0x80 -> 0x2A,0x2A,0xE5
|
||||
|
@ -155,6 +167,44 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*WHITE,*/ 0xFF,0xFF,0xFF),
|
||||
};
|
||||
|
||||
// Le Chat Mauve Feline's palette
|
||||
// extracted from a white-balanced RGB video capture
|
||||
static RGBQUAD PaletteRGB_Feline[] =
|
||||
{
|
||||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00),
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
SETRGBCOLOR(/*BLUE, */ 0x00,0x8A,0xB5),
|
||||
SETRGBCOLOR(/*ORANGE, */ 0xFF,0x72,0x47),
|
||||
SETRGBCOLOR(/*GREEN, */ 0x6F,0xE6,0x2C),
|
||||
SETRGBCOLOR(/*MAGENTA, */ 0xAA,0x1A,0xD1),
|
||||
|
||||
// TV emu
|
||||
SETRGBCOLOR(/*HGR_GREY1, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_GREY2, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_YELLOW,*/ 0x9E,0x9E,0x00),
|
||||
SETRGBCOLOR(/*HGR_AQUA, */ 0x00,0xCD,0x4A),
|
||||
SETRGBCOLOR(/*HGR_PURPLE,*/ 0x61,0x61,0xFF),
|
||||
SETRGBCOLOR(/*HGR_PINK, */ 0xFF,0x32,0xB5),
|
||||
|
||||
// Feline
|
||||
SETRGBCOLOR(/*BLACK,*/ 0x00,0x00,0x00),
|
||||
SETRGBCOLOR(/*DEEP_RED,*/ 0xAC,0x12,0x4C),
|
||||
SETRGBCOLOR(/*DARK_BLUE,*/ 0x00,0x07,0x83),
|
||||
SETRGBCOLOR(/*MAGENTA,*/ 0xAA,0x1A,0xD1),
|
||||
SETRGBCOLOR(/*DARK_GREEN,*/ 0x00,0x83,0x2F),
|
||||
SETRGBCOLOR(/*DARK_GRAY,*/ 0x9F,0x97,0x7E),
|
||||
SETRGBCOLOR(/*BLUE,*/ 0x00,0x8A,0xB5),
|
||||
SETRGBCOLOR(/*LIGHT_BLUE,*/ 0x9F,0x9E,0xFF),
|
||||
SETRGBCOLOR(/*BROWN,*/ 0x7A,0x5F,0x00),
|
||||
SETRGBCOLOR(/*ORANGE,*/ 0xFF,0x72,0x47),
|
||||
SETRGBCOLOR(/*LIGHT_GRAY,*/ 0x78,0x68,0x7F),
|
||||
SETRGBCOLOR(/*PINK,*/ 0xFF,0x7A,0xCF),
|
||||
SETRGBCOLOR(/*GREEN,*/ 0x6F,0xE6,0x2C),
|
||||
SETRGBCOLOR(/*YELLOW,*/ 0xFF,0xF6,0x7B),
|
||||
SETRGBCOLOR(/*AQUA,*/ 0x6C,0xEE,0xB2),
|
||||
SETRGBCOLOR(/*WHITE,*/ 0xFF,0xFF,0xFF),
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void V_CreateLookup_DoubleHires ()
|
||||
|
@ -493,8 +543,8 @@ static void CopyMixedSource(int x, int y, int sx, int sy, bgra_t *pVideoAddress)
|
|||
}
|
||||
else
|
||||
{
|
||||
_ASSERT( colormixbuffer[h] < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ colormixbuffer[h] ];
|
||||
_ASSERT( colormixbuffer[h] < (sizeof(PaletteRGB_NTSC)/sizeof(PaletteRGB_NTSC[0])) );
|
||||
const RGBQUAD& rRGB = g_pPaletteRGB[ colormixbuffer[h] ];
|
||||
*(pDst+nBytes) = *reinterpret_cast<const UINT32 *>(&rRGB);
|
||||
}
|
||||
|
||||
|
@ -525,8 +575,8 @@ static void CopySource(int w, int h, int sx, int sy, bgra_t *pVideoAddress, cons
|
|||
{
|
||||
for (int nBytes=0; nBytes<w; ++nBytes)
|
||||
{
|
||||
_ASSERT( *(pSrc+nBytes+nSrcAdjustment) < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ *(pSrc+nBytes+nSrcAdjustment) ];
|
||||
_ASSERT( *(pSrc+nBytes+nSrcAdjustment) < (sizeof(PaletteRGB_NTSC)/sizeof(PaletteRGB_NTSC[0])) );
|
||||
const RGBQUAD& rRGB = g_pPaletteRGB[ *(pSrc+nBytes+nSrcAdjustment) ];
|
||||
*(pDst+nBytes) = *reinterpret_cast<const UINT32 *>(&rRGB);
|
||||
}
|
||||
}
|
||||
|
@ -561,25 +611,25 @@ void UpdateHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
|||
#define COLOR ((xpixel + PIXEL) & 3)
|
||||
#define VALUE (dwordval >> (4 + PIXEL - COLOR))
|
||||
|
||||
void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool updateAux, bool updateMain)
|
||||
void UpdateDHiResCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool updateAux, bool updateMain)
|
||||
{
|
||||
const int xpixel = x*14;
|
||||
const int xpixel = x * 14;
|
||||
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
BYTE byteval1 = (x > 0) ? *(pMain-1) : 0;
|
||||
BYTE byteval1 = (x > 0) ? *(pMain - 1) : 0;
|
||||
BYTE byteval2 = *pAux;
|
||||
BYTE byteval3 = *pMain;
|
||||
BYTE byteval4 = (x < 39) ? *(pAux+1) : 0;
|
||||
BYTE byteval4 = (x < 39) ? *(pAux + 1) : 0;
|
||||
|
||||
DWORD dwordval = (byteval1 & 0x70) | ((byteval2 & 0x7F) << 7) |
|
||||
((byteval3 & 0x7F) << 14) | ((byteval4 & 0x07) << 21);
|
||||
DWORD dwordval = (byteval1 & 0x70) | ((byteval2 & 0x7F) << 7) |
|
||||
((byteval3 & 0x7F) << 14) | ((byteval4 & 0x07) << 21);
|
||||
|
||||
#define PIXEL 0
|
||||
if (updateAux)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
CopySource(7, 2, SRCOFFS_DHIRES + 10 * HIBYTE(VALUE) + COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
pVideoAddress += 7;
|
||||
}
|
||||
#undef PIXEL
|
||||
|
@ -587,11 +637,323 @@ void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool
|
|||
#define PIXEL 7
|
||||
if (updateMain)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
CopySource(7, 2, SRCOFFS_DHIRES + 10 * HIBYTE(VALUE) + COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
}
|
||||
#undef PIXEL
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// RGB videocards HGR
|
||||
|
||||
void UpdateHiResRGBCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress)
|
||||
{
|
||||
const int xpixel = x * 14;
|
||||
int xoffset = x & 1; // offset to start of the 2 bytes
|
||||
addr -= xoffset;
|
||||
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
// We need all 28 bits because each pixel needs a three bit evaluation
|
||||
uint8_t byteval1 = (x < 2 ? 0 : *(pMain - 1));
|
||||
uint8_t byteval2 = *pMain;
|
||||
uint8_t byteval3 = *(pMain + 1);
|
||||
uint8_t byteval4 = (x >= 38 ? 0 : *(pMain + 2));
|
||||
|
||||
// all 28 bits chained
|
||||
DWORD dwordval = (byteval1 & 0x7F) | ((byteval2 & 0x7F) << 7) | ((byteval3 & 0x7F) << 14) | ((byteval4 & 0x7F) << 21);
|
||||
|
||||
// Extraction of 14 color pixels
|
||||
UINT32 colors[14];
|
||||
int color = 0;
|
||||
DWORD dwordval_tmp = dwordval;
|
||||
dwordval_tmp = dwordval_tmp >> 7;
|
||||
bool offset = (byteval2 & 0x80) ? true : false;
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
if (i == 7) offset = (byteval3 & 0x80) ? true : false;
|
||||
color = dwordval_tmp & 0x3;
|
||||
// Two cases because AppleWin's palette is in a strange order
|
||||
if (offset)
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[1 + color]);
|
||||
else
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[6 - color]);
|
||||
if (i%2) dwordval_tmp >>= 2;
|
||||
}
|
||||
// Black and White
|
||||
UINT32 bw[2];
|
||||
bw[0] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[0]);
|
||||
bw[1] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[1]);
|
||||
|
||||
DWORD mask = 0x01C0; // 00|000001 1|1000000
|
||||
DWORD chck1 = 0x0140; // 00|000001 0|1000000
|
||||
DWORD chck2 = 0x0080; // 00|000000 1|0000000
|
||||
|
||||
// HIRES render in RGB works on a pixel-basis (1-bit data in framebuffer)
|
||||
// The pixel can be 'color', if it makes a 101 or 010 pattern with the two neighbour bits
|
||||
// In all other cases, it's black if 0 and white if 1
|
||||
// The value of 'color' is defined on a 2-bits basis
|
||||
|
||||
UINT32* pDst = (UINT32*)pVideoAddress;
|
||||
|
||||
if (xoffset)
|
||||
{
|
||||
// Second byte of the 14 pixels block
|
||||
dwordval = dwordval >> 7;
|
||||
xoffset = 7;
|
||||
}
|
||||
|
||||
for (int i = xoffset; i < xoffset+7; i++)
|
||||
{
|
||||
if (((dwordval & mask) == chck1) || ((dwordval & mask) == chck2))
|
||||
{
|
||||
// Color pixel
|
||||
*(pDst) = colors[i];
|
||||
*(pDst + 1) = *(pDst);
|
||||
pDst += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// B&W pixel
|
||||
*(pDst) = bw[(dwordval & chck2 ? 1 : 0)];
|
||||
*(pDst + 1) = *(pDst);
|
||||
pDst += 2;
|
||||
}
|
||||
// Next pixel
|
||||
dwordval = dwordval >> 1;
|
||||
}
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
|
||||
// Second line
|
||||
UINT32* pSrc = (UINT32*)pVideoAddress;
|
||||
pDst = pSrc - GetFrameBufferWidth();
|
||||
if (bIsHalfScanLines)
|
||||
{
|
||||
// Scanlines
|
||||
std::fill(pDst, pDst + 14, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 14; i++)
|
||||
*(pDst + i) = *(pSrc + i);
|
||||
}
|
||||
}
|
||||
|
||||
static bool g_dhgrLastCellIsColor = true;
|
||||
static int g_dhgrLastBit = 0;
|
||||
|
||||
void UpdateDHiResCellRGB(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool isMixMode, bool isBit7Inversed)
|
||||
{
|
||||
const int xpixel = x * 14;
|
||||
int xoffset = x & 1; // offset to start of the 2 bytes
|
||||
addr -= xoffset;
|
||||
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
// We need all 28 bits because one 4-bits pixel overlaps two 14-bits cells
|
||||
uint8_t byteval1 = *pAux;
|
||||
uint8_t byteval2 = *pMain;
|
||||
uint8_t byteval3 = *(pAux + 1);
|
||||
uint8_t byteval4 = *(pMain + 1);
|
||||
|
||||
// all 28 bits chained
|
||||
DWORD dwordval = (byteval1 & 0x7F) | ((byteval2 & 0x7F) << 7) | ((byteval3 & 0x7F) << 14) | ((byteval4 & 0x7F) << 21);
|
||||
|
||||
// Extraction of 7 color pixels and 7x4 bits
|
||||
int bits[7];
|
||||
UINT32 colors[7];
|
||||
int color = 0;
|
||||
DWORD dwordval_tmp = dwordval;
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
bits[i] = dwordval_tmp & 0xF;
|
||||
color = ((bits[i] & 7) << 1) | ((bits[i] & 8) >> 3); // DHGR colors are rotated 1 bit to the right
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + color]);
|
||||
dwordval_tmp >>= 4;
|
||||
}
|
||||
UINT32 bw[2];
|
||||
bw[0] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + 0]);
|
||||
bw[1] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + 15]);
|
||||
|
||||
if (isBit7Inversed)
|
||||
{
|
||||
// Invert mixed mode detection
|
||||
byteval1 = ~byteval1;
|
||||
byteval2 = ~byteval2;
|
||||
byteval3 = ~byteval3;
|
||||
byteval4 = ~byteval4;
|
||||
}
|
||||
|
||||
// RGB DHGR is quite a mess:
|
||||
// Color mode is a real 140x192 RGB mode with no color fringe (ref. patent US4631692, "THE 140x192 VIDEO MODE")
|
||||
// BW mode is a real 560x192 monochrome mode
|
||||
// Mixed mode seems easy but has a few traps since it's based on 4-bits cells coded into 7-bits bytes:
|
||||
// - Bit 7 of each byte defines the mode of the following 7 bits (BW or Color);
|
||||
// - BW pixels are 1 bit wide, color pixels are usually 4 bits wide;
|
||||
// - A color pixel can be less than 4 bits wide if it crosses a byte boundary and falls into a BW byte;
|
||||
// - If a 4-bit cell of BW bits crosses a byte boundary and falls into a Color byte, then the last BW bit is repeated until the next color pixel starts.
|
||||
//
|
||||
// (Tested on Le Chat Mauve IIc adapter, which was made under patent of Video-7)
|
||||
|
||||
UINT32* pDst = (UINT32*)pVideoAddress;
|
||||
|
||||
if (xoffset == 0) // First cell
|
||||
{
|
||||
if ((byteval1 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Color
|
||||
|
||||
// Color cell 0
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
// Color cell 1
|
||||
*(pDst++) = colors[1];
|
||||
*(pDst++) = colors[1];
|
||||
*(pDst++) = colors[1];
|
||||
|
||||
dwordval >>= 7;
|
||||
g_dhgrLastCellIsColor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// BW
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
g_dhgrLastBit = dwordval & 1;
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
g_dhgrLastCellIsColor = false;
|
||||
}
|
||||
|
||||
if ((byteval2 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 1
|
||||
if (g_dhgrLastCellIsColor)
|
||||
{
|
||||
*(pDst++) = colors[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit once
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
}
|
||||
// Color cell 2
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
// Color cell 3
|
||||
*(pDst++) = colors[3];
|
||||
*(pDst++) = colors[3];
|
||||
g_dhgrLastCellIsColor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
g_dhgrLastBit = dwordval & 1;
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
g_dhgrLastCellIsColor = false;
|
||||
}
|
||||
}
|
||||
else // Second cell
|
||||
{
|
||||
dwordval >>= 14;
|
||||
|
||||
if ((byteval3 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 3
|
||||
if (g_dhgrLastCellIsColor)
|
||||
{
|
||||
*(pDst++) = colors[3];
|
||||
*(pDst++) = colors[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit twice
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
}
|
||||
// Color cell 4
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
// Color cell 5
|
||||
*(pDst++) = colors[5];
|
||||
|
||||
dwordval >>= 7;
|
||||
g_dhgrLastCellIsColor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
g_dhgrLastBit = dwordval & 1;
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
g_dhgrLastCellIsColor = false;
|
||||
}
|
||||
|
||||
if ((byteval4 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 5
|
||||
if (g_dhgrLastCellIsColor)
|
||||
{
|
||||
*(pDst++) = colors[5];
|
||||
*(pDst++) = colors[5];
|
||||
*(pDst++) = colors[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit three times
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
}
|
||||
// Color cell 6
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
g_dhgrLastCellIsColor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
g_dhgrLastBit = dwordval & 1;
|
||||
*(pDst++) = bw[g_dhgrLastBit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
g_dhgrLastCellIsColor = false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
|
||||
// Second line
|
||||
UINT32* pSrc = (UINT32*)pVideoAddress ;
|
||||
pDst = pSrc - GetFrameBufferWidth();
|
||||
if (bIsHalfScanLines)
|
||||
{
|
||||
// Scanlines
|
||||
std::fill(pDst, pDst + 14, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 14; i++)
|
||||
*(pDst + i) = *(pSrc + i);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
// Squash the 640 pixel image into 560 pixels
|
||||
int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
|
@ -697,13 +1059,108 @@ void UpdateDLoResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Color TEXT (some RGB cards only)
|
||||
// Default BG and FG are usually defined by hardware switches, defaults to black/white
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character)
|
||||
{
|
||||
uint8_t foreground = g_nRegularTextFG;
|
||||
uint8_t background = g_nRegularTextBG;
|
||||
if (g_nTextFBMode)
|
||||
{
|
||||
const BYTE val = *MemGetAuxPtr(addr); // RGB cards with F/B text use their own AUX memory!
|
||||
foreground = val >> 4;
|
||||
background = val & 0x0F;
|
||||
}
|
||||
else if (g_RGBVideocard == RGB_Videocard_e::Video7_SL7 && character < 0x80)
|
||||
{
|
||||
// in regular 40COL mode, the SL7 videocard renders inverse characters as B&W
|
||||
foreground = 15;
|
||||
background = 0;
|
||||
}
|
||||
|
||||
UpdateDuochromeCell(2, 14, pVideoAddress, bits, foreground, background);
|
||||
}
|
||||
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character)
|
||||
{
|
||||
if (g_RGBVideocard == RGB_Videocard_e::Video7_SL7 && character < 0x80)
|
||||
{
|
||||
// in all 80COL modes, the SL7 videocard renders inverse characters as B&W
|
||||
UpdateDuochromeCell(2, 7, pVideoAddress, bits, 15, 0);
|
||||
}
|
||||
else
|
||||
UpdateDuochromeCell(2, 7, pVideoAddress, bits, g_nRegularTextFG, g_nRegularTextBG);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Duochrome HGR (some RGB cards only)
|
||||
void UpdateHiResDuochromeCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress)
|
||||
{
|
||||
BYTE bits = *MemGetMainPtr(addr);
|
||||
BYTE val = *MemGetAuxPtr(addr);
|
||||
const uint8_t foreground = val >> 4;
|
||||
const uint8_t background = val & 0x0F;
|
||||
|
||||
UpdateDuochromeCell(2, 14, pVideoAddress, bits, foreground, background);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Writes a duochrome cell
|
||||
// 7 bits define a foreground/background pattern
|
||||
// Used on many RGB cards but activated differently, depending on the card.
|
||||
// Can be used in TEXT or HGR mode. The foreground & background colors could be fixed by hardware switches or data lying in AUX.
|
||||
void UpdateDuochromeCell(int h, int w, bgra_t* pVideoAddress, uint8_t bits, uint8_t foreground, uint8_t background)
|
||||
{
|
||||
UINT32* pDst = (UINT32*)pVideoAddress;
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
const UINT frameBufferWidth = GetFrameBufferWidth();
|
||||
RGBQUAD colors[2];
|
||||
// use LoRes palette
|
||||
background += 12;
|
||||
foreground += 12;
|
||||
// get bg/fg colors
|
||||
colors[0] = g_pPaletteRGB[background];
|
||||
colors[1] = g_pPaletteRGB[foreground];
|
||||
int nbits = bits;
|
||||
int doublepixels = (w == 14); // Double pixel (HiRes or Text40)
|
||||
|
||||
while (h--)
|
||||
{
|
||||
bits = nbits;
|
||||
if (bIsHalfScanLines && !(h & 1))
|
||||
{
|
||||
// 50% Half Scan Line clears every odd scanline (and SHIFT+PrintScreen saves only the even rows)
|
||||
std::fill(pDst, pDst + w, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int nBytes = 0; nBytes < w; nBytes += (doublepixels?2:1))
|
||||
{
|
||||
int bit = (bits & 1);
|
||||
bits >>= 1;
|
||||
const RGBQUAD& rRGB = colors[bit];
|
||||
*(pDst + nBytes) = *reinterpret_cast<const UINT32*>(&rRGB);
|
||||
if (doublepixels)
|
||||
{
|
||||
*(pDst + nBytes + 1) = *reinterpret_cast<const UINT32*>(&rRGB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pDst -= frameBufferWidth;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static LPBYTE g_pSourcePixels = NULL;
|
||||
|
||||
static void V_CreateDIBSections(void)
|
||||
{
|
||||
g_pSourcePixels = new BYTE[SRCOFFS_TOTAL * MAX_SOURCE_Y];
|
||||
if (!g_pSourcePixels) // NB. Will be non-zero after a VM restart (GH#809)
|
||||
g_pSourcePixels = new BYTE[SRCOFFS_TOTAL * MAX_SOURCE_Y];
|
||||
|
||||
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE SOURCE IMAGE
|
||||
for (int y = 0; y < MAX_SOURCE_Y; y++)
|
||||
|
@ -724,15 +1181,29 @@ void VideoInitializeOriginal(baseColors_t pBaseNtscColors)
|
|||
// CREATE THE SOURCE IMAGE AND DRAW INTO THE SOURCE BIT BUFFER
|
||||
V_CreateDIBSections();
|
||||
|
||||
memcpy(&PalIndex2RGB[BLACK], *pBaseNtscColors, sizeof(RGBQUAD)*kNumBaseColors);
|
||||
PalIndex2RGB[HGR_BLUE] = PalIndex2RGB[BLUE];
|
||||
PalIndex2RGB[HGR_ORANGE] = PalIndex2RGB[ORANGE];
|
||||
PalIndex2RGB[HGR_GREEN] = PalIndex2RGB[GREEN];
|
||||
PalIndex2RGB[HGR_VIOLET] = PalIndex2RGB[MAGENTA];
|
||||
// Replace the default palette with true NTSC-generated colors
|
||||
memcpy(&PaletteRGB_NTSC[BLACK], *pBaseNtscColors, sizeof(RGBQUAD) * kNumBaseColors);
|
||||
PaletteRGB_NTSC[HGR_BLUE] = PaletteRGB_NTSC[BLUE];
|
||||
PaletteRGB_NTSC[HGR_ORANGE] = PaletteRGB_NTSC[ORANGE];
|
||||
PaletteRGB_NTSC[HGR_GREEN] = PaletteRGB_NTSC[GREEN];
|
||||
PaletteRGB_NTSC[HGR_VIOLET] = PaletteRGB_NTSC[MAGENTA];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// RGB videocards may use a different palette thant the NTSC-generated one
|
||||
void VideoSwitchVideocardPalette(RGB_Videocard_e videocard, VideoType_e type)
|
||||
{
|
||||
g_pPaletteRGB = PaletteRGB_NTSC;
|
||||
if (type==VideoType_e::VT_COLOR_VIDEOCARD_RGB && videocard == RGB_Videocard_e::LeChatMauve_Feline)
|
||||
{
|
||||
g_pPaletteRGB = PaletteRGB_Feline;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
|
||||
static UINT g_rgbFlags = 0;
|
||||
static UINT g_rgbMode = 0;
|
||||
static WORD g_rgbPrevAN3Addr = 0;
|
||||
|
@ -745,13 +1216,14 @@ static bool g_rgbInvertBit7 = false;
|
|||
// . NB. There's a final 5th AN3 transition to set DHGR mode
|
||||
void RGB_SetVideoMode(WORD address)
|
||||
{
|
||||
if ((address&~1) == 0x0C) // 0x0C or 0x0D? (80COL)
|
||||
|
||||
if ((address & ~1) == 0x0C) // 0x0C or 0x0D? (80COL)
|
||||
{
|
||||
g_rgbSet80COL = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address&~1) != 0x5E) // 0x5E or 0x5F? (DHIRES)
|
||||
if ((address & ~1) != 0x5E) // 0x5E or 0x5F? (DHIRES)
|
||||
return;
|
||||
|
||||
// Precondition before toggling AN3:
|
||||
|
@ -761,33 +1233,37 @@ void RGB_SetVideoMode(WORD address)
|
|||
// . Apple II desktop sets DHGR B&W mode with HIRES off! (GH#631)
|
||||
// Maybe there is no video-mode precondition?
|
||||
// . After setting 80COL on/off then need a 0x5E->0x5F toggle. So if we see a 0x5F then reset (GH#633)
|
||||
if ((g_uVideoMode & VF_MIXED) || (g_rgbSet80COL && address == 0x5F))
|
||||
{
|
||||
g_rgbMode = 0;
|
||||
g_rgbPrevAN3Addr = 0;
|
||||
g_rgbSet80COL = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (address == 0x5F && g_rgbPrevAN3Addr == 0x5E) // Check for AN3 clock transition
|
||||
// From Video7 patent and Le Chat Mauve manuals (under patent of Video7), no precondition is needed.
|
||||
|
||||
// In Prince of Persia, in the game demo, the RGB card switches to BW DHIRES after the HGR animation with Jaffar.
|
||||
// It's actually the same on real hardware (tested on IIc RGB adapter).
|
||||
|
||||
if (address == 0x5F)
|
||||
{
|
||||
g_rgbFlags = (g_rgbFlags<<1) & 3;
|
||||
g_rgbFlags |= ((g_uVideoMode & VF_80COL) ? 0 : 1); // clock in !80COL
|
||||
g_rgbMode = g_rgbFlags; // latch F2,F1
|
||||
if ((g_rgbPrevAN3Addr == 0x5E) && g_rgbSet80COL)
|
||||
{
|
||||
g_rgbFlags = (g_rgbFlags << 1) & 3;
|
||||
g_rgbFlags |= ((g_uVideoMode & VF_80COL) ? 0 : 1); // clock in !80COL
|
||||
g_rgbMode = g_rgbFlags; // latch F2,F1
|
||||
}
|
||||
|
||||
g_rgbSet80COL = false;
|
||||
}
|
||||
|
||||
g_rgbPrevAN3Addr = address;
|
||||
g_rgbSet80COL = false;
|
||||
}
|
||||
|
||||
bool RGB_Is140Mode(void) // Extended 80-Column Text/AppleColor Card's Mode 2
|
||||
{
|
||||
return g_rgbMode == 0;
|
||||
// Feline falls back to this mode instead of 160
|
||||
return g_rgbMode == 0 || (g_RGBVideocard == RGB_Videocard_e::LeChatMauve_Feline && g_rgbMode == 1);
|
||||
}
|
||||
|
||||
bool RGB_Is160Mode(void) // Extended 80-Column Text/AppleColor Card: N/A
|
||||
{
|
||||
return g_rgbMode == 1;
|
||||
// Unsupported by Feline
|
||||
return g_rgbMode == 1 && (g_RGBVideocard != RGB_Videocard_e::LeChatMauve_Feline);
|
||||
}
|
||||
|
||||
bool RGB_IsMixMode(void) // Extended 80-Column Text/AppleColor Card's Mode 3
|
||||
|
@ -856,3 +1332,50 @@ void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT cardVersion)
|
|||
|
||||
yamlLoadHelper.PopMap();
|
||||
}
|
||||
|
||||
RGB_Videocard_e RGB_GetVideocard(void)
|
||||
{
|
||||
return g_RGBVideocard;
|
||||
}
|
||||
|
||||
void RGB_SetVideocard(RGB_Videocard_e videocard, int text_foreground, int text_background)
|
||||
{
|
||||
g_RGBVideocard = videocard;
|
||||
|
||||
// black & white text
|
||||
RGB_SetRegularTextFG(15);
|
||||
RGB_SetRegularTextBG(0);
|
||||
|
||||
if (videocard == RGB_Videocard_e::Video7_SL7 &&
|
||||
(text_foreground == 6 || text_foreground == 9 || text_foreground == 12 || text_foreground == 15))
|
||||
{
|
||||
// SL7: Only Blue, Amber (Orange), Green, White are supported by hardware switches
|
||||
RGB_SetRegularTextFG(text_foreground);
|
||||
RGB_SetRegularTextBG(0);
|
||||
}
|
||||
}
|
||||
|
||||
void RGB_SetRegularTextFG(int color)
|
||||
{
|
||||
g_nRegularTextFG = color;
|
||||
}
|
||||
|
||||
void RGB_SetRegularTextBG(int color)
|
||||
{
|
||||
g_nRegularTextBG = color;
|
||||
}
|
||||
|
||||
void RGB_EnableTextFB()
|
||||
{
|
||||
g_nTextFBMode = 1;
|
||||
}
|
||||
|
||||
void RGB_DisableTextFB()
|
||||
{
|
||||
g_nTextFBMode = 0;
|
||||
}
|
||||
|
||||
int RGB_IsTextFB()
|
||||
{
|
||||
return g_nTextFBMode;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,30 @@
|
|||
// Handling of RGB videocards
|
||||
|
||||
enum RGB_Videocard_e
|
||||
{
|
||||
Apple,
|
||||
Video7_SL7,
|
||||
LeChatMauve_EVE,
|
||||
LeChatMauve_Feline
|
||||
};
|
||||
|
||||
|
||||
void UpdateHiResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool updateAux, bool updateMain);
|
||||
void UpdateDHiResCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool updateAux, bool updateMain);
|
||||
void UpdateDHiResCellRGB(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool isMixMode, bool isBit7Inversed);
|
||||
int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateLoResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateDLoResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character);
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character);
|
||||
void UpdateHiResDuochromeCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress);
|
||||
void UpdateDuochromeCell(int h, int w, bgra_t* pVideoAddress, uint8_t bits, uint8_t foreground, uint8_t background);
|
||||
void UpdateHiResRGBCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress);
|
||||
|
||||
const UINT kNumBaseColors = 16;
|
||||
typedef bgra_t (*baseColors_t)[kNumBaseColors];
|
||||
void VideoInitializeOriginal(baseColors_t pBaseNtscColors);
|
||||
void VideoSwitchVideocardPalette(RGB_Videocard_e videocard, VideoType_e type);
|
||||
|
||||
void RGB_SetVideoMode(WORD address);
|
||||
bool RGB_Is140Mode(void);
|
||||
|
@ -19,3 +37,11 @@ void RGB_SetInvertBit7(bool state);
|
|||
|
||||
void RGB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void RGB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT cardVersion);
|
||||
|
||||
RGB_Videocard_e RGB_GetVideocard(void);
|
||||
void RGB_SetVideocard(RGB_Videocard_e videocard, int text_foreground = -1, int text_background = -1);
|
||||
void RGB_SetRegularTextFG(int color);
|
||||
void RGB_SetRegularTextBG(int color);
|
||||
void RGB_EnableTextFB();
|
||||
void RGB_DisableTextFB();
|
||||
int RGB_IsTextFB();
|
||||
|
|
|
@ -28,10 +28,30 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "StdAfx.h"
|
||||
|
||||
extern std::string g_sConfigFile;
|
||||
|
||||
namespace _ini {
|
||||
//===========================================================================
|
||||
BOOL RegLoadString(LPCTSTR section, LPCTSTR key, BOOL peruser, LPTSTR buffer, DWORD chars)
|
||||
{
|
||||
DWORD n = GetPrivateProfileString(section, key, NULL, buffer, chars, g_sConfigFile.c_str());
|
||||
return n > 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void RegSaveString(LPCTSTR section, LPCTSTR key, BOOL peruser, const std::string& buffer)
|
||||
{
|
||||
BOOL updated = WritePrivateProfileString(section, key, buffer.c_str(), g_sConfigFile.c_str());
|
||||
_ASSERT(updated || GetLastError() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL RegLoadString (LPCTSTR section, LPCTSTR key, BOOL peruser, LPTSTR buffer, DWORD chars)
|
||||
{
|
||||
if (!g_sConfigFile.empty())
|
||||
return _ini::RegLoadString(section, key, peruser, buffer, chars);
|
||||
|
||||
TCHAR fullkeyname[256];
|
||||
StringCbPrintf(fullkeyname, 256, TEXT("Software\\AppleWin\\CurrentVersion\\%s"), section);
|
||||
|
||||
|
@ -88,6 +108,9 @@ BOOL RegLoadValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD* value, DWO
|
|||
|
||||
//===========================================================================
|
||||
void RegSaveString (LPCTSTR section, LPCTSTR key, BOOL peruser, const std::string & buffer) {
|
||||
if (!g_sConfigFile.empty())
|
||||
return _ini::RegSaveString(section, key, peruser, buffer);
|
||||
|
||||
TCHAR fullkeyname[256];
|
||||
StringCbPrintf(fullkeyname, 256, TEXT("Software\\AppleWin\\CurrentVersion\\%s"), section);
|
||||
|
||||
|
@ -122,3 +145,4 @@ void RegSaveValue (LPCTSTR section, LPCTSTR key, BOOL peruser, DWORD value) {
|
|||
StringCbPrintf(buffer, 32, "%d", value);
|
||||
RegSaveString(section, key, peruser, buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ static DWORD dwDataOffset;
|
|||
static DWORD g_dwTotalNumberOfBytesWritten = 0;
|
||||
static unsigned int g_NumChannels = 2;
|
||||
|
||||
int RiffInitWriteFile(char* pszFile, unsigned int sample_rate, unsigned int NumChannels)
|
||||
int 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);
|
||||
|
||||
|
@ -117,7 +117,7 @@ int RiffFinishWriteFile()
|
|||
return CloseHandle(g_hRiffFile);
|
||||
}
|
||||
|
||||
int RiffPutSamples(short* buf, unsigned int uSamples)
|
||||
int RiffPutSamples(const short* buf, unsigned int uSamples)
|
||||
{
|
||||
if(g_hRiffFile == INVALID_HANDLE_VALUE)
|
||||
return 1;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
int RiffInitWriteFile(char* pszFile, unsigned int sample_rate, unsigned int NumChannels);
|
||||
int RiffInitWriteFile(const char* pszFile, unsigned int sample_rate, unsigned int NumChannels);
|
||||
int RiffFinishWriteFile();
|
||||
int RiffPutSamples(short* buf, unsigned int uSamples);
|
||||
int RiffPutSamples(const short* buf, unsigned int uSamples);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue