Merge tag 'v1.28.0.0'
# Conflicts: # source/SaveState.cpp Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
commit
2ee0a01959
42 changed files with 1098 additions and 468 deletions
|
@ -913,6 +913,14 @@
|
|||
RelativePath=".\source\Video.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Video_OriginalColorTVMode.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Video_OriginalColorTVMode.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Configuration"
|
||||
|
|
|
@ -8,9 +8,22 @@ https://github.com/AppleWin/AppleWin/issues/new
|
|||
|
||||
Tom Charlesworth
|
||||
|
||||
|
||||
1.28.0.0 - 12 Jan 2019
|
||||
----------------------
|
||||
. [Change #357] Resurrected the AppleWin 1.25 "Color (Standard)" video mode as "Color (RGB Monitor)".
|
||||
- This is equivalent to emulating RGB video, ie. a video mode with sharp text and pixels.
|
||||
- NB. Unlike AppleWin 1.25, this is now cycle-accurate, so demos that synchronise with the video scanner will work correctly.
|
||||
. [Change #603] Removed support for v1 save-state files.
|
||||
- Any v1 save-state files should be loaded into AppleWin 1.27, and then re-saved to a v2 save-state file.
|
||||
. [Change #597] Removed the functionality for CTRL+F10 to reveal the mouse cursor.
|
||||
. [Change #585] Added a 'Swap' HDD button to the Configuration->Input property sheet.
|
||||
. [Bug #608] Mockingboard's 6522 TIMER1 wasn't generating an interrupt quickly enough for Broadside's detection routine.
|
||||
|
||||
|
||||
1.27.13.0 - 8 Dec 2018
|
||||
----------------------
|
||||
. [Bug #599] Fix for Ultima V not loading in Authentic Speed mode (regression introduced at 1.27.9.0).
|
||||
. [Bug #303, #599] Fix for Ultima V not loading in Authentic Speed mode (regression introduced at 1.27.9.0).
|
||||
. [Change #205] Added support for Apple II/II+ custom 2K video ROMs.
|
||||
- Extended command line switch: -videorom <file>
|
||||
- If the ROM size is 2K, then it replaces the video ROM for the Apple II/II+.
|
||||
|
|
|
@ -46,8 +46,7 @@
|
|||
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 Enhanced //e.<br>
|
||||
NB. There's currently no support for using an alternate video ROM for the original Apple //e or clones.<br><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>
|
||||
-printscreen<br>
|
||||
Enable the dialog box to display the last file saved to<br><br>
|
||||
-no-printscreen-key<br>
|
||||
|
|
|
@ -1,23 +1,13 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
|
||||
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
|
||||
|
||||
<title>Disk Settings</title>
|
||||
</head>
|
||||
|
||||
|
||||
<body style="background-color: rgb(255, 255, 255); font-family: verdana;" alink="#008000" link="#008000" vlink="#008000">
|
||||
|
||||
|
||||
<h2 style="color: rgb(0, 128, 0);">Disk Settings</h2>
|
||||
|
||||
|
||||
<hr size="4"><img style="width: 344px; height: 460px; float: right;" src="img/disk.png" alt="Disk settings" hspace="5" vspace="5">
|
||||
|
||||
<h3>Floppy Controller Settings:</h3>
|
||||
<p><strong>Disk Access Speed:</strong><br>
|
||||
Here you can choose the speed at which the system can access
|
||||
|
@ -26,14 +16,14 @@ By default, you would want "Enhanced Speed" so that data can
|
|||
be accessed as fast as possible. However, it is also possible that
|
||||
certain programs might depend on the "Authentic Speed" to function
|
||||
properly. This is the speed at which the real hardware
|
||||
would access data from your drives.</p>
|
||||
|
||||
would access data from your drives.
|
||||
</p>
|
||||
|
||||
<p><strong>Disk 1/2 drop-down menus:</strong><br>
|
||||
|
||||
These menus allow you to select floppy disk images (.dsk files) to
|
||||
'insert' into the
|
||||
emulated floppy drives 1 and 2. This can also be done during emulation by <a href="toolbar.html">using the toolbar</a> or using the F3/F4 keys. Diskettes can be swapped by pressing F5 during emulation. You can also eject images from this menu.</p>
|
||||
emulated floppy drives 1 and 2. This can also be done during emulation by <a href="toolbar.html">using the toolbar</a> or using the F3/F4 keys. Diskettes can be swapped by pressing F5 during emulation. You can also eject images from this menu.
|
||||
</p>
|
||||
|
||||
|
||||
<h3>Hard disk Controller Settings:</h3>
|
||||
|
@ -42,16 +32,20 @@ A hard disk controller (or interface) card can be plugged in to slot 7 by checki
|
|||
See <a href="ddi-harddisk.html">Hard disk Images</a> for more details.
|
||||
</p>
|
||||
|
||||
<p><strong>Swap:</strong><br>
|
||||
Swap the hard disk images.<br>
|
||||
WARNING! If done during image access this could result in undefined behavior (eg. Apple II program crash) or data corruption on the image.
|
||||
</p>
|
||||
|
||||
<p><strong>HDD 1/2 drop-down menus:</strong><br>
|
||||
|
||||
These menus allow you to select hard disk images (eg. .hdv files) to
|
||||
connect to the emulated hard disk controller card. You can also unplug images from this menu.</p>
|
||||
|
||||
|
||||
<strong>Path to CiderPress:</strong><br>
|
||||
connect to the emulated hard disk controller card. You can also unplug images from this menu.
|
||||
</p>
|
||||
|
||||
<p><strong>Path to CiderPress:</strong><br>
|
||||
Use this to specify where CiderPress is installed.<br>
|
||||
The right mouse button context menu on either of the drive icons allows you to open CiderPress with the image in the drive.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Transferring Disk Images</title>
|
||||
<title>Hard Disk Images</title>
|
||||
|
||||
|
||||
</head>
|
||||
|
@ -20,8 +20,9 @@
|
|||
Just check <span style="font-style: italic;">Enable hard disk controller in slot 7</span>.</p>
|
||||
|
||||
<p>There is provision to connect two hard disks to this card.
|
||||
This is done by using .hdv files on your PC.
|
||||
This is done by using .hdv or 800KB .2mg files on your PC.
|
||||
Each hard disk can have a maximum capacity of 32MB.</p>
|
||||
NB. The hard disk controller supports both fixed-disk types (up to 32MB) and 3.5" floppy types (800KB).
|
||||
|
||||
<p>On booting, the Apple will <span style="text-decoration: underline;">always</span>
|
||||
attempt to
|
||||
|
@ -33,9 +34,6 @@ interface card in it).</p>
|
|||
<p>To boot a floppy disk with the hard disk card enabled, either hold down the Open-Apple key during an Apple II restart or
|
||||
issue PR#6 from an AppleSoft prompt.</p>
|
||||
|
||||
<p>You can download sample .hdv
|
||||
images from Asimov (eg. <a target="_blank" href="ftp://public.asimov.net/pub/apple_II/">ftp://public.asimov.net/pub/apple_II/images/utility/misc/hardpc.zip</a>).</p>
|
||||
|
||||
<p style="font-weight: bold;">Warnings:</p>
|
||||
|
||||
<ul>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
@ -74,6 +74,8 @@
|
|||
Copy the text screen (auto detect 40/80 columns) to the clipboard.</p>
|
||||
<p><span style="font-weight: bold;">Alt+Enter:</span><br>
|
||||
Default: Toggle between windowed and full screen video modes. (NB. Will conflict with emulation and prevent Open Apple + Enter from being readable. Use the <a href="CommandLine.html">Command Line</a> switch to allow Open Apple + Enter to be readable.)</p>
|
||||
<p><span style="font-weight: bold;">Ctrl+Left Mouse Button:</span><br>
|
||||
This will show the Windows mouse cursor when emulating an Apple joystick with the PC's mouse or using a Mouse card.<br>
|
||||
<p><span style="font-weight: bold;">Function Keys F1-F8:</span><br>
|
||||
These PC function keys correspond to buttons on the <a href="toolbar.html">toolbar</a>.</p>
|
||||
<p><span style="font-weight: bold;">Function Key F2 + Ctrl:</span><br>
|
||||
|
@ -89,9 +91,6 @@
|
|||
<p><span style="font-weight: bold;">Function Key F10:</span><br>
|
||||
In //e or Enhanced //e emulation mode it will emulate the rocker switch for European video ROM selection. Use the <a href="CommandLine.html">Command Line</a> switch to use an alternate European video ROM file.<br>
|
||||
In Pravets 8A emulation mode it servers as Caps Lock.</p>
|
||||
<p><span style="font-weight: bold;">Function Key F10 + Ctrl (or Ctrl+left mouse button):</span><br>
|
||||
This PC function key combo will stop emulating an Apple joystick with the PC's mouse.<br>
|
||||
<p><span style="font-weight: bold;">Function Keys F11-F12:</span><br>
|
||||
These PC function keys correspond to saving/loading a <a href="savestate.html">save-state</a>
|
||||
file.</p>
|
||||
<p><span style="font-weight: bold;">Function Keys F11-F12:</span><br>
|
||||
These PC function keys correspond to saving/loading a <a href="savestate.html">save-state</a> file.</p>
|
||||
</body></html>
|
|
@ -12,7 +12,7 @@
|
|||
Copyright © 1994-1996, Michael O'Brien<br>
|
||||
Copyright © 2001, Oliver Schmidt<br>
|
||||
Copyright © 2002-2005, Tom Charlesworth<BR>
|
||||
Copyright © 2006-2018, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis
|
||||
Copyright © 2006-2019, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis
|
||||
<br>
|
||||
<br>
|
||||
<a href="applewin-team.html">AppleWin team</a>
|
||||
|
|
|
@ -175,6 +175,7 @@ BEGIN
|
|||
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
|
||||
|
@ -274,7 +275,7 @@ BEGIN
|
|||
VALUE "FileDescription", "Apple //e Emulator for Windows"
|
||||
VALUE "FileVersion", APPLEWIN_VERSION_STR
|
||||
VALUE "InternalName", "APPLEWIN"
|
||||
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
|
||||
VALUE "LegalCopyright", " 1994-2019 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
|
||||
VALUE "OriginalFilename", "APPLEWIN.EXE"
|
||||
VALUE "ProductName", "Apple //e Emulator"
|
||||
VALUE "ProductVersion", APPLEWIN_VERSION_STR
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#define IDC_EDIT_HDD1 1019
|
||||
#define IDC_EDIT_HDD2 1020
|
||||
#define IDC_HDD_ENABLE 1021
|
||||
#define IDC_HDD_SWAP 1022
|
||||
#define IDC_SPIN_XTRIM 1026
|
||||
#define IDC_SPIN_YTRIM 1027
|
||||
#define IDC_PHASOR_ENABLE 1029
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define APPLEWIN_VERSION 1,27,13,0
|
||||
#define APPLEWIN_VERSION 1,28,0,0
|
||||
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
|
|
|
@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
static UINT16 g_AppleWinVersion[4] = {0};
|
||||
char VERSIONSTRING[16] = "xx.yy.zz.ww";
|
||||
static UINT16 g_OldAppleWinVersion[4] = {0};
|
||||
|
||||
const TCHAR *g_pAppTitle = NULL;
|
||||
|
||||
|
@ -164,9 +165,9 @@ void SetApple2Type(eApple2Type type)
|
|||
SetMainCpuDefault(type);
|
||||
}
|
||||
|
||||
const UINT16* GetAppleWinVersion(void)
|
||||
const UINT16* GetOldAppleWinVersion(void)
|
||||
{
|
||||
return &g_AppleWinVersion[0];
|
||||
return g_OldAppleWinVersion;
|
||||
}
|
||||
|
||||
bool GetLoadedSaveStateFlag(void)
|
||||
|
@ -1134,6 +1135,29 @@ static void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBo
|
|||
MessageBox(g_hFrameWindow, "Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
|
||||
}
|
||||
|
||||
static bool CheckOldAppleWinVersion(void)
|
||||
{
|
||||
char szOldAppleWinVersion[sizeof(VERSIONSTRING)] = {0};
|
||||
RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, szOldAppleWinVersion, sizeof(szOldAppleWinVersion));
|
||||
const bool bShowAboutDlg = strcmp(szOldAppleWinVersion, VERSIONSTRING) != 0;
|
||||
|
||||
// version: xx.yy.zz.ww
|
||||
// offset : 0123456789
|
||||
char* p0 = szOldAppleWinVersion;
|
||||
szOldAppleWinVersion[strlen(szOldAppleWinVersion)] = '.'; // Overwrite null terminator with '.'
|
||||
for (UINT i=0; i<4; i++)
|
||||
{
|
||||
char* p1 = strstr(p0, ".");
|
||||
if (!p1)
|
||||
break;
|
||||
*p1 = 0;
|
||||
g_OldAppleWinVersion[i] = atoi(p0);
|
||||
p0 = p1+1;
|
||||
}
|
||||
|
||||
return bShowAboutDlg;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
|
@ -1477,6 +1501,9 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
|||
g_bRestart = false;
|
||||
ResetToLogoMode();
|
||||
|
||||
// NB. g_OldAppleWinVersion needed by LoadConfiguration() -> Config_Load_Video()
|
||||
const bool bShowAboutDlg = CheckOldAppleWinVersion(); // Post: g_OldAppleWinVersion
|
||||
|
||||
LoadConfiguration();
|
||||
LogFileOutput("Main: LoadConfiguration()\n");
|
||||
|
||||
|
@ -1531,10 +1558,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
|||
MemInitialize();
|
||||
LogFileOutput("Main: MemInitialize()\n");
|
||||
|
||||
char szOldAppleWinVersion[sizeof(VERSIONSTRING)] = {0};
|
||||
RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, szOldAppleWinVersion, sizeof(szOldAppleWinVersion));
|
||||
|
||||
const bool bShowAboutDlg = strcmp(szOldAppleWinVersion, VERSIONSTRING) != 0;
|
||||
// Show About dialog after creating main window (need g_hFrameWindow)
|
||||
if (bShowAboutDlg)
|
||||
{
|
||||
if (!AboutDlg())
|
||||
|
|
|
@ -9,7 +9,7 @@ void LogFileTimeUntilFirstKeyRead(void);
|
|||
void SetCurrentCLK6502();
|
||||
bool SetCurrentImageDir(const char* pszImageDir);
|
||||
|
||||
extern const UINT16* GetAppleWinVersion(void);
|
||||
extern const UINT16* GetOldAppleWinVersion(void);
|
||||
extern char VERSIONSTRING[]; // Constructed in WinMain()
|
||||
|
||||
extern const TCHAR *g_pAppTitle;
|
||||
|
|
|
@ -427,6 +427,13 @@ static __forceinline void CheckInterruptSources(ULONG uExecutedCycles)
|
|||
}
|
||||
}
|
||||
|
||||
// GH#608: IRQ needs to occur within 17 cycles (6 opcodes) of configuring the timer interrupt
|
||||
void CpuAdjustIrqCheck(UINT uCyclesUntilInterrupt)
|
||||
{
|
||||
if (uCyclesUntilInterrupt < IRQ_CHECK_TIMEOUT)
|
||||
g_nIrqCheckTimeout = uCyclesUntilInterrupt;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
|
@ -650,22 +657,6 @@ void CpuReset()
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void CpuSetSnapshot_v1(const BYTE A, const BYTE X, const BYTE Y, const BYTE P, const BYTE SP, const USHORT PC, const unsigned __int64 CumulativeCycles)
|
||||
{
|
||||
regs.a = A;
|
||||
regs.x = X;
|
||||
regs.y = Y;
|
||||
regs.ps = P | (AF_RESERVED | AF_BREAK);
|
||||
regs.sp = ((USHORT)SP) | 0x100;
|
||||
regs.pc = PC;
|
||||
|
||||
CpuIrqReset();
|
||||
CpuNmiReset();
|
||||
g_nCumulativeCycles = CumulativeCycles;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_CPU_TYPE "Type"
|
||||
#define SS_YAML_KEY_REGA "A"
|
||||
#define SS_YAML_KEY_REGX "X"
|
||||
|
|
|
@ -14,6 +14,7 @@ struct regsrec
|
|||
extern regsrec regs;
|
||||
extern unsigned __int64 g_nCumulativeCycles;
|
||||
|
||||
void CpuAdjustIrqCheck(UINT uCyclesUntilInterrupt);
|
||||
void CpuDestroy ();
|
||||
void CpuCalcCycles(ULONG nExecutedCycles);
|
||||
DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate);
|
||||
|
@ -27,7 +28,6 @@ void CpuNmiReset();
|
|||
void CpuNmiAssert(eIRQSRC Device);
|
||||
void CpuNmiDeassert(eIRQSRC Device);
|
||||
void CpuReset ();
|
||||
void CpuSetSnapshot_v1(const BYTE A, const BYTE X, const BYTE Y, const BYTE P, const BYTE SP, const USHORT PC, const unsigned __int64 CumulativeCycles);
|
||||
void CpuSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void CpuLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
|
|
|
@ -115,7 +115,9 @@ BOOL CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM l
|
|||
case IDC_HDD_ENABLE:
|
||||
EnableHDD(hWnd, IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE));
|
||||
break;
|
||||
|
||||
case IDC_HDD_SWAP:
|
||||
HandleHDDSwap(hWnd);
|
||||
break;
|
||||
case IDC_CIDERPRESS_BROWSE:
|
||||
{
|
||||
std::string CiderPressLoc = m_PropertySheetHelper.BrowseToFile(hWnd, TEXT("Select path to CiderPress"), REGVALUE_CIDERPRESSLOC, TEXT("Applications (*.exe)\0*.exe\0") TEXT("All Files\0*.*\0") );
|
||||
|
@ -131,8 +133,6 @@ BOOL CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM l
|
|||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_DISKTYPE, m_discchoices, Disk_GetEnhanceDisk() ? 1 : 0);
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_DISK1, m_defaultDiskOptions, -1);
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_DISK2, m_defaultDiskOptions, -1);
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD1, m_defaultHDDOptions, -1);
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD2, m_defaultHDDOptions, -1);
|
||||
|
||||
if (strlen(DiskGetFullName(DRIVE_1)) > 0)
|
||||
{
|
||||
|
@ -146,17 +146,7 @@ BOOL CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM l
|
|||
SendDlgItemMessage(hWnd, IDC_COMBO_DISK2, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
if (strlen(HD_GetFullName(HARDDISK_1)) > 0)
|
||||
{
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_1));
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
if (strlen(HD_GetFullName(HARDDISK_2)) > 0)
|
||||
{
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_2));
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
InitComboHDD(hWnd);
|
||||
|
||||
TCHAR PathToCiderPress[MAX_PATH] = "";
|
||||
RegLoadString(TEXT(REG_CONFIG), REGVALUE_CIDERPRESSLOC, 1, PathToCiderPress,MAX_PATH);
|
||||
|
@ -176,6 +166,24 @@ BOOL CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM l
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void CPageDisk::InitComboHDD(HWND hWnd)
|
||||
{
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD1, m_defaultHDDOptions, -1);
|
||||
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD2, m_defaultHDDOptions, -1);
|
||||
|
||||
if (strlen(HD_GetFullName(HARDDISK_1)) > 0)
|
||||
{
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_1));
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
if (strlen(HD_GetFullName(HARDDISK_2)) > 0)
|
||||
{
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_2));
|
||||
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CPageDisk::DlgOK(HWND hWnd)
|
||||
{
|
||||
const bool bNewEnhanceDisk = SendDlgItemMessage(hWnd, IDC_DISKTYPE,CB_GETCURSEL, 0, 0) ? true : false;
|
||||
|
@ -207,6 +215,7 @@ void CPageDisk::EnableHDD(HWND hWnd, BOOL bEnable)
|
|||
{
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_COMBO_HDD1), bEnable);
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_COMBO_HDD2), bEnable);
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_HDD_SWAP), bEnable);
|
||||
}
|
||||
|
||||
void CPageDisk::EnableDisk(HWND hWnd, BOOL bEnable)
|
||||
|
@ -340,19 +349,34 @@ void CPageDisk::HandleDiskCombo(HWND hWnd, UINT driveSelected, UINT comboSelecte
|
|||
}
|
||||
}
|
||||
|
||||
void CPageDisk::HandleHDDSwap(HWND hWnd)
|
||||
{
|
||||
if (!RemovalConfirmation(IDC_HDD_SWAP))
|
||||
return;
|
||||
|
||||
if (!HD_ImageSwap())
|
||||
return;
|
||||
|
||||
InitComboHDD(hWnd);
|
||||
}
|
||||
|
||||
UINT CPageDisk::RemovalConfirmation(UINT uCommand)
|
||||
{
|
||||
TCHAR szText[100];
|
||||
const size_t strLen = sizeof(szText)-1;
|
||||
bool bMsgBox = true;
|
||||
|
||||
if (uCommand == IDC_COMBO_DISK1 || uCommand == IDC_COMBO_DISK2)
|
||||
wsprintf(szText, "Do you really want to eject the disk in drive-%c ?", '1' + uCommand - IDC_COMBO_DISK1);
|
||||
_snprintf(szText, strLen, "Do you really want to eject the disk in drive-%c ?", '1' + uCommand - IDC_COMBO_DISK1);
|
||||
else if (uCommand == IDC_COMBO_HDD1 || uCommand == IDC_COMBO_HDD2)
|
||||
wsprintf(szText, "Do you really want to unplug harddisk-%c ?", '1' + uCommand - IDC_COMBO_HDD1);
|
||||
_snprintf(szText, strLen, "Do you really want to unplug harddisk-%c ?", '1' + uCommand - IDC_COMBO_HDD1);
|
||||
else if (uCommand == IDC_HDD_SWAP)
|
||||
_snprintf(szText, strLen, "Do you really want to swap the harddisk images?");
|
||||
else
|
||||
bMsgBox = false;
|
||||
|
||||
szText[strLen] = 0;
|
||||
|
||||
if (bMsgBox)
|
||||
{
|
||||
int nRes = MessageBox(g_hFrameWindow, szText, TEXT("Eject/Unplug Warning"), MB_ICONWARNING | MB_YESNO | MB_SETFOREGROUND);
|
||||
|
|
|
@ -25,10 +25,12 @@ protected:
|
|||
|
||||
private:
|
||||
void InitOptions(HWND hWnd);
|
||||
void InitComboHDD(HWND hWnd);
|
||||
void EnableHDD(HWND hWnd, BOOL bEnable);
|
||||
void EnableDisk(HWND hWnd, BOOL bEnable);
|
||||
void HandleHDDCombo(HWND hWnd, UINT driveSelected, UINT comboSelected);
|
||||
void HandleDiskCombo(HWND hWnd, UINT driveSelected, UINT comboSelected);
|
||||
void HandleHDDSwap(HWND hWnd);
|
||||
UINT RemovalConfirmation(UINT uCommand);
|
||||
|
||||
static CPageDisk* ms_this;
|
||||
|
|
|
@ -1301,94 +1301,6 @@ static BYTE __stdcall Disk_IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON
|
|||
|
||||
//===========================================================================
|
||||
|
||||
int DiskSetSnapshot_v1(const SS_CARD_DISK2* const pSS)
|
||||
{
|
||||
if(pSS->Hdr.UnitHdr.hdr.v1.dwVersion > MAKE_VERSION(1,0,0,2))
|
||||
return -1;
|
||||
|
||||
phases = pSS->phases;
|
||||
currdrive = pSS->currdrive;
|
||||
//diskaccessed = pSS->diskaccessed; // deprecated
|
||||
enhancedisk = pSS->enhancedisk ? true : false;
|
||||
floppylatch = pSS->floppylatch;
|
||||
floppymotoron = pSS->floppymotoron;
|
||||
floppywritemode = pSS->floppywritemode;
|
||||
|
||||
// Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
|
||||
for(UINT i=0; i<NUM_DRIVES; i++)
|
||||
{
|
||||
DiskEject(i); // Remove any disk & update Registry to reflect empty drive
|
||||
g_aFloppyDrive[i].clear();
|
||||
}
|
||||
|
||||
for(UINT i=0; i<NUM_DRIVES; i++)
|
||||
{
|
||||
if(pSS->Unit[i].szFileName[0] == 0x00)
|
||||
continue;
|
||||
|
||||
DWORD dwAttributes = GetFileAttributes(pSS->Unit[i].szFileName);
|
||||
if(dwAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
// Get user to browse for file
|
||||
DiskSelectImage(i, pSS->Unit[i].szFileName);
|
||||
|
||||
dwAttributes = GetFileAttributes(pSS->Unit[i].szFileName);
|
||||
}
|
||||
|
||||
bool bImageError = false;
|
||||
if(dwAttributes != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
if(DiskInsert(i, pSS->Unit[i].szFileName, dwAttributes & FILE_ATTRIBUTE_READONLY, IMAGE_DONT_CREATE) != eIMAGE_ERROR_NONE)
|
||||
bImageError = true;
|
||||
|
||||
// DiskInsert() sets up:
|
||||
// . imagename
|
||||
// . fullname
|
||||
// . writeprotected
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// strcpy(g_aFloppyDrive[i].fullname, pSS->Unit[i].szFileName);
|
||||
g_aFloppyDrive[i].track = pSS->Unit[i].track;
|
||||
g_aFloppyDrive[i].phase = pSS->Unit[i].phase;
|
||||
g_aFloppyDrive[i].spinning = pSS->Unit[i].spinning;
|
||||
g_aFloppyDrive[i].writelight = pSS->Unit[i].writelight;
|
||||
|
||||
g_aFloppyDrive[i].disk.byte = pSS->Unit[i].byte;
|
||||
// g_aFloppyDrive[i].disk.writeprotected = pSS->Unit[i].writeprotected;
|
||||
g_aFloppyDrive[i].disk.trackimagedata = pSS->Unit[i].trackimagedata ? true : false;
|
||||
g_aFloppyDrive[i].disk.trackimagedirty = pSS->Unit[i].trackimagedirty ? true : false;
|
||||
g_aFloppyDrive[i].disk.nibbles = pSS->Unit[i].nibbles;
|
||||
|
||||
//
|
||||
|
||||
if(!bImageError)
|
||||
{
|
||||
if((g_aFloppyDrive[i].disk.trackimage == NULL) && g_aFloppyDrive[i].disk.nibbles)
|
||||
AllocTrack(i);
|
||||
|
||||
if(g_aFloppyDrive[i].disk.trackimage == NULL)
|
||||
bImageError = true;
|
||||
else
|
||||
memcpy(g_aFloppyDrive[i].disk.trackimage, pSS->Unit[i].nTrack, NIBBLES_PER_TRACK);
|
||||
}
|
||||
|
||||
if(bImageError)
|
||||
{
|
||||
g_aFloppyDrive[i].disk.trackimagedata = false;
|
||||
g_aFloppyDrive[i].disk.trackimagedirty = false;
|
||||
g_aFloppyDrive[i].disk.nibbles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Unit version history:
|
||||
// 2: Added: Format Track state & DiskLastCycle
|
||||
// 3: Added: DiskLastReadLatchCycle
|
||||
|
|
|
@ -72,7 +72,6 @@ void DiskUpdateDriveState(DWORD);
|
|||
bool DiskDriveSwap(void);
|
||||
void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot);
|
||||
|
||||
int DiskSetSnapshot_v1(const struct SS_CARD_DISK2* const pSS);
|
||||
std::string DiskGetSnapshotCardName(void);
|
||||
void DiskSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
bool DiskLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||
|
|
|
@ -1316,11 +1316,7 @@ LRESULT CALLBACK FrameWndProc (
|
|||
}
|
||||
else if (wparam == VK_F10)
|
||||
{
|
||||
if (KeybGetCtrlStatus())
|
||||
{
|
||||
SetUsingCursor(FALSE); // Ctrl+F10
|
||||
}
|
||||
else if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED)
|
||||
if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED)
|
||||
{
|
||||
SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch
|
||||
NTSC_VideoInitAppleType();
|
||||
|
|
|
@ -695,6 +695,18 @@ void HD_GetLightStatus (Disk_Status_e *pDisk1Status_)
|
|||
}
|
||||
}
|
||||
|
||||
bool HD_ImageSwap(void)
|
||||
{
|
||||
std::swap(g_HardDisk[HARDDISK_1], g_HardDisk[HARDDISK_2]);
|
||||
|
||||
HD_SaveLastDiskImage(HARDDISK_1);
|
||||
HD_SaveLastDiskImage(HARDDISK_2);
|
||||
|
||||
FrameRefreshStatus(DRAW_LEDS, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define SS_YAML_VALUE_CARD_HDD "Generic HDD"
|
||||
|
|
|
@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
// 1.19.0.0 Hard Disk Status/Indicator Light
|
||||
void HD_GetLightStatus (Disk_Status_e *pDisk1Status_);
|
||||
bool HD_ImageSwap(void);
|
||||
|
||||
std::string HD_GetSnapshotCardName(void);
|
||||
void HD_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
|
|
|
@ -931,13 +931,6 @@ void JoyportControl(const UINT uControl)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void JoySetSnapshot_v1(const unsigned __int64 JoyCntrResetCycle)
|
||||
{
|
||||
g_nJoyCntrResetCycle = JoyCntrResetCycle;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_COUNTERRESETCYCLE "Counter Reset Cycle"
|
||||
#define SS_YAML_KEY_JOY0TRIMX "Joystick0 TrimX"
|
||||
#define SS_YAML_KEY_JOY0TRIMY "Joystick0 TrimY"
|
||||
|
|
|
@ -25,7 +25,6 @@ void JoySetTrim(short nValue, bool bAxisX);
|
|||
short JoyGetTrim(bool bAxisX);
|
||||
void JoyportControl(const UINT uControl);
|
||||
void JoySetHookAltKeys(bool hook);
|
||||
void JoySetSnapshot_v1(const unsigned __int64 JoyCntrResetCycle);
|
||||
void JoySaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void JoyLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
|
|
|
@ -544,13 +544,6 @@ void KeybToggleP8ACapsLock ()
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void KeybSetSnapshot_v1(const BYTE LastKey)
|
||||
{
|
||||
keycode = LastKey;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_LASTKEY "Last Key"
|
||||
#define SS_YAML_KEY_KEYWAITING "Key Waiting"
|
||||
|
||||
|
|
|
@ -18,6 +18,5 @@ void KeybToggleP8ACapsLock ();
|
|||
void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended);
|
||||
BYTE KeybReadData (void);
|
||||
BYTE KeybReadFlag (void);
|
||||
void KeybSetSnapshot_v1(const BYTE LastKey);
|
||||
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
|
||||
|
|
|
@ -229,7 +229,7 @@ static void ResetDefaultMachineMemTypes(void)
|
|||
g_MemTypeAppleIIe = CT_Extended80Col;
|
||||
}
|
||||
|
||||
// Called from MemInitialize(), MemLoadSnapshot(), MemSetSnapshot_v1()
|
||||
// Called from MemInitialize(), MemLoadSnapshot()
|
||||
static void SetExpansionMemTypeDefault(void)
|
||||
{
|
||||
SS_CARDTYPE defaultType = IsApple2Original(GetApple2Type()) ? g_MemTypeAppleII
|
||||
|
@ -1702,7 +1702,6 @@ inline DWORD getRandomTime()
|
|||
// Called by:
|
||||
// . MemInitialize()
|
||||
// . ResetMachineState() eg. Power-cycle ('Apple-Go' button)
|
||||
// . Snapshot_LoadState_v1()
|
||||
// . Snapshot_LoadState_v2()
|
||||
void MemReset()
|
||||
{
|
||||
|
@ -2037,29 +2036,6 @@ LPVOID MemGetSlotParameters(UINT uSlot)
|
|||
// . 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.
|
||||
|
||||
void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux)
|
||||
{
|
||||
// Create default LC type for AppleII machine (do prior to loading saved LC state)
|
||||
ResetDefaultMachineMemTypes();
|
||||
g_MemTypeAppleII = CT_LanguageCard; // SSv1 doesn't save machine type - so if current machine is Apple II then give it 64K + LC
|
||||
SetExpansionMemTypeDefault();
|
||||
CreateLanguageCard(); // Create LC here, as for SSv1 there is no slot-0 state
|
||||
|
||||
SetMemMode(MemMode ^ MF_INTCXROM); // Convert from SLOTCXROM to INTCXROM
|
||||
SetLastRamWrite(LastWriteRam);
|
||||
|
||||
memcpy(memmain, pMemMain, nMemMainSize);
|
||||
memcpy(memaux, pMemAux, nMemAuxSize);
|
||||
memset(memdirty, 0, 0x100);
|
||||
|
||||
//
|
||||
|
||||
// NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v1()
|
||||
UpdatePaging(1); // Initialize=1
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_MEMORYMODE "Memory Mode"
|
||||
#define SS_YAML_KEY_LASTRAMWRITE "Last RAM Write"
|
||||
#define SS_YAML_KEY_IOSELECT "IO_SELECT"
|
||||
|
|
|
@ -81,7 +81,6 @@ void MemReset ();
|
|||
void MemResetPaging ();
|
||||
void MemUpdatePaging(BOOL initialize);
|
||||
LPVOID MemGetSlotParameters (UINT uSlot);
|
||||
void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux);
|
||||
std::string MemGetSnapshotUnitAuxSlotName(void);
|
||||
void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
|
||||
|
|
|
@ -427,6 +427,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w;
|
||||
|
||||
StartTimer1(pMB);
|
||||
CpuAdjustIrqCheck(pMB->sy6522.TIMER1_LATCH.w); // Sync IRQ check timeout with 6522 counter underflow - GH#608
|
||||
break;
|
||||
case 0x07: // TIMER1H_LATCH
|
||||
// Clear Timer1 Interrupt Flag.
|
||||
|
@ -444,6 +445,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
|||
pMB->sy6522.TIMER2_COUNTER.w = pMB->sy6522.TIMER2_LATCH.w;
|
||||
|
||||
StartTimer2(pMB);
|
||||
CpuAdjustIrqCheck(pMB->sy6522.TIMER1_LATCH.w); // Sync IRQ check timeout with 6522 counter underflow - GH#608
|
||||
break;
|
||||
case 0x0a: // SERIAL_SHIFT
|
||||
break;
|
||||
|
@ -1871,52 +1873,6 @@ void MB_GetSnapshot_v1(SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot)
|
|||
}
|
||||
}
|
||||
|
||||
int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dwSlot*/)
|
||||
{
|
||||
if(pSS->Hdr.UnitHdr.hdr.v1.dwVersion != MAKE_VERSION(1,0,0,0))
|
||||
return -1;
|
||||
|
||||
UINT nMbCardNum = pSS->Hdr.Slot - SLOT4;
|
||||
UINT nDeviceNum = nMbCardNum*2;
|
||||
SY6522_AY8910* pMB = &g_MB[nDeviceNum];
|
||||
|
||||
g_nSSI263Device = 0;
|
||||
g_nCurrentActivePhoneme = -1;
|
||||
|
||||
for(UINT i=0; i<MB_UNITS_PER_CARD_v1; i++)
|
||||
{
|
||||
memcpy(&pMB->sy6522, &pSS->Unit[i].RegsSY6522, sizeof(SY6522));
|
||||
memcpy(AY8910_GetRegsPtr(nDeviceNum), &pSS->Unit[i].RegsAY8910, 16);
|
||||
memcpy(&pMB->SpeechChip, &pSS->Unit[i].RegsSSI263, sizeof(SSI263A));
|
||||
pMB->nAYCurrentRegister = pSS->Unit[i].nAYCurrentRegister;
|
||||
pMB->state = AY_INACTIVE;
|
||||
|
||||
StartTimer1_LoadStateV1(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)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
nDeviceNum++;
|
||||
pMB++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Unit version history:
|
||||
|
|
|
@ -18,7 +18,6 @@ DWORD MB_GetVolume();
|
|||
void MB_SetVolume(DWORD dwVolume, DWORD dwVolumeMax);
|
||||
|
||||
void MB_GetSnapshot_v1(struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot); // For debugger
|
||||
int MB_SetSnapshot_v1(const struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot);
|
||||
std::string MB_GetSnapshotCardName(void);
|
||||
void MB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
|
||||
bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||
|
|
249
source/NTSC.cpp
249
source/NTSC.cpp
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Frame.h"
|
||||
#include "Memory.h" // MemGetMainPtr() MemGetAuxPtr()
|
||||
#include "Video.h" // g_pFramebufferbits
|
||||
#include "Video_OriginalColorTVMode.h"
|
||||
|
||||
#include "NTSC.h"
|
||||
#include "NTSC_CharSet.h"
|
||||
|
@ -470,8 +471,8 @@ 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_APPLE2E: csbits = &csbits_2e[0]; break;
|
||||
case A2TYPE_APPLE2EENHANCED:csbits = GetEnhanced2e_csbits(); 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
|
||||
|
@ -745,6 +746,26 @@ inline void updatePixels( uint16_t bits )
|
|||
|
||||
//===========================================================================
|
||||
|
||||
inline void updateVideoScannerHorzEOLSimple()
|
||||
{
|
||||
if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
|
||||
{
|
||||
g_nVideoClockHorz = 0;
|
||||
|
||||
if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
|
||||
{
|
||||
g_nVideoClockVert = 0;
|
||||
|
||||
updateFlashRate();
|
||||
}
|
||||
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
updateVideoScannerAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !EXTEND_14M_VIDEO_BY_1_PIXEL
|
||||
// NOTE: This writes out-of-bounds for a 560x384 framebuffer
|
||||
inline void updateVideoScannerHorzEOL()
|
||||
|
@ -881,8 +902,8 @@ inline void updateVideoScannerAddress()
|
|||
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
|
||||
// NB. For VT_COLOR_MONITOR, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
|
||||
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV || (g_eVideoType == VT_COLOR_MONITOR && GetColorBurst()))
|
||||
// NB. For VT_COLOR_MONITOR_NTSC, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
|
||||
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV || (g_eVideoType == VT_COLOR_MONITOR_NTSC && GetColorBurst()))
|
||||
g_pVideoAddress -= 2;
|
||||
|
||||
// GH#555: For the 14M video modes (DHGR,DGR,80COL), start rendering 1x 14M pixel early to account for these video modes being shifted right by 1 pixel
|
||||
|
@ -890,10 +911,11 @@ inline void updateVideoScannerAddress()
|
|||
// . 7x 14M pixels early + 1x 14M pixel shifted right = 2 complete color phase rotations.
|
||||
// . ie. the 14M colors are correct, but being 1 pixel out is the closest we can get the 7M and 14M video modes to overlap.
|
||||
// . The alternative is to render the 14M correctly 7 pixels early, but have 7-pixel borders left (for 7M modes) or right (for 14M modes).
|
||||
if ((g_pFuncUpdateGraphicsScreen == updateScreenDoubleHires80) ||
|
||||
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_pVideoAddress -= 1;
|
||||
}
|
||||
|
@ -1270,8 +1292,8 @@ inline void zeroPixel0_14M(void) // GH#555
|
|||
if (g_nVideoClockHorz == VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
UINT32* p = ((UINT32*)g_pVideoAddress) - 14; // Point back to pixel-0
|
||||
// NB. For VT_COLOR_MONITOR, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
|
||||
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV || (g_eVideoType == VT_COLOR_MONITOR && GetColorBurst()))
|
||||
// NB. For VT_COLOR_MONITOR_NTSC, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
|
||||
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV || (g_eVideoType == VT_COLOR_MONITOR_NTSC && GetColorBurst()))
|
||||
{
|
||||
p[2] = 0;
|
||||
p[g_kFrameBufferWidth+2] = 0; // Next line (there are 2 lines per Apple II scanline)
|
||||
|
@ -1318,6 +1340,36 @@ void updateScreenDoubleHires40 (long cycles6502) // wsUpdateVideoHires0
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
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();
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
void updateScreenDoubleHires80 (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
|
@ -1396,6 +1448,36 @@ void updateScreenDoubleLores40 (long cycles6502) // wsUpdateVideo7MLores
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void updateScreenDoubleLores80Simplified (long cycles6502) // wsUpdateVideoDblLores
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen( cycles6502 );
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressTXT();
|
||||
|
||||
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 = getVideoScannerAddressTXT();
|
||||
UpdateDLoResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
|
@ -1446,6 +1528,33 @@ void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updateScreenSingleHires40Simplified (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();
|
||||
UpdateHiResCell(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)
|
||||
|
@ -1487,6 +1596,35 @@ void updateScreenSingleHires40 (long cycles6502)
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updateScreenSingleLores40Simplified (long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen( cycles6502 );
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressTXT();
|
||||
|
||||
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 = getVideoScannerAddressTXT();
|
||||
UpdateLoResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
void updateScreenSingleLores40 (long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
|
@ -1582,7 +1720,8 @@ void updateScreenText80 (long cycles6502)
|
|||
aux ^= g_nTextFlashMask;
|
||||
|
||||
uint16_t bits = (main << 7) | (aux & 0x7f);
|
||||
bits = (bits << 1) | g_nLastColumnPixelNTSC; // GH#555: Align TEXT80 chars with DHGR
|
||||
if (g_eVideoType != VT_COLOR_MONITOR_RGB) // No extra 14M bit needed for VT_COLOR_MONITOR_RGB
|
||||
bits = (bits << 1) | g_nLastColumnPixelNTSC; // GH#555: Align TEXT80 chars with DHGR
|
||||
updatePixels( bits );
|
||||
g_nLastColumnPixelNTSC = (bits >> 14) & 1;
|
||||
|
||||
|
@ -1686,38 +1825,71 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags )
|
|||
|
||||
g_nTextPage = 1;
|
||||
g_nHiresPage = 1;
|
||||
if (uVideoModeFlags & VF_PAGE2) {
|
||||
if (uVideoModeFlags & VF_PAGE2)
|
||||
{
|
||||
// Apple IIe, Technical Notes, #3: Double High-Resolution Graphics
|
||||
// 80STORE must be OFF to display page 2
|
||||
if (0 == (uVideoModeFlags & VF_80STORE)) {
|
||||
if (0 == (uVideoModeFlags & VF_80STORE))
|
||||
{
|
||||
g_nTextPage = 2;
|
||||
g_nHiresPage = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (uVideoModeFlags & VF_TEXT) {
|
||||
if (uVideoModeFlags & VF_TEXT)
|
||||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40;
|
||||
}
|
||||
else if (uVideoModeFlags & VF_HIRES) {
|
||||
else if (uVideoModeFlags & VF_HIRES)
|
||||
{
|
||||
if (uVideoModeFlags & VF_DHIRES)
|
||||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80;
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires40;
|
||||
}
|
||||
}
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40;
|
||||
}
|
||||
else {
|
||||
if (uVideoModeFlags & VF_DHIRES)
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80;
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uVideoModeFlags & VF_DHIRES)
|
||||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores40;
|
||||
}
|
||||
}
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40;
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1745,7 +1917,7 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
}
|
||||
break;
|
||||
|
||||
case VT_COLOR_MONITOR:
|
||||
case VT_COLOR_MONITOR_NTSC:
|
||||
default:
|
||||
r = 0xFF;
|
||||
g = 0xFF;
|
||||
|
@ -1776,7 +1948,6 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
}
|
||||
break;
|
||||
|
||||
// case VT_MONO_WHITE: //VT_MONO_MONITOR: //3:
|
||||
case VT_MONO_AMBER:
|
||||
r = 0xFF;
|
||||
g = 0x80;
|
||||
|
@ -1789,6 +1960,7 @@ void NTSC_SetVideoStyle() // (int v, int s)
|
|||
b = 0x00;
|
||||
goto _mono;
|
||||
|
||||
case VT_COLOR_MONITOR_RGB:
|
||||
case VT_MONO_WHITE:
|
||||
r = 0xFF;
|
||||
g = 0xFF;
|
||||
|
@ -1820,6 +1992,7 @@ _mono:
|
|||
|
||||
//===========================================================================
|
||||
void GenerateVideoTables( void );
|
||||
void GenerateBaseColors(baseColors_t pBaseNtscColors);
|
||||
|
||||
void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
|
||||
{
|
||||
|
@ -1842,6 +2015,10 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
|
|||
|
||||
VideoReinitialize(); // Setup g_pFunc_ntsc*Pixel()
|
||||
|
||||
bgra_t baseColors[kNumBaseColors];
|
||||
GenerateBaseColors(&baseColors);
|
||||
VideoInitializeOriginal(&baseColors);
|
||||
|
||||
#if HGR_TEST_PATTERN
|
||||
// Init HGR to almost all-possible-combinations
|
||||
// CALL-151
|
||||
|
@ -2121,3 +2298,31 @@ static void GenerateVideoTables( void )
|
|||
VideoResetState();
|
||||
SetApple2Type(currentApple2Type);
|
||||
}
|
||||
|
||||
void GenerateBaseColors(baseColors_t pBaseNtscColors)
|
||||
{
|
||||
for (UINT i=0; i<16; i++)
|
||||
{
|
||||
g_nColorPhaseNTSC = INITIAL_COLOR_PHASE;
|
||||
g_nSignalBitsNTSC = 0;
|
||||
|
||||
// 12 iterations for colour to "stabilise", then 4 iterations to calc the average
|
||||
// - after colour "stabilises" then it repeats through 4 phases (with different RGB values for each phase)
|
||||
uint32_t bits = (i<<12) | (i<<8) | (i<<4) | i; // 16 bits
|
||||
|
||||
uint32_t colors[4];
|
||||
for (UINT j=0; j<16; j++)
|
||||
{
|
||||
colors[j&3] = getScanlineColor(bits & 1, g_aHueColorTV[g_nColorPhaseNTSC]);
|
||||
bits >>= 1;
|
||||
updateColorPhase();
|
||||
}
|
||||
|
||||
int r = (((colors[0]>>16)&0xff) + ((colors[1]>>16)&0xff) + ((colors[2]>>16)&0xff) + ((colors[3]>>16)&0xff)) / 4;
|
||||
int g = (((colors[0]>> 8)&0xff) + ((colors[1]>> 8)&0xff) + ((colors[2]>> 8)&0xff) + ((colors[3]>> 8)&0xff)) / 4;
|
||||
int b = (((colors[0] )&0xff) + ((colors[1] )&0xff) + ((colors[2] )&0xff) + ((colors[3] )&0xff)) / 4;
|
||||
uint32_t color = ((r<<16) | (g<<8) | b) | ALPHA32_MASK;
|
||||
|
||||
(*pBaseNtscColors)[i] = * (bgra_t*) &color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "NTSC_CharSet.h"
|
||||
|
||||
unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
|
||||
static unsigned char csbits_enhanced2e_pal[2][256][8]; // PAL Enhanced //e (2764 8K video ROM - top 4K) via rocker switch under keyboard
|
||||
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_pravets82[1][256][8]; // Pravets 82
|
||||
|
@ -164,11 +164,15 @@ void userVideoRomForIIe(void)
|
|||
if (size == kVideoRomSize4K)
|
||||
{
|
||||
userVideoRom4K(&csbits_enhanced2e[0], pVideoRom);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
userVideoRom4K(&csbits_2e_pal[0], pVideoRom);
|
||||
userVideoRom4K(&csbits_enhanced2e[0], &pVideoRom[4*1024]);
|
||||
}
|
||||
|
||||
userVideoRom4K(&csbits_enhanced2e_pal[0], pVideoRom);
|
||||
userVideoRom4K(&csbits_enhanced2e[0], &pVideoRom[4*1024]);
|
||||
// NB. Same *custom* US video ROM for Original & Enhanced //e
|
||||
memcpy(csbits_2e, csbits_enhanced2e, sizeof(csbits_enhanced2e));
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -224,17 +228,19 @@ void make_csbits(void)
|
|||
memcpy(csbits_2e, csbits_enhanced2e, sizeof(csbits_enhanced2e));
|
||||
memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8);
|
||||
|
||||
// Try to use any user-provided video ROM for Enhanced //e
|
||||
// Try to use any user-provided video ROM for Original/Enhanced //e
|
||||
userVideoRomForIIe();
|
||||
|
||||
// Try to use any user-provided video ROM for II/II+
|
||||
userVideoRomForIIPlus();
|
||||
}
|
||||
|
||||
csbits_t GetEnhanced2e_csbits(void)
|
||||
csbits_t Get2e_csbits(void)
|
||||
{
|
||||
if (IsVideoRom4K())
|
||||
return csbits_enhanced2e;
|
||||
const csbits_t videoRom4K = (GetApple2Type() == A2TYPE_APPLE2E) ? csbits_2e : csbits_enhanced2e;
|
||||
|
||||
return GetVideoRomRockerSwitch() == false ? csbits_enhanced2e : csbits_enhanced2e_pal;
|
||||
if (IsVideoRom4K()) // 4K means US-only, so no secondary PAL video ROM
|
||||
return videoRom4K;
|
||||
|
||||
return GetVideoRomRockerSwitch() == false ? videoRom4K : csbits_2e_pal; // NB. Same PAL video ROM for Original & Enhanced //e
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
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_2e[2][256][8]; // Original //e (no mousetext)
|
||||
extern unsigned char csbits_a2[1][256][8]; // ][ and ][+
|
||||
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
|
||||
|
||||
void make_csbits(void);
|
||||
csbits_t GetEnhanced2e_csbits(void);
|
||||
csbits_t Get2e_csbits(void);
|
||||
|
|
|
@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "SaveState_Structs_v1.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
#include "Applewin.h"
|
||||
|
@ -112,129 +111,6 @@ const char* Snapshot_GetPath()
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void Snapshot_LoadState_v1() // .aws v1.0.0.1, up to (and including) AppleWin v1.25.0
|
||||
{
|
||||
std::string strOldImageDir(g_sCurrentDir);
|
||||
|
||||
APPLEWIN_SNAPSHOT_v1* pSS = (APPLEWIN_SNAPSHOT_v1*) new char[sizeof(APPLEWIN_SNAPSHOT_v1)]; // throw's bad_alloc
|
||||
|
||||
try
|
||||
{
|
||||
#if _MSC_VER >= 1600 // static_assert supported from VS2010 (cl.exe v16.00)
|
||||
static_assert(kSnapshotSize_v1 == sizeof(APPLEWIN_SNAPSHOT_v1), "Save-state v1 struct size mismatch");
|
||||
#else
|
||||
#if 0
|
||||
// A compile error here means sizeof(APPLEWIN_SNAPSHOT_v1) is wrong, eg. one of the constituent structs has been modified
|
||||
typedef char VerifySizesAreEqual[kSnapshotSize_v1 == sizeof(APPLEWIN_SNAPSHOT_v1) ? 1 : -1];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (kSnapshotSize_v1 != sizeof(APPLEWIN_SNAPSHOT_v1))
|
||||
throw std::string("Save-state v1 struct size mismatch");
|
||||
|
||||
SetCurrentImageDir(g_strSaveStatePath.c_str()); // Allow .dsk's load without prompting
|
||||
|
||||
memset(pSS, 0, sizeof(APPLEWIN_SNAPSHOT_v1));
|
||||
|
||||
//
|
||||
|
||||
HANDLE hFile = CreateFile( g_strSaveStatePathname.c_str(),
|
||||
GENERIC_READ,
|
||||
0,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
throw std::string("File not found: ") + g_strSaveStatePathname;
|
||||
|
||||
DWORD dwBytesRead;
|
||||
BOOL bRes = ReadFile( hFile,
|
||||
pSS,
|
||||
sizeof(APPLEWIN_SNAPSHOT_v1),
|
||||
&dwBytesRead,
|
||||
NULL);
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
if(!bRes || (dwBytesRead != sizeof(APPLEWIN_SNAPSHOT_v1)))
|
||||
// File size wrong: probably because of version mismatch or corrupt file
|
||||
throw std::string("File size mismatch");
|
||||
|
||||
if(pSS->Hdr.dwTag != AW_SS_TAG)
|
||||
throw std::string("File corrupt");
|
||||
|
||||
if(pSS->Hdr.dwVersion != MAKE_VERSION(1,0,0,1))
|
||||
throw std::string("Version mismatch");
|
||||
|
||||
// TO DO: Verify checksum
|
||||
|
||||
//
|
||||
// Reset all sub-systems
|
||||
MemReset();
|
||||
DiskReset();
|
||||
HD_Reset();
|
||||
KeybReset();
|
||||
VideoResetState();
|
||||
MB_Reset();
|
||||
sg_SSC.CommReset();
|
||||
|
||||
//
|
||||
// Apple2 unit
|
||||
//
|
||||
|
||||
SS_CPU6502& CPU = pSS->Apple2Unit.CPU6502;
|
||||
CpuSetSnapshot_v1(CPU.A, CPU.X, CPU.Y, CPU.P, CPU.S, CPU.PC, CPU.nCumulativeCycles);
|
||||
|
||||
SS_IO_Comms& SSC = pSS->Apple2Unit.Comms;
|
||||
sg_SSC.SetSnapshot_v1(SSC.baudrate, SSC.bytesize, SSC.commandbyte, SSC.comminactivity, SSC.controlbyte, SSC.parity, SSC.stopbits);
|
||||
|
||||
JoySetSnapshot_v1(pSS->Apple2Unit.Joystick.nJoyCntrResetCycle);
|
||||
KeybSetSnapshot_v1(pSS->Apple2Unit.Keyboard.nLastKey);
|
||||
SpkrSetSnapshot_v1(pSS->Apple2Unit.Speaker.nSpkrLastCycle);
|
||||
VideoSetSnapshot_v1(pSS->Apple2Unit.Video.bAltCharSet, pSS->Apple2Unit.Video.dwVidMode);
|
||||
MemSetSnapshot_v1(pSS->Apple2Unit.Memory.dwMemMode, pSS->Apple2Unit.Memory.bLastWriteRam, pSS->Apple2Unit.Memory.nMemMain, pSS->Apple2Unit.Memory.nMemAux);
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// Slot4: Mockingboard
|
||||
MB_SetSnapshot_v1(&pSS->Mockingboard1, 4);
|
||||
|
||||
//
|
||||
// Slot5: Mockingboard
|
||||
MB_SetSnapshot_v1(&pSS->Mockingboard2, 5);
|
||||
|
||||
//
|
||||
// Slot6: Disk][
|
||||
DiskSetSnapshot_v1(&pSS->Disk2);
|
||||
|
||||
SetLoadedSaveStateFlag(true);
|
||||
|
||||
MemUpdatePaging(TRUE);
|
||||
|
||||
// NB. g_Apple2Type doesn't change for v1, but replicate this (like v2)
|
||||
VideoReinitialize(); // g_CharsetType changed
|
||||
FrameUpdateApple2Type();
|
||||
}
|
||||
catch(std::string szMessage)
|
||||
{
|
||||
MessageBox( g_hFrameWindow,
|
||||
szMessage.c_str(),
|
||||
TEXT("Load State"),
|
||||
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
||||
|
||||
SetCurrentImageDir(strOldImageDir.c_str());
|
||||
|
||||
PostMessage(g_hFrameWindow, WM_USER_RESTART, 0, 0); // Power-cycle VM (undoing all the new state just loaded)
|
||||
}
|
||||
|
||||
delete [] pSS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static HANDLE m_hFile = INVALID_HANDLE_VALUE;
|
||||
static CConfigNeedingRestart m_ConfigNew;
|
||||
|
||||
|
@ -566,7 +442,12 @@ void Snapshot_LoadState()
|
|||
const size_t pos = g_strSaveStatePathname.size() - ext_aws.size();
|
||||
if (g_strSaveStatePathname.find(ext_aws, pos) != std::string::npos) // find ".aws" at end of pathname
|
||||
{
|
||||
Snapshot_LoadState_v1();
|
||||
MessageBox( g_hFrameWindow,
|
||||
"Save-state v1 no longer supported.\n"
|
||||
"Please load using AppleWin 1.27, and re-save as a v2 state file.",
|
||||
TEXT("Load State"),
|
||||
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1355,25 +1355,6 @@ void CSuperSerialCard::SetSerialPortName(const char* pSerialPortName)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void CSuperSerialCard::SetSnapshot_v1( const DWORD baudrate,
|
||||
const BYTE bytesize,
|
||||
const BYTE commandbyte,
|
||||
const DWORD comminactivity,
|
||||
const BYTE controlbyte,
|
||||
const BYTE parity,
|
||||
const BYTE stopbits)
|
||||
{
|
||||
// Redundant:
|
||||
// . baudrate, stopbits, bytesize (encapsulated in controlbyte)
|
||||
// . parity (encapsulated in commandbyte)
|
||||
// Obsolete:
|
||||
// . comminactivity
|
||||
|
||||
UpdateCommandAndControlRegs(commandbyte, controlbyte);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Unit version history:
|
||||
// 2: Added: Support DCD flag
|
||||
// Removed: redundant data (encapsulated in Command & Control bytes)
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
void CommReset();
|
||||
void CommDestroy();
|
||||
void CommSetSerialPort(HWND hWindow, DWORD dwNewSerialPortItem);
|
||||
void SetSnapshot_v1(const DWORD baudrate, const BYTE bytesize, const BYTE commandbyte, const DWORD comminactivity, const BYTE controlbyte, const BYTE parity, const BYTE stopbits);
|
||||
std::string GetSnapshotCardName(void);
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||
|
|
|
@ -931,13 +931,6 @@ void Spkr_DSUninit()
|
|||
|
||||
//=============================================================================
|
||||
|
||||
void SpkrSetSnapshot_v1(const unsigned __int64 SpkrLastCycle)
|
||||
{
|
||||
g_nSpkrLastCycle = SpkrLastCycle;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_LASTCYCLE "Last Cycle"
|
||||
|
||||
static std::string SpkrGetSnapshotStructName(void)
|
||||
|
|
|
@ -33,7 +33,6 @@ void Spkr_Demute();
|
|||
bool Spkr_IsActive();
|
||||
bool Spkr_DSInit();
|
||||
void Spkr_DSUninit();
|
||||
void SpkrSetSnapshot_v1(const unsigned __int64 SpkrLastCycle);
|
||||
void SpkrSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void SpkrLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
|
|
|
@ -83,14 +83,11 @@ static LPBITMAPINFO g_pFramebufferinfo = NULL;
|
|||
|
||||
HBITMAP g_hLogoBitmap;
|
||||
|
||||
const int MAX_SOURCE_Y = 512;
|
||||
static LPBYTE g_aSourceStartofLine[ MAX_SOURCE_Y ];
|
||||
|
||||
COLORREF g_nMonochromeRGB = RGB(0xC0,0xC0,0xC0);
|
||||
|
||||
uint32_t g_uVideoMode = VF_TEXT; // Current Video Mode (this is the last set one as it may change mid-scan line!)
|
||||
|
||||
DWORD g_eVideoType = VT_COLOR_TV;
|
||||
DWORD g_eVideoType = VT_DEFAULT;
|
||||
DWORD g_uHalfScanLines = 1; // drop 50% scan lines for a more authentic look
|
||||
|
||||
static const bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
||||
|
@ -100,9 +97,10 @@ static const bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
|||
// NOTE: KEEP IN SYNC: VideoType_e g_aVideoChoices g_apVideoModeDesc
|
||||
TCHAR g_aVideoChoices[] =
|
||||
TEXT("Monochrome (Custom)\0")
|
||||
TEXT("Color Monitor\0")
|
||||
TEXT("B&W TV\0")
|
||||
TEXT("Color (RGB Monitor)\0")
|
||||
TEXT("Color (NTSC Monitor)\0")
|
||||
TEXT("Color TV\0")
|
||||
TEXT("B&W TV\0")
|
||||
TEXT("Monochrome (Amber)\0")
|
||||
TEXT("Monochrome (Green)\0")
|
||||
TEXT("Monochrome (White)\0")
|
||||
|
@ -113,9 +111,10 @@ static const bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
|||
char *g_apVideoModeDesc[ NUM_VIDEO_MODES ] =
|
||||
{
|
||||
"Monochrome Monitor (Custom)"
|
||||
, "Color Monitor"
|
||||
, "B&W TV"
|
||||
, "Color (RGB Monitor)"
|
||||
, "Color (NTSC Monitor)"
|
||||
, "Color TV"
|
||||
, "B&W TV"
|
||||
, "Amber Monitor"
|
||||
, "Green Monitor"
|
||||
, "White Monitor"
|
||||
|
@ -720,15 +719,6 @@ bool VideoGetSWAltCharSet(void)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode)
|
||||
{
|
||||
g_nAltCharSetOffset = !AltCharSet ? 0 : 256;
|
||||
g_uVideoMode = VideoMode;
|
||||
g_dwCyclesThisFrame = 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define SS_YAML_KEY_ALTCHARSET "Alt Char Set"
|
||||
#define SS_YAML_KEY_VIDEOMODE "Video Mode"
|
||||
#define SS_YAML_KEY_CYCLESTHISFRAME "Cycles This Frame"
|
||||
|
@ -1202,14 +1192,42 @@ bool IsVideoRom4K(void)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
enum VideoType127_e
|
||||
{
|
||||
VT127_MONO_CUSTOM
|
||||
, VT127_COLOR_MONITOR_NTSC
|
||||
, VT127_MONO_TV
|
||||
, VT127_COLOR_TV
|
||||
, VT127_MONO_AMBER
|
||||
, VT127_MONO_GREEN
|
||||
, VT127_MONO_WHITE
|
||||
, VT127_NUM_VIDEO_MODES
|
||||
};
|
||||
|
||||
void Config_Load_Video()
|
||||
{
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_MODE ),&g_eVideoType);
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_HALF_SCAN_LINES),&g_uHalfScanLines);
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_MONO_COLOR ),&g_nMonochromeRGB);
|
||||
|
||||
const UINT16* pOldVersion = GetOldAppleWinVersion();
|
||||
if (pOldVersion[0] == 1 && pOldVersion[1] <= 27 && pOldVersion[2] <= 13)
|
||||
{
|
||||
switch (g_eVideoType)
|
||||
{
|
||||
case VT127_MONO_CUSTOM: g_eVideoType = VT_MONO_CUSTOM; break;
|
||||
case VT127_COLOR_MONITOR_NTSC: g_eVideoType = VT_COLOR_MONITOR_NTSC; break;
|
||||
case VT127_MONO_TV: g_eVideoType = VT_MONO_TV; break;
|
||||
case VT127_COLOR_TV: g_eVideoType = VT_COLOR_TV; break;
|
||||
case VT127_MONO_AMBER: g_eVideoType = VT_MONO_AMBER; break;
|
||||
case VT127_MONO_GREEN: g_eVideoType = VT_MONO_GREEN; break;
|
||||
case VT127_MONO_WHITE: g_eVideoType = VT_MONO_WHITE; break;
|
||||
default: g_eVideoType = VT_DEFAULT; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_eVideoType >= NUM_VIDEO_MODES)
|
||||
g_eVideoType = VT_COLOR_MONITOR;
|
||||
g_eVideoType = VT_DEFAULT;
|
||||
}
|
||||
|
||||
void Config_Save_Video()
|
||||
|
@ -1242,9 +1260,9 @@ static void videoCreateDIBSection()
|
|||
);
|
||||
SelectObject(g_hDeviceDC,g_hDeviceBitmap);
|
||||
|
||||
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER
|
||||
// DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER
|
||||
ZeroMemory( g_pFramebufferbits, GetFrameBufferWidth()*GetFrameBufferHeight()*sizeof(bgra_t) );
|
||||
|
||||
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER
|
||||
NTSC_VideoInit( g_pFramebufferbits );
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
enum VideoType_e
|
||||
{
|
||||
VT_MONO_CUSTOM
|
||||
, VT_COLOR_MONITOR
|
||||
, VT_MONO_TV
|
||||
, VT_COLOR_MONITOR_RGB // Color rendering from AppleWin 1.25 (GH#357)
|
||||
, VT_COLOR_MONITOR_NTSC
|
||||
, VT_COLOR_TV
|
||||
, VT_MONO_TV
|
||||
, VT_MONO_AMBER
|
||||
, VT_MONO_GREEN
|
||||
, VT_MONO_WHITE
|
||||
, NUM_VIDEO_MODES
|
||||
, VT_DEFAULT = VT_COLOR_TV
|
||||
};
|
||||
|
||||
extern TCHAR g_aVideoChoices[];
|
||||
|
@ -24,7 +26,7 @@
|
|||
VF_80COL = 0x00000001,
|
||||
VF_DHIRES = 0x00000002,
|
||||
VF_HIRES = 0x00000004,
|
||||
VF_80STORE= 0x00000008, // was called VF_MASK2
|
||||
VF_80STORE= 0x00000008,
|
||||
VF_MIXED = 0x00000010,
|
||||
VF_PAGE2 = 0x00000020,
|
||||
VF_TEXT = 0x00000040
|
||||
|
@ -61,6 +63,7 @@
|
|||
#define PACKED // TODO: FIXME: gcc/clang __attribute__
|
||||
#endif
|
||||
|
||||
// TODO: Replace with WinGDI.h / RGBQUAD
|
||||
struct bgra_t
|
||||
{
|
||||
uint8_t b;
|
||||
|
@ -182,7 +185,6 @@ bool VideoGetSWPAGE2(void);
|
|||
bool VideoGetSWTEXT(void);
|
||||
bool VideoGetSWAltCharSet(void);
|
||||
|
||||
void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode);
|
||||
void VideoSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
|
||||
|
|
651
source/Video_OriginalColorTVMode.cpp
Normal file
651
source/Video_OriginalColorTVMode.cpp
Normal file
|
@ -0,0 +1,651 @@
|
|||
// Sync'd with 1.25.0.4 source
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Frame.h"
|
||||
#include "Memory.h" // MemGetMainPtr() MemGetAuxPtr()
|
||||
#include "Video.h"
|
||||
#include "Video_OriginalColorTVMode.h"
|
||||
|
||||
const int SRCOFFS_LORES = 0; // 0
|
||||
const int SRCOFFS_HIRES = (SRCOFFS_LORES + 16); // 16
|
||||
const int SRCOFFS_DHIRES = (SRCOFFS_HIRES + 512); // 528
|
||||
const int SRCOFFS_TOTAL = (SRCOFFS_DHIRES + 2560); // 3088
|
||||
|
||||
const int MAX_SOURCE_Y = 512;
|
||||
static LPBYTE g_aSourceStartofLine[ MAX_SOURCE_Y ];
|
||||
#define SETSOURCEPIXEL(x,y,c) g_aSourceStartofLine[(y)][(x)] = (c)
|
||||
|
||||
// TC: Tried to remove HiresToPalIndex[] translation table, so get purple bars when hires data is: 0x80 0x80...
|
||||
// . V_CreateLookup_HiResHalfPixel_Authentic() uses both ColorMapping (CM_xxx) indices and Color_Palette_Index_e (HGR_xxx)!
|
||||
#define DO_OPT_PALETTE 0
|
||||
|
||||
enum Color_Palette_Index_e
|
||||
{
|
||||
// hires (don't change order) - For tv emulation HGR Video Mode
|
||||
#if DO_OPT_PALETTE
|
||||
HGR_VIOLET // HCOLOR=2 VIOLET , 2800: 01 00 55 2A
|
||||
, HGR_BLUE // HCOLOR=6 BLUE , 3000: 81 00 D5 AA
|
||||
, HGR_GREEN // HCOLOR=1 GREEN , 2400: 02 00 2A 55
|
||||
, HGR_ORANGE // HCOLOR=5 ORANGE , 2C00: 82 00 AA D5
|
||||
, HGR_BLACK
|
||||
, HGR_WHITE
|
||||
#else
|
||||
HGR_BLACK
|
||||
, HGR_WHITE
|
||||
, HGR_BLUE // HCOLOR=6 BLUE , 3000: 81 00 D5 AA
|
||||
, HGR_ORANGE // HCOLOR=5 ORANGE , 2C00: 82 00 AA D5
|
||||
, HGR_GREEN // HCOLOR=1 GREEN , 2400: 02 00 2A 55
|
||||
, HGR_VIOLET // HCOLOR=2 VIOLET , 2800: 01 00 55 2A
|
||||
#endif
|
||||
// TV emu
|
||||
, HGR_GREY1
|
||||
, HGR_GREY2
|
||||
, HGR_YELLOW
|
||||
, HGR_AQUA
|
||||
, HGR_PURPLE
|
||||
, HGR_PINK
|
||||
// lores & dhires
|
||||
, BLACK
|
||||
, DEEP_RED
|
||||
, DARK_BLUE
|
||||
, MAGENTA
|
||||
, DARK_GREEN
|
||||
, DARK_GRAY
|
||||
, BLUE
|
||||
, LIGHT_BLUE
|
||||
, BROWN
|
||||
, ORANGE
|
||||
, LIGHT_GRAY
|
||||
, PINK
|
||||
, GREEN
|
||||
, YELLOW
|
||||
, AQUA
|
||||
, WHITE
|
||||
};
|
||||
|
||||
// __ Map HGR color index to Palette index
|
||||
enum ColorMapping
|
||||
{
|
||||
CM_Violet
|
||||
, CM_Blue
|
||||
, CM_Green
|
||||
, CM_Orange
|
||||
, CM_Black
|
||||
, CM_White
|
||||
, NUM_COLOR_MAPPING
|
||||
};
|
||||
|
||||
const BYTE HiresToPalIndex[ NUM_COLOR_MAPPING ] =
|
||||
{
|
||||
HGR_VIOLET
|
||||
, HGR_BLUE
|
||||
, HGR_GREEN
|
||||
, HGR_ORANGE
|
||||
, HGR_BLACK
|
||||
, HGR_WHITE
|
||||
};
|
||||
|
||||
const BYTE LoresResColors[16] = {
|
||||
BLACK, DEEP_RED, DARK_BLUE, MAGENTA,
|
||||
DARK_GREEN,DARK_GRAY,BLUE, LIGHT_BLUE,
|
||||
BROWN, ORANGE, LIGHT_GRAY,PINK,
|
||||
GREEN, YELLOW, AQUA, WHITE
|
||||
};
|
||||
|
||||
const BYTE DoubleHiresPalIndex[16] = {
|
||||
BLACK, DARK_BLUE, DARK_GREEN,BLUE,
|
||||
BROWN, LIGHT_GRAY,GREEN, AQUA,
|
||||
DEEP_RED,MAGENTA, DARK_GRAY, LIGHT_BLUE,
|
||||
ORANGE, PINK, YELLOW, WHITE
|
||||
};
|
||||
|
||||
#define SETRGBCOLOR(r,g,b) {b,g,r,0}
|
||||
|
||||
static RGBQUAD PalIndex2RGB[] =
|
||||
{
|
||||
// hires
|
||||
#if DO_OPT_PALETTE
|
||||
SETRGBCOLOR(/*MAGENTA, */ 0xC7,0x34,0xFF), // FD Linards Tweaked 0xFF,0x00,0xFF -> 0xC7,0x34,0xFF
|
||||
SETRGBCOLOR(/*BLUE, */ 0x0D,0xA1,0xFF), // FC Linards Tweaked 0x00,0x00,0xFF -> 0x0D,0xA1,0xFF
|
||||
SETRGBCOLOR(/*GREEN, */ 0x38,0xCB,0x00), // FA Linards Tweaked 0x00,0xFF,0x00 -> 0x38,0xCB,0x00
|
||||
SETRGBCOLOR(/*ORANGE, */ 0xF2,0x5E,0x00), // 0xFF,0x80,0x00 -> Linards Tweaked 0xF2,0x5E,0x00
|
||||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00), // For TV emulation HGR Video Mode
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
#else
|
||||
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
|
||||
SETRGBCOLOR(/*ORANGE, */ 0xF2,0x5E,0x00), // 0xFF,0x80,0x00 -> Linards Tweaked 0xF2,0x5E,0x00
|
||||
SETRGBCOLOR(/*GREEN, */ 0x38,0xCB,0x00), // FA Linards Tweaked 0x00,0xFF,0x00 -> 0x38,0xCB,0x00
|
||||
SETRGBCOLOR(/*MAGENTA, */ 0xC7,0x34,0xFF), // FD Linards Tweaked 0xFF,0x00,0xFF -> 0xC7,0x34,0xFF
|
||||
#endif
|
||||
|
||||
// TV emu
|
||||
SETRGBCOLOR(/*HGR_GREY1, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_GREY2, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_YELLOW,*/ 0x9E,0x9E,0x00), // 0xD0,0xB0,0x10 -> 0x9E,0x9E,0x00
|
||||
SETRGBCOLOR(/*HGR_AQUA, */ 0x00,0xCD,0x4A), // 0x20,0xB0,0xB0 -> 0x00,0xCD,0x4A
|
||||
SETRGBCOLOR(/*HGR_PURPLE,*/ 0x61,0x61,0xFF), // 0x60,0x50,0xE0 -> 0x61,0x61,0xFF
|
||||
SETRGBCOLOR(/*HGR_PINK, */ 0xFF,0x32,0xB5), // 0xD0,0x40,0xA0 -> 0xFF,0x32,0xB5
|
||||
|
||||
// lores & dhires
|
||||
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
|
||||
SETRGBCOLOR(/*MAGENTA,*/ 0xC7,0x34,0xFF), // FD Linards Tweaked 0xFF,0x00,0xFF -> 0xC7,0x34,0xFF
|
||||
SETRGBCOLOR(/*DARK_GREEN,*/ 0x00,0x80,0x00), // 2 // not used
|
||||
SETRGBCOLOR(/*DARK_GRAY,*/ 0x80,0x80,0x80), // F8
|
||||
SETRGBCOLOR(/*BLUE,*/ 0x0D,0xA1,0xFF), // FC Linards Tweaked 0x00,0x00,0xFF -> 0x0D,0xA1,0xFF
|
||||
SETRGBCOLOR(/*LIGHT_BLUE,*/ 0xAA,0xAA,0xFF), // 0x60,0xA0,0xFF -> Linards Tweaked 0xAA,0xAA,0xFF
|
||||
SETRGBCOLOR(/*BROWN,*/ 0x55,0x55,0x00), // 0x80,0x50,0x00 -> Linards Tweaked 0x55,0x55,0x00
|
||||
SETRGBCOLOR(/*ORANGE,*/ 0xF2,0x5E,0x00), // 0xFF,0x80,0x00 -> Linards Tweaked 0xF2,0x5E,0x00
|
||||
SETRGBCOLOR(/*LIGHT_GRAY,*/ 0xC0,0xC0,0xC0), // 7 // GR: COLOR=10
|
||||
SETRGBCOLOR(/*PINK,*/ 0xFF,0x89,0xE5), // 0xFF,0x90,0x80 -> Linards Tweaked 0xFF,0x89,0xE5
|
||||
SETRGBCOLOR(/*GREEN,*/ 0x38,0xCB,0x00), // FA Linards Tweaked 0x00,0xFF,0x00 -> 0x38,0xCB,0x00
|
||||
SETRGBCOLOR(/*YELLOW,*/ 0xD5,0xD5,0x1A), // FB Linards Tweaked 0xFF,0xFF,0x00 -> 0xD5,0xD5,0x1A
|
||||
SETRGBCOLOR(/*AQUA,*/ 0x62,0xF6,0x99), // 0x40,0xFF,0x90 -> Linards Tweaked 0x62,0xF6,0x99
|
||||
SETRGBCOLOR(/*WHITE,*/ 0xFF,0xFF,0xFF),
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void V_CreateLookup_DoubleHires ()
|
||||
{
|
||||
#define OFFSET 3
|
||||
#define SIZE 10
|
||||
|
||||
for (int column = 0; column < 256; column++) {
|
||||
int coloffs = SIZE * column;
|
||||
for (unsigned byteval = 0; byteval < 256; byteval++) {
|
||||
int color[SIZE];
|
||||
ZeroMemory(color,sizeof(color));
|
||||
unsigned pattern = MAKEWORD(byteval,column);
|
||||
int pixel;
|
||||
for (pixel = 1; pixel < 15; pixel++) {
|
||||
if (pattern & (1 << pixel)) {
|
||||
int pixelcolor = 1 << ((pixel-OFFSET) & 3);
|
||||
if ((pixel >= OFFSET+2) && (pixel < SIZE+OFFSET+2) && (pattern & (0x7 << (pixel-4))))
|
||||
color[pixel-(OFFSET+2)] |= pixelcolor;
|
||||
if ((pixel >= OFFSET+1) && (pixel < SIZE+OFFSET+1) && (pattern & (0xF << (pixel-4))))
|
||||
color[pixel-(OFFSET+1)] |= pixelcolor;
|
||||
if ((pixel >= OFFSET+0) && (pixel < SIZE+OFFSET+0))
|
||||
color[pixel-(OFFSET+0)] |= pixelcolor;
|
||||
if ((pixel >= OFFSET-1) && (pixel < SIZE+OFFSET-1) && (pattern & (0xF << (pixel+1))))
|
||||
color[pixel-(OFFSET-1)] |= pixelcolor;
|
||||
if ((pixel >= OFFSET-2) && (pixel < SIZE+OFFSET-2) && (pattern & (0x7 << (pixel+2))))
|
||||
color[pixel-(OFFSET-2)] |= pixelcolor;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (g_eVideoType == VT_COLOR_TEXT_OPTIMIZED)
|
||||
{
|
||||
// Activate for fringe reduction on white HGR text - drawback: loss of color mix patterns in HGR Video Mode.
|
||||
for (pixel = 0; pixel < 13; pixel++)
|
||||
{
|
||||
if ((pattern & (0xF << pixel)) == (unsigned)(0xF << pixel))
|
||||
for (int pos = pixel; pos < pixel + 4; pos++)
|
||||
if (pos >= OFFSET && pos < SIZE+OFFSET)
|
||||
color[pos-OFFSET] = 15;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int y = byteval << 1;
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
SETSOURCEPIXEL(SRCOFFS_DHIRES+coloffs+x,y ,DoubleHiresPalIndex[ color[x] ]);
|
||||
SETSOURCEPIXEL(SRCOFFS_DHIRES+coloffs+x,y+1,DoubleHiresPalIndex[ color[x] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef SIZE
|
||||
#undef OFFSET
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#if 0
|
||||
static void V_CreateLookup_Hires()
|
||||
{
|
||||
// int iMonochrome = GetMonochromeIndex();
|
||||
|
||||
// BYTE colorval[6] = {MAGENTA,BLUE,GREEN,ORANGE,BLACK,WHITE};
|
||||
// BYTE colorval[6] = {HGR_MAGENTA,HGR_BLUE,HGR_GREEN,HGR_RED,HGR_BLACK,HGR_WHITE};
|
||||
for (int iColumn = 0; iColumn < 16; iColumn++)
|
||||
{
|
||||
int coloffs = iColumn << 5;
|
||||
|
||||
for (unsigned iByte = 0; iByte < 256; iByte++)
|
||||
{
|
||||
int aPixels[11];
|
||||
|
||||
aPixels[ 0] = iColumn & 4;
|
||||
aPixels[ 1] = iColumn & 8;
|
||||
aPixels[ 9] = iColumn & 1;
|
||||
aPixels[10] = iColumn & 2;
|
||||
|
||||
int nBitMask = 1;
|
||||
int iPixel;
|
||||
for (iPixel = 2; iPixel < 9; iPixel++) {
|
||||
aPixels[iPixel] = ((iByte & nBitMask) != 0);
|
||||
nBitMask <<= 1;
|
||||
}
|
||||
|
||||
int hibit = ((iByte & 0x80) != 0);
|
||||
int x = 0;
|
||||
int y = iByte << 1;
|
||||
|
||||
while (x < 28)
|
||||
{
|
||||
int adj = (x >= 14) << 1;
|
||||
int odd = (x >= 14);
|
||||
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
{
|
||||
int color = CM_Black;
|
||||
if (aPixels[iPixel])
|
||||
{
|
||||
if (aPixels[iPixel-1] || aPixels[iPixel+1])
|
||||
color = CM_White;
|
||||
else
|
||||
color = ((odd ^ (iPixel&1)) << 1) | hibit;
|
||||
}
|
||||
else if (aPixels[iPixel-1] && aPixels[iPixel+1])
|
||||
{
|
||||
// Activate fringe reduction on white HGR text - drawback: loss of color mix patterns in HGR video mode.
|
||||
// VT_COLOR_MONITOR_RGB = Fill in colors in between white pixels
|
||||
// VT_COLOR_TVEMU = Fill in colors in between white pixels (Post Processing will mix/merge colors)
|
||||
// VT_COLOR_TEXT_OPTIMIZED --> !(aPixels[iPixel-2] && aPixels[iPixel+2]) = Don't fill in colors in between white
|
||||
if ((g_eVideoType == VT_COLOR_TVEMU) || !(aPixels[iPixel-2] && aPixels[iPixel+2]) )
|
||||
color = ((odd ^ !(iPixel&1)) << 1) | hibit; // No white HGR text optimization
|
||||
}
|
||||
|
||||
//if (g_eVideoType == VT_MONO_AUTHENTIC) {
|
||||
// int nMonoColor = (color != CM_Black) ? iMonochrome : BLACK;
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y , nMonoColor); // buggy
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y , nMonoColor); // buggy
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y+1,BLACK); // BL
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y+1,BLACK); // BR
|
||||
//} else
|
||||
{
|
||||
// Colors - Top/Bottom Left/Right
|
||||
// cTL cTR
|
||||
// cBL cBR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y ,HiresToPalIndex[color]); // cTL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y ,HiresToPalIndex[color]); // cTR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y+1,HiresToPalIndex[color]); // cBL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y+1,HiresToPalIndex[color]); // cBR
|
||||
}
|
||||
x += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void V_CreateLookup_Lores()
|
||||
{
|
||||
for (int color = 0; color < 16; color++)
|
||||
for (int x = 0; x < 16; x++)
|
||||
for (int y = 0; y < 16; y++)
|
||||
SETSOURCEPIXEL(SRCOFFS_LORES+x,(color << 4)+y,LoresResColors[color]);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define HALF_PIXEL_SOLID 1
|
||||
#define HALF_PIXEL_BLEED 0
|
||||
|
||||
void V_CreateLookup_HiResHalfPixel_Authentic(VideoType_e videoType) // Colors are solid (100% coverage)
|
||||
{
|
||||
// 2-bits from previous byte, 2-bits from next byte = 2^4 = 16 total permutations
|
||||
for (int iColumn = 0; iColumn < 16; iColumn++)
|
||||
{
|
||||
int offsetx = iColumn << 5; // every column is 32 bytes wide -- 7 apple pixels = 14 pixels + 2 pad + 14 pixels + 2 pad
|
||||
|
||||
for (unsigned iByte = 0; iByte < 256; iByte++)
|
||||
{
|
||||
int aPixels[11]; // c2 c1 b7 b6 b5 b4 b3 b2 b1 b0 c8 c4
|
||||
|
||||
/*
|
||||
aPixel[i]
|
||||
A 9|8 7 6 5 4 3 2|1 0
|
||||
Z W|b b b b b b b|X Y
|
||||
----+-------------+----
|
||||
prev| existing |next
|
||||
bits| hi-res byte |bits
|
||||
|
||||
Legend:
|
||||
XYZW = iColumn in binary
|
||||
b = Bytes in binary
|
||||
*/
|
||||
// aPixel[] = 48bbbbbbbb12, where b = iByte in binary, # is bit-n of column
|
||||
aPixels[ 0] = iColumn & 4; // previous byte, 2nd last pixel
|
||||
aPixels[ 1] = iColumn & 8; // previous byte, last pixel
|
||||
aPixels[ 9] = iColumn & 1; // next byte, first pixel
|
||||
aPixels[10] = iColumn & 2; // next byte, second pixel
|
||||
|
||||
// Convert raw pixel Byte value to binary and stuff into bit array of pixels on off
|
||||
int nBitMask = 1;
|
||||
int iPixel;
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
{
|
||||
aPixels[iPixel] = ((iByte & nBitMask) != 0);
|
||||
nBitMask <<= 1;
|
||||
}
|
||||
|
||||
int hibit = (iByte >> 7) & 1; // ((iByte & 0x80) != 0);
|
||||
int x = 0;
|
||||
int y = iByte << 1;
|
||||
|
||||
/* Test cases
|
||||
81 blue
|
||||
2000:D5 AA D5 AA
|
||||
82 orange
|
||||
2800:AA D5 AA D5
|
||||
FF white bleed "thru"
|
||||
3000:7F 80 7F 80
|
||||
3800:FF 80 FF 80
|
||||
2028:80 7F 80 7F
|
||||
2828:80 FF 80 FF
|
||||
Edge Case for Half Luminance !
|
||||
2000:C4 00 // Green HalfLumBlue
|
||||
2400:C4 80 // Green Green
|
||||
Edge Case for Color Bleed !
|
||||
2000:40 00
|
||||
2400:40 80
|
||||
*/
|
||||
|
||||
// Fixup missing pixels that normally have been scan-line shifted -- Apple "half-pixel" -- but cross 14-pixel boundaries.
|
||||
if( hibit )
|
||||
{
|
||||
if ( aPixels[1] ) // preceeding pixel on?
|
||||
#if 0 // Optimization: Doesn't seem to matter if we ignore the 2 pixels of the next byte
|
||||
for (iPixel = 0; iPixel < 9; iPixel++) // NOTE: You MUST start with the preceding 2 pixels !!!
|
||||
if (aPixels[iPixel]) // pixel on
|
||||
#endif
|
||||
{
|
||||
if (aPixels[2] || aPixels[0]) // White if pixel from previous byte and first pixel of this byte is on
|
||||
{
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_WHITE );
|
||||
} else { // Optimization: odd = (iPixel & 1); if (!odd) case is same as if(odd) !!! // Reference: Gumball - Gumball Machine
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_ORANGE ); // left half of orange pixels
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_ORANGE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_BLUE ); // right half of blue pixels 4, 11, 18, ...
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_BLUE );
|
||||
}
|
||||
}
|
||||
#if HALF_PIXEL_SOLID
|
||||
// Test Patterns
|
||||
// 81 blue
|
||||
// 2000:D5 AA D5 AA -> 2001:AA D5 should not have black gap, should be blue
|
||||
// 82 orange
|
||||
// 2800:AA D5 AA D5
|
||||
// Game: Elite -- Loading Logo
|
||||
// 2444:BB F7 -> 2000:BB F7 // Should not have orange in-between gap -- Elite "Firebird" Logo
|
||||
// -> 2400:00 BB F7 // Should not have blue in-between gap )
|
||||
// 21D0:C0 00 -> HalfLumBlue
|
||||
// 25D0:C0 D0 88 -> Blue black orange black orange
|
||||
// 29D0:C0 90 88 -> Blue black orange
|
||||
// Game: Ultima 4 -- Ultima 4 Logo - bottom half of screen has a "mini-game" / demo -- far right has tree and blue border
|
||||
// 2176:2A AB green black_gap white blue_border // Should have black gap between green and white
|
||||
else if ( aPixels[0] ) // prev prev pixel on
|
||||
{
|
||||
// Game: Gumball
|
||||
// 218E:AA 97 => 2000: A9 87 orange_white // Should have no gap between orange and white
|
||||
// 229A:AB A9 87 -> 2000: 00 A9 87 white orange black blue_white // Should have no gap between blue and white
|
||||
// 2001:BB F7 white blue white (Gumball Intermission)
|
||||
// Torture Half-Pixel HGR Tests: This is a real bitch to solve -- we really need to check:
|
||||
// if (hibit_prev_byte && !aPixels[iPixel-3] && aPixels[iPixel-2] && !aPixels[iPixel] && hibit_this_byte) then set first half-pixel of this byte to either blue or orange
|
||||
// 2000:A9 87 halfblack blue black black orange black orange black
|
||||
// 2400:BB F7 halfblack white white black white white white halfblack
|
||||
// or
|
||||
// 2000:A0 83 orange should "bleed" thru
|
||||
// 2400:B0 83 should have black gap
|
||||
|
||||
if ( aPixels[2] )
|
||||
#if HALF_PIXEL_BLEED // No Half-Pixel Bleed
|
||||
if ( aPixels[3] ) {
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , DARK_BLUE ); // Gumball: 229A: AB A9 87
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, DARK_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , BROWN ); // half luminance red Elite: 2444: BB F7
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, BROWN ); // half luminance red Gumball: 218E: AA 97
|
||||
} else {
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_BLUE ); // 2000:D5 AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_ORANGE ); // 2000: AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_ORANGE );
|
||||
}
|
||||
#else
|
||||
if ((videoType == VT_COLOR_MONITOR_RGB) || ( !aPixels[3] ))
|
||||
{ // "Text optimized" IF this pixel on, and adjacent right pixel off, then colorize first half-pixel of this byte
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_BLUE ); // 2000:D5 AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_ORANGE ); // 2000: AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_ORANGE );
|
||||
}
|
||||
#endif // HALF_PIXEL_BLEED
|
||||
}
|
||||
#endif // HALF_PIXEL_SOLID
|
||||
}
|
||||
x += hibit;
|
||||
|
||||
while (x < 28)
|
||||
{
|
||||
int adj = (x >= 14) << 1; // Adjust start of 7 last pixels to be 16-byte aligned!
|
||||
int odd = (x >= 14);
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
{
|
||||
int color = CM_Black;
|
||||
if (aPixels[iPixel]) // pixel on
|
||||
{
|
||||
color = CM_White;
|
||||
if (aPixels[iPixel-1] || aPixels[iPixel+1]) // adjacent pixels are always white
|
||||
color = CM_White;
|
||||
else
|
||||
color = ((odd ^ (iPixel&1)) << 1) | hibit; // map raw color to our hi-res colors
|
||||
}
|
||||
#if HALF_PIXEL_SOLID
|
||||
else if (aPixels[iPixel-1] && aPixels[iPixel+1]) // IF prev_pixel && next_pixel THEN
|
||||
{
|
||||
// Activate fringe reduction on white HGR text - drawback: loss of color mix patterns in HGR video mode.
|
||||
if (
|
||||
(videoType == VT_COLOR_MONITOR_RGB) // Fill in colors in between white pixels
|
||||
// || (videoType == VT_COLOR_TVEMU) // Fill in colors in between white pixels (Post Processing will mix/merge colors)
|
||||
|| !(aPixels[iPixel-2] && aPixels[iPixel+2]) ) // VT_COLOR_TEXT_OPTIMIZED -> Don't fill in colors in between white
|
||||
{
|
||||
// Test Pattern: Ultima 4 Logo - Castle
|
||||
// 3AC8: 36 5B 6D 36
|
||||
color = ((odd ^ !(iPixel&1)) << 1) | hibit; // No white HGR text optimization
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Colors - Top/Bottom Left/Right
|
||||
// cTL cTR
|
||||
// cBL cBR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj ,y ,HiresToPalIndex[color]); // cTL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj+1,y ,HiresToPalIndex[color]); // cTR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj ,y+1,HiresToPalIndex[color]); // cBL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj+1,y+1,HiresToPalIndex[color]); // cBR
|
||||
x += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void CopySource(int w, int h, int sx, int sy, bgra_t *pVideoAddress)
|
||||
{
|
||||
UINT32* pDst = (UINT32*) pVideoAddress;
|
||||
LPBYTE pSrc = g_aSourceStartofLine[ sy ] + sx;
|
||||
int nBytes;
|
||||
|
||||
while (h--)
|
||||
{
|
||||
nBytes = w;
|
||||
while (nBytes)
|
||||
{
|
||||
--nBytes;
|
||||
if (g_uHalfScanLines && !(h & 1))
|
||||
{
|
||||
// 50% Half Scan Line clears every odd scanline (and SHIFT+PrintScreen saves only the even rows)
|
||||
*(pDst+nBytes) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ASSERT( *(pSrc+nBytes) < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ *(pSrc+nBytes) ];
|
||||
const UINT32 rgb = (((UINT32)rRGB.rgbRed)<<16) | (((UINT32)rRGB.rgbGreen)<<8) | ((UINT32)rRGB.rgbBlue);
|
||||
*(pDst+nBytes) = rgb;
|
||||
}
|
||||
}
|
||||
|
||||
pDst -= GetFrameBufferWidth();
|
||||
pSrc -= SRCOFFS_TOTAL;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void UpdateHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
{
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
BYTE byteval1 = (x > 0) ? *(pMain-1) : 0;
|
||||
BYTE byteval2 = *(pMain);
|
||||
BYTE byteval3 = (x < 39) ? *(pMain+1) : 0;
|
||||
|
||||
#define COLOFFS (((byteval1 & 0x60) << 2) | ((byteval3 & 0x03) << 5))
|
||||
#if 0
|
||||
if (g_eVideoType == VT_COLOR_TVEMU)
|
||||
{
|
||||
CopyMixedSource(
|
||||
xpixel >> 1, (ypixel+(yoffset >> 9)) >> 1,
|
||||
SRCOFFS_HIRES+COLOFFS+((x & 1) << 4), (((int)byteval2) << 1)
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CopySource(14,2, SRCOFFS_HIRES+COLOFFS+((x & 1) << 4), (((int)byteval2) << 1), pVideoAddress);
|
||||
}
|
||||
#undef COLOFFS
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
{
|
||||
const int xpixel = x*14;
|
||||
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
|
||||
BYTE byteval1 = (x > 0) ? *(pMain-1) : 0;
|
||||
BYTE byteval2 = *pAux;
|
||||
BYTE byteval3 = *pMain;
|
||||
BYTE byteval4 = (x < 39) ? *(pAux+1) : 0;
|
||||
|
||||
DWORD dwordval = (byteval1 & 0x70) | ((byteval2 & 0x7F) << 7) |
|
||||
((byteval3 & 0x7F) << 14) | ((byteval4 & 0x07) << 21);
|
||||
#define PIXEL 0
|
||||
#define COLOR ((xpixel + PIXEL) & 3)
|
||||
#define VALUE (dwordval >> (4 + PIXEL - COLOR))
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress);
|
||||
#undef PIXEL
|
||||
#define PIXEL 7
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress+7);
|
||||
#undef PIXEL
|
||||
#undef COLOR
|
||||
#undef VALUE
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Tested with Deater's Cycle-Counting Megademo
|
||||
void UpdateLoResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
{
|
||||
const BYTE val = *MemGetMainPtr(addr);
|
||||
|
||||
if ((y & 4) == 0)
|
||||
{
|
||||
CopySource(14,2, SRCOFFS_LORES+((x & 1) << 1), ((val & 0xF) << 4), pVideoAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopySource(14,2, SRCOFFS_LORES+((x & 1) << 1), (val & 0xF0), pVideoAddress);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define ROL_NIB(x) ( (((x)<<1)&0xF) | (((x)>>3)&1) )
|
||||
|
||||
// Tested with FT's Ansi Story
|
||||
void UpdateDLoResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
{
|
||||
BYTE auxval = *MemGetAuxPtr(addr);
|
||||
const BYTE mainval = *MemGetMainPtr(addr);
|
||||
|
||||
const BYTE auxval_h = auxval >> 4;
|
||||
const BYTE auxval_l = auxval & 0xF;
|
||||
auxval = (ROL_NIB(auxval_h)<<4) | ROL_NIB(auxval_l);
|
||||
|
||||
if ((y & 4) == 0)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_LORES+((x & 1) << 1), ((auxval & 0xF) << 4), pVideoAddress);
|
||||
CopySource(7,2, SRCOFFS_LORES+((x & 1) << 1), ((mainval & 0xF) << 4), pVideoAddress+7);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_LORES+((x & 1) << 1), (auxval & 0xF0), pVideoAddress);
|
||||
CopySource(7,2, SRCOFFS_LORES+((x & 1) << 1), (mainval & 0xF0), pVideoAddress+7);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static LPBYTE g_pSourcePixels = NULL;
|
||||
|
||||
static void V_CreateDIBSections(void)
|
||||
{
|
||||
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++)
|
||||
g_aSourceStartofLine[ y ] = g_pSourcePixels + SRCOFFS_TOTAL*((MAX_SOURCE_Y-1) - y);
|
||||
|
||||
// DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER
|
||||
ZeroMemory(g_pSourcePixels, SRCOFFS_TOTAL*MAX_SOURCE_Y); // 32 bytes/pixel * 16 colors = 512 bytes/row
|
||||
|
||||
V_CreateLookup_Lores();
|
||||
|
||||
// if ( g_eVideoType == VT_COLOR_TVEMU )
|
||||
// V_CreateLookup_Hires();
|
||||
// else
|
||||
V_CreateLookup_HiResHalfPixel_Authentic(VT_COLOR_MONITOR_RGB);
|
||||
|
||||
V_CreateLookup_DoubleHires();
|
||||
}
|
||||
|
||||
void VideoInitializeOriginal(baseColors_t pBaseNtscColors)
|
||||
{
|
||||
// CREATE THE SOURCE IMAGE AND DRAW INTO THE SOURCE BIT BUFFER
|
||||
V_CreateDIBSections();
|
||||
|
||||
#if 1
|
||||
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];
|
||||
#endif
|
||||
}
|
8
source/Video_OriginalColorTVMode.h
Normal file
8
source/Video_OriginalColorTVMode.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
void UpdateHiResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateDHiResCell(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);
|
||||
|
||||
const UINT kNumBaseColors = 16;
|
||||
typedef bgra_t (*baseColors_t)[kNumBaseColors];
|
||||
void VideoInitializeOriginal(baseColors_t pBaseNtscColors);
|
Loading…
Add table
Reference in a new issue