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