10
20
30
40
50
60 :
70 DIM mcode% 1024,L%-1:
80 OSASCI=&FFE3:OSNEWL=&FFE7:OSWRCH=&FFEE:OSBYTE=&FFF4
90 :
100 FOR pass%=0 TO 3
110 opt%=FNsm_pass(pass%)
120 [OPT opt%
130 .ROMStart
140 BRK:EQUW RelocTable
150 JMP Service
160 EQUB &82:EQUB Copyright-ROMStart
170 EQUB &00:EQUS "RAMCount"
180 EQUB &00:EQUS "0.02 (15 Oct 2014)"
190 .Copyright
200 EQUB &00:EQUS "(C)J.G.Harston":EQUB &00
210 :
220 .Service
230 PHA
240 CMP #&01:BEQ RAMCount
250 CMP #&2B:BEQ RAMCount
260 .ServExit
270 PLA:RTS
280 :
290 .RAMCount
300 LDA &28D:BEQ ServExit :\ Soft BREAK
310 LDA &27A:BNE ServExit :\ Tube active
320 LDA &267:BPL ServExit :\ Startup message already replaced
330 AND #&7F:STA &267 :\ Suppress startup message
340 TYA:PHA :\ Save Service1 Y register
350 :
360 LDA #0:LDX #1:JSR OSBYTE :\ Get machine type
370 TXA:PHA :\ Save machine type for banner
380 LDY #2 :\ Assume 2x16K main RAM
390 CPX #1:BNE CountShadow :\ Not BBC, always 2x16K main RAM
400 LDA &28E:BMI CountShadow :\ BBC with 32K
410 DEY :\ BBC with 16K, decrement to 1x16K
420 :
430 .CountShadow
440 TYA:PHA :\ Save amount of main RAM
450 LDA #114:LDX #0:JSR OSBYTE :\ Read Acorn Shadow RAM status
460 JSR OSBYTE :\ Restore Acorn Shadow RAM status
470 TXA:BPL FoundShadow :\ Acorn Shadow RAM present
480 :
490 LDA #111:LDX #64:JSR OSBYTE :\ Read status of non-Acorn Shadow RAM
500 TXA:BMI CountSRAM :\ No non-Acorn Shadow RAM present
510 .FoundShadow
520 PLA:CLC:ADC #2:PHA :\ Add 2x16K Shadow RAM
530 :
540 .CountSRAM
550 PLA:TAY :\ Y=RAM count so far
560 PLA:PHA:CMP #1 :\ Get machine type, Cy=CC if Electron
570 LDX #CodeEnd-CodeStart
580 .CopyCountCode
590 LDA CodeStart,X:PHA :\ Copy SRAM count code to stack
600 DEX:BPL CopyCountCode
610 JSR CallStackCode :\ Call routine on the stack
620 TSX:TXA
630 SEC:ADC #CodeEnd-CodeStart
640 TAX:TXS :\ Restore stack, dropping stacked code
650 :
660 PLA:TAX :\ X=machine type, Y=RAM count
670 LDA MsgOffset,X:TAX :\ X=>Banner message
680 .MsgLoop
690 LDA MsgBase,X:BEQ MsgDone :\ Print banner message
700 JSR OSASCI:INX:BNE MsgLoop
710 .MsgDone
720 :
730 LDA RAMhigh-1,Y :\ Get RAM size high digits
740 BEQ P%+5:JSR PrNyb :\ Print if non-zero
750 LDA RAMlow-1,Y:JSR PrHex :\ Print RAM size low digits
760 LDA #ASC"K":JSR OSWRCH :\ Print "K" suffix
770 JSR OSNEWL:JSR OSNEWL
780 :
790 PLA:TAY:LDX &F4 :\ Restore registers
800 PLA:RTS :\ And return unclaimed
810 :
820 .CallStackCode :\ Cy=Elk, A=??, X=??, Y=count, SP=>ret.lo, ret.hi, code...
830 LDA #1:PHA :\ Cy=Elk, A=&01, X=??, Y=count, SP=>&01, ret.lo, ret.hi, code...
840 TSX :\ Cy=Elk, A=&01, X=SP, Y=count, SP=>&01, ret.lo, ret.hi, code...
850 INX:INX:INX :\ Cy=Elk, A=&01, X=SP+2, Y=count, SP=>&01, ret.lo, ret.hi, code...
860 BCS CallStackNotElk :\ Not Electron
870 LDA #&05:STA &104+romselect2-CodeStart,X
880 .CallStackNotElk
890 TXA:PHA :\ Cy=Elk, A=SP+3, X=SP+2, Y=count, SP=>SP+3, &01, ret.lo, ret.hi, code...
900 SEC:ADC #romselect-CodeStart :\ Calculate low byte of SelectRom
910 STA &102+loop-CodeStart,X :\ Insert JSR SelectRom
920 ADC #(romselect2-romselect) :\ Calculate low byte of SelectRom2
930 STA &104+romselect-CodeStart,X :\ Insert JSR SelectRom2
940 LDX #15 :\ Start at X=ROM 15
950 LDA &F4 :\ Get current ROM number
960 RTS :\ Jump to code on stack
970 :
980 \ Code run from stack so can access other sideways ROM/RAM banks
990 \ This will count duplicate RAM banks on BBC
1000 .CodeStart
1010 PHA :\ save current ROM
1020 .loop
1030 JSR &100:\romselect :\ page in a bank
1040 LDA &8008:EOR #&AA:STA &8008 :\ modify version byte
1050 CMP &AAAA:CMP &8008:BNE rom :\ didn't change, is ROM
1060 EOR #&AA:STA &8008 :\ restore byte
1070 INY :\ increment number of RAM banks
1080 .rom
1090 DEX:BPL loop :\ loop for all 16 banks
1100 PLA:TAX :\ restore ROM and return
1110 .romselect
1120 LDA #12:JSR &100:\romselect2 :\ do Electron pre-select
1130 TXA:STA &FF30,X :\ WERAM write enable
1140 .romselect2
1150 STA &F4:STA &FE30:RTS :\ select ROM bank
1160 .CodeEnd
1170 :
1180 \ Banner messages and RAM sizes
1190 \ -----------------------------
1200 .MsgOffset
1210 EQUB MsgElk-MsgBase :\ 0=Electron
1220 EQUB MsgBBC-MsgBase :\ 1=BBC A/B
1230 EQUB MsgBBC-MsgBase :\ 2=BBC B+
1240 EQUB MsgMst-MsgBase :\ 3=Master
1250 EQUB MsgMst-MsgBase :\ 4=Master ET
1260 EQUB MsgCmp-MsgBase :\ 5=Compact
1270 .MsgBase
1280 .MsgElk:EQUB 13:EQUB 7:EQUS "Acorn Electron ":EQUB 0
1290 .MsgBBC:EQUB 13:EQUB 7:EQUS "BBC Computer ":EQUB 0
1300 .MsgMst:EQUB 13:EQUB 7:EQUS "Acorn Master ":EQUB 0
1310 .MsgCmp:EQUB 13:EQUB 7:EQUS "Master Compact ":EQUB 0
1320 :
1330 .RAMlow
1340 EQUD &64483216 :\ Low BCD of RAM count
1350 EQUD &28129680
1360 EQUD &92766044
1370 EQUD &56402408
1380 EQUD &20048872
1390 .RAMhigh
1400 EQUD &00000000 :\ High BCD of RAM count
1410 EQUD &01010000
1420 EQUD &01010101
1430 EQUD &02020202
1440 EQUD &03030202
1450 :
1460 .PrHex
1470 PHA:LSR A:LSR A:LSR A:LSR A
1480 JSR PrNyb:PLA
1490 .PrNyb
1500 AND #15:CMP #10:BCC P%+4:ADC #6
1510 ADC #ASC"0":JMP OSWRCH
1520 :
1530 \ Relocation table to make *SMLoad-able
1540 \ -------------------------------------
1550 .RelocTable
1560 ]:NEXT
1570 PROCsm_table
1580 PRINT"*Save RAMCount ";~(mcode%+mclen%);" ";~O%;" FFFF0000 FFFBBC00"
1590 END
1600 :
1610 DEFFNsm_pass(pass%)
1620 IFpass%=0:mclen%=0
1630 IFpass%=1:mclen%=O%-mcode%
1640 P%=&8100-128*(pass%AND2)
1650 O%=mcode%+mclen%*(pass%AND2)DIV2
1660 IFpass%=1:IF O%+mclen%*2.125>L%:PRINT"Code overrun":END
1670 =VALMID$("4647",pass%+1,1)
1680 :
1690 DEFPROCsm_table
1700 base80%=mcode%+mclen%:base81%=mcode%:byte%=0:count%=0:off%=0:REPEAT
1710 byte80%=base80%?off%:byte81%=base81%?off%:IF off%>=mclen%:byte80%=&80:byte81%=&80
1720 IF ((byte81%-byte80%) AND &FE)<>0 THEN PRINT "ERROR: Offset by more than one page at &";~&8000+off%
1730 IF (byte80% AND &C0)=&80:byte%=byte%DIV2+128*(byte81%-byte80%):count%=count%+1
1740 IF count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0
1750 off%=off%+1:UNTILoff%>=mclen% AND count%=0
1760 ENDPROC