(let ((code "SPDSxaxn")
      (D #xaa)
      (S #xcc)
      (P #xf0)
      (stack nil))
  (loop for letter across code
	do (ecase letter
	     (#\D (push D stack))
	     (#\S (push S stack))
	     (#\P (push P stack))
	     (#\n (push (logxor #xff (pop stack)) stack))
	     (#\a (push (logand (pop stack) (pop stack)) stack))
	     (#\o (push (logior (pop stack) (pop stack)) stack))
	     (#\x (push (logxor (pop stack) (pop stack)) stack)))
	do (format t "~(~X~)~%" stack)))

(cc)
(f0 cc)
(aa f0 cc)
(cc aa f0 cc)
(66 f0 cc)
(60 cc)
(ac)
(53)
NIL


(let ((bases nil))
  (dolist (code '(#x000042 #x010289 #x020C89 #x0300AA #x040C88 #x0500A9 #x060865 #x0702C5 #x080F08 #x090245 #x0A0329 #x0B0B2A #x0C0324 #x0D0B25 #x0E08A5 #x0F0001 #x100C85 #x1100A6 #x120868 #x1302C8 #x140869 #x1502C9 #x165CCA #x171D54 #x180D59 #x191CC8 #x1A06C5 #x1B0768 #x1C06CA #x1D0766 #x1E01A5 #x1F0385 #x200F09 #x210248 #x220326 #x230B24 #x240D55 #x251CC5 #x2606C8 #x271868 #x280369 #x2916CA #x2A0CC9 #x2B1D58 #x2C0784 #x2D060A #x2E064A #x2F0E2A #x30032A #x310B28 #x320688 #x330008 #x3406C4 #x351864 #x3601A8 #x370388 #x38078A #x390604 #x3A0644 #x3B0E24 #x3C004A #x3D18A4 #x3E1B24 #x3F00EA #x400F0A #x410249 #x420D5D #x431CC4 #x440328 #x450B29 #x4606C6 #x47076A #x480368 #x4916C5 #x4A0789 #x4B0605 #x4C0CC8 #x4D1954 #x4E0645 #x4F0E25 #x500325 #x510B26 #x5206C9 #x530764 #x5408A9 #x550009 #x5601A9 #x570389 #x580785 #x590609 #x5A0049 #x5B18A9 #x5C0649 #x5D0E29 #x5E1B29 #x5F00E9 #x600365 #x6116C6 #x620786 #x630608 #x640788 #x650606 #x660046 #x6718A8 #x6858A6 #x690145 #x6A01E9 #x6B178A #x6C01E8 #x6D1785 #x6E1E28 #x6F0C65 #x700CC5 #x711D5C #x720648 #x730E28 #x740646 #x750E26 #x761B28 #x7700E6 #x7801E5 #x791786 #x7A1E29 #x7B0C68 #x7C1E24 #x7D0C69 #x7E0955 #x7F03C9 #x8003E9 #x810975 #x820C49 #x831E04 #x840C48 #x851E05 #x8617A6 #x8701C5 #x8800C6 #x891B08 #x8A0E06 #x8B0666 #x8C0E08 #x8D0668 #x8E1D7C #x8F0CE5 #x900C45 #x911E08 #x9217A9 #x9301C4 #x9417AA #x9501C9 #x960169 #x97588A #x981888 #x990066 #x9A0709 #x9B07A8 #x9C0704 #x9D07A6 #x9E16E6 #x9F0345 #xA000C9 #xA11B05 #xA20E09 #xA30669 #xA41885 #xA50065 #xA60706 #xA707A5 #xA803A9 #xA90189 #xAA0029 #xAB0889 #xAC0744 #xAD06E9 #xAE0B06 #xAF0229 #xB00E05 #xB10665 #xB21974 #xB30CE8 #xB4070A #xB507A9 #xB616E9 #xB70348 #xB8074A #xB906E6 #xBA0B09 #xBB0226 #xBC1CE4 #xBD0D7D #xBE0269 #xBF08C9 #xC000CA #xC11B04 #xC21884 #xC3006A #xC40E04 #xC50664 #xC60708 #xC707AA #xC803A8 #xC90184 #xCA0749 #xCB06E4 #xCC0020 #xCD0888 #xCE0B08 #xCF0224 #xD00E0A #xD1066A #xD20705 #xD307A4 #xD41D78 #xD50CE9 #xD616EA #xD70349 #xD80745 #xD906E8 #xDA1CE9 #xDB0D75 #xDC0B04 #xDD0228 #xDE0268 #xDF08C8 #xE003A5 #xE10185 #xE20746 #xE306EA #xE40748 #xE506E5 #xE61CE8 #xE70D79 #xE81D74 #xE95CE6 #xEA02E9 #xEB0849 #xEC02E8 #xED0848 #xEE0086 #xEF0A08 #xF00021 #xF10885 #xF20B05 #xF3022A #xF40B0A #xF50225 #xF60265 #xF708C5 #xF802E5 #xF90845 #xFA0089 #xFB0A09 #xFC008A #xFD0A0A #xFE02A9 #xFF0062))
    (pushnew (logand #x1f code) bases))
  (setf bases (sort bases #'<))
  (format t "~{~5,'0B~%~}" bases))
00000
00001
00010

00100
00101
00110

01000
01001
01010

10100
10101

11000
11001

11100
11101
NIL

(dolist (rop '((#x000042 "0")
	       (#x010289 "DPSoon")
	       (#x020C89 "DPSona")
	       (#x0300AA "PSon")
	       (#x040C88 "SDPona")
	       (#x0500A9 "DPon")
	       (#x060865 "PDSxnon")
	       (#x0702C5 "PDSaon")
	       (#x080F08 "SDPnaa")
	       (#x090245 "PDSxon")
	       (#x0A0329 "DPna")
	       (#x0B0B2A "PSDnaon")
	       (#x0C0324 "SPna")
	       (#x0D0B25 "PDSnaon")
	       (#x0E08A5 "PDSonon")
	       (#x0F0001 "Pn")
	       (#x100C85 "PDSona")
	       (#x1100A6 "DSon")
	       (#x120868 "SDPxnon")
	       (#x1302C8 "SDPaon")
	       (#x140869 "DPSxnon")
	       (#x1502C9 "DPSaon")
	       (#x165CCA "PSDPSanaxx")
	       (#x171D54 "SSPxDSxaxn")
	       (#x180D59 "SPxPDxa")
	       (#x191CC8 "SDPSanaxn")
	       (#x1A06C5 "PDSPaox")
	       (#x1B0768 "SDPSxaxn")
	       (#x1C06CA "PSDPaox")
	       (#x1D0766 "DSPDxaxn")
	       (#x1E01A5 "PDSox")
	       (#x1F0385 "PDSoan")
	       (#x200F09 "DPSnaa")
	       (#x210248 "SDPxon")
	       (#x220326 "DSna")
	       (#x230B24 "SPDnaon")
	       (#x240D55 "SPxDSxa")
	       (#x251CC5 "PDSPanaxn")
	       (#x2606C8 "SDPSaox")
	       (#x271868 "SDPSxnox")
	       (#x280369 "DPSxa")
	       (#x2916CA "PSDPSaoxxn")
	       (#x2A0CC9 "DPSana")
	       (#x2B1D58 "SSPxPDxaxn")
	       (#x2C0784 "SPDSoax")
	       (#x2D060A "PSDnox")
	       (#x2E064A "PSDPxox")
	       (#x2F0E2A "PSDnoan")
	       (#x30032A "PSna")
	       (#x310B28 "SDPnaon")
	       (#x320688 "SDPSoox")
	       (#x330008 "Sn")
	       (#x3406C4 "SPDSaox")
	       (#x351864 "SPDSxnox")
	       (#x3601A8 "SDPox")
	       (#x370388 "SDPoan")
	       (#x38078A "PSDPoax")
	       (#x390604 "SPDnox")
	       (#x3A0644 "SPDSxox")
	       (#x3B0E24 "SPDnoan")
	       (#x3C004A "PSx")
	       (#x3D18A4 "SPDSonox")
	       (#x3E1B24 "SPDSnaox")
	       (#x3F00EA "PSan")
	       (#x400F0A "PSDnaa")
	       (#x410249 "DPSxon")
	       (#x420D5D "SDxPDxa")
	       (#x431CC4 "SPDSanaxn")
	       (#x440328 "SDna")
	       (#x450B29 "DPSnaon")
	       (#x4606C6 "DSPDaox")
	       (#x47076A "PSDPxaxn")
	       (#x480368 "SDPxa")
	       (#x4916C5 "PDSPDaoxxn")
	       (#x4A0789 "DPSDoax")
	       (#x4B0605 "PDSnox")
	       (#x4C0CC8 "SDPana")
	       (#x4D1954 "SSPxDSxoxn")
	       (#x4E0645 "PDSPxox")
	       (#x4F0E25 "PDSnoan")
	       (#x500325 "PDna")
	       (#x510B26 "DSPnaon")
	       (#x5206C9 "DPSDaox")
	       (#x530764 "SPDSxaxn")
	       (#x5408A9 "DPSonon")
	       (#x550009 "Dn")
	       (#x5601A9 "DPSox")
	       (#x570389 "DPSoan")
	       (#x580785 "PDSPoax")
	       (#x590609 "DPSnox")
	       (#x5A0049 "DPx")
	       (#x5B18A9 "DPSDonox")
	       (#x5C0649 "DPSDxox")
	       (#x5D0E29 "DPSnoan")
	       (#x5E1B29 "DPSDnaox")
	       (#x5F00E9 "DPan")
	       (#x600365 "PDSxa")
	       (#x6116C6 "DSPDSaoxxn")
	       (#x620786 "DSPDoax")
	       (#x630608 "SDPnox")
	       (#x640788 "SDPSoax")
	       (#x650606 "DSPnox")
	       (#x660046 "DSx")
	       (#x6718A8 "SDPSonox")
	       (#x6858A6 "DSPDSonoxxn")
	       (#x690145 "PDSxxn")
	       (#x6A01E9 "DPSax")
	       (#x6B178A "PSDPSoaxxn")
	       (#x6C01E8 "SDPax")
	       (#x6D1785 "PDSPDoaxxn")
	       (#x6E1E28 "SDPSnoax")
	       (#x6F0C65 "PDSxnan")
	       (#x700CC5 "PDSana")
	       (#x711D5C "SSDxPDxaxn")
	       (#x720648 "SDPSxox")
	       (#x730E28 "SDPnoan")
	       (#x740646 "DSPDxox")
	       (#x750E26 "DSPnoan")
	       (#x761B28 "SDPSnaox")
	       (#x7700E6 "DSan")
	       (#x7801E5 "PDSax")
	       (#x791786 "DSPDSoaxxn")
	       (#x7A1E29 "DPSDnoax")
	       (#x7B0C68 "SDPxnan")
	       (#x7C1E24 "SPDSnoax")
	       (#x7D0C69 "DPSxnan")
	       (#x7E0955 "SPxDSxo")
	       (#x7F03C9 "DPSaan")
	       (#x8003E9 "DPSaa")
	       (#x810975 "SPxDSxon")
	       (#x820C49 "DPSxna")
	       (#x831E04 "SPDSnoaxn")
	       (#x840C48 "SDPxna")
	       (#x851E05 "PDSPnoaxn")
	       (#x8617A6 "DSPDSoaxx")
	       (#x8701C5 "PDSaxn")
	       (#x8800C6 "DSa")
	       (#x891B08 "SDPSnaoxn")
	       (#x8A0E06 "DSPnoa")
	       (#x8B0666 "DSPDxoxn")
	       (#x8C0E08 "SDPnoa")
	       (#x8D0668 "SDPSxoxn")
	       (#x8E1D7C "SSDxPDxax")
	       (#x8F0CE5 "PDSanan")
	       (#x900C45 "PDSxna")
	       (#x911E08 "SDPSnoaxn")
	       (#x9217A9 "DPSDPoaxx")
	       (#x9301C4 "SPDaxn")
	       (#x9417AA "PSDPSoaxx")
	       (#x9501C9 "DPSaxn")
	       (#x960169 "DPSxx")
	       (#x97588A "PSDPSonoxx")
	       (#x981888 "SDPSonoxn")
	       (#x990066 "DSxn")
	       (#x9A0709 "DPSnax")
	       (#x9B07A8 "SDPSoaxn")
	       (#x9C0704 "SPDnax")
	       (#x9D07A6 "DSPDoaxn")
	       (#x9E16E6 "DSPDSaoxx")
	       (#x9F0345 "PDSxan")
	       (#xA000C9 "DPa")
	       (#xA11B05 "PDSPnaoxn")
	       (#xA20E09 "DPSnoa")
	       (#xA30669 "DPSDxoxn")
	       (#xA41885 "PDSPonoxn")
	       (#xA50065 "PDxn")
	       (#xA60706 "DSPnax")
	       (#xA707A5 "PDSPoaxn")
	       (#xA803A9 "DPSoa")
	       (#xA90189 "DPSoxn")
	       (#xAA0029 "D")
	       (#xAB0889 "DPSono")
	       (#xAC0744 "SPDSxax")
	       (#xAD06E9 "DPSDaoxn")
	       (#xAE0B06 "DSPnao")
	       (#xAF0229 "DPno")
	       (#xB00E05 "PDSnoa")
	       (#xB10665 "PDSPxoxn")
	       (#xB21974 "SSPxDSxox")
	       (#xB30CE8 "SDPanan")
	       (#xB4070A "PSDnax")
	       (#xB507A9 "DPSDoaxn")
	       (#xB616E9 "DPSDPaoxx")
	       (#xB70348 "SDPxan")
	       (#xB8074A "PSDPxax")
	       (#xB906E6 "DSPDaoxn")
	       (#xBA0B09 "DPSnao")
	       (#xBB0226 "DSno")
	       (#xBC1CE4 "SPDSanax")
	       (#xBD0D7D "SDxPDxan")
	       (#xBE0269 "DPSxo")
	       (#xBF08C9 "DPSano")
	       (#xC000CA "PSa")
	       (#xC11B04 "SPDSnaoxn")
	       (#xC21884 "SPDSonoxn")
	       (#xC3006A "PSxn")
	       (#xC40E04 "SPDnoa")
	       (#xC50664 "SPDSxoxn")
	       (#xC60708 "SDPnax")
	       (#xC707AA "PSDPoaxn")
	       (#xC803A8 "SDPoa")
	       (#xC90184 "SPDoxn")
	       (#xCA0749 "DPSDxax")
	       (#xCB06E4 "SPDSaoxn")
	       (#xCC0020 "S")
	       (#xCD0888 "SDPono")
	       (#xCE0B08 "SDPnao")
	       (#xCF0224 "SPno")
	       (#xD00E0A "PSDnoa")
	       (#xD1066A "PSDPxoxn")
	       (#xD20705 "PDSnax")
	       (#xD307A4 "SPDSoaxn")
	       (#xD41D78 "SSPxPDxax")
	       (#xD50CE9 "DPSanan")
	       (#xD616EA "PSDPSaoxx")
	       (#xD70349 "DPSxan")
	       (#xD80745 "PDSPxax")
	       (#xD906E8 "SDPSaoxn")
	       (#xDA1CE9 "DPSDanax")
	       (#xDB0D75 "SPxDSxan")
	       (#xDC0B04 "SPDnao")
	       (#xDD0228 "SDno")
	       (#xDE0268 "SDPxo")
	       (#xDF08C8 "SDPano")
	       (#xE003A5 "PDSoa")
	       (#xE10185 "PDSoxn")
	       (#xE20746 "DSPDxax")
	       (#xE306EA "PSDPaoxn")
	       (#xE40748 "SDPSxax")
	       (#xE506E5 "PDSPaoxn")
	       (#xE61CE8 "SDPSanax")
	       (#xE70D79 "SPxPDxan")
	       (#xE81D74 "SSPxDSxax")
	       (#xE95CE6 "DSPDSanaxxn")
	       (#xEA02E9 "DPSao")
	       (#xEB0849 "DPSxno")
	       (#xEC02E8 "SDPao")
	       (#xED0848 "SDPxno")
	       (#xEE0086 "DSo")
	       (#xEF0A08 "SDPnoo")
	       (#xF00021 "P")
	       (#xF10885 "PDSono")
	       (#xF20B05 "PDSnao")
	       (#xF3022A "PSno")
	       (#xF40B0A "PSDnao")
	       (#xF50225 "PDno")
	       (#xF60265 "PDSxo")
	       (#xF708C5 "PDSano")
	       (#xF802E5 "PDSao")
	       (#xF90845 "PDSxno")
	       (#xFA0089 "DPo")
	       (#xFB0A09 "DPSnoo")
	       (#xFC008A "PSo")
	       (#xFD0A0A "PSDnoo")
	       (#xFE02A9 "DPSoo")
	       (#xFF0062 "1")))
  #+nil
  (let ((code (cadr rop))
	(D #xaa)
	(S #xcc)
	(P #xf0)
	(stack nil))
    (loop for letter across code
	  do (ecase letter
	       (#\D (push D stack))
	       (#\S (push S stack))
	       (#\P (push P stack))
	       (#\n (push (logxor #xff (pop stack)) stack))
	       (#\a (push (logand (pop stack) (pop stack)) stack))
	       (#\o (push (logior (pop stack) (pop stack)) stack))
	       (#\x (push (logxor (pop stack) (pop stack)) stack))
	       (#\0 (push 0 stack))
	       (#\1 (push #xff stack))))
    (when (/= (car stack) (ldb (byte 8 16) (car rop)))
      (format t "ROP ~X computed ~X.~%" rop (car stack))))

  #+nil
  (let ((string-ops (let ((code (cadr rop)))
		      (coerce (loop for letter across code
				    when (lower-case-p letter)
				    collect letter) 'string)))
	
	(decoded-ops (let ((rop-code (car rop))
			   (ops nil))
		       (dotimes (i 5)
			 (push (elt '(#\n #\x #\o #\a)
				    (ldb (byte 2 (+ 6 i i)) rop-code)) ops))
		       (when (logbitp 5 rop-code)
			 (push #\n ops))
		       (loop while (and (eql (car ops) #\n)
					(eql (cadr ops) #\n))
			     do (setf ops (cddr ops)))
		       (coerce (reverse ops) 'string))))
    (when (not (string= string-ops decoded-ops))
      (format t "ROP ~X, string ~A decoded ~A~%" rop string-ops decoded-ops)))

  #+nil
  (when (logbitp 4 (car rop))
    (format t "~5,'0B ~X~%" (ldb (byte 5 0) (car rop)) rop))

  #+nil
  (format t "~5,'0B ~X~%" (ldb (byte 5 0) (car rop)) (coerce (loop for letter across (cadr rop) when (upper-case-p letter) collect letter) 'string))

  (when (not (logbitp 4 (car rop)))
    (let ((decoded-rop (let ((rop-code (car rop))
	  (ops nil))
      (dotimes (i 5)
	(push (elt '(#\n #\x #\o #\a)
		   (ldb (byte 2 (+ 6 i i)) rop-code)) ops))
      (when (logbitp 5 rop-code)
	(push #\n ops))
      (loop while (and (eql (car ops) #\n)
		       (eql (cadr ops) #\n))
	    do (setf ops (cddr ops)))

      (let* ((length (1+ (count-if-not (lambda (c) (char= c #\n)) ops)))
	     (shift (ldb (byte 2 0) rop-code))
	     (seq-id (ldb (byte 2 2) rop-code))
	     (seq (ecase seq-id
		    (0 (ecase shift
			 (0 "SSSSSS")
			 (1 "PPPPPP")
			 (2 "DDDDDD")))
		    (1 "SPDSPDSP")
		    (2 "SDPSDPSD"))))
	(concatenate 'string (subseq seq shift (+ shift length)) (reverse ops))))))
      (unless (string= decoded-rop (cadr rop))
	(format t "ROP ~X decoded ~X~%" rop decoded-rop))))

  (when (logbitp 4 (car rop))
    (let ((decoded-rop (let ((rop-code (car rop))
	  (ops nil))
      (dotimes (i 5)
	(push (elt '(#\n #\x #\o #\a)
		   (ldb (byte 2 (+ 6 i i)) rop-code)) ops))
      (when (logbitp 5 rop-code)
	(push #\n ops))
      (loop while (and (eql (car ops) #\n)
		       (eql (cadr ops) #\n))
	    do (setf ops (cddr ops)))

      (let* ((length (1+ (count-if-not (lambda (c) (char= c #\n)) ops)))
	     (shift (ldb (byte 2 0) rop-code))
	     (seq-id (ldb (byte 2 2) rop-code))
	     (seq (ecase seq-id
		    (1 "SSP")
		    (2 "SSP")
		    (3 "SSD"))))
	(concatenate 'string (subseq seq shift (+ shift length))
		     (last ops)
		     (if (logbitp 3 rop-code) "PD" "DS")
		     (reverse (butlast ops)))))))
      (unless (string= decoded-rop (cadr rop))
	(format t "ROP ~X decoded ~X~%" rop decoded-rop)))))
ROP (42 0) decoded DDx
ROP (FF0062 1) decoded DDxn
NIL

So that's basically it. The only other thing is to come up with a model
for running it on a register architecture instead of a stack architecture.

Oh, and possibly to rip into 16-bit gdi.exe to confirm. Maybe later.



00000 S
00001 P
00010 

For the base case, (logbitp 4 rop) => NIL, we have 0ppss where pp is a pattern type (???, SPD, DPS, ???), and ss is a shift count (shifting left).

00100 SP
00100 SPD
00100 SPDS

00101 PD
00101 PDS
00101 PDSP
00101 PDSPD

00110 DS
00110 DSP
00110 DSPD
00110 DSPDS

01000 S
01000 SD
01000 SDP
01000 SDPS

01001 D
01001 DP
01001 DPS
01001 DPSD
01001 DPSDP

01010 PS
01010 PSD
01010 PSDP
01010 PSDPS

10100 SSPDS
10101 SPDS
11000 SSPPD
11001 SPPD
11100 SSDPD
11101 SDPD
NIL


ROPs where (logbitp 4 rop):
10100 (171D54 SSPxDSxaxn)
10100 (4D1954 SSPxDSxoxn)
10100 (B21974 SSPxDSxox)
10100 (E81D74 SSPxDSxax)
10101 (240D55 SPxDSxa)
10101 (7E0955 SPxDSxo)
10101 (810975 SPxDSxon)
10101 (DB0D75 SPxDSxan)

11000 (2B1D58 SSPxPDxaxn)
11000 (D41D78 SSPxPDxax)
11001 (180D59 SPxPDxa)
11001 (E70D79 SPxPDxan)

11100 (711D5C SSDxPDxaxn)
11100 (8E1D7C SSDxPDxax)
11101 (420D5D SDxPDxa)
11101 (BD0D7D SDxPDxan)
NIL



(let ((code "SSPxDSxox"))
  (coerce (loop for letter across code
		when (lower-case-p letter)
		collect letter) 'string))

(let ((rop-code #x1974)
      (ops nil))
  (dotimes (i 5)
    (push (elt '(#\n #\x #\o #\a)
	       (ldb (byte 2 (+ 6 i i)) rop-code)) ops))
  (when (logbitp 5 rop-code)
    (push #\n ops))
  (loop while (and (eql (car ops) #\n)
		   (eql (cadr ops) #\n))
	do (setf ops (cddr ops)))
  (coerce (reverse ops) 'string))

