;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-2012, 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: Firmware for harddisk card
;
; Author: Copyright (c) 2005, Robert Hoem
;

; Modified by Tom Charlesworth:
; . Fixed so it can be assembled by a65 v1.06
; . Fixed so that ProDOS entrypoint is $c70a (26 Dev 2007) (Bug #12723)
; . Modified to support Apple Oasis' entrypoint: $c761 (8 Sept 2012) (Feature #5557)
; . Added support for SmartPort entrypoint (20 Oct 2012)
;   - EG. "Prince of Persia (Original 3.5 floppy for IIc+).2mg"
; . GH#370 (Robert Hoem, 27 Oct 2016):
    . Added a check against open-apple during boot to route boot to slot 6
    . This happens after the first two blocks are loaded from the HD.
; TODO:
; . Make code relocatable (so HDD controller card can go into any slot)
; . Remove support for Entrypoint_C746 (old AppleWin) & Entrypoint_C761 (Apple Oasis)
;   - provide a utility to convert these to use Entrypoint_ProDOS
; . Check SmartPort: Is it OK to trash Y and $42,..,$47 ?
;

; constants
hd_execute = $c0f0
hd_error = $c0f1
hd_command = $c0f2
hd_unitnum = $c0f3
hd_memblock  = $c0f4
hd_diskblock = $c0f6
hd_nextbyte = $c0f8

command = $42
unitnum = $43
memblock = $44
diskblock = $46

slot6   = $c600
OS      = $0801
BUTTON0 = $C061

; The Autoboot rom will call this.
; This is also the entry point for such things as IN#7 and PR#7

;; code
*= $c700	; org $c700

start

; 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
 lda #$20
 lda #$00
 lda #$03
 lda #$3C
 bne Bootstrap

Entrypoint_ProDOS		; $c70a - ProDOS entrypoint
 sec
 bcs Entrypoint

Entrypoint_SmartPort	; $c70d - SmartPort entrypoint
 clc
 
Entrypoint				; $c70e - entrypoint?
 bcs cmdproc
 bcc SmartPort

;;

Bootstrap
; Lets check to see if there's an image ready
 lda #$00
 sta hd_command

; Slot 7, disk 1
 lda #$70	; Slot# << 4
 sta hd_unitnum
 lda hd_execute

; error capturing code.  Applewin is picky
; about code assigning data to registers and
; memory.  The safest method is via I/O port
 pha
 lda hd_error
 clc
 cmp #1
 bne noerr0
 sec
noerr0
 pla
 bcc hdboot

; no image ready, boot diskette image instead
BootSlot6
 jmp slot6

;======================================

; TODO: Is it OK to trash Y and $42,..,$47 ?
; Pre: C=0
SmartPort
 pla
 sta $46
 pla
 sta $47		; ($47) = &cmd_hdr
 pha
 lda $46
 adc #3			; Pre: C=0, Post: assume C=0
 pha			; (sp).w += 3

 ldy #1
 lda ($46),y	; cmd
 sta $42
 iny
 bne SmartPort2

;======================================
; 2 unused bytes

*= $c746	; org $c746

Entrypoint_C746	; Old f/w 'cmdproc' entrypoint
				; Keep this for any DOSMaster HDD images created with old AppleWin HDD f/w.
				; DOSMaster hardcodes the entrypoint addr into its bootstrapping code:
				; - So DOSMaster images are tied to the HDD's controller's f/w
 sec
 bcs Entrypoint

;======================================

; Pre: Y=2
SmartPort2
 lda ($46),y	; param_l
 sta $45
 iny
 lda ($46),y	; param_h
 sta $46

 ldy #1			; skip paramLength (assume it's #$03)
 lda ($45),y	; unit
 sta $43
 iny
 lda ($45),y	; memblock_l
 sta $44
 iny
 bne SmartPort3

;======================================
; 1 unused byte
 
*= $c761	; org $c761

Entrypoint_C761	; Apple Oasis HDD controller entrypoint
				; Keep this for any DOSMaster HDD images created with Apple Oasis HDD f/w.
				; DOSMaster hardcodes the entrypoint addr into its bootstrapping code:
				; - So DOSMaster images are tied to the HDD's controller's f/w
 sec
 bcs Entrypoint

;======================================

; image ready.  Lets boot from it.
; we want to load block 1 from s7,d1 to $800 then jump there
hdboot
 lda #$70	; Slot# << 4
 sta unitnum
 lda #$0
 sta memblock
 sta diskblock
 sta diskblock+1
 lda #$8
 sta memblock+1
 lda #$1
 sta command
 jsr cmdproc
 bcs BootSlot6

goload
 bit BUTTON0   ; button 0 pressed?
 bmi BootSlot6

; X=device
 ldx #$70	; Slot# << 4
 jmp OS

; entry point for ProDOS' block driver
; simple really. Copy the command from $42..$47
; to our I/O ports then execute command
cmdproc
 clc
 lda $42
 sta hd_command
 lda $43
 sta hd_unitnum
 lda $44
 sta hd_memblock
 lda $45
 sta hd_memblock+1
 lda $46
 sta hd_diskblock
 lda $47
 sta hd_diskblock+1
 lda hd_execute

; check for error
 pha
 lda command
 cmp #1
 bne skipSread
 jsr sread
skipSread
 lda hd_error
 clc
 cmp #1
 bne noerr2
 sec
noerr2
 pla
 rts


; if there's no error, then lets read the block into memory
; because Applewin is picky about memory management, here's what I did:
; on read, hd_nextbyte = buffer[0], therefore we'll read that byte 256 times (in which
; the emulated code increments the buffer by 1 on each read) to (memblock),y
; increment memblock+1 and read the second 256 bytes via hd_nextbyte.
;
; if I could figure out how to consistantly get applewin to update it's memory regions all
; this code can be moved into the emulation code (although, this is how I'd build the hardware
; anyway...)

sread
 tya
 pha
 ldy #0
loop1
 lda hd_nextbyte
 sta (memblock),y
 iny
 bne loop1
 inc memblock+1
 ldy #0
loop2
 lda hd_nextbyte
 sta (memblock),y
 iny
 bne loop2
 dec memblock+1		; restore memblock+1 ($45) to original value (for Epyx's California Games)
 pla
 tay
 rts

;======================================

SmartPort3
 lda ($45),y	; memblock_h
 pha
 iny
 lda ($45),y	; diskblock_l
 pha
 iny
 lda ($45),y	; diskblock_h
 sta $47
 
 pla
 sta $46
 pla
 sta $45
 
 iny
 bne cmdproc

;======================================
; 12 unused bytes

; $CsFE = 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
; $BF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status (KEGS / IIGS)


; datablock.  This starts near the end of the firmware (at offset $FC)
;; data
*= $c7fc	; org $c7fc
 .word $7fff ; how many blocks are on the device.
 .byte $D7 ; specifics about the device (number of drives, read/write/format capability, etc)
 .byte <Entrypoint_ProDOS ; entry point offset for ProDOS (must be $0a)

 .end
