Support HDC SmartPort firmware for Enhanced //e (#1207, PR #1314)

Added new SmartPort Harddisk Controller (HDC) firmware for Enhanced //e. (@burniouf)
. remove the old DOSMaster entrypoints.
. firmware ID byte (at $FE) defaults to 4 ProDOS block devices (was 2 with older v2 f/w).
Enhanced //e defaults to using SP f/w, and older Apple II's still use the older v2 f/w.
Support up to 8 units per HDC (currently limited to 4GiB capacity for each unit).
Save-state: save HDC firmware in state file.
New slot-specific switches to configure each HDC's firmware: -s<N> -hdc-[sp|bm2|bm4].
New switch to select old non-SP firmware for all HDCs: -hdc-firmware-v2.
This commit is contained in:
TomCh 2024-07-28 16:12:36 +01:00 committed by GitHub
parent 72f0c03981
commit b371e3436f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 1267 additions and 320 deletions

View File

@ -90,6 +90,7 @@
<ClInclude Include="source\LanguageCard.h" />
<ClInclude Include="source\Log.h" />
<ClInclude Include="source\Memory.h" />
<ClInclude Include="source\MemoryDefs.h" />
<ClInclude Include="source\Mockingboard.h" />
<ClInclude Include="source\MockingboardCardManager.h" />
<ClInclude Include="source\MockingboardDefs.h" />

View File

@ -618,6 +618,9 @@
<ClInclude Include="source\MockingboardDefs.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
<ClInclude Include="source\MemoryDefs.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="resource\Applewin.bmp">

View File

