diff --git a/Source/DSPSpy/DSPSpy.vcproj b/Source/DSPSpy/DSPSpy.vcproj
index 67c8c803c7..8206a2316d 100644
--- a/Source/DSPSpy/DSPSpy.vcproj
+++ b/Source/DSPSpy/DSPSpy.vcproj
@@ -206,6 +206,18 @@
>
+
+
+
+
+
+
@@ -218,10 +230,6 @@
RelativePath=".\ConsoleHelper.h"
>
-
-
diff --git a/docs/DSP/unlockmemcard.ds b/docs/DSP/unlockmemcard.ds
new file mode 100644
index 0000000000..b0e152dc6a
--- /dev/null
+++ b/docs/DSP/unlockmemcard.ds
@@ -0,0 +1,142 @@
+; This is the ucode used to "unlock" memcards
+; RE purely out of interest, and hunch that it does trickies
+
+IROM_BASE: equ 0x8000
+
+; Exception vectors
+ nop nop
+ nop nop
+ nop nop
+ nop nop
+ nop nop
+ nop nop
+ nop halt
+ rti halt
+
+; Entry point
+; Standard init stuff
+ sbset #0x06
+ sbclr #0x03
+ sbclr #0x04
+ sbset #0x05
+ lri $CR, #0x00ff
+ lri $WR0, #0xffff
+ lri $WR1, #0xffff
+ lri $WR2, #0xffff
+ lri $WR3, #0xffff
+ set40
+
+; 0xdcd10000 is the init mail
+ call wait_for_dsp_mbox
+ si @DMBH, #0xdcd1
+ si @DMBL, #0x0000
+ si @DIRQ, #0x0001
+; Wait for cpu to say "go!" - i think
+wait_for_start_cmd:
+ call wait_for_cpu_mbox
+ lrs $AC1.L, @CMBL
+ cmpi $AC1.M, #0xff00
+ jnz wait_for_start_cmd
+
+dma_dram_and_prepare_for_crazy_irom_func:
+ call wait_for_cpu_mbox
+ mrr $AC0.M, $AC1.M
+ lrs $AC0.L, @CMBL ; main ram addr.l
+ andi $AC0.M, #0x0fff ; main ram addr.h & 0x0fff
+ lri $AX0.L, #0x0400 ; dsp addr
+ lri $AX0.H, #0x0010 ; length (bytes)
+ lri $AX1.L, #0x0000 ; dsp dram to cpu
+ set16
+ call do_dma
+ call IROM_BASE+0x0644; holy mother of jesus that func is gonna be hard
+
+; 0xdcd10003 means finished unlocking?
+ call wait_for_dsp_mbox
+ si @DMBH, #0xdcd1
+ si @DMBL, #0x0003
+ si @DIRQ, #0x0001
+ set40
+ call wait_for_cpu_mbox
+ cmpi $AC1.M, #0xcdd1
+ jnz dma_dram_and_prepare_for_crazy_irom_func
+ lrs $AC1.M, @CMBL
+ cmpi $AC1.M, #0x0001
+ jz _005afunc
+ cmpi $AC1.M, #0x0002
+ jz IROM_BASE ; End of this ucode, wait for a new one
+ jmp dma_dram_and_prepare_for_crazy_irom_func
+ halt ; Prolly never reached
+
+; 10 mails from cpu then irom func - looks interesting
+_005afunc:
+ set16
+ call wait_for_cpu_mbox
+ lrs $AC1.L, @CMBL
+ call wait_for_cpu_mbox
+ lrs $AC1.L, @CMBL
+ call wait_for_cpu_mbox
+ lrs $AC1.L, @CMBL
+ call wait_for_cpu_mbox
+ lr $IX1, @CMBL
+ andi $AC1.M, #0x0fff
+ mrr $IX0, $AC1.M
+ call wait_for_cpu_mbox
+ lr $IX3, @CMBL
+ call wait_for_cpu_mbox
+ lr $IX2, @CMBL
+ call wait_for_cpu_mbox
+ lr $AR0, @CMBL
+ call wait_for_cpu_mbox
+ lrs $AX0.L, @CMBL
+ andi $AC1.M, #0x0fff
+ mrr $AX0.H, $AC1.M
+ call wait_for_cpu_mbox
+ lrs $AX1.L, @CMBL
+ call wait_for_cpu_mbox
+ lrs $AX1.H, @CMBL
+ sbclr #0x05
+ sbclr #0x06
+ jmp IROM_BASE+0x00b5; IROM - can dma stuff
+ halt
+
+wait_for_dsp_mbox:
+ lrs $AC1.M, @DMBH
+ andcf $AC1.M, #0x8000
+ jlz wait_for_dsp_mbox
+ ret
+
+wait_for_cpu_mbox:
+ lrs $AC1.M, @CMBH
+ andcf $AC1.M, #0x8000
+ jlnz wait_for_cpu_mbox
+ ret
+
+do_dma:
+ srs @DSMAH, $AC0.M
+ srs @DSMAL, $AC0.L
+ sr @DSPA, $AX0.L
+ sr @DSCR, $AX1.L
+ sr @DSBL, $AX0.H
+wait_dma:
+ lrs $AC0.M, @DSCR
+ andcf $AC0.M, #0x0004
+ jlz wait_dma
+ ret
+
+; Trailing nops...
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+nop
+
+; uCode is 0xb0 words