diff --git a/VersionASM b/VersionASM
index 9706e8cbe6e9f05ececbb706fa19f5f25fdc13ad..e7c586b16fcd2bfec13450cfe96a2eacb71567fd 100644
--- a/VersionASM
+++ b/VersionASM
@@ -9,12 +9,12 @@
                         GBLS    Module_ApplicationDate
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
-Module_MajorVersion     SETS    "6.28"
-Module_Version          SETA    628
+Module_MajorVersion     SETS    "6.29"
+Module_Version          SETA    629
 Module_MinorVersion     SETS    ""
 Module_Date             SETS    "24 Nov 2019"
 Module_ApplicationDate  SETS    "24-Nov-19"
 Module_ComponentName    SETS    "Kernel"
-Module_FullVersion      SETS    "6.28"
-Module_HelpVersion      SETS    "6.28 (24 Nov 2019)"
+Module_FullVersion      SETS    "6.29"
+Module_HelpVersion      SETS    "6.29 (24 Nov 2019)"
                         END
diff --git a/VersionNum b/VersionNum
index 401d2c98cbd7842879fb51428c37c81edd84935e..7501eb1b8baa3457c0dbe380c3884e45683d5c06 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,14 +1,14 @@
-/* (6.28)
+/* (6.29)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG        6.28
+#define Module_MajorVersion_CMHG        6.29
 #define Module_MinorVersion_CMHG        
 #define Module_Date_CMHG                24 Nov 2019
 
-#define Module_MajorVersion             "6.28"
-#define Module_Version                  628
+#define Module_MajorVersion             "6.29"
+#define Module_Version                  629
 #define Module_MinorVersion             ""
 #define Module_Date                     "24 Nov 2019"
 
@@ -16,6 +16,6 @@
 
 #define Module_ComponentName            "Kernel"
 
-#define Module_FullVersion              "6.28"
-#define Module_HelpVersion              "6.28 (24 Nov 2019)"
-#define Module_LibraryVersionInfo       "6:28"
+#define Module_FullVersion              "6.29"
+#define Module_HelpVersion              "6.29 (24 Nov 2019)"
+#define Module_LibraryVersionInfo       "6:29"
diff --git a/hdr/OSMem b/hdr/OSMem
index d28c54b463f8f4adbeb59485f1a2049e8f40f1c9..dc976678ded6e1c3f34f44efe95dc6778460becb 100644
--- a/hdr/OSMem
+++ b/hdr/OSMem
@@ -15,6 +15,19 @@
 
 ; Definitions for OS_DynamicArea, OS_Memory and other related SWIs
 
+; System-defined dynamic area numbers
+                     ^ -1
+ChangeDyn_AplSpace   # 1 ; -1, Not recognised by all APIs
+ChangeDyn_SysHeap    # 1 ; 0
+ChangeDyn_RMA        # 1 ; 1
+ChangeDyn_Screen     # 1 ; 2
+ChangeDyn_SpriteArea # 1 ; 3
+ChangeDyn_FontArea   # 1 ; 4
+ChangeDyn_RamFS      # 1 ; 5
+ChangeDyn_FreePool   # 1 ; 6
+ChangeDyn_MaxArea    # 0 ; For internal use by kernel
+ReadDyn_ReturnMax    * 128 ; OS_ReadDynamicArea flag to return max size of area in R2 (for areas 0 to 127 inclusive; other areas always return max size)
+
 ; OS_DynamicArea reason codes
 
 DAReason_Create          *  0
@@ -36,7 +49,9 @@ DAReason_PMP_Resize      * 23
 DAReason_PMP_GetInfo     * 24
 DAReason_PMP_GetPages    * 25
 DAReason_AplSpaceLimit   * 26
-DAReason_Limit           * 27   ;end of defined DA reasons
+DAReason_ReturnFreePages * 27
+DAReason_EnumerateInfo2  * 28
+DAReason_Limit           * 29   ;end of defined DA reasons
 
 ; Dynamic area / page flags
 
diff --git a/s/ChangeDyn b/s/ChangeDyn
index 7f93d6e34558b6d1e322fd3963c5a64af49d261a..c9143e29ded12aea4366bd5b67757724617fd24f 100644
--- a/s/ChangeDyn
+++ b/s/ChangeDyn
@@ -160,15 +160,7 @@ DebuggerSpace        DefAreaFlags Read, PageFlags_Unavailable
 ChangeDyn_Batcall    * -3               ; special DA number to select Batman usage of OS_ChangeDynamicArea
   ]
 ; -2 was an internal value, now no longer used
-ChangeDyn_AplSpace   * -1
-ChangeDyn_SysHeap    * 0
-ChangeDyn_RMA        * 1
-ChangeDyn_Screen     * 2
-ChangeDyn_SpriteArea * 3
-ChangeDyn_FontArea   * 4
-ChangeDyn_RamFS      * 5
-ChangeDyn_FreePool   * 6
-ChangeDyn_MaxArea    * 6
+; -> See hdr.OSMem for other area definitions
 
 ; Number of entries in page block on stack
 
@@ -338,8 +330,7 @@ Call_CAM_Mapping
 
 ReadDynamicArea ROUT
 
-readdyn_returnR2bit     *       &80
-        ASSERT  ChangeDyn_MaxArea < readdyn_returnR2bit
+        ASSERT  ChangeDyn_MaxArea < ReadDyn_ReturnMax
 
         CMP     r0, #ChangeDyn_AplSpace         ; if finding out about app space
       [ ZeroPage = 0
@@ -360,7 +351,7 @@ readdyn_returnR2bit     *       &80
         Push    "r1,lr"
         CMP     r0, #&100                       ; if area >= &100
         MOVCS   r1, r0                          ; then just use area
-        BICCC   r1, r0, #readdyn_returnR2bit    ; else knock off bit 7
+        BICCC   r1, r0, #ReadDyn_ReturnMax      ; else knock off bit 7
   [ DynArea_QuickHandles
         BL      QCheckAreaNumber                ; out: r10 -> node
   |
@@ -703,6 +694,16 @@ DynAreaSub
         B       DynArea_PMP_GetInfo
         B       DynArea_PMP_GetPages
         B       DynArea_AplSpaceLimit
+ [ ShrinkableDAs
+        B       DynArea_ReturnFreePages
+ |
+        B       DynArea_Unknown
+ ]
+ [ DynArea_QuickHandles
+        B       DynArea_EnumerateInfo2
+ |
+        B       DynArea_Unknown
+ ]
 
 ;
 ; unknown OS_DynamicArea reason code
@@ -1675,6 +1676,8 @@ DynArea_GetChangeInfo ROUT
 
   ] ;DynArea_QuickHandles
 
+  [ DynArea_QuickHandles
+
 ;**************************************************************************
 ;
 ;       DynArea_EnumerateInfo
@@ -1686,21 +1689,61 @@ DynArea_GetChangeInfo ROUT
 ;       r1 = -1 to start enumeration, or area number to continue from
 ;
 ; out:  r1 = number of next area found, or -1 if no more areas
-;       r2 = current size of area, if area found
+;       r2 = current size of area (in bytes), if area found
 ;       r3 = base logical address, if area found
 ;       r4 = area flags, if area found
-;       r5 = maximum size of area, if area found
+;       r5 = maximum size of area (in bytes), if area found
 ;       r6 -> title string, if area found
 ;
 ;Notes:
 ; (1) r2-r6 on exit are undefined if r1 = -1
 ;
 
-  [ DynArea_QuickHandles
-
 DynArea_EnumerateInfo ROUT
+        Push    "r2,lr"
+        MOV     r2, #0
+        BL      DynArea_EnumerateInfo2
+        Pull    "r2,pc",VS
+        CMP     r1, #-1
+        Pull    "r2,pc",EQ
+        ; Clamp at safe values
+        CMP     r2, #DynArea_PMP_BigPageCount
+        MOVLO   r2, r2, LSL #12
+        LDRHS   r2, =DynArea_PMP_BigByteCount
+        CMP     r5, #DynArea_PMP_BigPageCount
+        MOVLO   r5, r5, LSL #12
+        LDRHS   r5, =DynArea_PMP_BigByteCount
+        ADD     sp, sp, #4
+        Pull    "pc"
+
+;**************************************************************************
+;
+;       DynArea_EnumerateInfo2
+;
+;       Enumerate *non-system* dynamic areas, returning selected info
+;       Reserved for Acorn use (intended for TaskManager)
+;
+; in:   r0 = reason code (28)
+;       r1 = -1 to start enumeration, or area number to continue from
+;       r2 = flags (reserved)
+;
+; out:  r1 = number of next area found, or -1 if no more areas
+;       r2 = current size of area (in pages), if area found
+;       r3 = base logical address, if area found
+;       r4 = area flags, if area found
+;       r5 = maximum size of area (in pages), if area found
+;       r6 -> title string, if area found
+;
+;Notes:
+; (1) r2-r6 on exit are undefined if r1 = -1
+;
+
+DynArea_EnumerateInfo2 ROUT
         Push    "lr"
 
+        CMP     r2, #0
+        BNE     %FT90
+
         LDR     r11, =ZeroPage
         LDR     r11, [r11, #DynArea_ws]
 
@@ -1729,17 +1772,13 @@ DynArea_EnumerateInfo ROUT
         LDR     r3, [r10, #DANode_Base]
         LDR     r6, [r10, #DANode_Title]
         TST     r4, #DynAreaFlags_PMP
-        LDREQ   r2, [r10, #DANode_Size]
-        LDREQ   r5, [r10, #DANode_MaxSize]
-        BEQ     %FT11
-        LDR     r2, [r10, #DANode_PMPSize]
-        LDR     r5, [r10, #DANode_PMPMaxSize]
-        CMP     r2, #DynArea_PMP_BigPageCount
-        MOVLO   r2, r2, LSL #12
-        LDRHS   r2, =DynArea_PMP_BigByteCount
-        CMP     r5, #DynArea_PMP_BigPageCount
-        MOVLO   r5, r5, LSL #12
-        LDRHS   r5, =DynArea_PMP_BigByteCount
+        LDRNE   r2, [r10, #DANode_PMPSize]
+        LDRNE   r5, [r10, #DANode_PMPMaxSize]
+        BNE     %FT11
+        LDR     r2, [r10, #DANode_Size]
+        LDR     r5, [r10, #DANode_MaxSize]
+        MOV     r2, r2, LSR #12
+        MOV     r5, r5, LSR #12
 11
 
         LDR     r11, =ZeroPage
@@ -1750,15 +1789,18 @@ DynArea_EnumerateInfo ROUT
         CLRV
         Pull    "PC"
 
-;it's a reserved call, so naff off internationalisation
 14
-        ADR     r0,DynArea_badei
+        ADRL    r0, ErrorBlock_BadDynamicArea
+        B       %FT90
+80
+        ADRL    r0, ErrorBlock_BadParameters
+90
+ [ International
+        BL      TranslateError
+ |
         SETV
+ ]
         Pull    "PC"
-DynArea_badei
-        DCD     0
-        DCB     "bad DA number",0
-        ALIGN
 
   ] ;DynArea_QuickHandles
 
@@ -2191,10 +2233,32 @@ DynArea_NaughtyRenum
 ; in:   r0 = reason code (5)
 ;       r1 = area number to exclude, or -1 to include all shrinkable areas
 ;
-; out:  r2 = total amount of free memory
+; out:  r2 = total amount of free memory, bytes
 ;
 
-DynArea_ReturnFree ALTENTRY
+DynArea_ReturnFree
+        Push    "lr"
+        BL      DynArea_ReturnFreePages
+        Pull    "pc",VS
+        ; Clamp at safe value
+        CMP     r2, #DynArea_PMP_BigPageCount
+        MOVLO   r2, r2, LSL #12
+        LDRHS   r2, =DynArea_PMP_BigByteCount
+        Pull    "pc"
+
+;**************************************************************************
+;
+;       DynArea_ReturnFreePages - Return total free space, including shrinkables
+;
+;       Internal routine called by DynamicAreaSWI
+;
+; in:   r0 = reason code (27)
+;       r1 = area number to exclude, or -1 to include all shrinkable areas
+;
+; out:  r2 = total amount of free memory, in pages
+;
+
+DynArea_ReturnFreePages ALTENTRY
         CMP     r1, #-1                         ; if no excluded area,
         MOVEQ   r10, r1                         ; then point r10 nowhere
         BEQ     %FT10
@@ -2243,9 +2307,6 @@ DynArea_ReturnFree ALTENTRY
         B       %BT20                           ; then go back for more
 
 90
-        CMP     r2, #DynArea_PMP_BigPageCount
-        MOVLO   r2, r2, LSL #12
-        LDRHS   r2, =DynArea_PMP_BigByteCount
         EXIT
  ]