From ffa41e35ccf73e05cebf618650ef42c4dbd6b048 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 17 Mar 2019 15:01:51 +0000 Subject: [PATCH 1/7] Added test cmd-line switch: -screenshot-and-exit --- source/Applewin.cpp | 12 ++++++++++++ source/Video.cpp | 16 +++++++++++++--- source/Video.h | 3 ++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index a28c5f74..a69a138a 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -1179,6 +1179,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) int newVideoType = -1; int newVideoStyleEnableMask = 0; int newVideoStyleDisableMask = 0; + LPSTR szScreenshotFilename = NULL; while (*lpCmdLine) { @@ -1415,6 +1416,11 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) { newVideoStyleDisableMask = VS_COLOR_VERTICAL_BLEND; } + else if (strcmp(lpCmdLine, "-screenshot-and-exit") == 0) // GH#616: For testing - Use in combination with -load-state + { + szScreenshotFilename = GetCurrArg(lpNextArg); + lpNextArg = GetNextArg(lpNextArg); + } else // unsupported { LogFileOutput("Unsupported arg: %s\n", lpCmdLine); @@ -1655,6 +1661,12 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) LogFileOutput("Main: Snapshot_Startup()\n"); } + if (szScreenshotFilename) + { + Video_RedrawAndTakeScreenShot(szScreenshotFilename); + bShutdown = true; + } + if (bShutdown) { PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down diff --git a/source/Video.cpp b/source/Video.cpp index 6185f131..f65d2168 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -127,7 +127,7 @@ static const bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL) bool g_bShowPrintScreenWarningDialog = true; void Util_MakeScreenShotFileName( char *pFinalFileName_ ); bool Util_TestScreenShotFileName( const char *pFileName ); - void Video_SaveScreenShot( const char *pScreenShotFileName, const VideoScreenShot_e ScreenShotType ); + void Video_SaveScreenShot( const VideoScreenShot_e ScreenShotType, const char *pScreenShotFileName ); void Video_MakeScreenShot( FILE *pFile, const VideoScreenShot_e ScreenShotType ); void videoCreateDIBSection(); @@ -959,10 +959,20 @@ void Video_TakeScreenShot( const VideoScreenShot_e ScreenShotType ) g_nLastScreenShot++; } - Video_SaveScreenShot( sScreenShotFileName, ScreenShotType ); + Video_SaveScreenShot( ScreenShotType, sScreenShotFileName ); g_nLastScreenShot++; } +void Video_RedrawAndTakeScreenShot( const char* pScreenshotFilename ) +{ + _ASSERT(pScreenshotFilename); + if (!pScreenshotFilename) + return; + + VideoRedrawScreen(); + Video_SaveScreenShot( SCREENSHOT_560x384, pScreenshotFilename ); +} + WinBmpHeader_t g_tBmpHeader; #if SCREENSHOT_TGA @@ -1121,7 +1131,7 @@ static void Video_MakeScreenShot(FILE *pFile, const VideoScreenShot_e ScreenShot } //=========================================================================== -static void Video_SaveScreenShot( const char *pScreenShotFileName, const VideoScreenShot_e ScreenShotType ) +static void Video_SaveScreenShot( const VideoScreenShot_e ScreenShotType, const char *pScreenShotFileName ) { FILE *pFile = fopen( pScreenShotFileName, "wb" ); if( pFile ) diff --git a/source/Video.h b/source/Video.h index 69888c14..2a7e2253 100644 --- a/source/Video.h +++ b/source/Video.h @@ -204,7 +204,8 @@ enum VideoScreenShot_e SCREENSHOT_560x384 = 0, SCREENSHOT_280x192 }; -void Video_TakeScreenShot( VideoScreenShot_e iScreenShotType ); +void Video_TakeScreenShot( VideoScreenShot_e ScreenShotType ); +void Video_RedrawAndTakeScreenShot( const char* pScreenshotFilename ); void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel ); BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles); From 7096a0a05aef421bcfcbc92ea8cc8bfb048ce3ac Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 6 Apr 2019 11:18:48 +0100 Subject: [PATCH 2/7] Support Enhanced //e soft switches (fixes #636) . IOUDIS, RDIOUDIS, RDDHIRES Also: . Persist annunciators to save-state . Fix so that $C07X trigger paddles 555 timers reset (before was just $C070) --- source/Common.h | 13 +++++--- source/Memory.cpp | 79 ++++++++++++++++++++++++++++++++------------ source/Memory.h | 1 + source/SaveState.cpp | 6 +++- 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/source/Common.h b/source/Common.h index 3a0eaabe..f72fbfa4 100644 --- a/source/Common.h +++ b/source/Common.h @@ -163,8 +163,8 @@ enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE}; #define APPLECLONE_MASK 0x100 #define IS_APPLE2 ((g_Apple2Type & (APPLE2E_MASK|APPLE2C_MASK)) == 0) -#define IS_APPLE2E (g_Apple2Type & APPLE2E_MASK) -#define IS_APPLE2C (g_Apple2Type & APPLE2C_MASK) +#define IS_APPLE2E() (g_Apple2Type & APPLE2E_MASK) +#define IS_APPLE2C() (g_Apple2Type & APPLE2C_MASK) #define IS_CLONE() (g_Apple2Type & APPLECLONE_MASK) // NB. These get persisted to the Registry & save-state file, so don't change the values for these enums! @@ -215,9 +215,14 @@ inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+ or clone ][,][ } extern eApple2Type g_Apple2Type; -inline bool IsOriginal2E(void) +inline bool IsEnhancedIIE(void) { - return (g_Apple2Type == A2TYPE_APPLE2E); + return ( (g_Apple2Type == A2TYPE_APPLE2EENHANCED) || (g_Apple2Type == A2TYPE_TK30002E) ); +} + +inline bool IsEnhancedIIEorIIC(void) +{ + return ( (g_Apple2Type == A2TYPE_APPLE2EENHANCED) || (g_Apple2Type == A2TYPE_TK30002E) || IS_APPLE2C() ); } enum eBUTTON {BUTTON0=0, BUTTON1}; diff --git a/source/Memory.cpp b/source/Memory.cpp index 88bfa9cc..7beca0b3 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -75,6 +75,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define SW_SLOTC3ROM (memmode & MF_SLOTC3ROM) #define SW_INTCXROM (memmode & MF_INTCXROM) #define SW_WRITERAM (memmode & MF_WRITERAM) +#define SW_IOUDIS (memmode & MF_IOUDIS) /* MEMORY MANAGEMENT SOFT SWITCHES @@ -90,6 +91,8 @@ MEMORY MANAGEMENT SOFT SWITCHES $C009 W ALTZPON Enable aux memory from $0000-$01FF & avl BSR $C00A W SLOTC3ROMOFF Enable main ROM from $C300-$C3FF $C00B W SLOTC3ROMON Enable slot ROM from $C300-$C3FF + $C07E W IOUDIS [Enhanced //e] On: disable IOU access for addresses $C058 to $C05F; enable access to DHIRES switch + $C07F W IOUDIS [Enhanced //e] Off: enable IOU access for addresses $C058 to $C05F; disable access to DHIRES switch VIDEO SOFT SWITCHES $C00C W 80COLOFF Turn off 80 column display @@ -104,6 +107,8 @@ VIDEO SOFT SWITCHES $C055 R/W PAGE2ON Select page2 display (or aux video memory) $C056 R/W HIRESOFF Select low resolution graphics $C057 R/W HIRESON Select high resolution graphics + $C05E R/W DHIRESOFF Select single (7M) resolution graphics + $C05F R/W DHIRESON Select double (14M) resolution graphics SOFT SWITCH STATUS FLAGS $C010 R7 AKD 1=key pressed 0=keys free (clears strobe) @@ -122,6 +127,8 @@ SOFT SWITCH STATUS FLAGS $C01D R7 HIRES 1=high resolution graphics 0=low resolution $C01E R7 ALTCHARSET 1=alt character set on 0=alt char set off $C01F R7 80COL 1=80 col display on 0=80 col display off + $C07E R7 RDIOUDIS [Enhanced //e] 1=IOUDIS off 0=IOUDIS on + $C07F R7 RDDHIRES [Enhanced //e] 1=DHIRES on 0=DHIRES off */ @@ -211,6 +218,9 @@ static UINT g_uActiveBank = 0; // 0 = aux 64K for: //e extended 80 Col card, static LPBYTE RWpages[kMaxExMemoryBanks]; // pointers to RW memory banks #endif +static const UINT kNumAnnunciators = 4; +static bool g_Annunciator[kNumAnnunciators] = {}; + BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles); //============================================================================= @@ -468,8 +478,9 @@ static BYTE __stdcall IORead_C05x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG case 0xB: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); case 0xC: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); case 0xD: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); - case 0xE: return VideoSetMode(pc, addr, bWrite, d, nExecutedCycles); - case 0xF: return VideoSetMode(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); } return 0; @@ -493,8 +504,9 @@ static BYTE __stdcall IOWrite_C05x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON case 0xB: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); case 0xC: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); case 0xD: return IO_Annunciator(pc, addr, bWrite, d, nExecutedCycles); - case 0xE: return VideoSetMode(pc, addr, bWrite, d, nExecutedCycles); - case 0xF: return VideoSetMode(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); } return 0; @@ -556,8 +568,10 @@ static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG case 0xB: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0xC: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0xD: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); - case 0xE: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); - case 0xF: return MemReadFloatingBus(VideoGetSWDHIRES(), nExecutedCycles); + case 0xE: return IsEnhancedIIE() ? MemReadFloatingBus(SW_IOUDIS ? true : false, nExecutedCycles) // GH#636 + : IO_Null(pc, addr, bWrite, d, nExecutedCycles); + case 0xF: return IsEnhancedIIEorIIC() ? MemReadFloatingBus(VideoGetSWDHIRES(), nExecutedCycles) // GH#636 + : IO_Null(pc, addr, bWrite, d, nExecutedCycles); } return 0; @@ -565,9 +579,12 @@ static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG static BYTE __stdcall IOWrite_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { + // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle time and resets the VBLINT(*)." (*) //c only! + JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); + switch (addr & 0xf) { - case 0x0: return JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); + case 0x0: break; #ifdef RAMWORKS case 0x1: return MemSetPaging(pc, addr, bWrite, d, nExecutedCycles); // extended memory card set page case 0x2: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); @@ -587,15 +604,16 @@ static BYTE __stdcall IOWrite_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON case 0xB: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0xC: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0xD: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); - - //http://www.kreativekorp.com/miscpages/a2info/iomemory.shtml - //- Apparently Apple//e & //c (but maybe enhanced//e not //e?) - //IOUDISON (W): $C07E Disable IOU - //IOUDISOFF (W): $C07F Enable IOU - //RDIOUDIS (R7): $C07E Status of IOU Disabling - //RDDHIRES (R7): $C07F Status of Double HiRes - case 0xE: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); // TODO: IOUDIS - case 0xF: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); // TODO: IOUDIS + case 0xE: if (IsEnhancedIIE()) + SetMemMode(memmode & ~MF_IOUDIS); // disable IOU access for addresses $C058 to $C05F; enable access to DHIRES switch + else + return IO_Null(pc, addr, bWrite, d, nExecutedCycles); + break; + case 0xF: if (IsEnhancedIIE()) + SetMemMode(memmode | MF_IOUDIS); // enable IOU access for addresses $C058 to $C05F; disable access to DHIRES switch + else + return IO_Null(pc, addr, bWrite, d, nExecutedCycles); + break; } return 0; @@ -649,12 +667,15 @@ BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nExecutedCycles) { // Apple//e ROM: - // . PC=FA6F: LDA $C058 (SETAN0) - // . PC=FA72: LDA $C05A (SETAN1) - // . PC=C2B5: LDA $C05D (CLRAN2) + // . $FA6F: LDA $C058 (SETAN0) ; AN0 = TTL LO + // . $FA72: LDA $C05A (SETAN1) ; AN1 = TTL LO + // . $C2B5: LDA $C05D (CLRAN2) ;SETUP + // . $C2B8: LDA $C05F (CLRAN3) ; ANNUNCIATORS // NB. AN3: For //e & //c these locations are now used to enabled/disabled DHIRES + g_Annunciator[(address>>1) & 3] = (address&1) ? true : false; + if (address >= 0xC058 && address <= 0xC05B) { JoyportControl(address & 0x3); // AN0 and AN1 control @@ -1997,7 +2018,7 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE bool MemOptimizeForModeChanging(WORD programcounter, WORD address) { - if (IS_APPLE2E) + if (IS_APPLE2E()) { // 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 @@ -2044,6 +2065,7 @@ LPVOID MemGetSlotParameters(UINT uSlot) #define SS_YAML_KEY_IOSELECT_INT "IO_SELECT_InternalROM" // INTC8ROM #define SS_YAML_KEY_EXPANSIONROMTYPE "Expansion ROM Type" #define SS_YAML_KEY_PERIPHERALROMSLOT "Peripheral ROM Slot" +#define SS_YAML_KEY_ANNUNCIATOR "Annunciator" // @@ -2117,6 +2139,12 @@ void MemSaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT_INT, INTC8ROM ? 1 : 0); yamlSaveHelper.SaveUint(SS_YAML_KEY_EXPANSIONROMTYPE, (UINT) g_eExpansionRomType); yamlSaveHelper.SaveUint(SS_YAML_KEY_PERIPHERALROMSLOT, g_uPeripheralRomSlot); + + for (UINT i=0; i Date: Sat, 6 Apr 2019 11:26:33 +0100 Subject: [PATCH 3/7] Fix read so that trigger paddles 555 timers reset (before was just ) --- source/Memory.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Memory.cpp b/source/Memory.cpp index 7beca0b3..9b63b340 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -552,9 +552,12 @@ static BYTE __stdcall IOWrite_C06x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { + // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle time and resets the VBLINT(*)." (*) //c only! + JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C07X Analog input reset + switch (addr & 0xf) { - case 0x0: return JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C070 Analog input reset + case 0x0: break; case 0x1: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0x2: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0x3: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); @@ -580,7 +583,7 @@ static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG static BYTE __stdcall IOWrite_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle time and resets the VBLINT(*)." (*) //c only! - JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); + JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C07X Analog input reset switch (addr & 0xf) { From ec36eae817c2bfe5f4f9a8645d0715d5f14a66b2 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 6 Apr 2019 13:44:52 +0100 Subject: [PATCH 4/7] Updates for DHGR MIX and B&W modes (#631): . Relax the video-mode precondition to just checking VF_MIXED . In DHGR B&W mode, then HGR screen is also B&W . For '50% scan lines', don't blend in NTSC B&W mode (as this was inconsistent with the RGB colour rendering), and DHGR MIX mode would look odd! --- source/NTSC.cpp | 24 ++++++++++++++++++++---- source/RGBMonitor.cpp | 4 +++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/source/NTSC.cpp b/source/NTSC.cpp index ea3f70b2..95e7c54f 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -659,8 +659,8 @@ inline void updateFramebufferMonitorSingleScanline( uint16_t signal, bgra_t *pTa /* */ uint32_t *pLine0Address = getScanlineThis0Address(); /* */ uint32_t *pLine1Address = getScanlineNext1Address(); const uint32_t color0 = getScanlineColor( signal, pTable ); - const uint32_t color1 = ((color0 & 0x00fcfcfc) >> 2); // 25% Blend (original) -// const uint32_t color1 = ((color0 & 0x00fefefe) >> 1); // 50% Blend -- looks OK most of the time; Archon looks poor + const uint32_t color1 = 0; // Remove blending for consistent DHGR MIX mode (GH#631) +// const uint32_t color1 = ((color0 & 0x00fcfcfc) >> 2); // 25% Blend (original) /* */ *pLine1Address = color1 | ALPHA32_MASK; /* */ *pLine0Address = color0; @@ -1591,8 +1591,24 @@ static void updateScreenSingleHires40Simplified (long cycles6502) else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START) { uint16_t addr = getVideoScannerAddressHGR(); - UpdateHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress); - g_pVideoAddress += 14; + + if (!RGB_Is560Mode()) + { + UpdateHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress); + g_pVideoAddress += 14; + } + else // Color Burst is off - duplicate code from updateScreenSingleHires40() (GH#631) + { + uint8_t *pMain = MemGetMainPtr(addr); + uint8_t m = pMain[0]; + uint16_t bits = g_aPixelDoubleMaskHGR[m & 0x7F]; // Optimization: hgrbits second 128 entries are mirror of first 128 + if (m & 0x80) + bits = (bits << 1) | g_nLastColumnPixelNTSC; + updatePixels( bits ); + + if (g_nVideoClockHorz == (VIDEO_SCANNER_MAX_HORZ-1)) + g_nLastColumnPixelNTSC = 0; + } } } updateVideoScannerHorzEOLSimple(); diff --git a/source/RGBMonitor.cpp b/source/RGBMonitor.cpp index 3c0f5787..81d41d34 100644 --- a/source/RGBMonitor.cpp +++ b/source/RGBMonitor.cpp @@ -752,7 +752,9 @@ void RGB_SetVideoMode(WORD address) // . Video7 manual: set 80STORE, but "King's Quest 1"(*) will re-enable RGB card's MIX mode with only VF_TEXT & VF_HIRES set! // . "Extended 80-Column Text/AppleColor Card" manual: TEXT off($C050), MIXED off($C052), HIRES on($C057) // . (*) "King's Quest 1" - see routine at 0x5FD7 (trigger by pressing TAB twice) - if ((g_uVideoMode & (VF_MIXED|VF_HIRES)) != (VF_HIRES)) + // . Apple II desktop sets DHGR B&W mode with HIRES off! (GH#631) + // Maybe there is no video-mode precondition? + if (g_uVideoMode & VF_MIXED) { g_rgbMode = 0; g_rgbPrevAN3Addr = 0; From 2463aae54588a726a2edbdaa14e147fc7c19fa5e Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 6 Apr 2019 15:17:18 +0100 Subject: [PATCH 5/7] Updates for DHGR MIX and detection (#633): . Support DHGR MIX mode and AN2 off to invert bit7 (undocumented) . Improve the video-mode precondition to check for 80COL access occurring before $C05F --- source/Memory.cpp | 34 +++++++++++++++++++++------------- source/Memory.h | 5 +++-- source/NTSC.cpp | 6 ++++++ source/RGBMonitor.cpp | 21 ++++++++++++++++++--- source/RGBMonitor.h | 2 +- 5 files changed, 49 insertions(+), 19 deletions(-) diff --git a/source/Memory.cpp b/source/Memory.cpp index 9b63b340..5c551104 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -2058,6 +2058,13 @@ LPVOID MemGetSlotParameters(UINT uSlot) //=========================================================================== +bool MemGetAnnunciator(UINT annunciator) +{ + return g_Annunciator[annunciator]; +} + +//=========================================================================== + // 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. @@ -2078,7 +2085,8 @@ static const UINT kUNIT_AUXSLOT_VER = 2; // Unit version history: // 2: Added: RGB card state -static const UINT kUNIT_VER = 2; +// 3: Extended: RGB card state ('80COL changed') +static const UINT kUNIT_CARD_VER = 3; #define SS_YAML_VALUE_CARD_80COL "80 Column" #define SS_YAML_VALUE_CARD_EXTENDED80COL "Extended 80 Column" @@ -2156,14 +2164,14 @@ void MemSaveSnapshot(YamlSaveHelper& yamlSaveHelper) MemSaveSnapshotMemory(yamlSaveHelper, true); } -bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) +bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT unitVersion) { if (!yamlLoadHelper.GetSubMap(MemGetSnapshotStructName())) return false; // Create default LC type for AppleII machine (do prior to loading saved LC state) ResetDefaultMachineMemTypes(); - if (version == 1) + if (unitVersion == 1) g_MemTypeAppleII = CT_LanguageCard; // version=1: original Apple II always has a LC else g_MemTypeAppleIIPlus = CT_Empty; // version=2+: Apple II/II+ initially start with slot-0 empty @@ -2178,7 +2186,7 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) g_eExpansionRomType = (eExpansionRomType) yamlLoadHelper.LoadUint(SS_YAML_KEY_EXPANSIONROMTYPE); g_uPeripheralRomSlot = yamlLoadHelper.LoadUint(SS_YAML_KEY_PERIPHERALROMSLOT); - if (version == 1) + if (unitVersion == 1) { SetMemMode( yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE) ^ MF_INTCXROM ); // Convert from SLOTCXROM to INTCXROM SetLastRamWrite( yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE ); @@ -2194,7 +2202,7 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) SetLastRamWrite( yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE ); // NB. This is set later for II,II+ by slot-0 LC or Saturn } - if (version == 3) + if (unitVersion == 3) { for (UINT i=0; i kUNIT_AUXSLOT_VER) + if (unitVersion < 1 || unitVersion > kUNIT_AUXSLOT_VER) throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Version mismatch"); - if (version == 1) + if (unitVersion == 1) MemLoadSnapshotAuxVer1(yamlLoadHelper); else - MemLoadSnapshotAuxVer2(yamlLoadHelper, version); + MemLoadSnapshotAuxVer2(yamlLoadHelper); return true; } diff --git a/source/Memory.h b/source/Memory.h index 6f4c440f..8e2a4a58 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -80,11 +80,12 @@ void MemReset (); void MemResetPaging (); void MemUpdatePaging(BOOL initialize); LPVOID MemGetSlotParameters (UINT uSlot); +bool MemGetAnnunciator(UINT annunciator); std::string MemGetSnapshotUnitAuxSlotName(void); void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); -bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version); +bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion); void MemSaveSnapshotAux(class YamlSaveHelper& yamlSaveHelper); -bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT version); +bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion); BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles); diff --git a/source/NTSC.cpp b/source/NTSC.cpp index 95e7c54f..186e3ba5 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -1378,6 +1378,12 @@ void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblH uint8_t a = *MemGetAuxPtr(addr); uint8_t m = *MemGetMainPtr(addr); + if (RGB_IsMixMode() && !MemGetAnnunciator(2)) // AN2 inverts high bit? (GH#633) + { + a ^= 0x80; + m ^= 0x80; + } + if (RGB_Is160Mode()) { int width = UpdateDHiRes160Cell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress); diff --git a/source/RGBMonitor.cpp b/source/RGBMonitor.cpp index 81d41d34..93a8a0db 100644 --- a/source/RGBMonitor.cpp +++ b/source/RGBMonitor.cpp @@ -738,6 +738,7 @@ void VideoInitializeOriginal(baseColors_t pBaseNtscColors) static UINT g_rgbFlags = 0; static UINT g_rgbMode = 0; static WORD g_rgbPrevAN3Addr = 0; +static bool g_rgbSet80COL = false; // Video7 RGB card: // . Clock in the !80COL state to define the 2 flags: F2, F1 @@ -745,7 +746,13 @@ static WORD g_rgbPrevAN3Addr = 0; // . NB. There's a final 5th AN3 transition to set DHGR mode void RGB_SetVideoMode(WORD address) { - if ((address&~1) != 0x5E) // 0x5E or 0x5F? + if ((address&~1) == 0x0C) // 0x0C or 0x0D? (80COL) + { + g_rgbSet80COL = true; + return; + } + + if ((address&~1) != 0x5E) // 0x5E or 0x5F? (DHIRES) return; // Precondition before toggling AN3: @@ -754,10 +761,12 @@ void RGB_SetVideoMode(WORD address) // . (*) "King's Quest 1" - see routine at 0x5FD7 (trigger by pressing TAB twice) // . Apple II desktop sets DHGR B&W mode with HIRES off! (GH#631) // Maybe there is no video-mode precondition? - if (g_uVideoMode & VF_MIXED) + // . 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; } @@ -769,6 +778,7 @@ void RGB_SetVideoMode(WORD address) } g_rgbPrevAN3Addr = address; + g_rgbSet80COL = false; } bool RGB_Is140Mode(void) // Extended 80-Column Text/AppleColor Card's Mode 2 @@ -806,6 +816,7 @@ void RGB_ResetState(void) #define SS_YAML_KEY_RGB_FLAGS "RGB mode flags" #define SS_YAML_KEY_RGB_MODE "RGB mode" #define SS_YAML_KEY_RGB_PREVIOUS_AN3 "Previous AN3" +#define SS_YAML_KEY_RGB_80COL_CHANGED "80COL changed" void RGB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper) { @@ -814,9 +825,10 @@ void RGB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_RGB_FLAGS, g_rgbFlags); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_RGB_MODE, g_rgbMode); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_RGB_PREVIOUS_AN3, g_rgbPrevAN3Addr); + yamlSaveHelper.SaveBool(SS_YAML_KEY_RGB_80COL_CHANGED, g_rgbSet80COL); } -void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper) +void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT cardVersion) { if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_RGB_CARD)) throw std::string("Card: Expected key: ") + std::string(SS_YAML_KEY_RGB_CARD); @@ -825,5 +837,8 @@ void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper) g_rgbMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_RGB_MODE); g_rgbPrevAN3Addr = yamlLoadHelper.LoadUint(SS_YAML_KEY_RGB_PREVIOUS_AN3); + if (cardVersion >= 3) + g_rgbSet80COL = yamlLoadHelper.LoadBool(SS_YAML_KEY_RGB_80COL_CHANGED); + yamlLoadHelper.PopMap(); } diff --git a/source/RGBMonitor.h b/source/RGBMonitor.h index 0f7a16b8..b6b26ab7 100644 --- a/source/RGBMonitor.h +++ b/source/RGBMonitor.h @@ -16,4 +16,4 @@ bool RGB_Is560Mode(void); void RGB_ResetState(void); void RGB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper); -void RGB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper); +void RGB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT cardVersion); From dad590b8c14cc84313919044764ecadb5d40bcda Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 6 Apr 2019 17:31:26 +0100 Subject: [PATCH 6/7] Bumped to 1.28.5.0 and updated History.txt Updates for DHGR MIX (#633): . Support new switch -rgb-card-invert-bit7 to invert bit7 for Dragon Wars. - Reverted DHGR MIX mode and AN2 off to invert bit7 --- bin/History.txt | 12 ++++++++++++ help/CommandLine.html | 10 +++++++--- resource/version.h | 2 +- source/Applewin.cpp | 5 +++++ source/NTSC.cpp | 2 +- source/RGBMonitor.cpp | 16 ++++++++++++++++ source/RGBMonitor.h | 2 ++ 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/bin/History.txt b/bin/History.txt index d969fd36..4578fb44 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -8,6 +8,18 @@ https://github.com/AppleWin/AppleWin/issues/new Tom Charlesworth + +1.28.5.0 - 6 Apr 2019 +--------------------- +. [Change #631] Improvements for the RGB AppleColor card: + - Relax the video-mode precondition to just ignore if VF_MIXED (previously required HIRES on) for Apple II Desktop. + - Changing from DHGR B&W mode to HGR remains in B&W (color burst if off). + - For '50% scan lines', don't blend in NTSC B&W mode, as this was inconsistent with the RGB colour rendering. +. [Change #633] Improvements for the RGB AppleColor card: + - Improved the video-mode precondition to ignore if 80COL ($C00C/D) occurs before DHIRESON ($C05F) for Renegade. + - Support new switch -rgb-card-invert-bit7 to invert bit7 for Dragon Wars. + + 1.28.4.0 - 16 Mar 2019 ---------------------- . [Change #616] Improved accuracy for 'RGB (Color Monitor)' for hires. diff --git a/help/CommandLine.html b/help/CommandLine.html index f6dec26e..aca64edb 100644 --- a/help/CommandLine.html +++ b/help/CommandLine.html @@ -97,15 +97,19 @@
  • Either: Toggle between windowed and full screen video modes (default).
  • Or: Allow the emulated Apple II to read the Enter key state when Alt (Open Apple key) is pressed. + -rgb-card-invert-bit7
    + Force the RGB card (in "Color (RGB Monitor)" video mode) to invert bit7 in MIX mode. Enables the correct rendering for Dragon Wars.

    Debug arguments:

    -l or -log
    - Enable logging. Creates an AppleWin.log file

    + Enable logging. Creates an AppleWin.log file.

    -m
    - Disable DirectSound support

    + Disable DirectSound support.

    -no-printscreen-dlg
    - Suppress the warning message-box if AppleWin fails to capture the PrintScreen key

    + Suppress the warning message-box if AppleWin fails to capture the PrintScreen key.

    + -screenshot-and-exit
    + For testing. Use in combination with -load-state.

    diff --git a/resource/version.h b/resource/version.h index ec8ebb7a..4b56dec7 100644 --- a/resource/version.h +++ b/resource/version.h @@ -1,4 +1,4 @@ -#define APPLEWIN_VERSION 1,28,4,0 +#define APPLEWIN_VERSION 1,28,5,0 #define xstr(a) str(a) #define str(a) #a diff --git a/source/Applewin.cpp b/source/Applewin.cpp index a69a138a..4cf53765 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -53,6 +53,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Speech.h" #endif #include "Video.h" +#include "RGBMonitor.h" #include "NTSC.h" #include "Configuration/About.h" @@ -1416,6 +1417,10 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) { newVideoStyleDisableMask = VS_COLOR_VERTICAL_BLEND; } + else if (strcmp(lpCmdLine, "-rgb-card-invert-bit7") == 0) // GH#633 + { + RGB_SetInvertBit7(true); + } else if (strcmp(lpCmdLine, "-screenshot-and-exit") == 0) // GH#616: For testing - Use in combination with -load-state { szScreenshotFilename = GetCurrArg(lpNextArg); diff --git a/source/NTSC.cpp b/source/NTSC.cpp index 186e3ba5..fe7b7c82 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -1378,7 +1378,7 @@ void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblH uint8_t a = *MemGetAuxPtr(addr); uint8_t m = *MemGetMainPtr(addr); - if (RGB_IsMixMode() && !MemGetAnnunciator(2)) // AN2 inverts high bit? (GH#633) + if (RGB_IsMixModeInvertBit7()) // Invert high bit? (GH#633) { a ^= 0x80; m ^= 0x80; diff --git a/source/RGBMonitor.cpp b/source/RGBMonitor.cpp index 93a8a0db..3312b3a6 100644 --- a/source/RGBMonitor.cpp +++ b/source/RGBMonitor.cpp @@ -739,6 +739,7 @@ static UINT g_rgbFlags = 0; static UINT g_rgbMode = 0; static WORD g_rgbPrevAN3Addr = 0; static bool g_rgbSet80COL = false; +static bool g_rgbInvertBit7 = false; // Video7 RGB card: // . Clock in the !80COL state to define the 2 flags: F2, F1 @@ -801,6 +802,11 @@ bool RGB_Is560Mode(void) // Extended 80-Column Text/AppleColor Card's Mode 1 return g_rgbMode == 3; } +bool RGB_IsMixModeInvertBit7(void) +{ + return RGB_IsMixMode() && g_rgbInvertBit7; +} + void RGB_ResetState(void) { g_rgbFlags = 0; @@ -808,6 +814,11 @@ void RGB_ResetState(void) g_rgbPrevAN3Addr = 0; } +void RGB_SetInvertBit7(bool state) +{ + g_rgbInvertBit7 = state; +} + //=========================================================================== #define SS_YAML_KEY_RGB_CARD "AppleColor RGB Adaptor" @@ -817,6 +828,7 @@ void RGB_ResetState(void) #define SS_YAML_KEY_RGB_MODE "RGB mode" #define SS_YAML_KEY_RGB_PREVIOUS_AN3 "Previous AN3" #define SS_YAML_KEY_RGB_80COL_CHANGED "80COL changed" +#define SS_YAML_KEY_RGB_INVERT_BIT7 "Invert bit7" void RGB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper) { @@ -826,6 +838,7 @@ void RGB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_RGB_MODE, g_rgbMode); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_RGB_PREVIOUS_AN3, g_rgbPrevAN3Addr); yamlSaveHelper.SaveBool(SS_YAML_KEY_RGB_80COL_CHANGED, g_rgbSet80COL); + yamlSaveHelper.SaveBool(SS_YAML_KEY_RGB_INVERT_BIT7, g_rgbInvertBit7); } void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT cardVersion) @@ -838,7 +851,10 @@ void RGB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT cardVersion) g_rgbPrevAN3Addr = yamlLoadHelper.LoadUint(SS_YAML_KEY_RGB_PREVIOUS_AN3); if (cardVersion >= 3) + { g_rgbSet80COL = yamlLoadHelper.LoadBool(SS_YAML_KEY_RGB_80COL_CHANGED); + g_rgbInvertBit7 = yamlLoadHelper.LoadBool(SS_YAML_KEY_RGB_INVERT_BIT7); + } yamlLoadHelper.PopMap(); } diff --git a/source/RGBMonitor.h b/source/RGBMonitor.h index b6b26ab7..14cb72c0 100644 --- a/source/RGBMonitor.h +++ b/source/RGBMonitor.h @@ -13,7 +13,9 @@ bool RGB_Is140Mode(void); bool RGB_Is160Mode(void); bool RGB_IsMixMode(void); bool RGB_Is560Mode(void); +bool RGB_IsMixModeInvertBit7(void); void RGB_ResetState(void); +void RGB_SetInvertBit7(bool state); void RGB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper); void RGB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT cardVersion); From adcfb9ef3d346ca22de09b5b367bf63257c3b826 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 6 Apr 2019 18:23:42 +0100 Subject: [PATCH 7/7] Fix reads to $C07X to return floating bus (broke at 7c95c0f6c4) --- source/Joystick.cpp | 4 +--- source/Joystick.h | 2 +- source/Memory.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/source/Joystick.cpp b/source/Joystick.cpp index 30e77c23..a7edb82a 100644 --- a/source/Joystick.cpp +++ b/source/Joystick.cpp @@ -643,7 +643,7 @@ void JoyReset() } //=========================================================================== -BYTE __stdcall JoyResetPosition(WORD, WORD, BYTE, BYTE, ULONG nExecutedCycles) +void JoyResetPosition(ULONG nExecutedCycles) { CpuCalcCycles(nExecutedCycles); g_nJoyCntrResetCycle = g_nCumulativeCycles; @@ -652,8 +652,6 @@ BYTE __stdcall JoyResetPosition(WORD, WORD, BYTE, BYTE, ULONG nExecutedCycles) CheckJoystick0(); if((joyinfo[joytype[1]] == DEVICE_JOYSTICK) || (joyinfo[joytype[1]] == DEVICE_JOYSTICK_THUMBSTICK2)) CheckJoystick1(); - - return MemReadFloatingBus(nExecutedCycles); } //=========================================================================== diff --git a/source/Joystick.h b/source/Joystick.h index 09f322c9..668d650a 100644 --- a/source/Joystick.h +++ b/source/Joystick.h @@ -30,4 +30,4 @@ void JoyLoadSnapshot(class YamlLoadHelper& yamlLoadHelper); BYTE __stdcall JoyReadButton(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles); BYTE __stdcall JoyReadPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles); -BYTE __stdcall JoyResetPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles); +void JoyResetPosition(ULONG nExecutedCycles); diff --git a/source/Memory.cpp b/source/Memory.cpp index 5c551104..5457e991 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -552,12 +552,12 @@ static BYTE __stdcall IOWrite_C06x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { - // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle time and resets the VBLINT(*)." (*) //c only! - JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C07X Analog input reset + // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle timer and resets the VBLINT(*)." (*) //c only! + JoyResetPosition(nExecutedCycles); //$C07X Analog input reset switch (addr & 0xf) { - case 0x0: break; + case 0x0: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0x1: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0x2: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); case 0x3: return IO_Null(pc, addr, bWrite, d, nExecutedCycles); @@ -582,8 +582,8 @@ static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG static BYTE __stdcall IOWrite_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { - // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle time and resets the VBLINT(*)." (*) //c only! - JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C07X Analog input reset + // Apple//e TRM, pg-258: "Reading or writing any address in the range $C070-$C07F also triggers the paddle timer and resets the VBLINT(*)." (*) //c only! + JoyResetPosition(nExecutedCycles); //$C07X Analog input reset switch (addr & 0xf) {