;license:MIT ;(c) 2019-2020 by 4am & qkumba ; ; Functions to enable and disable acceleration on various ; Apple II models, cards, and environments ; ; Forked from NORMFAST Release 6 (see changelog below) ; ; For Total Replay, we split the machine identification code from ; the (de)acceleration code, because we can do the ID part once ; at program startup (when ROM is easily available), then ; (de)accelerate repeatedly from the language card (when ROM ; is switched out). ; ; -------------------------------------------------------------- ; ; Original changelog and documentation: ; ;;; NORMFAST Disable/enable Apple II compatible accelerator ; (no copyright info given) ; ; Release 7 2019-11-27 FASTChip control just like ZipChip. ; Prevents unexpected acceleration by user. ; ; Release 6 2017-10-05 Fix Mac IIe card check ; ; Release 5 2017-09-27 Add Macintosh IIe Card. Addon ; accelerators are now set blindly, so will access ; annunciators/IIc locations and may trigger the ; paddle timer. ; No plans for the Saturn Systems Accelerator which would ; require a slot search. ; ; Release 4 2017-09-06 Add Laser 128EX, TransWarp I, UW ; ; Release 3 2017-08-29 Change FASTChip partially back to ; release 1, which seems to work the way release 2 was ; intended?! ; ; Release 2 2017-08-27 change enable entry point, add Zip ; Chip, change setting FASTChip speed to disable/enable ; ; Release 1 2017-08-25 IIGS, //c+ and FASTChip ; ; WARNING: The memory location to set the accelerator ; speed may overlap existing locations such as: ; annuciators or Apple //c specific hardware ; paddle trigger ; ; Known to work: IIGS, //c+ ; Theoretically: FASTChip, Laser 128EX, Mac IIe Card, ; TransWarp I, trademarked German product, Zip Chip ; ; BRUN NORMFAST or CALL 768 to disable the accelerator. ; CALL 771 to enable the accelerator. ; Enabling an older accelerator may set maximum speed. ; Accelerators such as the FASTChip or Zip Chip can run ; slower than 1Mhz when enabled. ; ; NORMFAST is position independent and can be loaded most ; anywhere in the first 48K of memory. ; The ROMs must be enabled to identify the model of the ; computer. ; ; This was originally for the //c+ which is normally ; difficult to set to 1Mhz speed. ; The other expected use is to set the speed in a program. ; ; Written for Andrew Jacobs' Java based dev65 assembler at ; http://sourceforge.net/projects/dev65 but has portability ; in mind. ; addresses are lowercase, constant values are in CAPS romid = $FBB3 ; $38=][, $EA=][+, $06=//e compatible ROMID_IIECOMPAT = 6 romid_ec = $FBC0 ; $EA=//e original, $E0=//e enhanced, $E1=//e EDM, $00=//c ; Laser 128s are $E0 romid_c = $FBBF ; $FF=original, $00=Unidisk 3.5 ... $05=//c+ ROMID_CPLUS = 5 romid_maciie_2 = $FBDD ; 2 ; IIGS idroutine = $FE1F ; SEC, JSR $FE1F, BCS notgs gsspeed = $C036 GS_FAST = $80 ; mask ; //c+ Cache Glue Gate Array (accelerator) cgga = $C7C7 ; entry point CGGA_ENABLE = 1 ; fast CGGA_DISABLE = 2 ; normal CGGA_LOCK = 3 CGGA_UNLOCK = 4 ; required to make a change ; Macintosh IIe Card maciie = $C02B MACIIE_FAST = 4 ; mask l128irqpage = $C4 ; From the 4.2, 4.5 and EX2 ROM dumps at the Apple II ; Documentation Project, the Laser 128 IRQ handlers are ; in the $C4 page. ; A comp.sys.apple2 post says the 6.0 ROM for the 128 and ; 128EX are identical, so there may not be an easy way to ; tell a plain 128 from an (accelerated) 128EX. irq = $FFFE ; 6502 IRQ vector ; may overlap with paddle trigger ex_cfg = $C074 ; bits 7 & 6 for speed EX_NOTSPEED = $3F EX_1MHZMASK = $0 EX_2MHZMASK = $80 ; 2.3Mhz EX_3MHZMASK = $C0 ; 3.6Mhz ; FASTChip fc_lock = $C06A fc_enable = $C06B fc_speed = $C06D fc_config = $C06E fc_data = $C06F FC_UNLOCK = $6A ; write 4 times FC_LOCK = $A6 FC_1MHZ = 9 FC_ON = 40 ; doco says 16.6Mhz ; TransWarp I ; may overlap with paddle trigger tw1_speed = $C074 TW1_1MHZ = 1 TW1_MAX = 0 ; Zip Chip ; overlaps annunciator 1 & //c vertical blank zc_lock = $C05A ZC_UNLOCK = $5A ; write 4 times ZC_LOCK = $A5 zc_enable = $C05B iobase = $C000 ; easily confused with kbd BuildAcceleratorFunction ; in: none ; out: A/Y points to lo/hi address of code block ; X contains length of code block ;; first check built-in accelerators ldx romid cpx #ROMID_IIECOMPAT bne build_addon ; not a //e ldx romid_ec beq iic ; //c family ; not worth the bytes for enhanced //e check ldx irq+1 cpx #l128irqpage bne gscheck ; a Laser 128, hopefully harmless on a non EX ldy #EX_3MHZMASK ; phew, all needed bits set ldx #<(ex_cfg) bne build_setspeed ; always branches gscheck pha sec jsr idroutine pla bcs maccheck ; not a gs ; set IIGS speed ldy #GS_FAST ldx #<(gsspeed) bne build_setspeed ; always branches maccheck ldx romid_maciie_2 cpx #2 bne build_addon ; no built-in accelerator ; the IIe Card in a Mac ldy #MACIIE_FAST ldx #<(maciie) bne build_setspeed ; always branches iic lda #$9D sta fixiic lda #$C0 sta fixiic+2 ldx romid_c cpx #ROMID_CPLUS bne build_addon ; not a //c+, eventually hit Zip lda #iicplus ldx #(end_iicplus-iicplus) rts build_setspeed stx setspeed_x sty setspeed_y lda #setspeed ldx #(end_setspeed-setspeed) rts build_addon lda #addon ldx #(end_addon-addon) rts ;----------------------------------------------------------- ; 3 distinct accelerator functions ; ; Only 1 of these will be required on any particular machine. ; ; Each has 2 entry points, +0 to disable acceleration and ; +3 to enable acceleration. ; ; setspeed must be self-modified before use (setspeed_x and ; setspeed_y). ; ;----------------------------------------------------------- ; Function #1: Apple IIc+ iicplus !pseudopc DisableAccelerator { ; Set //c+ speed. Uses the horrible firmware in case other ; code works "by the book", that is can check and set ; whether the accelerator is enabled. ; The //c+ is otherwise Zip compatible. ; This code cannot run from LC, and *must* bank in ROM. ; CGGA assumes that ROM is already banked in. lda #$3A ; DEC, disable accelerator entry point !byte $2C ; BIT , hide next lda # lda #$4A ; LSR, enable accelerator entry point sta @pokery ; action after CGGA_UNLOCK ; cgga calls save X and Y regs but sets $0 to 0 ; (this will get a laugh from C programmers) lda $0 pha php sei ; timing sensitive jsr @jiggerypokery lda gMachineInDHGRMode bne + ; DHGR mode doesn't need fix sta $C05B ; fix HGR-mode colouring + plp ; restore interrupt state pla sta $0 rts @jiggerypokery tsx ldy #(@endpokery - @jiggery) @copyiicp lda @jiggery-1,y pha dey bne @copyiicp txa tsx iny !cpu 65c02 phy phx !cpu 6502 tax rts @jiggery +READ_ROM_NO_WRITE lda #CGGA_LOCK ; should lock after a change pha @pokery nop ; SMC pha lda #CGGA_UNLOCK ; unlock to change pha jsr cgga ; disable/enable jsr cgga jsr cgga ; reads parm from stack, must JSR txs +READ_RAM2_WRITE_RAM2 rts @endpokery } end_iicplus ; Function #2: IIgs, Laser 128EX, or IIe card ;; setspeed - set 1Mhz with AND and fast with OR ; ; A = lsb set for normal speed ; X = low byte address of speed location ; Y = OR mask for fast setspeed lda #1 ; disable accelerator entry point !byte $2C ; BIT , hide next lda # lda #0 ; enable accelerator entry point setspeed_x=*+1 ldx #$FD ; SMC setspeed_y=*+1 ldy #$FD ; SMC lsr tya bcs setnorm ora iobase,x ldy #$d6 bne setsta ; always branches setnorm eor #$FF and iobase,x ldy #$56 setsta sta iobase,x sty $7FE ; Laser checks it rts end_setspeed ; Function #3: Card-based accelerator (TransWarp, ZipChip, ; FastChip, &c.) ; We blindly set switches for all known cards. addon lda #1 ; disable accelerator entry point !byte $2C ; BIT , hide next lda # lda #0 ; enable accelerator entry point ; TransWarp I sta tw1_speed ; no UW support here because the softswitch to enable ; acceleration triggers DHGR bugs in OpenEmulator :-( ; Zip Chip ldy #FC_1MHZ eor #1 tax beq + ldy #FC_ON + lda #ZC_UNLOCK php sei ; following sequence is timing sensitive sta zc_lock sta zc_lock sta zc_lock sta zc_lock lsr ; not ZC_LOCK or ZC_UNLOCK sta zc_lock,x ; disable/enable lda #ZC_LOCK sta zc_lock FASTChip lda #FC_UNLOCK sta fc_lock sta fc_lock sta fc_lock sta fc_lock sta fc_enable sty fc_speed lda #FC_LOCK sta fc_lock ldx gMachineInDHGRMode fixiic bit $D05F ; fix colouring on IIc (SMC to STA,X on IIc) + plp ; restore interrupt state rts end_addon