10 REM > Reset/s
   20 REM Needs to be assembled with 65C12 assembler
   30 :
   40 OSBYTE=&FFF4:OSFILE=&FFDD:OSARGS=&FFDA
   50 DIM mcode% &200
   60 load%=&FFFF0900
   70 :
   80 FOR P=0 TO 1
   90   O%=mcode%:P%=load%
  100   [OPT P*3+4+16
  110   .go%
  120   LDA #1:LDX #&A8:LDY #0:JSR OSARGS
  130   LDA (&A8),Y:CMP #13:BEQ reset:TAY \ *RESET<cr> or *RESET <num>
  140   .reset
  150   TYA:AND #7:PHA                    \ Reduce to 0-7
  160   LDX #253:LDA #163:JSR OSBYTE      \ Initially try OSBYTE call
  170   PLA                               \ Otherwise, do manually
  180   :
  190   .ForceReset
  200   \ A=RESET type
  210   \   0=Soft Break
  220   \   1=Power On
  230   \   2=Hard Break
  240   :
  250   SEI:CLD                        :\ Disable IRQs, ensure binary mode
  260   LDX #&FF:TXS:PHA               :\ Reset stack, save Break type
  270   LDA #&8F:LDX #&0C
  280   LDY #&FF:JSR OSBYTE            :\ Claim NMIs
  290   LDX #&40:STX &0D00             :\ Disable NMIs
  300   LDA #0:JSR OSBYTE              :\ Read machine type
  310   LDA &FFFC:STA &A8              :\ &A8/9=>RESET code
  320   LDA &FFFD:STA &A9
  330   TXA:BEQ ResetElk               :\ Jump if &00=Electron
  340   :
  350   LDA #&C0:STA &FEA0             :\ Reset hardware
  360   LDA #&A0:STA &FEE0             :\ Tube Reset
  370   LDA #&20:STA &FEE0             :\ Release Tube Reset
  380   PLA:BEQ ResetJump              :\ Soft Break
  390   LSR A:BCC ResetHard            :\ Hard Reset is fiddly
  400   LDA #127:STA &FE4E             :\ Reset system VIA
  410   .ResetJump
  420   JMP (&FFFC)                    :\ Enter RESET code
  430   :
  440   .ResetElk
  450   LDA #&C0:STA &FC28             :\ Reset Electron hardware
  460   LDA #&A0:STA &FCE0             :\ Electron Tube Reset
  470   LDA #&20:STA &FCE0             :\ Release Electron Tube Reset
  480   PLA:BEQ ResetJump              :\ Soft Break
  490   LDY #24:LSR A:BCS ResetElkJump :\ Power On
  500   TAY:DEX                        :\ Y=0, X=&FF
  510   .ResetElkHard
  520   LDA (&A8),Y:INY
  530   CMP #&20:BNE ResetElkHard      :\ Look for JSR
  540   INY:INY:LDA (&A8),Y
  550   CMP #&08:BNE ResetElkHard      :\ Look for PHP
  560   .ResetElkJump
  570   LDA &F4:ORA #&F0:STA &FE05     :\ Set up the ULA, set M=Ctrl Pressed
  580   PHA:PHP                        :\ Push NotPowerOn, push CTRL pressed
  590   BMI ResetAddJump               :\ Branch to jump into reset code
  600   :
  610   .ResetHard
  620   LDY #&0F:STY &FE42             :\ SysVIA PortB=iiiioooo
  630   .ResetIO
  640   DEY:STY &FE40                  :\ Write to I/O latch
  650   CPY #&09:BCS ResetIO           :\ Loop to set up internal I/O
  660   CPX #&03:BCS ResetMaster
  670   :
  680   \ Read BBC keyboard links
  690   LDX #&09
  700   .ResetBBCLinks
  710   LDY #&03:STY &FE40
  720   LDY #&7F:STY &FE43
  730   STX &FE4F:LDX &FE4F
  740   CPX #&80:ROR &FC               :\ Rotate keystate in bit 7 into &FC
  750   DEX:BNE ResetBBCLinks
  760   ROL &FC                        :\ &FC holds link state
  770   :
  780   LDY #0                         :\ Y=0, X=&FF
  790   .ResetBBClp
  800   LDA (&A8),Y:INY
  810   CMP #&26:BNE ResetBBClp        :\ Look for 'ROL zp'
  820   .ResetAddJump
  830   TYA:ADC &A8:STA &A8            :\ Update (&A8) to next instruction
  840   LDA #0:STA &028D:STA &FE00     :\ Initialise last BREAK flag and Elk ULA
  850   ADC &A9:STA &A9                :\ (A8)=>continuation of reset code
  860   SEC:LDA #2:JMP (&A8)           :\ CS=CTRL pressed, jump to RESET code
  870   :
  880   .ResetMaster
  890   LDY #0
  900   .ResetMasterLp1
  910   LDA (&A8),Y:INY                :\ Look for JSR
  920   CMP #&20:BNE ResetMasterLp1
  930   INY:INY:LDA (&A8),Y            :\ Check if followed by JMP
  940   CMP #&4C:BNE ResetMasterLp1
  950   INY:LDA (&A8),Y:STA &F6        :\ (F6)=>reset code in ROM 15
  960   INY:LDA (&A8),Y:STA &F7
  970   .ResetMasterLp2
  980   JSR ResetROMByte               :\ Read byte from ROM 15
  990   CMP #&E0:BNE ResetMasterLp2    :\ Look for 'CPX'
 1000   JSR ResetROMByte               :\ Read next byte from ROM 15
 1010   CMP #&80:BNE ResetMasterLp2    :\ Look for 'CPX #&80'
 1020   \ &F6/7 now points to rest of RESET code
 1030   :
 1040   LDA #&53:STA &FE8E             :\ Write to hardware I/O RESET
 1050   TRB &0366                      :\ Reset VDU 23,16 settings
 1060   LDX #&FF:STX &FE63             :\ User VIA Port A=output
 1070   LDA #&CF:STA &FE42             :\ System VIA Port B=ooiioooo
 1080   LDA #&0D:STA &DC00             :\ Command line = <cr>
 1090   LDA #&DC:STA &DF05:STZ &DF04   :\ Point to command line
 1100   STZ &DFDD                      :\ Clear *MOVE flag
 1110   LDX #(ResetCodeEnd-ResetCode-1) AND &FF
 1120   .ResetLoop
 1130   LDA ResetCode,X:STA &100,X
 1140   DEX:BPL ResetLoop:TXS          :\ Reset stack
 1150   LDA &F7:AND #&40               :\ Test if code is in SROM or I/O area
 1160   STA &FE34:STA &FC              :\ Set memory map according to &F7
 1170   LDA #&0F:STA &028E             :\ Set keypad SHIFT setting, prepare ROM=15
 1180   PHA:SEC:JMP &100               :\ Push <>0=Not PowerOn, CS=CTRL pressed
 1190   :
 1200   .ResetCode
 1210   STA &FE30                      :\ Page in MOS ROM (IRQs are off)
 1220   JMP (&F6)                      :\ Jump to RESET code
 1230   .ResetCodeEnd
 1240   :
 1250   .ResetROMByte
 1260   LDA #&40:STA &FE34             :\ Set memory map
 1270   LDA (&F6)                      :\ Read byte manually
 1280   BIT &F7:BVS ResetByte          :\ Exit if in high memory
 1290   LDY #&0F:JSR &FFB9             :\ Read byte from ROM 15
 1300   .ResetByte
 1310   INC &F6:BNE P%+4:INC &F7       :\ Increment address
 1320   RTS
 1330   :
 1340   EQUS "0.10"
 1350 ]NEXT
 1360 PRINT"*SAVE RESET ";~mcode%;" ";~O%;" ";~go% OR &FFFF0000;" ";~load%'