@ -0,0 +1,379 @@
;--------------------------------------
;AppleWin : An Apple //e emulator for Windows
;
;Copyright (C) 1994-1996, Michael O'Brien
;Copyright (C) 1999-2001, Oliver Schmidt
;Copyright (C) 2002-2005, Tom Charlesworth
;Copyright (C) 2006-2024, Tom Charlesworth, Michael Pohoreski
;
;AppleWin is free software; you can redistribute it and/or modify
;it under the terms of the GNU General Public License as published by
;the Free Software Foundation; either version 2 of the License, or
;(at your option) any later version.
;
;AppleWin is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with AppleWin; if not, write to the Free Software
;Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;
; Description: SmartPort firmware for Hard Disk Controller card
;
; Author: Copyright (c) 2024, Rémy Gibert
; . derived from works: Copyright (c) 2005, Robert Hoem
;
;--------------------------------------
!cpu 6502 ; Compatible with all Apple2's
!to "HDC-SmartPort.bin", plain
!sl "HDC-SmartPort.labels"
;--------------------------------------
!src "IO_Apple.inc"
!src "IO_Applewin.inc"
!src "MON.inc"
!src "ProDOS.inc"
;--------------------------------------
; SP commands
;--------------------------------------
SP_Cmd_status = $00
SP_Cmd_status_STATUS = $00
SP_Cmd_status_GETDCB = $01
SP_Cmd_status_GETNL = $02
SP_Cmd_status_GETDIB = $03
SP_Cmd_readblock = $01
SP_Cmd_writeblock = $02
SP_Cmd_format = $03
SP_Cmd_control = $04
SP_Cmd_init = $05
SP_Cmd_open = $06
SP_Cmd_close = $07
SP_Cmd_read = $08
SP_Cmd_write = $09
SP_Cmd_extended = $40
;--------------------------------------
; ZP locations
;--------------------------------------
Ptr1 = $3C
BLK_Cmd = $42
BLK_Cmd_Status = $0
BLK_Cmd_Read = $1
BLK_Cmd_Write = $2
BLK_Cmd_Format = $3
BLK_UnitNum = $43
BLK_MemPtr = $44
BLK_BlockNum = $46
;--------------------------------------
; Screen holes (scratch space)
;--------------------------------------
Slot_n0 = $478
; = $4F8
; = $578
; = $5F8
; = $678
; = $6F8
; = $778
;Slot_C8 = $7F8 ; IRQ protocol for handling $C800 space properly
; Screen holes,Cn indexed
; = $478-$C0
; = $4F8-$C0
; = $578-$C0
; = $5F8-$C0
; = $678-$C0
; = $6F8-$C0
; = $778-$C0
; = $7F8-$C0
;--------------------------------------
BootBlocklA3 = $800
BootBlocklA2 = $801
;--------------------------------------
; The Autoboot rom will call this.
; This is also the entry point for such things as IN#7 and PR#7
; Autoboot and ProDOS look at the following few opcodes to detect block devices
; NB. $Cn07 should be $00 for a SmartPort Interface, but changing this means that it won't autoboot on ][, ][+ and unenhanced IIe.
; . ref: http://www.1000bit.it/support/manuali/apple/technotes/udsk/tn.udsk.2.html
;--------------------------------------
!zone code
* = $0000 ; org $0000 - position-independent code, so doesn't matter (but the other fixed org positions need to be on the same page)
Cn_start lda #$20
lda #$00
cmp #$03 ; will set C=0
lda #$00 ; SP mode
; lda #$3C ; BLK mode
bcc Cn_Bootstrap
Cn_Entry_BLK sec ; $Cn0A - BLK entrypoint
bcs Cn_Entry
Cn_Entry_SP clc ; $Cn0D - SmartPort entrypoint
Cn_Entry php
sei ; disable ints, in case an int handler races our $0000/RTS and stack accesses!
;--------------------------------------
; NB. need RAM that's guaranteed to be both read & writeable:
; . can't use $0200-$BFFF, due to eg. RAMRD=0/RAMWRT=1 combination
; . can't use LC as ROM might be enabled.
; So use ZP (specifically $0000) as whatever the state of ALTZP, both read & write will be to the same physical memory location.
;--------------------------------------
lda $00 ; save $00
ldx #$60 ; opcode RTS
stx $00
jsr $0000 ; RTS immediately (NB. can't use $FF58, since LC RAM may be switched in)
sta $00 ; restore $00
tsx
lda $0100,x ; $Cn
asl
asl
asl
asl
sta Slot_n0
plp ; + restore int status
bcs Cn_BLK ; C=1: ProDOS mode .....
;--------------------------------------
; C=0: fall through to SmartPort...
;--------------------------------------
lda Ptr1 ; X = Stack Ptr from TSX above
pha
lda Ptr1+1
pha
lda $102,x ; jsr LO byte
sta Ptr1
; clc ; from bcs above
adc #3
sta $102,x ; jsr LO byte
lda $103,x ; jsr HI byte
sta Ptr1+1
adc #0
sta $103,x ; jsr HI byte
ldy #1 ; CMD byte
bne Cn_SP ; Always
;--------------------------------------
Cn_Sloop jmp MON_SLOOP
;--------------------------------------
Cn_Bootstrap bit IO_IIE_OPENAPPLE
bmi Cn_Sloop
jsr MON_RTS ; ROM supposed to be enabled at BOOT time or PR#7
tsx
lda $0100,x ; $Cn
asl
asl
asl
asl
sta Slot_n0
; Lets check to see if there's an image ready
; Slot n, disk 1
tax ; A=%0SSS0000
sta IO_Unitnum,x ; b7=0 (and b6:4=SSS) => disk 1
lda #BLK_Cmd_Status
sta IO_Command,x
lda IO_Execute,x ; Post: A=STATUS (BLK_Cmd_Status completes immediately, no need to check STATUS.b7 busy bit)
; on error A = 0eeeeee1, where eeeeee = Standard ProDOS error codes (see ProDOS.inc)
lsr ; Post: C=0 or 1
bcs Cn_Sloop ; no image ready, boot Slot n-1 image instead
;--------------------------------------
; image ready. Lets boot from it.
; we want to load block 1 from disk 1 to $800 then jump there
; Pre: X = Slot# << 4
;--------------------------------------
lda #$1
sta BLK_Cmd
stx BLK_UnitNum ; DSSS0000, where D=0 (ie. disk 1)
lda #$0
sta BLK_MemPtr
sta BLK_BlockNum
sta BLK_BlockNum+1
lda #$8
sta BLK_MemPtr+1
; clc ; C = 0 from bcs Cn_Sloop
;--------------------------------------
; entry point for BLK driver
; simple really. Copy the command from BLK_Cmd..BLK_BlockNum+1
; to our I/O ports then execute command
; Pre:
; X = Slot# << 4
; C = 0 from Cn_Bootstrap
; C = 1 from Cn_Entry_BLK
; Post:
; C = IO_Status b0
; A = result of IO_Execute
; Read or write command
; X = Slot# << 4
; Y = command
; Status command
; X = low byte of disk size
; Y = high byte of disk size
;--------------------------------------
Cn_BLK php
ldx Slot_n0
ldy #0
- lda BLK_Cmd,y
sta IO_BlkCmdFifo,x ; BLK_Cmd's are $0x
iny ; BLK_UnitNum's are DSSS0000 : if SSS does NOT match physical slot...
; ...hardware should handle the remap by adding +2 to the REAL dev_ID
cpy #6 ; that way, a BLK controller can support 4 devices (see $CnFE byte below)
bcc -
- lda IO_Execute,x ; A = result of IO_Execute (NB. instantaneous 512 byte r/w!)
bmi - ; b7=busy doing DMA?
plp ; restore C
bcs Cn_BLK_Done ; from Cn_Entry_BLK
lsr ; Post: C=0 or 1
bcs Cn_Sloop ; Boot Failed....
jmp BootBlocklA2 ; Success, run $801 BOOT code for Apple ][ (not /// at $800)
Cn_BLK_Done lsr ; Post: C=0 or 1
ldy BLK_Cmd ; Was it status ?
bne + ; no, go home
pha ; Save result
ldy IO_Imgsizehi,x ; Get high byte of size
lda IO_Imgsizelo,x ; Get low byte of size
tax ; Transfer into X
pla ; Get back status call result
+ rts
;--------------------------------------
Cn_SP lda (Ptr1),y ; CMD byte
cmp #SP_Cmd_format
bcs Cn_SP_E_BADCALL ; only STATUS, READBLOCK & WRITEBLOCK supported
ldx Slot_n0
sta IO_SPCmdFifo,x ; Smartport calls = $8x (OR'd with $80 by h/w), Statuscode written at IO_StatusCode
iny ; param LO
lda (Ptr1),y
pha
iny ; param HI
lda (Ptr1),y
sta Ptr1+1
pla
sta Ptr1 ; Now Ptr1 = Param list
ldy #0 ; Param Cnt
lda (Ptr1),y
cmp #3 ; STATUS, READBLOCK & WRITEBLOCK = all 3 parameters
sec
bne Cn_SP_E_BADCNT
- iny ; UnitNum (B), MemPtr (L/H), DiskBlock (L/M/H) -> IO (R,W)
lda (Ptr1),y ; UnitNum (B), MemPtr (L/H), StatusCode (B) -> IO (S)
sta IO_SPCmdFifo,x ; UnitNum Range is 0 (smartport controller itself), 1,2,3.....
cpy #6 ; blockNums are 24-bit for SP calls
bcc -
- lda IO_Execute,x ; A = result of IO_Execute (NB. instantaneous 512 byte r/w!)
bmi - ; b7=busy doing DMA?
lsr ; get C=1 & A = ERROR CODE ... or C=0 & A = 0
tax ; Save Error Code
!byte $2C ; BIT ABS
Cn_SP_E_BADCALL ldx #E_BADCALL
!byte $2C ; BIT ABS
Cn_SP_E_BADCNT ldx #E_BADCNT
pla
sta Ptr1+1
pla
sta Ptr1
txa ; Restore Error Code
ldx #0
ldy #2 ; exit returning YX = $0200 bytes transferred if success
rts ; or C=1 & A=ERROR CODE
;--------------------------------------
!zone data
;--------------------------------------
; datablock. This starts near the end of the firmware (at offset $CnFB)
;
; $CnFB :
; 7 : 1 = Support Extended commands
; 6 : [Reserved]
; 5 : [Reserved]
; 4 : [Reserved]
; 3 : [Reserved]
; 2 : [Reserved]
; 1 : 1 = Supports SCSI devices (Helps ProDOS build SP device list)
; 0 : 1 = Supports RAMDisk Card
;
; $CnFC/D : size in blocks (BLK) if $0000 Software must issue a BLK Status Call to get size in blocks
;
; $CnFE = status bits (BAP p7-14)
; 7 = medium is removable
; 6 = device is interruptable
; 5-4 = number of volumes (0..3 means 1..4)
; 3 = device supports Format call
; 2 = device can be written to
; 1 = device can be read from (must be 1)
; 0 = device status can be read (must be 1)
;
; $C7 = Removable, Interruptable, #Volumes=1, Supports write/read/status
; $D7 = Removable, Interruptable, #Volumes=2, Supports write/read/status
; $F7 = Removable, Interruptable, #Volumes=4, Supports write/read/status
; $BF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status (KEGS / IIGS)
;
; $CnFF = offset to BLK entry point
;--------------------------------------
@checkCsFB
*= $00FB ; org $00FB
!warn "CsFB padding = ", * - @checkCsFB
;--------------------------------------
!byte $00 ; Smart port ID Type byte
!word $0000 ; how many blocks are on the device. Zero means use status call
!byte $F7 ; specifics about the device (number of drives, read/write/format capability, etc)
!byte <Cn_Entry_BLK ; entry point offset for ProDOS (must be $0a)
;--------------------------------------

Binary file not shown.

View File

@ -0,0 +1,31 @@
;--------------------------------------
; All ][
;--------------------------------------
IO_KBD = $C000 ; R
IO_KBDSTROBE = $C010 ; W
IO_CLRPAGE2 = $C054 ; W
IO_SETPAGE2 = $C055 ; W
IO_RROMBNK2 = $C082 ; R
;--------------------------------------
; IIe Specific
;--------------------------------------
IO_IIE_CLR80STORE = $C000 ; W
IO_IIE_SET80STORE = $C001 ; W
IO_IIE_CLR80DISP = $C00C ; W
IO_IIE_SET80DISP = $C00D ; W
IO_IIE_CLRALTCHAR = $C00E ; W
IO_IIE_SETALTCHAR = $C00F ; W
IO_IIE_RD80STORE = $C018 ; R
IO_IIE_RDALTCHAR = $C01E ; R
IO_IIE_RD80DISP = $C01F ; R
IO_IIE_OPENAPPLE = $C061 ; R
IO_IIE_SOLIDAPPLE = $C062 ; R
;--------------------------------------
; IIgs Specific
;--------------------------------------
IO_IIGS_DMAREG = $00C037 ; R,W
;--------------------------------------

View File

@ -0,0 +1,33 @@
;--------------------------------------
; Applewin HD Controller IOs
;--------------------------------------
IO_Execute = $c080 ; R : Execute command & return IO_Status. Then on subsequent IO_Execute reads just return IO_Status
IO_Status = $c081 ; R : b7=busy, b6..b1=ProDOS error code, b0=error
;--------------------------------------
IO_Command = $c082 ; W : BLK = $00 status, $01 read, $02 write. SP = $80 status, $81 read, $82 write,
IO_Unitnum = $c083 ; W : BLK = DSSS0000 if SSS != n from CnXX, add 2 to D (4 drives support). SP = $00,$01.....
IO_MemPtr = $c084 ; W : 16-bit values
;IO_MemPtrH = $c085 ; W
;--------------------------------------
IO_StatusCode = $c086 ; W : write SP status code $00, $03
;(see HDC-SmartPort.a65 : SP_Commands)
;--------------------------------------
IO_BlockNum = $c086 ; W : BLK = 16-bit values. SP = 24-bit values, see below
;IO_BlockNumM = $c087 ; W
;IO_BlockNumH = $c088 ; W : 3rd byte for SP 24-bit blocknum
;--------------------------------------
IO_Nextbyte = $c088 ; R : legacy read-only port (still supported by AppleWin)
IO_Imgsizelo = $c089 ; R
IO_Imgsizehi = $c08a ; R
;--------------------------------------
IO_BlkCmdFifo = $c089 ; W : a 6-deep FIFO to write: command, unitNum, memPtr(2), blockNum(2)
IO_SPCmdFifo = $c08a ; W : a 7-deep FIFO to write: command, unitNum, memPtr(2), blockNum(3); first byte gets OR'd with $80 (ie. to indicate it's an SP command)
;--------------------------------------
; Notes on accesses to I/O registers:
; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register:
; 6502: double read (old data), write (old data), write (new data). The writes are harmless as writes to STATUS are ignored.
; 65C02: double read (old data), write (new data). The write is harmless as writes to STATUS are ignored.
; . STA ABS16,X does a false-read. This is harmless for writable I/O registers, since the false-read has no side effect.
;--------------------------------------

View File

@ -0,0 +1,26 @@
;--------------------------------------
CH = $24 ; CURSOR HORIZONTAL
CV = $25 ; CURSOR VERTICAL
BASL = $28 ; TEXT BASE LOW
BASH = $29 ; TEXT BASE HIGH
INVFLG = $32 ; NORMAL/INVERSE /FLASH (FF,7F,3F)
;--------------------------------------
MON_POWERUP = $3F2
MON_POWERUPBYTE = $3F4
;--------------------------------------
MON_SLOOP = $FABA
MON_SETTXT = $FB39
MON_HOME = $FC58
MON_VTABA = $FC24
MON_CR = $FC62
MON_CROUT = $FD8E
MON_PRBYTE = $FDDA
MON_COUT = $FDED
MON_INVERSE = $FE80
MON_NORM = $FE84
MON_IN0 = $FE89
MON_PR0 = $FE93
MON_RTS = $FF58
;--------------------------------------

View File

@ -0,0 +1,19 @@
;--------------------------------------
; ProDOS defines
;--------------------------------------
PRODOS_MAXPATH = 64
;--------------------------------------
; Error codes
;--------------------------------------
E_BADCALL = $01 ; Bad Call Number
E_BADCNT = $04 ; Bad Parameter Count
E_BUSERR = $06 ; Communications Error
E_BADCTL = $21 ; Invalid Status Code
E_IO = $27 ; I/O Error
E_NODEV = $28 ; No Device Connected
E_WRTPROT = $2B ; Write Protected
E_BADBLOCK = $2D ; Invalid Block Number
E_DSKSWIT = $2E ; Disk Switched
E_OFFLINE = $2F ; Device Offline
;--------------------------------------

View File

@ -0,0 +1,11 @@
@REM ACME only ever returns 0!
acme.exe HDC-SmartPort.a65
@IF %ERRORLEVEL% NEQ 0 goto error
copy HDC-SmartPort.bin ..\..\resource
@goto end
:error
@echo "ACME failed"
:end

View File

@ -332,6 +332,7 @@ IDR_DISK2_16SECTOR_FW FIRMWARE "Disk2.rom"
IDR_SSC_FW FIRMWARE "SSC.rom"
IDR_HDDRVR_FW FIRMWARE "Hddrvr.bin"
IDR_HDDRVR_V2_FW FIRMWARE "Hddrvr-v2.bin"
IDR_HDC_SMARTPORT_FW FIRMWARE "HDC-SmartPort.bin"
IDR_PRINTDRVR_FW FIRMWARE "Parallel.rom"
IDR_MOCKINGBOARD_D_FW FIRMWARE "Mockingboard-D.rom"
IDR_MOUSEINTERFACE_FW FIRMWARE "MouseInterface.rom"

BIN
resource/HDC-SmartPort.bin Normal file

Binary file not shown.

View File

@ -55,6 +55,7 @@
#define IDR_BASE_64A_ROM 153
#define IDR_BASE64A_VIDEO_ROM 154
#define IDR_HDDRVR_V2_FW 155
#define IDR_HDC_SMARTPORT_FW 156
#define IDC_KEYB_BUFFER_ENABLE 1005
#define IDC_SAVESTATE 1006
#define IDC_SAVESTATE_ON_EXIT 1007

View File

@ -188,6 +188,21 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
}
if (strcmp(lpCmdLine, "hdc") == 0)
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
if (strcmp(lpCmdLine, "hdc-sp") == 0)
{
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcSmartPort;
}
if (strcmp(lpCmdLine, "hdc-bm2") == 0)
{
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcBlockMode2Devices;
}
if (strcmp(lpCmdLine, "hdc-bm4") == 0)
{
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcBlockMode4Devices;
}
if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) // Support Saturn128 card in slot 1-7 too (GH#1279)
g_cmdLine.slotInsert[slot] = CT_Saturn128K;
if (strcmp(lpCmdLine, "megaaudio") == 0)
@ -237,11 +252,12 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
g_cmdLine.szImageName_drive[slot][drive] = lpCmdLine;
}
}
else if (lpCmdLine[3] == 'h' && (lpCmdLine[4] == '1' || lpCmdLine[4] == '2')) // -s[1..7]h[1|2] <dsk-image>
else if (lpCmdLine[3] == 'h' && (lpCmdLine[4] >= '1' || lpCmdLine[4] <= '8')) // -s[1..7]h[1|2|...|8] <dsk-image>
{
const UINT drive = lpCmdLine[4] == '1' ? HARDDISK_1 : HARDDISK_2;
const UINT drive = lpCmdLine[4] - '1';
bool badDrive = drive >= NUM_HARDDISKS;
if (slot != SLOT5 && slot != SLOT7)
if (badDrive || (slot != SLOT5 && slot != SLOT7))
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
}
@ -641,6 +657,10 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
{
g_cmdLine.useHdcFirmwareV1 = true;
}
else if (strcmp(lpCmdLine, "-hdc-firmware-v2") == 0)
{
g_cmdLine.useHdcFirmwareV2 = true;
}
else // unsupported
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);

