10 REM > EELoad/src v2.11
   20 REM Load file to AT28C256 EEPROM
   30 REM Syntax: EELOAD <filename>|<@> <rom>
   40 :
   50 REM v2.10 27-Nov-2015 JGH: rewritten, tidied up
   60 REM       Runs from command buffer, reads command line correctly,
   70 REM       doesn't trash language workspace, allows hex and dec <rom>,
   80 REM       runs on Electron and non-Electron, corrected error messages,
   90 REM       write tests version byte so doesn't trash ROM entry point.
  100 REM v2.11 23-Jan-2016 JGH: Changes to small screen MODE on Electron.
  110 :
  120 DIM mcode% &200:load%=&FFFF0900
  130 OSARGS=&FFDA:OSFILE=&FFDD:OSBYTE=&FFF4:OSWRCH=&FFEE
  140 lptr=&A8:buf=&A8:dst=&AA
  150 rambuf=&2000 :REM Use &2000-&5FFF as file buffer
  160 nbytes=64    :REM Write 64 bytes at a time
  170 ver$="2.11"
  180 :
  190 FOR P=0 TO 1
  200   P%=load%:O%=mcode%
  210   [OPT P*2+4
  220   .errSyntax
  230   BRK:EQUB 220:EQUS "Syntax: EELOAD <afsp>|@ <rom>":BRK
  240   :
  250   .exec%
  260   LDA #0:LDX #1:JSR OSBYTE           :\ Read machine type
  270   TXA:BNE InitNotElectron
  280   LDA #&05:STA ROMSEL+1              :\ Use Electron ROMSEL
  290   DEC ROMTABLE+1                     :\ Use Electrom ROM table
  300   .InitNotElectron
  310   :
  320   LDA #1:LDX #lptr:JSR OSARGS        :\ Get command line, Y=0 from above
  330   LDA (lptr),Y:CMP #13:BEQ errSyntax :\ No parameters
  340   :
  350   \ (lptr),Y => filename, skip past to <rom>
  360   \ ----------------------------------------
  370   DEY                                :\ Prepare for next INY
  380   .SkipToSpace
  390   INY:LDA (lptr),Y
  400   CMP #ASC"!":BCS SkipToSpace        :\ Step past filename
  410   DEY                                :\ Prepare for next INY
  420   .SkipSpace
  430   INY:LDA (lptr),Y
  440   CMP #ASC" ":BEQ SkipSpace          :\ Step past spaces
  450   CMP #13:BEQ errSyntax              :\ Only one parameter
  460   :
  470   \ (lptr),Y now => <rom>
  480   \ ---------------------
  490   LDA (lptr),Y                       :\ Get <rom>
  500   CMP #ASC"0":BCC errSyntax          :\ <'0' - error
  510   CMP #ASC"9"+1:BCC decnum           :\ '0'-'9' - decimal digit
  520   CMP #ASC"A":BCC errSyntax          :\ >'9' <'A' - error
  530   AND #&DF
  540   CMP #ASC"G":BCS errSyntax          :\ >'F' - error
  550   SBC #6                             :\ Convert hex digit to offset from '9'
  560   .decnum
  570   AND #15:TAX                        :\ Convert to binary
  580   CMP #1:BNE romnumber               :\ Not 1, don't check for 1x
  590   INY:LDA (lptr),Y                   :\ Look for a second digit
  600   CMP #ASC"!":BCC romnumber          :\ Single digit, use as decimal number
  610   CMP #ASC"0":BCC errSyntax          :\ Can only be '10'-'15'
  620   CMP #ASC"6":BCS errSyntax
  630   AND #15:ADC #10:TAX                :\ Convert to binary
  640   .romnumber
  650                                      :\ X=ROM number to write to
  660   :
  670   \ First, test the device is writable before we overwrite memory
  680   \ -------------------------------------------------------------
  690   LDA &F4:PHA                        :\ Save current ROM
  700   PHP:SEI                            :\ Prevent accidently calling EEPROM
  710   JSR SelectRom                      :\ Page in the requested ROM
  720   LDA &8008:EOR #&AA:TAX:STA &8008   :\ Try toggling version byte
  730   NOP:CMP &8008:BEQ testOK           :\ Written immediately, it must be RAM
  740   LDA &8008:CMP &8008                :\ Try two successive reads
  750   BNE testEEP                        :\ If not the same, probably EEPROM
  760   BRK:EQUB 135:EQUS "Device is ROM":BRK    :\ Error 135='Not SRAM'
  770   .testEEP
  780   LDA &8008:CMP &8008:BNE testEEP    :\ Loop until two identical reads
  790   CPX &8008:BEQ testOK               :\ Settled at correct data, it's ok
  800   BRK:EQUB 134:EQUS "Device is locked":BRK :\ Error 134='ROM in use'
  810   .testOK
  820   TXA:EOR #&AA:STA &8008             :\ Restore original value
  830   .testOKlp
  840   LDA &8008:CMP &8008:BNE testOKlp   :\ Loop until two identical reads
  850   \ Need to wait until data settles as while it is settling the EEPROM
  860   \ returns status data instead of its actual contents. Need to avoid
  870   \ accidently trying to execute that status data via a sideways ROM call.
  880   :
  890   \ Now load the file
  900   \ -----------------
  910   LDY #0:LDA (lptr),Y                :\ Check first character of filename
  920   CMP #ASC"@":BNE loadfile           :\ Not *EELOAD @...
  930   INY:LDA (lptr),Y                   :\ Check for following space
  940   CMP #ASC" ":BEQ copyimage          :\ *EELOAD @ <rom>, use image in RAM
  950   .loadfile
  960   LDA lptr+0:STA file+0              :\ Copy filename pointer to OSFILE block
  970   LDA lptr+1:STA file+1
  980   LDA ROMSEL+1
  990   CMP #&05:BNE loadfile2             :\ Not Electron, continue
 1000   LDA #132:JSR OSBYTE                :\ Read top of user memory
 1010   CPY #&60:BCS loadfile2             :\ Small screen MODE, continue
 1020   LDA #22:JSR OSWRCH                 :\ Change to a small screen MODE
 1030   LDA #7:JSR OSWRCH
 1040   .loadfile2
 1050   LDX #file AND 255:LDY #file DIV 256
 1060   LDA #255:JSR OSFILE                :\ Load the file
 1070   :
 1080   \ Now program the device from the image in memory
 1090   \ -----------------------------------------------
 1100   .copyimage
 1110   LDA #0:LDX &F4
 1120   .ROMTABLE
 1130   STA &2A1,X                         :\ Remove ROM from ROM table
 1140   STA buf+0:STA dst+0
 1150   LDA #rambuf DIV 256:STA buf+1      :\ buf=>rambuf at &2000
 1160   LDA #&80:STA dst+1                 :\ dst=&8000
 1170   .proglp1
 1180   LDY #0
 1190   .proglp2
 1200   LDA (buf),Y:STA (dst),Y            :\ Copy to EEPROM
 1210   INY:CPY #nbytes:BNE proglp2        :\ Loop for 'nbytes'
 1220   :
 1230   \ Now check the data has written correctly
 1240   \ ----------------------------------------
 1250   LDX #0:LDY #0
 1260   .proglp3
 1270   LDA (dst),Y:CMP (dst),Y            :\ Read twice to see if matches
 1280   BNE proglp3                        :\ Keep testing until it matches
 1290   CMP (buf),Y                        :\ Has it settled to correct value?
 1300   BEQ progmatch:INX                  :\ If it doesn't match, inc. X
 1310   .progmatch
 1320   INY:CPY #nbytes:BNE proglp3        :\ X now holds number of differences
 1330   TXA:BEQ write_ok
 1340   BRK:EQUB 132:EQUS "Write error":BRK   :\ Error 132='Bad bank' (not usable somehow)
 1350   :
 1360   .write_ok
 1370   CLC
 1380   LDA #nbytes:ADC buf+0:STA buf+0    :\ Update buffer address
 1390   LDA #0:ADC buf+1:STA buf+1
 1400   LDA #nbytes:ADC dst+0:STA dst+0    :\ Update dest. address
 1410   LDA #0:ADC dst+1:STA dst+1
 1420   CMP #&C0:BNE proglp1               :\ Keep going until end of ROM space
 1430   :
 1440   \ All done, restore and return
 1450   \ ----------------------------
 1460   PLP                                :\ Restore IRQs
 1470   PLA:TAX                            :\ Restore ROM
 1480   :
 1490   .SelectRom
 1500   LDA #12:JSR SelectRom2:TXA         :\ Electron ROM pre-select
 1510   .SelectRom2
 1520   STA &F4
 1530   .ROMSEL
 1540   STA &FE30:RTS
 1550   :
 1560   .file
 1570   EQUW 0                    :\ Filename
 1580   EQUD &FFFF0000+rambuf     :\ Address to load to
 1590   EQUD 0:EQUD 0:EQUD 0      :\ 0=use specified address
 1600   EQUS ver$
 1610 ]:NEXT
 1620 PRINT" *SAVE EELOAD ";~mcode%;" ";~O%;" ";~exec%OR&FFFF0000;" ";~load%