#include #include #include "engine-win32.h" #include "win32.h" static void utf8_emit(uint32_t cp, char* dst, size_t size, size_t* need, size_t* wrote) { uint8_t b[4]; size_t k; if (cp < 0x80) { b[0]=(uint8_t)cp; k=1; } else if (cp < 0x800) { b[0]=0xC0|(uint8_t)(cp>>6); b[1]=0x80|(cp&0x3F); k=2; } else if (cp < 0x10000) { b[0]=0xE0|(uint8_t)(cp>>12); b[1]=0x80|((cp>>6)&0x3F); b[2]=0x80|(cp&0x3F); k=3; } else { b[0]=0xF0|(uint8_t)(cp>>18); b[1]=0x80|((cp>>12)&0x3F); b[2]=0x80|((cp>>6)&0x3F); b[3]=0x80|(cp&0x3F); k=4; } if (dst && *need + k < size) { for (size_t j = 0; j < k; j++) dst[*need + j] = (char)b[j]; *wrote = *need + k; /* end of last full code point */ } *need += k; } size_t gva_read_text(vmie_win32* v, uintptr_t cr3, uintptr_t va, size_t nmemb, char* dst, size_t size) { vmie_mem* m = &v->mem; size_t need = 0, wrote = 0; uint16_t stage[256]; uint32_t hi = 0; nmemb &= ~(size_t)1; while (nmemb) { size_t chunk = nmemb < sizeof stage ? nmemb : sizeof stage; if (gva_read(m, cr3, va, stage, chunk)) { break; } const size_t units = chunk / 2; for (size_t i = 0; i < units; i++) { uint32_t u = stage[i]; if (hi) { if (u >= 0xDC00 && u <= 0xDFFF) { utf8_emit(0x10000u + ((hi - 0xD800u) << 10) + (u - 0xDC00u), dst, size, &need, &wrote); hi = 0; continue; } utf8_emit(0xFFFD, dst, size, &need, &wrote); hi = 0; } if (u >= 0xD800 && u <= 0xDBFF) hi = u; else if (u >= 0xDC00 && u <= 0xDFFF) utf8_emit(0xFFFD, dst, size, &need, &wrote); else utf8_emit(u, dst, size, &need, &wrote); } va += chunk; nmemb -= chunk; } if (hi) utf8_emit(0xFFFD, dst, size, &need, &wrote); if (dst && size) dst[need < size ? need : wrote] = 0; return need; }