View File

@ -14,9 +14,11 @@ struct CmdLine
SlotInfo()
{
isDiskII13 = false;
useHdcFirmwareMode = HdcDefault;
}
bool isDiskII13;
HdcMode useHdcFirmwareMode;
};
CmdLine()
@ -35,6 +37,7 @@ struct CmdLine
supportExtraMBCardTypes = false;
noDisk2StepperDefer = false;
useHdcFirmwareV1 = false;
useHdcFirmwareV2 = false;
szSnapshotName = NULL;
szScreenshotFilename = NULL;
uHarddiskNumBlocks = 0;
@ -80,6 +83,7 @@ struct CmdLine
bool supportExtraMBCardTypes;
bool noDisk2StepperDefer; // debug
bool useHdcFirmwareV1; // debug
bool useHdcFirmwareV2;
SS_CARDTYPE slotInsert[NUM_SLOTS];
SlotInfo slotInfo[NUM_SLOTS];
LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];

View File

@ -121,8 +121,7 @@ enum AppMode_e
#define REGVALUE_GAME_IO_TYPE "Game I/O type"
#define REGVALUE_LAST_DISK_1 "Last Disk Image 1"
#define REGVALUE_LAST_DISK_2 "Last Disk Image 2"
#define REGVALUE_LAST_HARDDISK_1 "Last Harddisk Image 1"
#define REGVALUE_LAST_HARDDISK_2 "Last Harddisk Image 2"
#define REGVALUE_LAST_HARDDISK_ "Last Harddisk Image "
// Preferences
#define REG_PREFS "Preferences"

