code wiki / (root) / nx_pe_dll_d3d11.nx

nx_pe_dll_d3d11.nx source

↩ module page · 229 lines · 13847 B

1// nx_pe_dll_d3d11.nx -- the REAL game entry point. Superset of nx_pe_dll_id3d11: same data-driven 43-slot ID3D11Device 2// vtable (compiled IUnknown+GetFeatureLevel bodies) PLUS the actual export D3D11CreateDeviceAndSwapChain (the literal 3// first function a game calls). That export is MS-x64 glue that reads the out-params from the STACK (args 8-11 at 4// [rsp+0x48..0x60] -- proving stack-arg access) and returns a STATIC device (real D3D allocates internally; a singleton 5// static device in a new RW .data section is the honest minimal form). Verified against Microsoft's own 6// PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN typedef so the arg->stack mapping comes from <d3d11.h>, not us. 7// Method bodies = sovereign nx_cc NishiLang; vtable+glue = sovereign emitter (NO C++). ⚠static vtable/device baked @ fixed 8// base 0x180000000 (.reloc TODO). Input /tmp/nishi_export_lib.s Output knowledge/nishi_d3d11.dll license_tier: ORIGINAL expect_exit: 0 9import "nx_syscalls.nx" 10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 11import "nxasm_x86.nx" 12import "nx_pe_writer.nx" 13 14const N_SLOTS: i64 = 43 15 16func d11_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 18// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 19// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 20// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 21func d11_putn(v: i64) -> i64 { nxi_out(v); return 0 } 22func d11_wstr(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ buf[off+i]=s[i]; i=i+1 } buf[off+i]=0 as u8; return i+1 } 23 24func d11_assemble(src: *u8, n: i64, out: *u8, out_cap: i64, names: *i64, offs: *i64, cnt: i64) -> i64 { 25 let lab_off: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 26 let lab_len: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 27 let lab_addr: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 28 let lab_sec: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 29 let op0: *i64 = sys_mmap(72) as *i64 // 9 slots for SIB (matches nxasm_x86) 30 let op1: *i64 = sys_mmap(72) as *i64 31 let op2: *i64 = sys_mmap(72) as *i64 // API DRIFT FIX: axc_pass gained op2 32 let scratch: *u8 = sys_mmap(64) 33 let posbox: *i64 = sys_mmap(16) as *i64 34 let n_lab_box: *i64 = sys_mmap(16) as *i64 35 n_lab_box[0] = 0 36 let lh: *i64 = sys_mmap(ASM_LH_SIZE * 8) as *i64 37 let text_size: i64 = axc_pass(src, n, out, 0, 0, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox) 38 if text_size < 0 { return text_size } 39 let n_lab: i64 = n_lab_box[0] 40 var k: i64 = 0 41 while k < n_lab { 42 if lab_sec[k] == 1 { lab_addr[k] = lab_addr[k] + text_size } 43 var m: i64 = 0 44 while m < cnt { if axc_tok_is(src, lab_off[k], lab_len[k], names[m] as *u8) == 1 { offs[m] = lab_addr[k] } m = m + 1 } 45 k = k + 1 46 } 47 axc_lh_build(src, lab_off, lab_len, n_lab, lh) 48 let total: i64 = axc_pass(src, n, out, text_size, 1, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox) 49 if total < 0 { return total } 50 if total > out_cap { return 0 - 200 } 51 return total 52} 53 54func d11_thunk(buf: *u8, tco: i64, moff: i64) -> i64 { 55 let t: i64 = 0x200 + tco 56 _w8(buf,t+0,0x57); _w8(buf,t+1,0x56) 57 _w8(buf,t+2,0x48); _w8(buf,t+3,0x89); _w8(buf,t+4,0xCF) 58 _w8(buf,t+5,0x48); _w8(buf,t+6,0x89); _w8(buf,t+7,0xD6) 59 _w8(buf,t+8,0x4C); _w8(buf,t+9,0x89); _w8(buf,t+10,0xC2) 60 _w8(buf,t+11,0x4C); _w8(buf,t+12,0x89); _w8(buf,t+13,0xC9) 61 _w8(buf,t+14,0x48); _w8(buf,t+15,0x83); _w8(buf,t+16,0xEC); _w8(buf,t+17,0x08) 62 _w8(buf,t+18,0xE8); _w32(buf, t+19, moff - (tco + 23)) 63 _w8(buf,t+23,0x48); _w8(buf,t+24,0x83); _w8(buf,t+25,0xC4); _w8(buf,t+26,0x08) 64 _w8(buf,t+27,0x5E); _w8(buf,t+28,0x5F); _w8(buf,t+29,0xC3) 65 return 0 66} 67 68func d11_slot_method(slot: i64) -> i64 { 69 if slot == 0 { return 0 } 70 if slot == 1 { return 1 } 71 if slot == 2 { return 2 } 72 if slot == 37 { return 3 } 73 return 4 74} 75 76func d11_emit(buf: *u8, code: *u8, code_len: i64, offs: *i64) -> i64 { 77 if (buf as i64) == 0 { return 0 - NX_PE_BAD_INPUT } 78 let FF: i64 = code_len + 150 // factory create_device (22B) 79 let CG: i64 = FF + 22 // D3D11CreateDeviceAndSwapChain glue (73B) 80 let VT: i64 = ((CG + 73 + 7) / 8) * 8 // 43-slot vtable (8-aligned) 81 let text_used: i64 = VT + N_SLOTS * 8 82 let text_pages: i64 = (text_used + 4095) / 4096 83 let text_raw: i64 = text_pages * 4096 84 let data_rva: i64 = 0x1000 + text_raw // .data (static device) -- contiguous after .text 85 let data_file: i64 = 0x200 + text_raw 86 let edata_rva: i64 = data_rva + 0x1000 87 let edata_file: i64 = data_file + 0x200 88 let size_of_image: i64 = edata_rva + 0x1000 89 let file_size: i64 = edata_file + 0x200 90 let vt_rva: i64 = 0x1000 + VT 91 92 // headers (3 sections) 93 _w16(buf, 0, 0x5A4D); _w32(buf, 0x3C, 0x80); _w32(buf, 0x80, 0x00004550) 94 _w16(buf, 0x84 + 0, PE_MACHINE_AMD64); _w16(buf, 0x84 + 2, 3); _w16(buf, 0x84 + 16, 0xF0); _w16(buf, 0x84 + 18, 0x2022) 95 let O: i64 = 0x98 96 _w16(buf, O + 0, PE_OH_MAGIC_PEPLUS); _w8(buf, O + 2, 1) 97 _w32(buf, O + 4, text_raw); _w32(buf, O + 8, 0x400) 98 _w32(buf, O + 16, 0); _w32(buf, O + 20, 0x1000) 99 _w64(buf, O + 24, 0x80000000, 0x1) 100 _w32(buf, O + 32, 0x1000); _w32(buf, O + 36, 0x200) 101 _w16(buf, O + 40, 6); _w16(buf, O + 48, 6) 102 _w32(buf, O + 56, size_of_image); _w32(buf, O + 60, 0x200) 103 _w16(buf, O + 68, PE_SUBSYSTEM_CONSOLE) 104 _w64(buf, O + 72, 0x100000, 0); _w64(buf, O + 80, 0x1000, 0); _w64(buf, O + 88, 0x100000, 0); _w64(buf, O + 96, 0x1000, 0) 105 _w32(buf, O + 108, 16) 106 _w32(buf, O + 112 + 0, edata_rva); _w32(buf, O + 112 + 4, 0x7E) // DataDir[0] Export 107 108 _emit_section_header(buf, FOFF_SECT_TBL, 46,116,101,120,116,0,0,0, text_used, 0x1000, text_raw, 0x200, PE_SECT_CODE_X_R) // .text 109 _emit_section_header(buf, FOFF_SECT_TBL + 40, 46,100,97,116,97,0,0,0, 16, data_rva, 0x200, data_file, PE_SECT_DATA_RW) // .data 110 _emit_section_header(buf, FOFF_SECT_TBL + 80, 46,101,100,97,116,97,0,0, 0x7E, edata_rva, 0x200, edata_file, PE_SECT_DATA_R) // .edata 111 112 var i: i64 = 0 113 while i < code_len { buf[0x200 + i] = code[i]; i = i + 1 } 114 115 // 5 uniform thunks 116 var j: i64 = 0 117 while j < 5 { d11_thunk(buf, code_len + j*30, offs[j]); j = j + 1 } 118 119 // factory create_device @ FF (builds device in caller mem; 22B): mov rax,rcx; lea rdx,[rip+dV]; mov[rcx],rdx; mov qword[rcx+8],1; ret 120 let f: i64 = 0x200 + FF 121 _w8(buf,f+0,0x48); _w8(buf,f+1,0x89); _w8(buf,f+2,0xC8) 122 _w8(buf,f+3,0x48); _w8(buf,f+4,0x8D); _w8(buf,f+5,0x15); _w32(buf, f+6, VT - (FF + 10)) 123 _w8(buf,f+10,0x48); _w8(buf,f+11,0x89); _w8(buf,f+12,0x11) 124 _w8(buf,f+13,0x48); _w8(buf,f+14,0xC7); _w8(buf,f+15,0x41); _w8(buf,f+16,0x08); _w32(buf, f+17, 1) 125 _w8(buf,f+21,0xC3) 126 127 // D3D11CreateDeviceAndSwapChain glue @ CG (MS-ABI, reads out-params from stack; 73B). ppSwapChain=[rsp+0x48] 128 // ppDevice=[rsp+0x50] pFeatureLevel=[rsp+0x58] ppImmediateContext=[rsp+0x60]. static device @ .data (data_rva). 129 let g: i64 = 0x200 + CG 130 // *ppDevice = &static_device 131 _w8(buf,g+0,0x48); _w8(buf,g+1,0x8B); _w8(buf,g+2,0x44); _w8(buf,g+3,0x24); _w8(buf,g+4,0x50) // mov rax,[rsp+0x50] 132 _w8(buf,g+5,0x48); _w8(buf,g+6,0x85); _w8(buf,g+7,0xC0) // test rax,rax 133 _w8(buf,g+8,0x74); _w8(buf,g+9,0x0A) // je +10 (after_dev) 134 _w8(buf,g+10,0x48); _w8(buf,g+11,0x8D); _w8(buf,g+12,0x15); _w32(buf, g+13, data_rva - (vt_rva - VT + CG + 17)) // lea rdx,[rip+dD] 135 _w8(buf,g+17,0x48); _w8(buf,g+18,0x89); _w8(buf,g+19,0x10) // mov [rax],rdx 136 // *pFeatureLevel = 0xb000 137 _w8(buf,g+20,0x48); _w8(buf,g+21,0x8B); _w8(buf,g+22,0x44); _w8(buf,g+23,0x24); _w8(buf,g+24,0x58) // mov rax,[rsp+0x58] 138 _w8(buf,g+25,0x48); _w8(buf,g+26,0x85); _w8(buf,g+27,0xC0) // test rax,rax 139 _w8(buf,g+28,0x74); _w8(buf,g+29,0x06) // je +6 (after_fl) 140 _w8(buf,g+30,0xC7); _w8(buf,g+31,0x00); _w32(buf, g+32, 0xB000) // mov dword[rax],0xb000 141 // *ppSwapChain = 0 142 _w8(buf,g+36,0x48); _w8(buf,g+37,0x8B); _w8(buf,g+38,0x44); _w8(buf,g+39,0x24); _w8(buf,g+40,0x48) // mov rax,[rsp+0x48] 143 _w8(buf,g+41,0x48); _w8(buf,g+42,0x85); _w8(buf,g+43,0xC0) // test rax,rax 144 _w8(buf,g+44,0x74); _w8(buf,g+45,0x07) // je +7 (after_sc) 145 _w8(buf,g+46,0x48); _w8(buf,g+47,0xC7); _w8(buf,g+48,0x00); _w32(buf, g+49, 0) // mov qword[rax],0 146 // *ppImmediateContext = 0 147 _w8(buf,g+53,0x48); _w8(buf,g+54,0x8B); _w8(buf,g+55,0x44); _w8(buf,g+56,0x24); _w8(buf,g+57,0x60) // mov rax,[rsp+0x60] 148 _w8(buf,g+58,0x48); _w8(buf,g+59,0x85); _w8(buf,g+60,0xC0) // test rax,rax 149 _w8(buf,g+61,0x74); _w8(buf,g+62,0x07) // je +7 (after_ctx) 150 _w8(buf,g+63,0x48); _w8(buf,g+64,0xC7); _w8(buf,g+65,0x00); _w32(buf, g+66, 0) // mov qword[rax],0 151 _w8(buf,g+70,0x31); _w8(buf,g+71,0xC0) // xor eax,eax (S_OK) 152 _w8(buf,g+72,0xC3) // ret 153 154 // static vtable @ VT (43 baked-absolute thunk pointers) 155 var s: i64 = 0 156 while s < N_SLOTS { 157 let mj: i64 = d11_slot_method(s) 158 _w64(buf, 0x200 + VT + s*8, 0x80000000 + 0x1000 + code_len + mj*30, 1) 159 s = s + 1 160 } 161 162 // static device @ .data (data_file): device[0]=&vtable (abs), device[1]=refcount 1 163 _w64(buf, data_file + 0, 0x80000000 + vt_rva, 1) 164 _w64(buf, data_file + 8, 1, 0) 165 166 // .edata: 2 exports SORTED ("D3D11CreateDeviceAndSwapChain" < "nishi_d3d_create_device") 167 let E: i64 = edata_file 168 _w32(buf, E + 12, edata_rva + 0x72) // Name -> dllname 169 _w32(buf, E + 16, 1); _w32(buf, E + 20, 2); _w32(buf, E + 24, 2) 170 _w32(buf, E + 28, edata_rva + 0x28); _w32(buf, E + 32, edata_rva + 0x30); _w32(buf, E + 36, edata_rva + 0x38) 171 _w32(buf, E + 0x28, 0x1000 + FF) // func[0] = create_device factory 172 _w32(buf, E + 0x2C, 0x1000 + CG) // func[1] = D3D11CreateDeviceAndSwapChain glue 173 _w32(buf, E + 0x30, edata_rva + 0x3C) // name[0] = "D3D11Create..." 174 _w32(buf, E + 0x34, edata_rva + 0x5A) // name[1] = "nishi_d3d_create_device" 175 _w16(buf, E + 0x38, 1) // "D3D11Create..." -> func[1] 176 _w16(buf, E + 0x3A, 0) // "nishi_d3d..." -> func[0] 177 d11_wstr(buf, E + 0x3C, "D3D11CreateDeviceAndSwapChain\x00" as *u8) 178 d11_wstr(buf, E + 0x5A, "nishi_d3d_create_device\x00" as *u8) 179 d11_wstr(buf, E + 0x72, "nishicc.dll\x00" as *u8) 180 return file_size 181} 182 183func main() -> i64 { 184 d11_puts("=== nx_pe_dll_d3d11 -- real D3D11CreateDeviceAndSwapChain export + conformant ID3D11Device ===\n" as *u8) 185 let lenbox: *i64 = sys_mmap(16) as *i64 186 let src: *u8 = sys_read_file("/tmp/nishi_export_lib.s" as *u8, lenbox) 187 if (src as i64) == 0 { d11_puts("FAIL no /tmp/nishi_export_lib.s\n" as *u8); sys_exit(1); return 1 } 188 let n: i64 = lenbox[0] 189 if n <= 0 { d11_puts("FAIL empty .s\n" as *u8); sys_exit(2); return 2 } 190 191 let names: *i64 = sys_mmap(8*5) as *i64 192 names[0] = "nx_dev_qi" as *u8 as i64 193 names[1] = "nx_dev_addref" as *u8 as i64 194 names[2] = "nx_dev_release" as *u8 as i64 195 names[3] = "nx_dev_getfl" as *u8 as i64 196 names[4] = "nx_dev_notimpl" as *u8 as i64 197 let offs: *i64 = sys_mmap(8*5) as *i64 198 var z: i64 = 0 199 while z < 5 { offs[z] = 0 - 1; z = z + 1 } 200 201 let code: *u8 = sys_mmap(1048576) 202 let code_len: i64 = d11_assemble(src, n, code, 1048576, names, offs, 5) 203 if code_len < 0 { d11_puts("FAIL assemble rc="); d11_putn(code_len); d11_puts("\n" as *u8); sys_exit(3); return 3 } 204 var miss: i64 = 0 205 var q: i64 = 0 206 while q < 5 { if offs[q] < 0 { miss = miss + 1 } q = q + 1 } 207 if miss > 0 { d11_puts("FAIL method(s) not found\n" as *u8); sys_exit(4); return 4 } 208 d11_puts(" code_len="); d11_putn(code_len); d11_puts(" factory@"); d11_putn(code_len+150); d11_puts(" create-glue@"); d11_putn(code_len+172); d11_puts("\n" as *u8) 209 210 let buf: *u8 = sys_mmap(0x20000) 211 let fsz: i64 = d11_emit(buf, code, code_len, offs) 212 if fsz < 0 { d11_puts("FAIL emit rc="); d11_putn(fsz); d11_puts("\n" as *u8); sys_exit(5); return 5 } 213 214 let fd: i64 = sys_openat_wr("knowledge/nishi_d3d11.dll\x00" as *u8, 0x1a4) 215 if fd < 0 { d11_puts("FAIL open output\n" as *u8); sys_exit(6); return 6 } 216 let wrote: i64 = sys_write(fd, buf, fsz) 217 sys_close(fd) 218 d11_puts(" wrote "); d11_putn(wrote); d11_puts(" bytes -> knowledge/nishi_d3d11.dll (D3D11CreateDeviceAndSwapChain + ID3D11Device)\n" as *u8) 219 220 var fails: i64 = 0 221 if (buf[0] as i64) != 0x4D { fails=fails+1 } 222 if (buf[0x84+18] as i64) != 0x22 { fails=fails+1 } 223 if (buf[0x84+2] as i64) != 3 { fails=fails+1 } 224 if wrote != fsz { fails=fails+1 } 225 if fails == 0 { d11_puts("NX-PE-D3D11 GREEN -- real create export + conformant device; harness must call the real signature\n" as *u8); sys_exit(0); return 0 } 226 d11_puts("NX-PE-D3D11 RED fails="); d11_putn(fails); d11_puts("\n" as *u8) 227 sys_exit(1) 228 return 1 229}