10 REM >MDump105/s
   20 REM Source for *MDUMP by J.G.Harston
   30 REM v0.10 12-Feb-1986 Original MG version
   40 REM v1.00 10-Mar-1989 Tidied up for Micro User article
   50 REM v1.01 23-Aug-2006 Added -80 option
   60 REM v1.02 23-Aug-2006 Tidied up and compacted code
   70 REM v1.03 25-Aug-2006 Ensured 4-byte Tube address
   80 REM v1.04 27-Sep-2006 Uses &FFFDxxxx and &FFFExxxx for screen memory
   90 REM v1.05 29-Sep-2006 Accesses shadow memory on B, not yet B+, ROMs on Electron
  100 :
  110 OSWRCH=&FFEE:OSNEWL=&FFE7:OSARGS=&FFDA:OSBYTE=&FFF4
  120 :
  130 DIM mcode% &300:load%=&FFFF0900:ver$="v1.05"
  140 :
  150 addr=&A8:end=&AC:rom=addr+2:mem=addr+3:os=&AE:cols=&AF:lptr=&F0:tube=&27A
  160 FOR P=0 TO 1
  170   P%=load%:O%=mcode%
  180   [OPT P*3+4
  190   .buff
  200   .syntax
  210   \BRK:\EQUB 220:\EQUS "Syntax:\ MDump (-<cols>) <start> <end>|+<length>":\BRK
  220   BRK:EQUB 220:EQUS "Syntax: MDump <start> <end>|+<length>":BRK
  230   :
  240   .start%
  250   LDA #135:JSR OSBYTE
  260   LDX #&16:TYA:BEQ setcols
  270   CPY #3:BEQ setcols:LDX #8
  280   .setcols
  290   STX addr
  300   LDA #1:LDX #lptr:LDY #0:JSR OSARGS:\ NB! writes 4 bytes of memory
  310   LDX #addr
  320   LDA (lptr),Y:CMP #ASC"-":BNE mdumpcols
  330   INY:JSR GetHex
  340   .mdumpcols
  350   CMP #13:BEQ syntax:LDA addr:PHA
  360   JSR GetHex:BEQ syntax
  370   CMP #ASC"+":PHP:BNE P%+5:JSR SkipSpace1
  380   LDX #end:JSR GetHex:PLP:BNE mdump:CLC
  390   LDA addr+0:ADC end+0:STA end+0
  400   LDA addr+1:ADC end+1:STA end+1
  410   :
  420   .mdump
  430   PLA:AND #&1F:CMP #&10:BCC P%+4:SBC #6:STA cols:\ Columns in decimal
  440   LDX #&FF:LDA tube:BMI mdump1:LDA rom:BPL mdump1
  450   STX mem:\ If no Tube, extend &Fxxxxx to &FFFxxxxx
  460   .mdump1
  470   \LDA #0:\JSR OSBYTE:\STX os
  480   :
  490   .loop
  500   LDX #2
  510   .praddr
  520   LDA addr,X:JSR PrHex
  530   DEX:BPL praddr
  540   JSR GetBytes:LDX #0
  550   .loop1
  560   JSR PrSpace
  570   LDA buff,X:JSR PrHex
  580   INX:CPX cols:BNE loop1
  590   JSR PrSpace:LDX #0
  600   .loop2
  610   LDA buff,X:AND #127
  620   CMP #32:BCS pr_char
  630   .pr_dot:LDA #ASC"."
  640   .pr_char:CMP #127:BEQ pr_dot
  650   JSR OSWRCH
  660   INX:CPX cols:BNE loop2
  670   JSR OSNEWL
  680   BIT &FF:BMI escape
  690   :
  700   LDX #&FC:CLC:LDA cols
  710   .inc_addr
  720   ADC addr+4,X:STA addr+4,X
  730   LDA #0:INX:BNE inc_addr
  740   LDA addr+1:EOR end+1:BNE loop
  750   LDA end+0:EOR addr+0
  760   AND #&F0:BNE loop
  770   .escape
  780   LDA #124:JMP OSBYTE          :\ Clear Escape and exit
  790   :
  800   .GetBytes
  810   PHP:SEI:LDA &F4:PHA          :\ Disable IRQs, save ROM
  820   LDA &FE34:PHA                :\ Save ACCCON
  830   LDX mem:INX:BNE GetTube      :\ addr<&FFxxxxxx, language memory
  840   AND #&13:JSR SetACCCON       :\ Master, ACCCON=I/O, no FS RAM, main RAM
  850   LDA rom:PHA:\TAX
  860   CLC:ADC #&40:JSR SelectROM   :\ Select the specified ROM
  870   PLA:TAX
  880   INX:BEQ GetIOMem             :\ &FFFF - Main memory
  890   INX:BEQ GetDisplay           :\ &FFFE - Display memory
  900   INX:BEQ GetShadow            :\ &FFFD - Shadow memory
  910   ASL A:EOR #&40:AND #&C0      :\ &FFxx0x - page in hidden MOS
  920   BPL P%+4:ORA #&08:AND #&48   :\ &FFx0xx - page in FS RAM
  930   ORA &FE34:JSR SetACCCON      :\ Page in requested memory
  940   BNE GetIOMem
  950   :
  960   .GetDisplay
  970   \LDA &D0:\AND #16:\BEQ GetIOMem :\ Not shadow screen displayed
  980   LDA #&84:JSR OSBYTE
  990   TYA:BPL GetIOMem             :\ Not shadow screen displayed
 1000   .GetShadow
 1010   LDA #1:JSR vramSelect        :\ Page in shadow memory
 1020   :
 1030   .GetIOMem
 1040   LDY #0
 1050   .GetByteLp
 1060   LDA (addr),Y:STA buff,Y
 1070   INY:CPY cols:BNE GetByteLp
 1080   :
 1090   LDA #0:JSR vramSelect
 1100   PLA:JSR SetACCCON:PLA:PLP    :\ Restore ACCCON, restore ROM and IRQs
 1110   .SelectROM
 1120   STA &F4:JMP &FFB9:\STA &FE30:\RTS
 1130   :
 1140   .SetACCCON
 1150   \LDX os:\CPX #3
 1160   \BCC P%+5:\STA &FE34         :\ Set ACCCON if on Master
 1170   LDX OSARGS:CPX #&5C
 1180   BCS P%+5:STA &FE34           :\ Set ACCCON if on Master
 1190   .vramOk
 1200   RTS
 1210   :
 1220   .vramSelect
 1230   PHA:TAX                  :\ A=0 main RAM, A=1 video RAM
 1240   LDA #108:JSR OSBYTE      :\ Attempt to select Master video RAM
 1250   PLA:INX:BNE vramOk       :\ X<>255, successful
 1260   EOR #1:TAX               :\ A=1 main RAM, A=0 video RAM
 1270   LDA #111:JMP OSBYTE      :\ Attempt to select Aries/Watford RAM
 1280   :
 1290   .GetTube
 1300   BIT tube:BPL GetIOMem   :\ No Tube present
 1310   .GetTubeClaim
 1320   LDA #&C0+&10:JSR &406
 1330   BCC GetTubeClaim        :\ Claim Tube
 1340   LDX #addr:LDY #0
 1350   TYA:JSR &406:LDY #0     :\ Read bytes from Tube
 1360   .GetTubeLp
 1370   LDX #9                  :\ Delay between each byte
 1380   .GetTubeWait
 1390   DEX:BNE GetTubeWait     :\ 2+(2+3)*9+2+2 = 51 cycles = 25.5us
 1400   LDA &FEE5:STA buff,Y    :\ Fetch from Tube
 1410   INY:CPY cols:BNE GetTubeLp
 1420   PLA:PLA:PLP             :\ Drop from stack, restore IRQs
 1430   LDA #&80+&10:JMP &406   :\ Release Tube
 1440   :
 1450   .PrSpace
 1460   LDA #32:BNE PrChar
 1470   .PrHex
 1480   PHA:LSR A:LSR A:LSR A:LSR A
 1490   JSR PrDigit:PLA
 1500   .PrDigit
 1510   AND #15:CMP #10:BCC PrNybble:ADC #6
 1520   .PrNybble:ADC #48
 1530   .PrChar  :JMP OSWRCH
 1540   :
 1550   .GetHex
 1560   LDA #0
 1570   STA 0,X:STA 1,X
 1580   STA 2,X:STA 3,X
 1590   .GetHexNext
 1600   LDA (lptr),Y
 1610   CMP #ASC"0":BCC SkipSpace
 1620   CMP #ASC"9"+1:BCC GetHexDigit
 1630   SBC #7:BCC SkipSpace
 1640   CMP #ASC"@":BCS SkipSpace
 1650   .GetHexDigit
 1660   AND #&0F:PHA:TYA:PHA:LDY #4
 1670   .GetHexMultiply
 1680   ASL 0,X:ROL 1,X:ROL 2,X:ROL 3,X
 1690   DEY:BNE GetHexMultiply
 1700   PLA:TAY
 1710   PLA:ORA 0,X:STA 0,X
 1720   INY:BNE GetHexNext
 1730   :
 1740   .SkipSpace1
 1750   INY
 1760   .SkipSpace
 1770   LDA (lptr),Y:CMP #ASC" ":BEQ SkipSpace1
 1780   CMP #13:RTS
 1790   :
 1800   EQUS ver$
 1810   :
 1820 ]:NEXT
 1830 PRINT"*SAVE MDump "+STR$~mcode%+" "+STR$~O%+" "+STR$~(start%OR&FFFF0000)+" "+STR$~(load%OR&FFFF0000)