View File

@ -9,6 +9,7 @@ void LogFileTimeUntilFirstKeyReadReset(void);
void LogFileTimeUntilFirstKeyRead(void);
extern const UINT16* GetOldAppleWinVersion(void);
extern UINT16 g_AppleWinVersion[4];
extern std::string g_VERSIONSTRING; // Constructed in WinMain()
void SetAppleWinVersion(UINT16 major, UINT16 minor, UINT16 fix, UINT16 fix_minor);

File diff suppressed because it is too large Load Diff

View File

@ -26,15 +26,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Card.h"
#include "DiskImage.h"
#include "DiskImageHelper.h"
#include "MemoryDefs.h" // APPLE_SLOT_SIZE
enum HardDrive_e
{
HARDDISK_1 = 0,
HARDDISK_2,
NUM_HARDDISKS
NUM_BLK_HARDDISKS = 2,
NUM_HARDDISKS = 8
};
const UINT kHarddiskMaxNumBlocks = 0xffff; // Maximum number of blocks we can report.
enum HdcMode
{
HdcDefault, HdcSmartPort, HdcBlockMode2Devices, HdcBlockMode4Devices
};
// For SP read/write block cmds, a 24-bit blockNum => 8GiB capacity
// . but eg. in CImageBase::ReadBlock() only 32-bit byte positions are supported (ie. 4GiB capacity)
const UINT kHarddiskMaxNumBlocks = 0x007FFFFF; // Maximum number of blocks we can report.
const UINT kMaxSmartPortUnits = NUM_HARDDISKS;
class HardDiskDrive
{
@ -98,10 +108,11 @@ public:
bool Select(const int iDrive);
bool Insert(const int iDrive, const std::string& pathname);
void Unplug(const int iDrive);
bool IsDriveUnplugged(const int iDrive);
void LoadLastDiskImage(const int iDrive);
void SetUserNumBlocks(UINT numBlocks) { m_userNumBlocks = numBlocks; }
void UseHdcFirmwareV1(void) { m_useHdcFirmwareV1 = true; }
void UseHdcFirmwareV2(void) { m_useHdcFirmwareV2 = true; }
void SetHdcFirmwareMode(HdcMode hdcMode) { m_useHdcFirmwareMode = hdcMode; }
void GetLightStatus(Disk_Status_e* pDisk1Status);
bool ImageSwap(void);
@ -121,19 +132,36 @@ private:
const std::string& DiskGetBaseName(const int iDrive);
bool SelectImage(const int drive, LPCSTR pszFilename);
void UpdateLightStatus(HardDiskDrive* pHDD);
UINT GetImageSizeInBlocks(ImageInfo* const pImageInfo);
void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit);
BYTE GetNumConnectedDevices(void);
BYTE GetProDOSBlockDeviceUnit(void);
HardDiskDrive* GetUnit(void);
BYTE CmdExecute(HardDiskDrive* pHDD);
BYTE CmdStatus(HardDiskDrive* pHDD);
void SetIdString(WORD addr, const char* str);
BYTE SmartPortCmdStatus(HardDiskDrive* pHDD);
UINT GetImageSizeInBlocks(ImageInfo* const pImageInfo, const bool is16bit = false);
void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, const UINT unit);
bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, const UINT unit, const UINT version);
//
BYTE m_unitNum; // b7=unit
BYTE m_command;
BYTE m_fifoIdx;
BYTE m_statusCode;
UINT64 m_notBusyCycle;
UINT m_userNumBlocks;
bool m_useHdcFirmwareV1;
bool m_useHdcFirmwareV2;
HdcMode m_useHdcFirmwareMode;
bool m_saveDiskImage; // Save the DiskImage name to Registry
HardDiskDrive m_hardDiskDrive[NUM_HARDDISKS];
HardDiskDrive m_smartPortController; // unit-0 is the SmartPort controller
bool m_saveStateFirmwareV1;
bool m_saveStateFirmwareV2;
BYTE m_saveStateFirmware[APPLE_SLOT_SIZE];
bool m_saveStateFirmwareValid;
};

