; bug: in the emulator (with _LoadOps, when inst1=1, if Adjust, then there is
; no update of dtIncEip)

H.: high part, higher half-part
L.: low part, lower half-part
B: byte
W: word
D: dword

  Cpu Emulator:
  > initial eip is (buffer+400h)
    first 400h bytes are data
    dword ptr [buffer+0] is the current eip
    dword ptr [buffer+4] is the stack pointer (>48h, <400h), stack is 0eeh dwords
    [buffer+8] to [buffer+40h] is the 'registers' data (there are 14 registers)
    reg_1 to reg_14
    mem_XXXX is mem at buffer[XXXX], that is mem at (XXXX-0400h) in data.cod
    video buffer is (buffer+010000h)
    it is dwords (one for each pixel), 0113h columns and 05ah rows
  > HB[eip] (4 most significant bits at eip) is the instruction set
    LB[eip] (4 less significant bits at eip) is the opcode to use in the instruction set

  Instruction Sets:
________________________________________________________________________
   Instructions on 'register'
    Address of Op1 is LB[eip+1] (Op1 is dword at buffer[4*LB[eip+1]])
    Address of Op2 is HB[eip+1]
    (put result in Op1)
  >  0: OpCode0
    opcodes :
	 0: Add Op1,Op2
	 1: Sub Op1,Op2
	 2: Imul Op1,Op2
	 3: Idiv Op1,Op2
	 4: Iquo Op1,Op2
	 5: And Op1,Op2
	 6: Or Op1,Op2
	 7: Xor Op1,Op2
	 8: IsNull Op1,Op2 ([Op1]=1 if Op2=0, [Op1]=0 if Op2!=0)
	 9: Neg Op1
	10: Inc Op1
	11: Dec Op1
  >  1: OpCode1
    opcodes :
	 0: Rol Op1, byte@Op2
	 1: Ror Op1, byte@Op2
	 2: Shl Op1, byte@Op2
	 3: Shr Op1, byte@Op2
  >  2: OpCode2
    opcodes :
	 0: Mov
  >  3: OpCode3
    here Op1 and Op2 are inversed (so we just have to keep them the same way, and replace jl by jg)
    Op3 can be negged to jump backwards, if msb of LB[eip] is set
    if opcode is 0, Op3 is W[eip+1]
    else, Op3 is W[eip+2]
    opcodes :
	 0: Jmp (Jmp $+Op3)
	 1: CJnz (Cmp Op1,Op2 Jnz $+Op3)
	 2: CJz (Cmp Op1,Op2 Jz $+Op3)
	 3: CJg (Cmp Op1,Op2 Jg $+Op3)
	 4: CJl (Cmp Op1,Op2 Jl $+Op3)
	 5: J1nz (Cmp Op1,0 Jnz $+Op3)
	 6: J1z (Cmp Op1,0 Jz $+Op3)
  >  4: OpCode4
	 0: push (Op2)
	 1: pop (*Op1)

   Instructions on 'memory'
    sets 8,9,10,11,12
    corresponds to set 0,1,2,3,4, but first it loads Op1 and Op2 in a different way :
    load Op2:
 HB[eip+1]:
	 0: load dword buffer[HB(eip+2)*4] in Op2 (ADJUST)
	 1: load dword buffer[W(eip+2) + (OP2S<<16)] in Op2
	 2: load (LB(eip+1) + 1) bytes at (eip+2) in Op2
	 3: load dword buffer[d@buffer[HB(eip+2)*4] + (OP2S<<16)] in Op2 (ADJUST)

    load Op1:
HLB[eip+1]:
	 0: pOp1 <- offset buffer[LB(eip+2+Var1ADJUSTED)*4]
	 1: pOp1 <- offset buffer[W(eip+Var1+2) + (OP1S<<16)]
	 3: pOp1 <- offset buffer[d@buffer[LB(eip+2+Var1ADJUSTED)*4] + (OP1S<<16)]

    if Op2 has been loaded with (ADJUST), then Var1ADJUSTED=0
    else, Var1 points to the next bytes to get
    for the jumps, if opcode is 0, then Op3 is W[eip+1]
    else, Op3 follows the loading bytes


   Special Instructions
  >  5: SetMemory
    for use in instructions on memory
    HighMem dword is OP1S|OP2S
	 0: OP2S=DATA
	 1: OP2S=VIDEO
	 2: OP2S=HIGHMEM (10b)
	 3: OP1S=DATA
	 4: OP1S=VIDEO
	 5: OP1S=HIGHMEM (10b)
  >  6: OpCode6
	 0: callpush (store the 'registers' and next eip), jmp (change eip to (W[eip+1]+3-0400h)) 0400h: code base
	 1: retpop (restore the 'registers' and eip)
	 2: get:
		LoadOps
		Choose a dword with Op2:
			060h: MemDword
			061h: dtCharTyped	; char that has been typed (from WM_CHAR)
			062h: dtMouseX		; x position of the mouse
			063h: dtMouseY		; y position of the mouse (msb of dword is set if button is down)
			064h: dtRepaintControls	; should we update controls ?
			065h: dtInstructionsCounter
		Put the content of the dword in Op1
	 3: set:
		LoadOps
		Choose a dword with Op2:
			060h: MemDword
			061h: dtCharTyped	; char that has been typed (from WM_CHAR)
			062h: dtMouseX		; x position of the mouse
			063h: dtMouseY		; y position of the mouse (msb of dword is set if button is down)
			064h: dtRepaintControls	; should we update controls ?f
			065h: dtInstructionsCounter
		Put the content of Op1 in the dword
  > 15: Flow
	14: Wait Next Window Message
	15: Halt Emulator

