diff --git a/TestSrc/Begin b/TestSrc/Begin
index 2a30356125caf541d7961980cc98151cfafea1ca..0d7287f44605e1ccde488ce9297de82bf1aff98e 100644
--- a/TestSrc/Begin
+++ b/TestSrc/Begin
@@ -707,9 +707,9 @@ ts_Self_test_startup ROUT
         LDRB    r0, [r2, #IOMD_ROMCR0]          ; Get contents of ROMCR0 in to r0
         AND     r0, r0, #&40                    ; clear all but the 16-bit mode flag
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     |
-        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
         STRB    r0, [r2, #IOMD_ROMCR0]          ; Prog. the reg.s
   [ CanLiveOnROMCard
@@ -758,9 +758,9 @@ ts_Self_test_startup ROUT
         LDRB    r0, [r2, #IOMD_ROMCR0]          ; Get contents of ROMCR0 in to r0
         AND     r0, r0, #&40                    ; clear all but the 16-bit mode flag
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeed_NSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     |
-        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeed_NSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
         STRB    r0, [r2, #IOMD_ROMCR0]          ; Prog. the reg.s
   [ CanLiveOnROMCard
@@ -1357,7 +1357,11 @@ Speedset
         ALIGN
 
 RAMtest
-        B       ts_VIDCtest	; skip memory test altogether; was	ADR     r4,%BT1
+ [ {TRUE}
+        B       ts_VIDCtest	; skip memory test altogether
+ |
+	ADR     r4,%BT1
+ ]
         BL      ts_SendText
 ;
 ; if (R_MEMSKIP && R_HARD)
diff --git a/TestSrc/ExtIO b/TestSrc/ExtIO
index 6115db36eb6524ea5817f1f89b7c68ac9ca7c778..cab813c2cb33f9ec5b08ad09aa2bf10f12c6acff 100644
--- a/TestSrc/ExtIO
+++ b/TestSrc/ExtIO
@@ -83,23 +83,6 @@ ts_GetCommand  ROUT
 ;
 ; Load up the registers for the test interface communication -
 ;
-  [ :LNOT: CanLiveOnROMCard
-        LDR     r0,%01                  ; set zero in r0
-        ADD     pc,pc,r0  ;(generally useful constant - especially for skip)
-01
-        &       0
-        LDR     r1,%02                  ; set FFFFFFFF in r1
-        ADD     pc,pc,r0  ;(test value : sets carry when added to non-zero)
-02
-        &       (-1)
-        LDR     r2,%03                  ; set pointer to test address
-        ADD     pc,pc,r0  ;(points to aliased copy of a zero word)
-03
-        &       (ts_Alias_bits + (%01 - %04))
-        ADDS    r2,pc,r2                ; adjust r2 for ROM-relative address
-        ADDS    r4,r0,r0                ; clear output accumulator
-04                                      ; where pc is when added to r2
-  |
 ; Point r2 at a word which contains 0 in 0-8MB physical space.
 ; Note that this code doesn't cope with the case where it can't find a zero
 ; word anywhere in the whole ROM. I don't think that this is a problem.
@@ -114,7 +97,6 @@ ts_GetCommand  ROUT
 	ADD	r2, r2, #ts_Alias_bits	; point to zero word in ghost
 	MOV	r1, #-1			; expected below
 04
-  ]
         ; do an RD operation (four strobes) to ensure interface cleared
 
         LDR     r3,[r2]
@@ -629,23 +611,6 @@ ts_PosText      ROUT
 ;
 
 ts_SendLCDCmd
-  [ STB :LAND: :LNOT: CanLiveOnROMCard
-        LDR     r0,%01                  ; set zero in r0
-        ADD     pc,pc,r0
-01
-        &       0
-        LDR     r1,%02                  ; set FFFFFFFF in r1
-        ADD     pc,pc,r0  ;(test value : sets carry when added to non-zero)
-02
-        &       (-1)
-        LDR     r2,%03                  ; set pointer to test address
-        ADD     pc,pc,r0  ;(points to aliased copy of a zero word)
-03
-        &       (ts_Alias_bits + (%01 - %04))
-        ADDS    r2,pc,r2                ; adjust r2 for ROM-relative address
-        ADDS    r0,r0,r0                ; dummy (to keep labels nearby !)
-04                                      ; where pc points when added to r2
-  |
 ; Point r2 at a word which contains 0 in 0-8MB physical space.
 ; If this word still reads as 0 when its ghost/alias is read from 8-16MB space
 ; (A23 set) then we don't have a test box, otherwise we do.
@@ -661,7 +626,6 @@ ts_SendLCDCmd
 
 	ADD	r2, r2, #ts_Alias_bits	; point to zero word in ghost
 04
-  ]
 
 ; Wait - gap between successive WS attempts or successive bytes
 
diff --git a/VersionASM b/VersionASM
index 6f09e4c61386024e401f173b1ca8a6ea3d9bde8d..a2e4ada16e99737087334ddcb41bed6c866eec85 100644
--- a/VersionASM
+++ b/VersionASM
@@ -5,8 +5,8 @@
 			GBLA    Module_Version
 			GBLS	Module_MinorVersion
 			GBLS	Module_Date
-Module_MajorVersion	SETS    "4.68"
-Module_Version          SETA    468
+Module_MajorVersion	SETS    "4.69"
+Module_Version          SETA    469
 Module_MinorVersion	SETS	""
-Module_Date		SETS    "16 Dec 1998"
+Module_Date		SETS    "09 Feb 1999"
 		        END
diff --git a/VersionNum b/VersionNum
index 9e4a8657ae4ccbc4fa9e24e4e510fa0466dcfcc6..39a27994dbfe9935790dd29093144a495d562983 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,14 +1,14 @@
-/* (4.68)
+/* (4.69)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG     	4.68
+#define Module_MajorVersion_CMHG     	4.69
 #define Module_MinorVersion_CMHG	
-#define Module_Date_CMHG      		16 Dec 1998
+#define Module_Date_CMHG      		09 Feb 1999
 
-#define Module_MajorVersion     	"4.68"
-#define Module_Version                  468
+#define Module_MajorVersion     	"4.69"
+#define Module_Version                  469
 #define Module_MinorVersion		""
-#define Module_Date      		"16 Dec 1998"
+#define Module_Date      		"09 Feb 1999"
 
diff --git a/hdr/KernelWS b/hdr/KernelWS
index cbc42b31ce1d508e53b0fb428843d7371c6c2f1f..e6c1dda5e7412746b07694ddb682c1b970f7a02c 100644
--- a/hdr/KernelWS
+++ b/hdr/KernelWS
@@ -660,7 +660,7 @@ VIDCClockSpeed # 4      ; current VIDC clock speed in kHz
 
 CurrentMonitorType # 4  ; initialised from configured one
 
- [ ChrontelSupport
+ [ STB
 PixelRate # 4   ; Pixel Rate in kHz
  ]
 
diff --git a/s/ARM600 b/s/ARM600
index d888ee7a940c510ce9316535b69c81879ea4ea43..22119a003bae0045cedb4c0953158179b044cdd7 100644
--- a/s/ARM600
+++ b/s/ARM600
@@ -989,9 +989,9 @@ init7500FEcpu
         ORR     r0, r0, #IOMD_ROMCR_HalfSpeed + IOMD_ROMCR_NSTicks_5 + IOMD_ROMCR_BTicks_3
   |
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     |
-        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
   ]
         STRB    r0, [r12, #IOMD_ROMCR0]         ; Prog. the reg.s
@@ -1070,9 +1070,9 @@ init7500cpu
         ORR     r0, r0, #IOMD_ROMCR_Normal + IOMD_ROMCR_NSTicks_5 + IOMD_ROMCR_BTicks_3
   |
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     |
-        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
   ]
         STRB    r0, [r12, #IOMD_ROMCR0]          ; Prog. the reg.s
@@ -1409,8 +1409,6 @@ CommonInit
 ; 256Kbyte       4K          32*64kx1        A13,A20,A12,A18 fail, A21,A19 ok
 ;
 
-Z_Flag     * &40000000
-
 ; MemSize routine... enter with 32K pagesize set
 ; R0 returns page size
 ; R1 returns memory size
@@ -1462,14 +1460,6 @@ MemSize ROUT
   ]
         MOV     r14, #IOMD_Base
         STRB    r11, [r14, #IOMD_DRAMWID]
-
- [ 1 = 0
-        MOV     R10, #DRAM0PhysRam
-        MOV     R11, #(2*OneMByte)
-        STMIA   R10!, {R10, R11}
-        B       AllocateTheRAM
-        ! 0, "*** WARNING *** Bodged RAM sizing version ment for PSwindell"
- ]
         MOV     r10, #0                                 ;indicate no RAM found yet
         MOV     r9, #IOMD_DRAMWID_DRAM_16bit            ;bit to OR into DRAMWID to set 16bit
         MOV     r0, #DRAM0PhysRam
@@ -1490,259 +1480,53 @@ ExamineDRAMBank                                         ;examine first/next DRAM
         EOR     r6, r6, r4                              ; if memory is 32bits wide
        ;TEQ     r5, #0
         TEQEQ   r6, #0
-        BEQ     %FT1010                                   ;32bit wide memory
+        BEQ     %FT05                                   ;32bit wide memory
 
         TST     r5, #&00FF                              ;If the bottom 16bits of each location
         TSTEQ   r5, #&FF00                              ; are correct, the memory is 16bits wide
         TSTEQ   r6, #&00FF
         TSTEQ   r6, #&FF00
+        ADDNE   r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
         BNE     NoRamInBank                             ;No memory in this bank
 
         ORR     r11, r11, r9                            ;Bank is 16bits wide
-1010
+05
         STMIA   r0, {r1, r2}                            ;Restore the two locations we widdled on
                                                         ;Must do BEFORE poking the DRAMWID register
         MOV     r14, #IOMD_Base                         ;
         STRB    r11, [r14, #IOMD_DRAMWID]               ;
-;
-; minimum ram test
-;
-        ADD     r1, r0, #A18
-        BL      DistinctAddresses
-        BNE     NoRamInBank                             ;Less than 512KBytes, so ignore this bank
-
-        MOV     r6, #0                                  ;Fragment address
-        MOV     r7, #0                                  ;Fragment address
-        MOV     r8, #A19                                ; now go through address lines A19-A25
-1015
-        ADD     r1, r0, r8                              ; see if this address line is unique
-        BL      DistinctAddresses
-        BNE     %FT1020                                   ; if we've failed then r8 is true size, so exit
-        MOV     r8, r8, LSL #1                          ; else shift up to next
-        TEQ     r8, #A26                                ; only test up to A25
-        BNE     %BT1015
-        BEQ     %FT1035                           ;Bank fully occupied, DON'T test for higher fragments
-1020
-;
-; Found some DRAM, at address r0, size r8.
-; There may be one or two higher address lines connected, so scan upto A25 looking for
-; extra DRAM chunks.
-;
-        MOV     r1, r8
-1025
-        TEQ     r1, #A25
-        BEQ     %FT1035                           ;No higher active address lines found ie one lump of DRAM
-        ADD     r1, r0, r1,LSL #1
-        BL      DistinctAddresses
-        SUB     r1, r1, r0                              ;Recover bit value
-        BNE     %BT1025
-;
-; Got a 2nd fragment, at address r1 (also of size r8)
-;
-        MOV     r6, r1
-1030
-        TEQ     r1, #A25
-        BEQ     %FT1035                           ;No higher active address lines found ie two lumps of DRAM
-        ADD     r1, r0, r1,LSL #1
-        BL      DistinctAddresses
-        SUB     r1, r1, r0                              ;Recover bit value
-        BNE     %BT1030
-;
-; Got another active address line (ie total four fragments)
-;
-        MOV     r7, r1
-;
-1035
-;
-; Found 1, 2 or 4 lumps of DRAM
-;
-  [ 1 = 1
-;
-; New code which relies on reflection to merge fragments into larger blocks
-;
-        TEQ     r10, #0                         ;Need some ram to dump block/fragment data
-        MOVEQ   r10, r0                         ;
-
-        TEQ     r6, #0                          ;Do we have one fragment?
-        MOVEQ   r1, r0                          ;EQ: First and only fragment in this bank
-        MOVEQ   r2, r8                          ;EQ:   so save actual address and size
-        ADDNE   r1, r0, r6                      ;NE: Use reflection to make 1st fragment appear
-        SUBNE   r1, r1, r8                      ;NE:   to start just below 2nd fragment
-        MOVNE   r2, r8, LSL #1                  ;NE:   treat as one double size fragment
-
-        STMIA   r10!, {r1, r2}                  ; {address, size}
-
-        TEQ     r7, #0                          ;Do 3rd and 4th fragments exist
-        ADDNE   r1, r1, r7                      ;NE: yes, merge 3 and 4 together
-        STMNEIA r10!, {r1, r2}                  ;  {address, size}
-  |
-;
-; Old code which enters each fragment as found
-;
-        TEQ     r10, #0                         ;Need some ram to dump block/fragment data
-        MOVEQ   r10, r0                         ;
-
-        STMIA   r10!, {r0, r8}                  ;First fragment
-
-        TEQ     r6, #0
-        ADDNE   r1, r0, r6
-        STMNEIA r10!, {r1, r8}                  ;Second fragment
-
-        TEQ     r7, #0
-        ADDNE   r1, r0, r7
-        STMNEIA r10!, {r1, r8}                  ;Third
-        ADDNE   r1, r1, r6
-        STMNEIA r10!, {r1, r8}                  ;and fourth fragments
-  ]
-  [ Simulator
-        TubeString r2, r3, r4, "Address  Size"
-        TubeDumpNoStack r0, r2, r3, r4
-        TubeDumpNoStack r8, r2, r3, r4
-        TubeNewlNoStack r3, r4
-
-        TEQ     R7, #0
-        BEQ     skip1
-        TubeString r2, r3, r4, "Fragment (1): "
-        TubeDumpNoStack r7, r2, r3, r4
-        TubeNewlNoStack r3, r4
-skip1
-        TEQ     R6, #0
-        BEQ     skip2
-        TubeString r2, r3, r4, "Fragment (2): "
-        TubeDumpNoStack r6, r2, r3, r4
-        TubeNewlNoStack r3, r4
-skip2
-  ]
-
 
+        BL	Add_DRAM_bank
 
 NoRamInBank
-        ADD     r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
         MOV     r9, r9, LSL #1                          ; shunt up position in DRAMWID
         CMP     r9, #&0010                              ; if more banks to do
         BLT     ExamineDRAMBank                         ; then loop
 
-        TEQ     r10, #0                                 ; have we got any DRAM?
-;NoDRAMPanic
-        BEQ     NoDRAMPanic                             ; we'd better stop now
-
-;
-; Having dumped our block/fragment data to the first bit of DRAM that we found.
-; We now go back through it, allocating some for the screen, and some for 'PageZero'.
-; The data has been dumped into RAM that we now allocate as screen ram, so it needs
-; to be copied into 'PageZero'.
-;
-; r10 -> byte after last fragment(address, size) pair
-;
-AllocateTheRAM
-        AND     r7, r10, #DRAMBaseAddressMask           ;point to first fragment data
-        MOV     r2, #0                                  ;MOS workspace not yet allocated
-
-        LDMIA   r7!, {r4, r5}                           ;first fragment address & size
-        CMP     r10, r7                                 ;is there only 1 fragment
- [ 1 = 1
-;
-; New - requested by Tim Dobson
-;
-        MOVHI   r1, r5                                  ;if >1 fragments, take first fragment for the screen
-        SUBLS   r1, r5, #OneMByte                       ;if this is the only fragment, take all but 1MByte of it
-        MOV     r0, r4                                  ;screen starts at beginning of fragment
-  [ 1 = 1
-;
-; New - also requested by Tim Dobson
-;
-        CMP     r1, #SixteenMByte                       ;Limit our claim to 16Mbyte
-        MOVGT   r1, #SixteenMByte
-  ]
- |
-        MOVHI   r1, r5                                  ;if >1 fragments, consider taking first fragment for the screen
-        MOVLS   r1, r5, LSR #1                          ;if this is the only fragment, try for half of it
-        MOV     r0, r4                                  ;screen starts at beginning of fragment
-
-        CMP     r1, #OneMByte                           ;Limit our claim to 1Mbyte
-        MOVGT   r1, #OneMByte
- ]
-        ADD     r4, r4, r1                              ;adjust fragment for amount claimed by screen
-        SUBS    r5, r5, r1
-        BEQ     %FT1065                                 ;EQ whole fragment used
-                                                        ;NE part of fragment remains to be allocated
-1060
-        TEQ     r2, #0                                  ;allocate MOS workspace if not already done so
-        LDREQ   r2, =DRAMOffset_PageZero + DRAMPhysAddrA
-        ADDEQ   r2, r2, r4
-        MOVEQ   r3, r2
-
-        STMIA   r3!, {r4, r5}                           ;write fragment data to correct place in PageZero
-1065
-        CMP     r10, r7                                 ;any more fragment (address, size) pairs?
-        LDMHIIA r7!, {r4, r5}                           ;HI, yes so load next fragment pair (size
-        BHI     %BT1060                                 ;HI, mustbe non-zero) and loop back
-
-        STMDB   r2!, {r0, r1}                           ;write VideoPhysAddr, VideoSize
-;
-; r2 -> start of PhysRamTable
-; r3 -> byte after last used entry in PhysRamTable
-;
-        MOV     r7, r2
-       ;MOV     r2, r2                                  ; r2 -> start of PhysRamTable
-        MOV     r10, r3
-       ;MOV     r3, r3                                  ; r3 -> byte after last used entry in PhysRamTable
-
-
-;
-; r0 screen start address
-; r1 screen size
-; r2 -> start of PhysRamTable
-; r3 -> byte after last used entry in PhysRamTable
-
-        MOV     r4, #0                                  ;Morris cannot support VRAM, so...
-        STR     r4, [r2, #VRAMWidth-PhysRamTable]       ; store width of VRAM (0,1 or 2)
-        STR     r4, [r2, #VRAMSize-PhysRamTable]        ; and size of VRAM (fixes DForth's bug of 6/3/95)
-
+	MOV	r6, #0					; No VRAM
+	MOV	r0, #0
         MOV     r14, #IOMD_Base
 
-        MOV     r4, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
-        STRB    r4, [r14, #IOMD_VIDCR]
-        STR     r0, [r14, #IOMD_VIDCUR]                 ; set up VIDCUR to start of video RAM
-        STR     r0, [r14, #IOMD_VIDSTART]               ; do same for VIDSTART
-        STR     r0, [r14, #IOMD_VIDINIT]                ; and for VIDINIT
-                                                        ; so we don't get a mess when we turn video DMA on later
-
-
 	LDRB	r4, [r14, #IOMD_ID0]
 	LDRB	r7, [r14, #IOMD_ID1]
 	ORR	r4, r4, r7, LSL #8
 	LDR	r7, =IOMD_7500FE			; if FE part, then assume EDO DRAM
 	TEQ	r4, r7
-	LDREQ	r4, =80000000				; so allow 80E6 bytes/s
+	LDREQ	r2, =80000000				; so allow 80E6 bytes/s
  [ STB
-	LDRNE	r4, =44000000				; else only allow 44E6 bytes/s
+	LDRNE	r2, =44000000				; else only allow 44E6 bytes/s
  |
-        LDRNE   r4, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
+        LDRNE   r2, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
  ]
-        STR     r4, [r2, #VideoBandwidth-PhysRamTable]  ; store video bandwidth
-
-        ADD     r4, r0, r1                              ;form VIDEND (will be on mult. of SAM)
-        SUB     r4, r4, #4096
-        STR     r4, [r14, #IOMD_VIDEND]                 ;this instruction put in on 6/3/95 after inspection of RPC code
-;
-;
-;
-        MOV     r7, r2
-        MOV     r10, r3
+	MOV	r1, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
 
-        B       MemSizeTotalRAM
+        B       Allocate_DRAM
 
 MemSizeIOMD
  ]
 
 ; Right, let's find out where our memory is
 
-; First, we check out the VRAM. This is so that if there's no VRAM, we know to take out the 1st Mbyte of DRAM
-; that we find.
-
-; Don't bother checking for more than 2M of VRAM, because we don't know what the 1/2 SAM length is for larger sizes
-
 ; StrongARM - aha! but we still have no nice MMU, nor even fast core clock, and this memory sizing type
 ; stuff is going to be very slow for large memory. So turn on I cache (allowed with MMU off), and fast
 ; core clock now - this is then ok until MMU etc comes on (near CritStart)
@@ -1772,29 +1556,6 @@ MemSizeIOMD_notSA
     ]
 MemSizeIOMD_not810
   ]
-        MOV     r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default
-        STRB    r2, [r12, #IOMD_VREFCR]
-
-        MOV     r0, #VideoPhysRam                       ; point at VRAM
-        ADD     r1, r0, #A2                             ; test A2
-        BL      DistinctAddresses
-        MOVEQ   r6, #2                                  ; we've got 2M of VRAM
-        BEQ     %FT08
-
-        MOV     r2, #IOMD_VREFCR_VRAM_256Kx32 :OR: IOMD_VREFCR_REF_16
-        STRB    r2, [r12, #IOMD_VREFCR]
-        ADD     r1, r0, #A2                             ; check for any VRAM at all
-        BL      DistinctAddresses
-        MOVEQ   r6, #1                                  ; we've got 1M of VRAM
-        MOVNE   r6, #0                                  ; no VRAM
-08
- [ IgnoreVRAM
-        MOV     r6, #0                                  ; pretend there's no VRAM
- ]
-        MOVS    r12, r6                                 ; if no VRAM, then video RAM has yet to be found
-        MOVNE   r12, r0                                 ; else point at VRAM
-
-; Now, we have to find a bank of DRAM, so we've got somewhere to store our results!
 
         MOV     r11, #IOMD_DRAMCR_DRAM_Large * &55      ; set all banks to be large initially
         MOV     r14, #IOMD_Base
@@ -1806,81 +1567,115 @@ MemSizeIOMD_not810
 10
         ADD     r1, r0, #A10                            ; this should be OK for both configurations
         BL      DistinctAddresses
-        BNE     %FT25                                   ; [no RAM in this bank at all]
+        ADDNE   r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
+        BNE     %FT15                                   ; [no RAM in this bank at all]
 
         ADD     r1, r0, #A11                            ; test for 256K DRAM
         BL      DistinctAddresses
         ORRNE   r11, r11, r9                            ; it is, so select small multiplexing
         MOVNE   r14, #IOMD_Base
         STRNEB  r11, [r14, #IOMD_DRAMCR]                ; store new value of DRAMCR, so we can use memory immediately
-        MOVNE   r8, #1024*1024                          ; must be 1Mbyte at this address
-        BNE     %FT20
 
-; it's bigger than 256K words, so test address lines A21-A25 in sequence
-; we assume that the size of each bank is a power of 2
+	BL	Add_DRAM_bank
 
-        MOV     r8, #A21                                ; now go through address lines A21-A25
+; Now, we have to find a bank of DRAM, so we've got somewhere to store our results!
 15
-        ADD     r1, r0, r8                              ; see if this address line is unique
-        BL      DistinctAddresses
-        BNE     %FT20                                   ; if we've failed then r8 is true size, so exit
-        MOV     r8, r8, LSL #1                          ; else shift up to next
-        TEQ     r8, #A26                                ; only test up to A25
-        BNE     %BT15
-20
-        TEQ     r12, #0                                 ; have we found any video RAM yet?
-        BNE     %FT22                                   ; yes, so no worries
-
-        MOV     r12, r0                                 ; no, so use this as video RAM
-        ADD     r0, r0, #1024*1024                      ; advance RAM pointer by 1M
-        SUBS    r8, r8, #1024*1024                      ; take 1 Mbyte off the size
-        BEQ     %FT25                                   ; if that's all there was, then go look for the next bank
-22
-        TEQ     r10, #0                                 ; is this the first lot we've found?
-        LDREQ   r10, =DRAMOffset_PageZero + DRAMPhysAddrA
-        ADDEQ   r10, r10, r0                            ; then point r10 at DRAM part of PhysRamTable
-        MOVEQ   r7, r10                                 ; points to beginning of table
-        STMIA   r10!, {r0, r8}                          ; store address, size
-25
-        AND     r0, r0, #DRAMBaseAddressMask            ; move back to start of DRAM bank (in case we stole some video DRAM)
-        ADD     r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
         MOV     r9, r9, LSL #2                          ; shunt up position in DRAMCR
         CMP     r9, #&100                               ; if more banks to do
         BCC     %BT10                                   ; then loop
 
-        TEQ     r10, #0                                 ; have we got any DRAM?
+; Now, we check out the VRAM.
+; Don't bother checking for more than 2M of VRAM, because we don't know what the 1/2 SAM length is for larger sizes
+
+        MOV     r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default
+        STRB    r2, [r12, #IOMD_VREFCR]
+
+        MOV     r0, #VideoPhysRam                       ; point at VRAM
+        ADD     r1, r0, #A2                             ; test A2
+        BL      DistinctAddresses
+        MOVEQ   r6, #2                                  ; we've got 2M of VRAM
+        BEQ     %FT20
+
+        MOV     r2, #IOMD_VREFCR_VRAM_256Kx32 :OR: IOMD_VREFCR_REF_16
+        STRB    r2, [r12, #IOMD_VREFCR]
+        ADD     r1, r0, #A2                             ; check for any VRAM at all
+        BL      DistinctAddresses
+        MOVEQ   r6, #1                                  ; we've got 1M of VRAM
+        MOVNE   r6, #0                                  ; no VRAM
+20
+ [ IgnoreVRAM
+        MOV     r6, #0                                  ; pretend there's no VRAM
+ ]
+        CMP     r6, #1
+        MOVCC   r1, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
+        MOVEQ   r1, #SAMLength/2/256                    ; if 1M VRAM, then use VRAM mode, and set increment for 1/2 SAM
+        MOVHI   r1, #SAMLength/2/256*2                  ; if 2M VRAM, then use VRAM mode, and set increment for 2*1/2 SAM
+        LDRCC   r2, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
+        LDREQ   r2, =80000000                           ; if 1M VRAM, then 80E6   ---------""--------
+        LDRHI   r2, =160000000                          ; if 2M VRAM, then 160E6  ---------""--------
+	MOVCC	r0, #0					; Clear VRAM base if there is no VRAM
+
+; Allocate_DRAM
+;   r0  = Video base if r6!=0
+;   r1  = Value for IOMD VIDCR
+;   r2  = Bandwidth limit
+;   r6  = VRAM size in Mb
+;   r10 = End of DRAM list
+Allocate_DRAM
+
 NoDRAMPanic
-        BEQ     NoDRAMPanic                             ; we'd better stop now
+	TST	r10, r10
+	BEQ	NoDRAMPanic				; Stop here if there is no DRAM (we could use VRAM I suppose...)
+
+	MOV	r7, r6, LSL #20				; r7 = size of video memory
+	LDR	r8, [r10]				; r8 = the number of DRAM blocks.
+	SUB	r11, r10, r8, LSL #3			; Jump back to the start of the list
+
+	LDMIA	r11!, {r4, r5}				; Get a block from the list. (r4,r5) = (base,size)
+	CMP	r6, #0					; Did we find any VRAM?
+	BNE	%FT30					; Skip this bit if we did.
+	MOV	r0, r4					; Allocate this block as video memory
+	MOV	r7, r5
+	CMP	r10, r11				; Was this the only block?  If so, leave 1M
+	SUBEQS	r7, r7, #1024*1024
+	MOVCC	r7, r5, ASR #1				; If that overflowed, take half the bank.
+	CMP	r7, #16*1024*1024
+	MOVCS	r7, #16*1024*1024			; Limit allocation to 16M - the size of the logical space
+
+	ADD	r4, r4, r7				; Adjust the DRAM block base...
+	SUBS	r5, r5, r7				; ... and the size.
+	LDMEQIA	r11!, {r4, r5}				; Fetch the next block if we claimed it all.
+
+30	ADD	r12, r4, #DRAMOffset_PageZero		; Use the first block for kernel workspace.
+	ADD	r3, r12, #DRAMPhysAddrA			; Set the table address as well
+
+	CMP	r8, #5
+	ADDCS	r10, r11, #3:SHL:3			; Limit to 4 blocks of DRAM (3 + this one)
+
+35	STMIA	r3!, {r4, r5}				; Put the DRAM block into the table
+	TEQ	r10, r11
+	LDMNEIA	r11!, {r4, r5}				; Get the next block if there is one.
+	BNE	%BT35
 
 ; Now go back and put the VRAM information in, and also program VIDCR and VIDCUR
 
-        STR     r6, [r7, #VRAMWidth-DRAMPhysAddrA]      ; store width of VRAM (0,1 or 2)
-        CMP     r6, #1
-        MOVCC   r2, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
-        MOVEQ   r2, #SAMLength/2/256                    ; if 1M VRAM, then use VRAM mode, and set increment for 1/2 SAM
-        MOVHI   r2, #SAMLength/2/256*2                  ; if 2M VRAM, then use VRAM mode, and set increment for 2*1/2 SAM
-        LDRCC   r3, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
-        LDREQ   r3, =80000000                           ; if 1M VRAM, then 80E6   ---------""--------
-        LDRHI   r3, =160000000                          ; if 2M VRAM, then 160E6  ---------""--------
+        STR     r6, [r12, #VRAMWidth]                   ; store width of VRAM (0,1 or 2)
         MOV     r14, #IOMD_Base
-        STRB    r2, [r14, #IOMD_VIDCR]
-        STR     r12, [r14, #IOMD_VIDCUR]                ; set up VIDCUR to start of video RAM
-        STR     r12, [r14, #IOMD_VIDSTART]              ; do same for VIDSTART
-        STR     r12, [r14, #IOMD_VIDINIT]               ; and for VIDINIT
+        STRB    r1, [r14, #IOMD_VIDCR]
+        STR     r0, [r14, #IOMD_VIDCUR]                 ; set up VIDCUR to start of video RAM
+        STR     r0, [r14, #IOMD_VIDSTART]               ; do same for VIDSTART
+        STR     r0, [r14, #IOMD_VIDINIT]                ; and for VIDINIT
                                                         ; so we don't get a mess when we turn video DMA on later
-        STR     r3, [r7, #VideoBandwidth-DRAMPhysAddrA] ; store video bandwidth
-
-        ADD     r3, r12, #1024*1024-4096                ; add on a bit to form VIDEND (will be on mult. of SAM)
-        STR     r3, [r14, #IOMD_VIDEND]                 ; yes I know it's a bit of a bodge
+        STR     r2, [r12, #VideoBandwidth]              ; store video bandwidth
 
-        MOVS    r14, r6, LSL #20                        ; convert amount of VRAM to bytes
-        STR     r14, [r7, #VRAMSize-DRAMPhysAddrA]      ; and store
+        ADD     r4, r0, #1024*1024-4096                 ; add on a bit to form VIDEND (will be on mult. of SAM)
+        STR     r4, [r14, #IOMD_VIDEND]                 ; yes I know it's a bit of a bodge
 
-        MOVEQ   r14, #1024*1024                         ; if no VRAM, then video RAM size is 1M
-        STMDB   r7!, {r12, r14}                         ; store video information
+        MOV     r4, r6, LSL #20                         ; convert amount of VRAM to bytes
+        STR     r4, [r12, #VRAMSize]                    ; and store
 
-        MOV     r2, r7                                  ; r2 -> start of PhysRamTable
-        MOV     r3, r10                                 ; r3 -> byte after last used entry in PhysRamTable
+	ADD	r2, r12, #VideoPhysAddr			; r2 -> Start of PhysRamTable
+        STMIA   r2, {r0, r7}                            ; store video memory block
 MemSizeTotalRAM
 ; Now we have to work out the total RAM size
 
@@ -1888,7 +1683,8 @@ MemSizeTotalRAM
         TubeString r4, r5, r6, "Address  Size"
   ]
         MOV     r1, #0
-26
+        MOV     r7, r2
+40
         LDMIA   r7!, {r4, r5}                           ; get address, size
         ADD     r1, r1, r5                              ; add on size
   [ Simulator
@@ -1896,11 +1692,13 @@ MemSizeTotalRAM
         TubeDumpNoStack r5, r6, r8, r9
         TubeNewlNoStack r6, r8
   ]
-        TEQ     r7, r10
-        BNE     %BT26
+        TEQ     r7, r3
+        BNE     %BT40
 
         MOV     r0, #Page4K                             ; something to put in MEMC CR soft copy
                                                         ; (it's probably irrelevant)
+	ADRL	r4, ROM
+
  |
 
 ; MEMC based memory sizing
@@ -1985,7 +1783,6 @@ MemSizeDone
 
         LDR     r4, =38400000                   ; indicate 38.4E6 bytes/sec video bandwidth
         STR     r4, [r2, #VideoBandwidth-PhysRamTable]
- ]
 
         ADRL    r4, ROM                         ; use PC-relative addressing to get to start of image
         TEQ     r4, #PhysROM                    ; then see if it's the normal ROM address
@@ -2047,6 +1844,14 @@ MemSizeDone
         STMIA   r8, {r5, r9}                    ; store end lump
         ADD     r3, r3, #8                      ; advance end pointer
 
+ ]
+
+; r0 = Page size
+; r1 = Total memory size (bytes)
+; r2 = PhysRamTable
+; r3 = After last used entry in PhysRamTable
+; r4 = Address of ROM
+
 ; now store zeros to fill out table
 
 55
@@ -2268,6 +2073,188 @@ CritEnd                                         ; 2 words after we go up into RO
  ]
         MOV     pc, r13
 
+ [ MEMC_Type = "IOMD"
+; add_dram_bank
+;   Entry: r10 -> workspace (initially 0)
+;          r0  =  bank address
+;   Exit:  r10 -> workspace (allocated if 0 on entry)
+;          r0  =  next bank address
+;          r9, r11, r13 preserved
+;   Probe a DRAM bank, and add any DRAM found to the workspace
+Add_DRAM_bank
+	ROUT
+	MOV	r12, lr			; r12 = return address
+	EOR	r1, r0, #A16		; Check there is some RAM in the bank
+	BL	DistinctAddresses
+	ADDNE	r0, r0, #DRAM1PhysRam-DRAM0PhysRam
+	MOVNE	pc, r12			; Return if no RAM in the bank
+
+	; Only some address lines are decoded by the SIMM.  For example, a 4M SIMM may be split
+	; into 2 banks, with A2-A20 decoded on each, or A2-A19,A21 decoded.  First we need to
+	; find out which address lines are decoded, and which are ignored.
+	MOV	r6, #DRAM1PhysRam-DRAM0PhysRam
+	MOV	r7, #A17
+	SUB	r6, r6, #1		; Get address lines which select address within bank.
+
+	; Loop through the address lines, finding out which are decoded.  We clear the bits in r6
+	; which correspond to non-decoded address lines.
+	; r6 = address line mask
+	; r7 = current address line
+10	EOR	r1, r0, r7		; Toggle the address line
+	BL	DistinctAddresses	; Check if address line has any effect.
+	BICNE	r6, r6, r7		; Clear the bit if the address line fails.
+	MOV	r7, r7, LSL #1		; Move onto the next address line.
+	TST	r6, r7			; Have we reached the limit?
+	BNE	%BT10			; Repeat if not.
+
+	; r6 = decoded address lines in bank. (ie in A0-A25)
+	; r7 = The size of the DRAM bank
+	; Since the DRAM bank may not be contiguous, we now split the bank up into contiguous
+	; blocks.  We make these as large as possible to save work.  Here we set r8 to the
+	; size of the smallest contiguous block(s) of RAM.  (There will also be some contiguous
+	; blocks which are twice this size in some cases.)
+	ADD	r8, r6, #A17
+	BIC	r8, r8, r6		; r8 = First clear bit in r6 from A17 up.
+
+	RSB	r4, r8, #0		; r4 = All bits at or above r8 set since r8 is a power of 2.
+
+	RSB	r7, r7, #0		; r7 = address bits which select the bank since r7 was a
+					;      power of 2.
+	ORR	r3, r7, r6		; r3 = All decoded address lines.
+	AND	r7, r4, r3		; r7 = All decoded bits at or above r8.
+
+; Make sure that the dram bank may not be contained within the image.  The code below fails
+; to work correctly if a dram bank is contained within an OS image.  Currently this would
+; require an image larger than 64M.
+		ASSERT	OSROM_ImageSize*1024 <= DRAM1PhysRam-DRAM0PhysRam
+
+15	MOV	r1, r0			; r1 = Address of start of block (inclusive).
+	ADD	r2, r1, r8		; r2 = End of the block (exclusive).
+
+	; Move the end of the block if the OS image begins in this block.
+	ADRL	r4, ROM			; r4 = Start of the OS image (which may be in RAM).
+	EOR	r5, r4, r1		; r5 = Difference between image and memory block.
+	TST	r5, r7			; Check if the image begins in this block of RAM.
+	ANDEQ	r2, r4, r3		; Set end of block to start of image.
+
+	; Move the start of the block if the OS image ends in this block.
+	ADD	r4, r4, #OSROM_ImageSize*1024
+	SUB	r4, r4, #1		; r4 = Last byte of the OS image.
+	EOR	r5, r4, r1		; r5 = Difference between end of image and block.
+	TST	r5, r7			; Check if the image ends in this block of RAM.
+	ANDEQ	r5, r4, r3		; r5 = Address of last byte of the image within this block.
+	ADDEQ	r1, r5, #1		; Set start of block to the byte after the image.
+
+	; If the image is contained in the block, we will have swapped the start and end
+	; addresses.  This means that the block is split into two parts.  The bit below
+	; the image and the bit above the image.
+	CMP	r1, r2
+	BLS	%FT20			; If start <= end, then block is not fragmented.
+	CMP	r2, r0			; Check the size of the fragment before the image.
+	MOV	r0, r1			; Store old start address
+	AND	r1, r1, r7		; Get the start of the block
+	BLNE	Allocate_DRAM_fragment	; Allocate it if it's non-zero.
+	MOV	r1, r0			; Restore the old start of fragment
+	AND	r0, r0, r7		; Get the start of the block again.
+	ADD	r2, r0, r8		; End of next fragment is the end of the block.
+
+	CMP	r1, r2			; Compare start and (modified) end.
+20	BLNE	Allocate_DRAM_fragment
+
+	; Now move onto the next block.  We add the non-decoded address lines to cause the
+	; carry to be propagated across them.  Then we mask them out.
+	MVN	r4, r7			; Add the non-connected address lines to ...
+	ADD	r4, r4, r0		; ... the block address ...
+	ADD	r4, r4, r8		; ... and the block size.
+;	EOR	r5, r0, r4		; Compare with old address
+	AND	r0, r4, r7		; Leave only the decoded lines set.
+;	BIC	r5, r5, r6		; Clear decoded lines within the bank.
+;	TST	r5, r7			; Check only the bank lines.
+;	BEQ	%BT15			; Repeat for next block.
+
+	TST	r0, r6
+	BNE	%BT15
+
+	MOV	pc, r12			; Done for this bank.
+
+; Allocate_DRAM_block
+;   Entry:
+;     r1 = block start (inclusive)
+;     r2 = block end (exclusive)
+;     r3 = All decoded address lines
+;     r7 = All decoded bits at or above r8
+;     r8 = Size of largest contiguous block
+;     block length is assumed to be at least the size of the static data - ie. 160k
+;     The maximum block list size is then 4k, which fits easily into the cursor chunk
+;   Exit:
+;     r10 updated
+;     r0, r3, r6-r9, r11-r13 preserved
+;     r10 points to a word containing the number of blocks stored.
+;     The pairs of words before
+Allocate_DRAM_fragment
+	ROUT
+	CMP	r10, #0
+	BEQ	%FT20
+
+	; We are not dealing with the first block since r10 != 0.  Make an attempt to merge this block
+	; with the previous block.
+	LDMDB	r10, {r4, r5}		; Get details of the previous block
+	ADD	r5, r4, r5		; Get the end address
+	EOR	r5, r5, r1		; Compare with the current block start address...
+	TST	r5, r3			; ... but only check the decoded bits.
+	EOR	r5, r5, r1		; Restore the previous block end address.
+	BNE	%FT10			; We can't merge it after the previous block
+
+	; r4 = previous start
+	; r5 = previous end
+	; The block is just after the previous block.  That means the start address is unchanged, but
+	; the length is increased.
+	SUB	r5, r5, r4		; Calculate the previous block length.
+	SUB	r2, r2, r1		; Find the length of the new block.
+	; r2 = length of block
+	ADD	r5, r5, r2		; Add it to the previous length.
+	STR	r5, [r10, #-4]		; Update the block size in memory.
+	MOV	pc, lr
+
+	; The block is not just after the previous block, but it may be just before.  This may be the
+	; case if we are softloaded.
+10	SUB	r4, r4, #1		; Compare the address before the previous block start ...
+	SUB	r2, r2, #1		; ... with the address of the last byte in this block ...
+	EOR	r4, r4, r2
+	TST	r4, r3			; ... but check only the decoded bits.
+	ADD	r2, r2, #1		; Restore the end address.
+	BNE	%FT20			; Skip if we cannot merge the block.
+
+	; The block is just before the previous block.  The start address and length both change.
+	LDR	r4, [r10, #-8]		; Get the previous block start again.
+
+	SUB	r2, r2, r1		; Calculate the current block size.
+	SUB	r4, r4, r2		; Subtract from the previous block start address.
+	SUB	r5, r5, r4		; Calculate the new length=end-start
+	STMDB	r10, {r4, r5}		; Update the block info in memory.
+	MOV	pc, lr
+
+	; We now have a region which does not merge with a previous region.  We move it up to the
+	; highest address we can in the hope that this block will merge with the next block.
+20	SUB	r2, r2, r1		; Calculate the block size
+	MVN	r4, r3			; Get the non-decoded address lines.
+	ORR	r1, r4, r1		; Set the non-decoded address bit in the start address.
+
+30	CMP	r10, #0			; If the workspace has not been allocated...
+	MOVEQ	r10, r1			; ... use this block.
+	MOVEQ	r4, #0			; Initialise the counter.
+
+	; The block/fragment to be added is between r1 and r1+r2.
+	LDRNE	r4, [r10]		; Get the old counter if there was one.
+	STMIA	r10!, {r1, r2}		; Store address and size.
+	ADD	r4, r4, #1		; Increment the counter.
+	STR	r4, [r10]		; Store the counter.
+
+	MOV	pc, lr			; We've done with this block now.
+
+
+ ]
+
 ; Memory map initialisation table
 ; Consists of word triplets (size,logaddr,type)
 ; where size    is size in bytes of area (size=0 terminates list)
@@ -2568,11 +2555,6 @@ TimeCPU ROUT            ;ONLY WORKS FOR IOMD(L) machines - this shouldn't be a p
         MOVEQ   pc,lr
   ]
 
-  [ STB
-        BIC     r9, r9, #3 :SHL: 8
-        STR     r9, [r9]                ; turn off refresh for a bit
-  ]
-
 ; Time CPU/Memory speed
         LDR     r1, =&7FFE              ; 32K @ 2MHz = ~16ms limit
         MOV     r3, #IOC                ; Address of the IO controller
@@ -3856,56 +3838,66 @@ L1L2PTe_WPROMdone
 
         LDR     r0,=MaxCamEntry
         LDR     r0,[r0]
-        ADD     r0,r0,#1               ; = no. of 4k RAM pages in machine
-        MOV     r0,r0,LSR #8           ; = no. of Mbytes in machine
-        ADD     r0,r0,#3
-        BIC     r0,r0,#3               ; round up to next 4 Mb
-        CMP     r0,#28                 ; if 28Mb or more, no pages to be rescued from L2PT AppSpace
+        ADD     r0,r0,#1+255+768		; = no. of 4k RAM pages in machine + 255 + 3*256
+        MOV     r0,r0,LSR #8			; = no. of Mbytes in machine rounded up + 3
+        BIC     r0,r0,#3			; round up to next 4 Mb
+        CMP     r0,#28				; if 28Mb or more, no pages to be rescued from L2PT AppSpace
         BHS     %FT09
         LDR     r1,=AppSpaceDANode
         MOV     r2,r0,LSL #20
-        STR     r2,[r1,#DANode_MaxSize] ; update AppSpace max size
-        MOV     r0,r0,LSR #2           ; no. of L2PT AppSpace pages which cannot be rescued
+        STR     r2,[r1,#DANode_MaxSize]		; update AppSpace max size
+        MOV     r0,r0,LSR #2			; no. of L2PT AppSpace pages which cannot be rescued
         MOV     r1,#L2PT
-        ADD     r1,r1,#(L2PT :SHR: 10) ;the L2PT of the L2PT (and first 7 entries are for App Space)
-        ADD     r1,r1,r0,LSL #2        ;first entry for rescue
+        ADD	r4, r1, #L1PT-L2PT
+        ADD	r4, r4, r0, LSL #4		;the L1PT entry to blank out (4 L1 entries per L2 entry)
+        ADD     r1,r1,#(L2PT :SHR: (12-2))	;the L2PT of the L2PT (and first 7 entries are for App Space)
+        ADD     r1,r1,r0,LSL #2			;first entry for rescue
         LDR     r3,=FreePoolDANode
         LDR     r2,[r3,#DANode_Base]
-        LDR     r3,[r3,#DANode_Size]
-        ADD     r2,r2,r3               ; r2 -> next logical address for a rescued page
-        MOV     r5,r3                  ; FreePool size so far
+        LDR     r5,[r3,#DANode_Size]		; FreePool size so far
+        ADD     r2,r2,r5			; r2 -> next logical address for a rescued page
 
-        SUB     sp,sp,#16              ; room for 1 page block entry + terminator
+        SUB     sp,sp,#16			; room for 1 page block entry + terminator
         MOV     r3,sp
 05
-        LDR     r4,[r1],#4             ; pick up the L2PT entry
-        BIC     r4,r4,#&0FF
-        BIC     r4,r4,#&F00            ; mask to leave physical address only
-        STR     r4,[r3,#8]             ; store physical address in word 2 of page block entry
-        Push    "r0-r2"
+        Push    "r0"
+        LDR     r0,[r1],#4			; pick up the L2PT entry
+        BIC     r0,r0,#&0FF
+        BIC     r0,r0,#&F00			; mask to leave physical address only
+        STR     r0,[r3,#8]			; store physical address in word 2 of page block entry
+
+        Push    "r1-r2"
         MOV     r0,#&0C00
         MOV     r1,r3
         MOV     r2,#1
-        SWI     XOS_Memory             ; fill in page number, given physical address
-        Pull    "r0-r2"
-        MOV     r4,#2                  ; means inaccessible in user mode (destined for FreePool)
-        STR     r4,[r3,#8]
-        MOV     r4,#-1
-        STR     r4,[r3,#12]            ; terminator
-        STR     r2,[r3,#4]             ; new logical address for page
-        Push    "r0"
+        SWI     XOS_Memory			; fill in page number, given physical address
+
+        MOV     r0,#2				; means inaccessible in user mode (destined for FreePool)
+        STR     r0,[r3,#8]
+        MOV     r0,#-1
+        STR     r0,[r3,#12]			; terminator
+        Pull    "r1-r2"
+
+        STR     r2,[r3,#4]			; new logical address for page
         MOV     r0,r3
         SWI     XOS_SetMemMapEntries
+
+	MOV	r0, #0				; Blank out the L1PT entries for the page table we just removed
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+
         Pull    "r0"
         ADD     r2,r2,#4096
-        ADD     r5,r5,#4096            ; next page
+        ADD     r5,r5,#4096			; next page
         ADD     r0,r0,#1
-        CMP     r0,#7                  ;7 entries in total for full 28Mb AppSpace
+        CMP     r0,#7				;7 entries in total for full 28Mb AppSpace
         BNE     %BT05
-        ADD     sp,sp,#16              ;drop the workspace
+        ADD     sp,sp,#16			;drop the workspace
 
-        LDR     r4,=FreePoolDANode
-        STR     r5,[r4,#DANode_Size]   ;update FreePoolSize
+        LDR     r0,=FreePoolDANode
+        STR     r5,[r0,#DANode_Size]		;update FreePoolSize
 
 09
         Pull    "r0-r5,pc"
diff --git a/s/GetAll b/s/GetAll
index 773e80b16bd27343cd8879a36b079e29a618f812..04d4b5af9064e4818fd511192c908f9fbe5f3ed7 100644
--- a/s/GetAll
+++ b/s/GetAll
@@ -200,7 +200,7 @@ Module          SETL    {FALSE}
                 GBLL    IncludeTestSrc  ; whether test code is included
                 ! 0, "Modified code"
  [ MorrisSupport
-IncludeTestSrc  SETL    {FALSE}
+IncludeTestSrc  SETL    {TRUE}
  |
 IncludeTestSrc  SETL    :LNOT: (MEMM_Type = "MEMC2") ; not on internal test versions
  ]
@@ -621,6 +621,7 @@ largest_rma_size    * (128*1024)                 ; and the ceiling for rma use
         GET     Hdr:Wimp
         GET     Hdr:ColourTran
         GET     Hdr:Debug
+        GET	Hdr:nvram
         GET     s.PMF.DEF          ; Common with 6502 code in the keyboard
         Protocol
 
diff --git a/s/Middle b/s/Middle
index 4085e005d400c0d81ac4efd034fca381bc31ed7e..0d3c8254baa403d44cd23e3fb0a7c6f580ae3780 100644
--- a/s/Middle
+++ b/s/Middle
@@ -1313,36 +1313,65 @@ GetMachineAddressCMOS
 ;       r1 = upper 2 bytes (or 0)
 ;       EQ => valid, NE => invalid
 ;
-        Push    "r2-r5,lr"
-        MOV     r1, #EtherAddrCMOS
-        MOV     r2, #0                                  ; For lower 4 bytes
-        MOV     r3, #0                                  ; For upper 2 bytes
-        MOV     r4, #0                                  ; For checksum
-        MOV     r5, #6                                  ; Read 6 bytes
-01
-        MOV     r0, r1
-        BL      Read
-        ADD     r1, r1, #1                              ; Move on to next byte
-        MOV     lr, r2, LSR #24                         ; Get top byte of lower word
-        ORR     r3, lr, r3, LSL #8                      ; and put it into bottom byte of upper word
-        ORR     r2, r0, r2, LSL #8                      ; Put byte read into bottom byte of upper word
-        ADD     r4, r4, r0                              ; Add byte to checksum
-        SUBS    r5, r5, #1                              ; Any more bytes?
-        BNE     %BT01
+	Entry	"r2,r3", 8				; Preserve these
+
+	ADR	r0, NVRAM_TAG_MACAddress		; Read the MAC address
+	MOV	r1, sp
+	MOV	r2, #6
+	SWI	XNVRAM_Read
+	MOVVS	r0, #&ffffffff
+	TST	r0, #&80000000				; Check for errors
+	BNE	%FT10
+
+	ADR	r0, NVRAM_TAG_MACAddressChecksum	; Read the checksum
+	ADD	r1, sp, #6
+	MOV	r2, #1
+	SWI	NVRAM_Read
+	MOVVS	r0, #&ffffffff
+	TST	r0, #&80000000				; Check for errors
+10
+	MOV	r0, #0
+	MOV	r1, #0
+	BNE	%FT20					; Return zero on error
 
-        ASSERT  EtherCheckCMOS = EtherAddrCMOS+6
-        MOV     r0, r1                                  ; Read checksum byte
-        BL      Read
-        AND     r4, r4, #&FF                            ; Bottom byte of checksum
-        EOR     r0, r0, #&FF                            ; should be inverted in CMOS
-        TEQ     r0, r4
-        MOVEQ   r0, r2                                  ; Use CMOS values if valid
-        MOVEQ   r1, r3
-        MOVNE   r0, #0                                  ; otherwise no address.
-        MOVNE   r1, #0
-        Pull    "r2-r5,pc"
-        ]
+	LDRB	r3, [sp, #0]				; Get the first byte into checksum
+	MOV	r1, r3, ASL #8				; Store into result
+
+	LDRB	r2, [sp, #1]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r1, r1, r2, ASL #0			; Store into the result
+
+	LDRB	r2, [sp, #2]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	MOV	r0, r2, ASL #24				; Store into the result
 
+	LDRB	r2, [sp, #3]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #16			; Store into the result
+
+	LDRB	r2, [sp, #4]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #8			; Store into the result
+
+	LDRB	r2, [sp, #5]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #0			; Store into the result
+
+	LDRB	r2, [sp, #6]				; Get the checksum
+	AND	r3, r3, #&FF
+	EOR	r3, r3, #&FF
+	TEQ	r2, r3					; Check against the computed value
+	MOVNE	r0, #0					; Zero the MAC address on failure
+	MOVNE	r1, #0
+
+20
+	EXITS
+
+NVRAM_TAG_MACAddress
+	= "MACAddress", 0
+NVRAM_TAG_MACAddressChecksum
+	= "MACAddressChecksum", 0
+        ]
 
 ; OS_ReadSysInfo 5
 ;
diff --git a/s/NewReset b/s/NewReset
index 9215d7319b82ab14274e040bfab6735bc1841226..2c6b71e1740fe5fc89f66b099341d8410ea9967b 100644
--- a/s/NewReset
+++ b/s/NewReset
@@ -968,7 +968,7 @@ reset_loop
 
 	MOV	R0, #VduCMOS
 	BL	Read
- [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0
+ [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0 :LAND: IOMD_C_PALNTSCType = 0
 ; Force TV if we don't have a MonitorType auto-detect bit
 	TEQ	R0, #(Sync_Separate :OR: MonitorType0)
  |
@@ -1232,7 +1232,7 @@ DefaultCMOSTable ; list of non-zero options wanted :
         =       DBTBCMOS,	        (1:SHL:4)				; Boot
         =       YearCMOS,               97
         =       YearCMOS+1,             19
-  [ IOMD_C_MonitorType = 0
+  [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0 :LAND: IOMD_C_PALNTSCType = 0
 ; TV if we don't have a MonitorType auto-detect bit
 	=	VduCMOS,	        Sync_Separate :OR: MonitorType0
   |
diff --git a/s/PMF/osinit b/s/PMF/osinit
index a93658ad514b35091f690470c6c4a81ef77beea4..8714c95f884f9bffa4c3ae4883a2dec333548c7a 100644
--- a/s/PMF/osinit
+++ b/s/PMF/osinit
@@ -20,7 +20,7 @@ ErrorsInR0 SETL Module                  ; if FALSE, use XOS_GenerateError for
                                         ; if TRUE, return error ptr in R0
 
         GBLL    ProtectStationID        ; if TRUE, disallow OSBYTE &A2,0,n
-ProtectStationID SETL {TRUE}
+ProtectStationID SETL {TRUE}:LAND::LNOT:STB
 
 ; *****************************************************************************