View File

@ -2,6 +2,7 @@
#include "Common.h"
#include "Card.h"
#include "MemoryDefs.h"
// Memory Flag
#define MF_80STORE 0x00000001
@ -22,23 +23,6 @@
#define MF_LANGCARD_MASK (MF_WRITERAM|MF_HIGHRAM|MF_BANK2)
enum
{
// Note: All are in bytes!
TEXT_PAGE1_BEGIN = 0x0400,
APPLE_SLOT_SIZE = 0x0100, // 1 page = $Cx00 .. $CxFF (slot 1 .. 7)
APPLE_IO_BEGIN = 0xC000,
APPLE_SLOT_BEGIN = 0xC100, // each slot has 1 page reserved for it
APPLE_SLOT_END = 0xC7FF, //
FIRMWARE_EXPANSION_SIZE = 0x0800, // 8 pages = $C800 .. $CFFF
FIRMWARE_EXPANSION_BEGIN = 0xC800, // [C800,CFFF)
FIRMWARE_EXPANSION_END = 0xCFFF, //
MEMORY_LENGTH = 0x10000
};
enum MemoryInitPattern_e
{
MIP_ZERO

18
source/MemoryDefs.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
enum
{
// Note: All are in bytes!
TEXT_PAGE1_BEGIN = 0x0400,
APPLE_SLOT_SIZE = 0x0100, // 1 page = $Cx00 .. $CxFF (slot 1 .. 7)
APPLE_IO_BEGIN = 0xC000,
APPLE_SLOT_BEGIN = 0xC100, // each slot has 1 page reserved for it
APPLE_SLOT_END = 0xC7FF, //
FIRMWARE_EXPANSION_SIZE = 0x0800, // 8 pages = $C800 .. $CFFF
FIRMWARE_EXPANSION_BEGIN = 0xC800, // [C800,CFFF)
FIRMWARE_EXPANSION_END = 0xCFFF, //
MEMORY_LENGTH = 0x10000
};

View File

@ -1,7 +1,6 @@
#pragma once
#include "Card.h"
#include "Memory.h"
class ParallelPrinterCard : public Card
{

View File

@ -283,10 +283,13 @@ void LoadConfiguration(bool loadImages)
GetCurrentDirectory(sizeof(szFilename), szFilename);
SetCurrentImageDir(szFilename);
if (loadImages && GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
for (UINT slot = SLOT1; slot <= SLOT7; slot++)
{
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).LoadLastDiskImage(HARDDISK_1);
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).LoadLastDiskImage(HARDDISK_2);
if (loadImages && GetCardMgr().QuerySlot(slot) == CT_GenericHDD)
{
for (UINT i = 0; i < NUM_HARDDISKS; i++)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(slot)).LoadLastDiskImage(i);
}
}
//
@ -429,29 +432,33 @@ void InsertHardDisks(const UINT slot, LPCSTR szImageName_harddisk[NUM_HARDDISKS]
{
_ASSERT(slot == 5 || slot == 7);
if (!szImageName_harddisk[HARDDISK_1] && !szImageName_harddisk[HARDDISK_2])
// If no HDDs then just return (and don't insert an HDC into this slot)
bool res = true;
for (UINT i = 0; i < NUM_HARDDISKS; i++)
res &= szImageName_harddisk[i] == NULL;
if (res)
return;
if (GetCardMgr().QuerySlot(slot) != CT_GenericHDD)
GetCardMgr().Insert(slot, CT_GenericHDD); // Enable the Harddisk controller card
bool bRes = true;
if (szImageName_harddisk[HARDDISK_1])
res = true;
for (UINT i = 0; i < NUM_HARDDISKS; i++)
{
bRes = DoHardDiskInsert(slot, HARDDISK_1, szImageName_harddisk[HARDDISK_1]);
LogFileOutput("Init: DoHardDiskInsert(HDD1), res=%d\n", bRes);
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS); // harddisk activity LED
bBoot = true;
if (szImageName_harddisk[i])
{
res &= DoHardDiskInsert(slot, i, szImageName_harddisk[i]);
LogFileOutput("Init: DoHardDiskInsert(HDD-%d), res=%d\n", i, res);
if (i == HARDDISK_1)
{
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS); // harddisk activity LED
bBoot = true;
}
}
}
if (szImageName_harddisk[HARDDISK_2])
{
bRes &= DoHardDiskInsert(slot, HARDDISK_2, szImageName_harddisk[HARDDISK_2]);
LogFileOutput("Init: DoHardDiskInsert(HDD2), res=%d\n", bRes);
}
if (!bRes)
if (!res)
GetFrame().FrameMessageBox("Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
}

