10
20
30
40
50
60
70
80
90
100
110 :
120 file$="AP6Count"
130 DIM mcode% 1024,L%-1:
140 OSASCI=&FFE3:OSNEWL=&FFE7:OSWRCH=&FFEE:OSBYTE=&FFF4
150 :
160 FOR pass%=0 TO 3
170 opt%=FNsm_pass(pass%)
180 [OPT opt%
190 .ROMStart
200 BRK:EQUW RelocTable
210 JMP Service
220 EQUB &82:EQUB Copyright-ROMStart
230 EQUB &00:EQUS "RAMCountAP6"
240 EQUB &00:EQUS "0.05 (20 May 2016)"
250 .Copyright
260 EQUB &00:EQUS "(C)J.G.Harston":EQUB &00
270 :
280 .Service
290 PHA
300 CMP #&01:BEQ RAMCount
310 CMP #&2B:BEQ RAMCount
320 .ServExit
330 PLA:RTS
340 :
350 .RAMCount
360 LDA &28D:BEQ ServExit :\ Soft BREAK
370 LDA &27A:BNE ServExit :\ Tube active
380 LDA &267:BPL ServExit :\ Startup message already replaced
390 AND #&7F:STA &267 :\ Suppress startup message
400 TYA:PHA :\ Save Service1 Y register
410 :
420 LDA #2:PHA :\ Assume 2x16K main RAM
430 LDA &27F:BMI FoundShadow :\ Turbo 64K
440 LDA #114:LDX #0:JSR OSBYTE :\ Read Acorn Shadow RAM status
450 JSR OSBYTE :\ Restore Acorn Shadow RAM status
460 TXA:BPL FoundShadow :\ Acorn Shadow RAM present
470 :
480 LDA #111:LDX #64:JSR OSBYTE :\ Read status of non-Acorn Shadow RAM
490 TXA:BMI CountSRAM :\ No non-Acorn Shadow RAM present
500 .FoundShadow
510 PLA:CLC:ADC #2:PHA :\ Add 2x16K Shadow RAM
520 :
530 .CountSRAM
540 STA &FCD8:STA &FCDA :\ Enable sideways RAM
550 STA &FCDC:STA &FCDE
560 PLA:TAY :\ Y=RAM count so far
570 PHP:SEI :\ Prevent EEPROMs unexpectedly getting IRQs
580 LDX #CodeEnd-CodeStart
590 .CopyCountCode
600 LDA CodeStart,X:PHA :\ Copy SRAM count code to stack
610 DEX:BPL CopyCountCode
620 JSR CallStackCode :\ Call routine on the stack
630 TSX:TXA
640 SEC:ADC #CodeEnd-CodeStart
650 TAX:TXS:PLP :\ Restore stack, dropping stacked code, restore IRQs
660 STA &FCD9:STA &FCDB :\ Write protect sideways RAM
670 STA &FCDD:STA &FCDF
680 :
690 TYA:PHA :\ Save RAM count
700 LDX #0:JSR PrMsg :\ Print <beep>'Electron'
710 :
720 LDA &FFFC:STA &F6 :\ &F6/7=>start of RESET code
730 LDA &FFFD:STA &F7
740 .FindAcorn
750 LDY #10 :\ Offset to code to check for
760 LDA (&F6),Y:CMP #&13:BNE FindAcornNext :\ Not #&13
770 DEY
780 LDA (&F6),Y:CMP #&A0:BEQ FindAcornFound :\ Found LDY #&13
790 .FindAcornNext
800 INC &F6:BNE FindAcorn
810 INC &F7:BNE FindAcorn
820 .FindAcornFound
830 LDA #&60:BNE AcornCopyByte :\ Put RTS at end of copied code
840 .AcornCopyLp
850 LDA (&F6),Y :\ Get byte from MOS ROM
860 .AcornCopyByte
870 STA &100,Y :\ Copy to stack
880 DEY:BPL AcornCopyLp :\ Copy Acorn drawing code
890 JSR &100 :\ Draw the Acorn
900 LDA #9:JSR OSWRCH:JSR OSWRCH
910 :
920 LDX #MsgSha-MsgBase :\ Point to 'Shadow'
930 LDA &27F:BMI PrExtra :\ Print 'Shadow' if b7=1
940 LSR A:BCC PrNoExtra :\ If b0=0, not Turbo
950 LDX #MsgTub-MsgBase :\ Point to 'Turbo'
960 .PrExtra
970 JSR PrMsg :\ Print 'Shadow' or 'Turbo'
980 .PrNoExtra
990 :
1000 PLA:TAY:LDA RAMhigh-1,Y :\ Get RAM size high digits
1010 BEQ P%+5:JSR PrNyb :\ Print if non-zero
1020 LDA RAMlow-1,Y:JSR PrHex :\ Print RAM size low digits
1030 LDA #ASC"K":JSR OSWRCH :\ Print "K" suffix
1040 JSR OSNEWL:JSR OSNEWL
1050 :
1060 PLA:TAY:LDX &F4 :\ Restore registers
1070 PLA:RTS :\ And return unclaimed
1080 :
1090 .CallStackCode :\ Cy=Elk, A=??, X=??, Y=count, SP=>ret.lo, ret.hi, code...
1100 LDA #1:PHA :\ Cy=Elk, A=&01, X=??, Y=count, SP=>&01, ret.lo, ret.hi, code...
1110 TSX :\ Cy=Elk, A=&01, X=SP, Y=count, SP=>&01, ret.lo, ret.hi, code...
1120 INX:INX:INX :\ Cy=Elk, A=&01, X=SP+2, Y=count, SP=>&01, ret.lo, ret.hi, code...
1130 TXA:PHA :\ Cy=Elk, A=SP+3, X=SP+2, Y=count, SP=>SP+3, &01, ret.lo, ret.hi, code...
1140 SEC:ADC #romselect-CodeStart :\ Calculate low byte of SelectRom
1150 STA &102+loop-CodeStart,X :\ Insert JSR SelectRom
1160 ADC #(romselect2-romselect) :\ Calculate low byte of SelectRom2
1170 STA &104+romselect-CodeStart,X :\ Insert JSR SelectRom2
1180 LDX #15 :\ Start at X=ROM 15
1190 LDA &F4 :\ Get current ROM number
1200 RTS :\ Jump to code on stack
1210 :
1220 \ Code run from stack so can access other sideways ROM/RAM banks
1230 \ This will count duplicate RAM banks on BBC
1240 .CodeStart
1250 PHA :\ save current ROM
1260 .loop
1270 JSR &100:\romselect :\ page in a bank
1280 LDA &8008:EOR #&AA :\ modify version byte
1290 STA &8008:NOP:CMP &8008:PHP :\ EQ=RAM or ROM/EEPROM
1300 EOR #&AA:STA &8008 :\ Restore byte
1310 .toggle
1320 LDA &8008:CMP &8008:BNE toggle :\ Toggling, must be EEPROM
1330 PLP:BNE rom :\ NE from earlier, ROM or EEPROM
1340 INY :\ increment number of RAM banks
1350 .rom
1360 DEX:BPL loop :\ loop for all 16 banks
1370 PLA:TAX :\ restore ROM and return
1380 .romselect
1390 LDA #12:JSR &100:\romselect2 :\ do Electron pre-select
1400 TXA
1410 .romselect2
1420 STA &F4:STA &FE05:RTS :\ select ROM bank
1430 .CodeEnd
1440 :
1450 \ Print messages offset from X
1460 \ ----------------------------
1470 .PrMsg
1480 LDA MsgBase,X:BEQ MsgDone
1490 JSR OSASCI:INX:BNE PrMsg
1500 .MsgDone
1510 RTS
1520 :
1530 \ Banner messages and RAM sizes
1540 \ -----------------------------
1550 .MsgBase
1560 .MsgElk:EQUB 13:EQUB 7:EQUS "Acorn Electron ":EQUB 0
1570 .MsgSha:EQUS "Shadow ":EQUB 0
1580 .MsgTub:EQUS "Turbo ":EQUB 0
1590 :
1600 .RAMlow
1610 EQUD &64483216 :\ Low BCD of RAM count
1620 EQUD &28129680
1630 EQUD &92766044
1640 EQUD &56402408
1650 EQUD &20048872
1660 .RAMhigh
1670 EQUD &00000000 :\ High BCD of RAM count
1680 EQUD &01010000
1690 EQUD &01010101
1700 EQUD &02020202
1710 EQUD &03030202
1720 :
1730 .PrHex
1740 PHA:LSR A:LSR A:LSR A:LSR A
1750 JSR PrNyb:PLA
1760 .PrNyb
1770 AND #15:CMP #10:BCC P%+4:ADC #6
1780 ADC #ASC"0":JMP OSWRCH
1790 :
1800 \ Relocation table to make *SMLoad-able
1810 \ -------------------------------------
1820 .RelocTable
1830 ]:NEXT
1840 PROCsm_table
1850 A$="Save "+file$+" "+STR$~(mcode%+mclen%)+" "+STR$~O%+" FFFF0000 FFFBBC00"
1860 PRINT"Saving ";file$;:OSCLIA$:PRINT
1870 END
1880 :
1890 DEFFNsm_pass(pass%)
1900 IFpass%=0:mclen%=0
1910 IFpass%=1:mclen%=O%-mcode%
1920 P%=&8100-128*(pass%AND2)
1930 O%=mcode%+mclen%*(pass%AND2)DIV2
1940 IFpass%=1:IF O%+mclen%*2.125>L%:PRINT"Code overrun":END
1950 =VALMID$("4646",pass%+1,1)
1960 :
1970 DEFPROCsm_table
1980 base80%=mcode%+mclen%:base81%=mcode%:byte%=0:count%=0:off%=0:REPEAT
1990 byte80%=base80%?off%:byte81%=base81%?off%:IF off%>=mclen%:byte80%=&80:byte81%=&80
2000 IF ((byte81%-byte80%) AND &FE)<>0 THEN PRINT "ERROR: Offset by more than one page at &";~&8000+off%
2010 IF (byte80% AND &C0)=&80:byte%=byte%DIV2+128*(byte81%-byte80%):count%=count%+1
2020 IF count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0
2030 off%=off%+1:UNTILoff%>=mclen% AND count%=0
2040 ENDPROC