Merge tag 'v1.28.5.0'

This commit is contained in:
Andrea Odetti 2019-04-19 21:07:30 +01:00
commit e04d5cac04
15 changed files with 219 additions and 61 deletions

View file

@ -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.

View file

@ -97,15 +97,19 @@
<li>Either: Toggle between windowed and full screen video modes (default).
<li>Or: Allow the emulated Apple II to read the Enter key state when Alt (Open Apple key) is pressed.
</ul>
-rgb-card-invert-bit7<br>
Force the RGB card (in "Color (RGB Monitor)" video mode) to invert bit7 in MIX mode. Enables the correct rendering for Dragon Wars.
<br>
<P style="FONT-WEIGHT: bold">Debug arguments:
</P>
-l or -log<br>
Enable logging. Creates an AppleWin.log file<br><br>
Enable logging. Creates an AppleWin.log file.<br><br>
-m<br>
Disable DirectSound support<br><br>
Disable DirectSound support.<br><br>
-no-printscreen-dlg<br>
Suppress the warning message-box if AppleWin fails to capture the PrintScreen key<br><br>
Suppress the warning message-box if AppleWin fails to capture the PrintScreen key.<br><br>
-screenshot-and-exit<br>
For testing. Use in combination with -load-state.<br><br>
</body>
</html>

View file

@ -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

View file

@ -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"
@ -1179,6 +1180,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 +1417,15 @@ 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);
lpNextArg = GetNextArg(lpNextArg);
}
else // unsupported
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
@ -1655,6 +1666,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

View file

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

View file

@ -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);
}
//===========================================================================

View file

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

View file

@ -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;
@ -540,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 timer and resets the VBLINT(*)." (*) //c only!
JoyResetPosition(nExecutedCycles); //$C07X Analog input reset
switch (addr & 0xf)
{
case 0x0: return JoyResetPosition(pc, addr, bWrite, d, nExecutedCycles); //$C070 Analog input reset
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);
@ -556,8 +571,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 +582,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 timer and resets the VBLINT(*)." (*) //c only!
JoyResetPosition(nExecutedCycles); //$C07X Analog input reset
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 +607,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 +670,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 +2021,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
@ -2034,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.
@ -2044,6 +2075,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"
//
@ -2053,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"
@ -2117,6 +2150,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<kNumAnnunciators; i++)
{
std::string annunciator = SS_YAML_KEY_ANNUNCIATOR + std::string(1,'0'+i);
yamlSaveHelper.SaveBool(annunciator.c_str(), g_Annunciator[i]);
}
}
if (IsApple2PlusOrClone(GetApple2Type()))
@ -2125,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
@ -2147,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 );
@ -2163,6 +2202,15 @@ 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 (unitVersion == 3)
{
for (UINT i=0; i<kNumAnnunciators; i++)
{
std::string annunciator = SS_YAML_KEY_ANNUNCIATOR + std::string(1,'0'+i);
g_Annunciator[i] = yamlLoadHelper.LoadBool(annunciator.c_str());
}
}
yamlLoadHelper.PopMap();
//
@ -2173,7 +2221,7 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
memset(memmain+0xC000, 0, LanguageCardSlot0::kMemBankSize); // Clear it, as high 16K may not be in the save-state's "Main Memory" (eg. the case of II+ Saturn replacing //e LC)
yamlLoadHelper.LoadMemory(memmain, _6502_MEM_END+1);
if (version == 1 && IsApple2PlusOrClone(GetApple2Type()))
if (unitVersion == 1 && IsApple2PlusOrClone(GetApple2Type()))
{
// v1 for II/II+ doesn't have a dedicated slot-0 LC, instead the 16K is stored as the top 16K of memmain
memcpy(g_pMemMainLanguageCard, memmain+0xC000, LanguageCardSlot0::kMemBankSize);
@ -2200,7 +2248,7 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
return; // No Aux slot for AppleII
}
if (IS_APPLE2C)
if (IS_APPLE2C())
{
_ASSERT(g_uMaxExPages == 1);
}
@ -2216,7 +2264,7 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
SS_YAML_VALUE_CARD_RAMWORKSIII;
yamlSaveHelper.SaveString(SS_YAML_KEY_CARD, card.c_str());
yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_VERSION, kUNIT_VER);
yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_VERSION, kUNIT_CARD_VER);
// Card state
{
@ -2308,7 +2356,7 @@ static void MemLoadSnapshotAuxVer1(YamlLoadHelper& yamlLoadHelper)
MemLoadSnapshotAuxCommon(yamlLoadHelper, card);
}
static void MemLoadSnapshotAuxVer2(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
static void MemLoadSnapshotAuxVer2(YamlLoadHelper& yamlLoadHelper)
{
std::string card = yamlLoadHelper.LoadString(SS_YAML_KEY_CARD);
UINT cardVersion = yamlLoadHelper.LoadUint(SS_YAML_KEY_VERSION);
@ -2318,18 +2366,18 @@ static void MemLoadSnapshotAuxVer2(YamlLoadHelper& yamlLoadHelper, UINT unitVers
MemLoadSnapshotAuxCommon(yamlLoadHelper, card);
RGB_LoadSnapshot(yamlLoadHelper);
RGB_LoadSnapshot(yamlLoadHelper, cardVersion);
}
bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT version)
bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
{
if (version < 1 || version > 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;
}

View file

@ -14,6 +14,7 @@
#define MF_SLOTC3ROM 0x00000100
#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_IMAGEMASK 0x000003F7
#define MF_LANGCARD_MASK (MF_WRITERAM|MF_HIGHRAM|MF_BANK2)
@ -81,11 +82,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);

View file

@ -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;
@ -1378,6 +1378,12 @@ void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblH
uint8_t a = *MemGetAuxPtr(addr);
uint8_t m = *MemGetMainPtr(addr);
if (RGB_IsMixModeInvertBit7()) // Invert 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);
@ -1591,9 +1597,25 @@ static void updateScreenSingleHires40Simplified (long cycles6502)
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
{
uint16_t addr = getVideoScannerAddressHGR();
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();
}

View file

@ -738,6 +738,8 @@ 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;
static bool g_rgbInvertBit7 = false;
// Video7 RGB card:
// . Clock in the !80COL state to define the 2 flags: F2, F1
@ -745,17 +747,27 @@ 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:
// . 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?
// . 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;
}
@ -767,6 +779,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
@ -789,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;
@ -796,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"
@ -804,6 +827,8 @@ 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"
#define SS_YAML_KEY_RGB_INVERT_BIT7 "Invert bit7"
void RGB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
@ -812,9 +837,11 @@ 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);
yamlSaveHelper.SaveBool(SS_YAML_KEY_RGB_INVERT_BIT7, g_rgbInvertBit7);
}
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);
@ -823,5 +850,11 @@ 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);
g_rgbInvertBit7 = yamlLoadHelper.LoadBool(SS_YAML_KEY_RGB_INVERT_BIT7);
}
yamlLoadHelper.PopMap();
}

View file

@ -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);
void RGB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT cardVersion);

View file

@ -64,7 +64,11 @@ static YamlHelper yamlHelper;
#define SS_FILE_VER 2
#define UNIT_APPLE2_VER 2
// Unit version history:
// v2: Extended: keyboard (added 'Key Waiting'), memory (LC mem type for II/II+, inverted MF_INTCXROM bit)
// v3: Extended: memory (added 'AnnunciatorN')
#define UNIT_APPLE2_VER 3
#define UNIT_SLOTS_VER 1
//-----------------------------------------------------------------------------

View file

@ -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 )

View file

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