View File

@ -784,19 +784,19 @@ static void RepeatInitialization(void)
if (g_cmdLine.slotInsert[SLOT5] != CT_Empty)
{
if (GetCardMgr().QuerySlot(SLOT5) != CT_Disk2) // Ignore if already got Disk2 in slot 5
if (GetCardMgr().QuerySlot(SLOT5) != g_cmdLine.slotInsert[SLOT5]) // Ignore if already got this card type in slot 5
GetCardMgr().Insert(SLOT5, g_cmdLine.slotInsert[SLOT5]);
}
if (g_cmdLine.slotInsert[SLOT6] == CT_Disk2) // For now just support Disk2 in slot 6
{
if (GetCardMgr().QuerySlot(SLOT6) != CT_Disk2) // Ignore if already got Disk2 in slot 6
if (GetCardMgr().QuerySlot(SLOT6) != g_cmdLine.slotInsert[SLOT6]) // Ignore if already got this card type in slot 6
GetCardMgr().Insert(SLOT6, g_cmdLine.slotInsert[SLOT6]);
}
if (g_cmdLine.slotInsert[SLOT7] != CT_Empty)
{
if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD) // Ignore if already got HDC in slot 7
if (GetCardMgr().QuerySlot(SLOT7) != g_cmdLine.slotInsert[SLOT7]) // Ignore if already got this card type in slot 7
GetCardMgr().Insert(SLOT7, g_cmdLine.slotInsert[SLOT7]);
}
@ -809,6 +809,9 @@ static void RepeatInitialization(void)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(i)).SetUserNumBlocks(g_cmdLine.uHarddiskNumBlocks);
if (g_cmdLine.useHdcFirmwareV1)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(i)).UseHdcFirmwareV1();
if (g_cmdLine.useHdcFirmwareV2)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(i)).UseHdcFirmwareV2();
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(i)).SetHdcFirmwareMode(g_cmdLine.slotInfo[i].useHdcFirmwareMode);
}
}
@ -855,10 +858,12 @@ static void RepeatInitialization(void)
g_cmdLine.szImageName_drive[SLOT6][DRIVE_1] = g_cmdLine.szImageName_drive[SLOT6][DRIVE_2] = NULL; // Don't insert on a restart
InsertHardDisks(SLOT5, g_cmdLine.szImageName_harddisk[SLOT5], temp);
g_cmdLine.szImageName_harddisk[SLOT5][HARDDISK_1] = g_cmdLine.szImageName_harddisk[SLOT5][HARDDISK_2] = NULL; // Don't insert on a restart
for (UINT i = 0; i < NUM_HARDDISKS; i++)
g_cmdLine.szImageName_harddisk[SLOT5][i] = NULL; // Don't insert on a restart
InsertHardDisks(SLOT7, g_cmdLine.szImageName_harddisk[SLOT7], g_cmdLine.bBoot);
g_cmdLine.szImageName_harddisk[SLOT7][HARDDISK_1] = g_cmdLine.szImageName_harddisk[SLOT7][HARDDISK_2] = NULL; // Don't insert on a restart
for (UINT i = 0; i < NUM_HARDDISKS; i++)
g_cmdLine.szImageName_harddisk[SLOT7][i] = NULL; // Don't insert on a restart
if (g_cmdLine.bSlotEmpty[SLOT7])
{