// shellExport.c — DXE export table and wrapper functions for DVX Shell // // Exports all dvx*/wgt*/ts* symbols that DXE apps need. A few functions // are wrapped for resource tracking (window ownership via appId). // // DXE3 is DJGPP's dynamic linking mechanism. Unlike ELF shared libraries, // DXE modules have no implicit access to the host's symbol table. Every // function or variable the DXE needs must be explicitly listed in an // export table registered via dlregsym() BEFORE any dlopen() call. If a // symbol is missing, dlopen() returns NULL with a "symbol not found" error. // // This file is essentially the ABI contract between the shell and apps. // Three categories of exports: // // 1. Wrapped functions: dvxCreateWindow, dvxCreateWindowCentered, // dvxDestroyWindow. These are intercepted to stamp win->appId for // resource ownership tracking. The DXE sees them under their original // names — the app code calls dvxCreateWindow() normally and gets our // wrapper transparently. // // 2. Direct exports: all other dvx/wgt/wm/ts functions. These are safe // to call without shell-side interception. // // 3. libc functions: DXE modules are statically linked against DJGPP's // libc, but DJGPP's DXE3 loader requires explicit re-export of any // libc symbols the module references. Without these entries, the DXE // would fail to load with unresolved symbol errors. This is a DXE3 // design limitation — there's no automatic fallback to the host's libc. #include "shellApp.h" #include "shellInfo.h" #include "shellTaskMgr.h" #include "dvxApp.h" #include "dvxDialog.h" #include "dvxWidget.h" #include "dvxDraw.h" #include "dvxPrefs.h" #include "platform/dvxPlatform.h" #include "dvxVideo.h" #include "dvxWm.h" #include "taskswitch.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // stb headers (no IMPLEMENTATION — symbols are in libdvx.a / libtasks.a) #include "thirdparty/stb_image.h" #include "thirdparty/stb_image_write.h" #include "thirdparty/stb_ds.h" // DJGPP stdio internals — the stdin/stdout/stderr macros dereference // these pointers. Without exporting them, any DXE that uses printf // or fprintf gets an unresolved symbol. extern FILE __dj_stdin; extern FILE __dj_stdout; extern FILE __dj_stderr; // libgcc 64-bit integer math helpers (no header declares these) extern long long __divdi3(long long, long long); extern long long __moddi3(long long, long long); extern long long __muldi3(long long, long long); extern unsigned long long __udivdi3(unsigned long long, unsigned long long); extern unsigned long long __udivmoddi4(unsigned long long, unsigned long long, unsigned long long *); extern unsigned long long __umoddi3(unsigned long long, unsigned long long); // ============================================================ // Prototypes // ============================================================ static void shellRegisterExports(void); static WindowT *shellWrapCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable); static WindowT *shellWrapCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w, int32_t h, bool resizable); static void shellWrapDestroyWindow(AppContextT *ctx, WindowT *win); // ============================================================ // Wrapper: dvxCreateWindow — stamps win->appId // ============================================================ // The wrapper calls the real dvxCreateWindow, then tags the result with // sCurrentAppId. This is how the shell knows which app owns which window, // enabling per-app window cleanup on crash/termination. The app never // sees the difference — the wrapper has the same signature and is // exported under the same name as the original function. static WindowT *shellWrapCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable) { WindowT *win = dvxCreateWindow(ctx, title, x, y, w, h, resizable); if (win) { win->appId = sCurrentAppId; } return win; } // ============================================================ // Wrapper: dvxCreateWindowCentered — stamps win->appId // ============================================================ static WindowT *shellWrapCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w, int32_t h, bool resizable) { WindowT *win = dvxCreateWindowCentered(ctx, title, w, h, resizable); if (win) { win->appId = sCurrentAppId; } return win; } // ============================================================ // Wrapper: dvxDestroyWindow — checks for last-window reap // ============================================================ // Beyond just destroying the window, this wrapper implements the lifecycle // rule for callback-only apps: when their last window closes, they're done. // Main-loop apps manage their own lifetime (their task returns from // appMain), so this check only applies to callback-only apps. // The appId is captured before destruction because the window struct is // freed by dvxDestroyWindow. static void shellWrapDestroyWindow(AppContextT *ctx, WindowT *win) { int32_t appId = win->appId; dvxDestroyWindow(ctx, win); // If this was a callback-only app's last window, mark for reaping if (appId > 0) { ShellAppT *app = shellGetApp(appId); if (app && !app->hasMainLoop && app->state == AppStateRunningE) { // Check if app still has any windows bool hasWindows = false; for (int32_t i = 0; i < ctx->stack.count; i++) { if (ctx->stack.windows[i]->appId == appId) { hasWindows = true; break; } } if (!hasWindows) { app->state = AppStateTerminatingE; } } } } // ============================================================ // Export table // ============================================================ // DXE_EXPORT_TABLE generates a DXE symbol table array. DXE_EXPORT(fn) // expands to { "_fn", (void *)fn } — the underscore prefix matches COFF // symbol naming. For wrapped functions we use raw entries with explicit // names so the DXE sees "_dvxCreateWindow" but gets our wrapper's address. DXE_EXPORT_TABLE(shellExportTable) // Wrapped functions (exported under original names, but pointing to // our wrappers that add resource tracking) { "_dvxCreateWindow", (void *)shellWrapCreateWindow }, { "_dvxDestroyWindow", (void *)shellWrapDestroyWindow }, // dvxPlatform.h — platform abstraction DXE_EXPORT(platformLineEnding) DXE_EXPORT(platformChdir) DXE_EXPORT(platformGetMemoryInfo) DXE_EXPORT(platformMouseSetAccel) DXE_EXPORT(platformMouseWarp) DXE_EXPORT(platformPathDirEnd) DXE_EXPORT(platformStripLineEndings) DXE_EXPORT(platformValidateFilename) DXE_EXPORT(platformVideoEnumModes) // dvxPrefs.h — preferences DXE_EXPORT(prefsGetBool) DXE_EXPORT(prefsGetInt) DXE_EXPORT(prefsGetString) DXE_EXPORT(prefsLoad) DXE_EXPORT(prefsRemove) DXE_EXPORT(prefsSave) DXE_EXPORT(prefsSaveAs) DXE_EXPORT(prefsSetBool) DXE_EXPORT(prefsSetInt) DXE_EXPORT(prefsSetString) // dvxApp.h — direct exports DXE_EXPORT(dvxApplyColorScheme) DXE_EXPORT(dvxChangeVideoMode) DXE_EXPORT(dvxColorName) DXE_EXPORT(dvxGetColor) DXE_EXPORT(dvxInit) DXE_EXPORT(dvxLoadTheme) DXE_EXPORT(dvxResetColorScheme) DXE_EXPORT(dvxSaveTheme) DXE_EXPORT(dvxSetColor) DXE_EXPORT(dvxSetMouseConfig) DXE_EXPORT(dvxSetWallpaper) DXE_EXPORT(dvxShutdown) DXE_EXPORT(dvxUpdate) { "_dvxCreateWindowCentered", (void *)shellWrapCreateWindowCentered }, DXE_EXPORT(dvxFitWindow) DXE_EXPORT(dvxInvalidateRect) DXE_EXPORT(dvxInvalidateWindow) DXE_EXPORT(dvxMinimizeWindow) DXE_EXPORT(dvxMaximizeWindow) DXE_EXPORT(dvxQuit) DXE_EXPORT(dvxSetTitle) DXE_EXPORT(dvxGetFont) DXE_EXPORT(dvxGetColors) DXE_EXPORT(dvxGetDisplay) DXE_EXPORT(dvxGetVideoModes) DXE_EXPORT(dvxGetBlitOps) DXE_EXPORT(dvxSetWindowIcon) DXE_EXPORT(dvxLoadImage) DXE_EXPORT(dvxFreeImage) DXE_EXPORT(dvxSaveImage) DXE_EXPORT(dvxScreenshot) DXE_EXPORT(dvxWindowScreenshot) DXE_EXPORT(dvxCreateAccelTable) DXE_EXPORT(dvxFreeAccelTable) DXE_EXPORT(dvxAddAccel) DXE_EXPORT(dvxCascadeWindows) DXE_EXPORT(dvxTileWindows) DXE_EXPORT(dvxTileWindowsH) DXE_EXPORT(dvxTileWindowsV) DXE_EXPORT(dvxClipboardCopy) DXE_EXPORT(dvxClipboardGet) // dvxDialog.h DXE_EXPORT(dvxMessageBox) DXE_EXPORT(dvxFileDialog) // dvxDraw.h DXE_EXPORT(rectFill) DXE_EXPORT(rectCopy) DXE_EXPORT(drawBevel) DXE_EXPORT(drawChar) DXE_EXPORT(drawText) DXE_EXPORT(drawTextN) DXE_EXPORT(textWidth) DXE_EXPORT(drawTextAccel) DXE_EXPORT(textWidthAccel) DXE_EXPORT(drawFocusRect) DXE_EXPORT(drawHLine) DXE_EXPORT(drawVLine) // dvxVideo.h DXE_EXPORT(packColor) DXE_EXPORT(resetClipRect) DXE_EXPORT(setClipRect) // dvxWm.h DXE_EXPORT(wmAddMenuBar) DXE_EXPORT(wmAddMenu) DXE_EXPORT(wmAddMenuItem) DXE_EXPORT(wmAddMenuCheckItem) DXE_EXPORT(wmAddMenuRadioItem) DXE_EXPORT(wmAddMenuSeparator) DXE_EXPORT(wmAddSubMenu) DXE_EXPORT(wmAddVScrollbar) DXE_EXPORT(wmAddHScrollbar) DXE_EXPORT(wmMinimizedIconPos) DXE_EXPORT(wmMinimizedIconRect) DXE_EXPORT(wmSetTitle) DXE_EXPORT(wmSetIcon) DXE_EXPORT(wmCreateMenu) DXE_EXPORT(wmFreeMenu) DXE_EXPORT(wmUpdateContentRect) DXE_EXPORT(wmReallocContentBuf) // dvxWidget.h — window integration DXE_EXPORT(wgtInitWindow) // dvxWidget.h — containers DXE_EXPORT(wgtVBox) DXE_EXPORT(wgtHBox) DXE_EXPORT(wgtFrame) // dvxWidget.h — basic widgets DXE_EXPORT(wgtLabel) DXE_EXPORT(wgtButton) DXE_EXPORT(wgtCheckbox) DXE_EXPORT(wgtTextInput) DXE_EXPORT(wgtPasswordInput) DXE_EXPORT(wgtMaskedInput) // dvxWidget.h — radio buttons DXE_EXPORT(wgtRadioGroup) DXE_EXPORT(wgtRadio) // dvxWidget.h — spacing DXE_EXPORT(wgtSpacer) DXE_EXPORT(wgtHSeparator) DXE_EXPORT(wgtVSeparator) // dvxWidget.h — complex widgets DXE_EXPORT(wgtListBox) DXE_EXPORT(wgtTextArea) // dvxWidget.h — dropdown/combo DXE_EXPORT(wgtDropdown) DXE_EXPORT(wgtDropdownSetItems) DXE_EXPORT(wgtDropdownGetSelected) DXE_EXPORT(wgtDropdownSetSelected) DXE_EXPORT(wgtComboBox) DXE_EXPORT(wgtComboBoxSetItems) DXE_EXPORT(wgtComboBoxGetSelected) DXE_EXPORT(wgtComboBoxSetSelected) // dvxWidget.h — progress bar DXE_EXPORT(wgtProgressBar) DXE_EXPORT(wgtProgressBarV) DXE_EXPORT(wgtProgressBarSetValue) DXE_EXPORT(wgtProgressBarGetValue) // dvxWidget.h — slider DXE_EXPORT(wgtSlider) DXE_EXPORT(wgtSliderSetValue) DXE_EXPORT(wgtSliderGetValue) // dvxWidget.h — spinner DXE_EXPORT(wgtSpinner) DXE_EXPORT(wgtSpinnerSetValue) DXE_EXPORT(wgtSpinnerGetValue) DXE_EXPORT(wgtSpinnerSetRange) DXE_EXPORT(wgtSpinnerSetStep) // dvxWidget.h — tab control DXE_EXPORT(wgtTabControl) DXE_EXPORT(wgtTabPage) DXE_EXPORT(wgtTabControlSetActive) DXE_EXPORT(wgtTabControlGetActive) // dvxWidget.h — status bar / toolbar DXE_EXPORT(wgtStatusBar) DXE_EXPORT(wgtToolbar) // dvxWidget.h — tree view DXE_EXPORT(wgtTreeView) DXE_EXPORT(wgtTreeViewGetSelected) DXE_EXPORT(wgtTreeViewSetSelected) DXE_EXPORT(wgtTreeViewSetMultiSelect) DXE_EXPORT(wgtTreeViewSetReorderable) DXE_EXPORT(wgtTreeItem) DXE_EXPORT(wgtTreeItemSetExpanded) DXE_EXPORT(wgtTreeItemIsExpanded) DXE_EXPORT(wgtTreeItemIsSelected) DXE_EXPORT(wgtTreeItemSetSelected) // dvxWidget.h — timer DXE_EXPORT(wgtTimer) DXE_EXPORT(wgtTimerIsRunning) DXE_EXPORT(wgtTimerSetInterval) DXE_EXPORT(wgtTimerStart) DXE_EXPORT(wgtTimerStop) // dvxWidget.h — list view DXE_EXPORT(wgtListView) DXE_EXPORT(wgtListViewSetColumns) DXE_EXPORT(wgtListViewSetData) DXE_EXPORT(wgtListViewGetSelected) DXE_EXPORT(wgtListViewSetSelected) DXE_EXPORT(wgtListViewSetSort) DXE_EXPORT(wgtListViewSetHeaderClickCallback) DXE_EXPORT(wgtListViewSetMultiSelect) DXE_EXPORT(wgtListViewIsItemSelected) DXE_EXPORT(wgtListViewSetItemSelected) DXE_EXPORT(wgtListViewSelectAll) DXE_EXPORT(wgtListViewClearSelection) DXE_EXPORT(wgtListViewSetReorderable) // dvxWidget.h — scroll pane / splitter DXE_EXPORT(wgtScrollPane) DXE_EXPORT(wgtSplitter) DXE_EXPORT(wgtSplitterSetPos) DXE_EXPORT(wgtSplitterGetPos) // dvxWidget.h — image / image button DXE_EXPORT(wgtImageButton) DXE_EXPORT(wgtImageButtonFromFile) DXE_EXPORT(wgtImageButtonSetData) DXE_EXPORT(wgtImage) DXE_EXPORT(wgtImageFromFile) DXE_EXPORT(wgtImageSetData) // dvxWidget.h — canvas DXE_EXPORT(wgtCanvas) DXE_EXPORT(wgtCanvasClear) DXE_EXPORT(wgtCanvasSetMouseCallback) DXE_EXPORT(wgtCanvasSetPenColor) DXE_EXPORT(wgtCanvasSetPenSize) DXE_EXPORT(wgtCanvasSave) DXE_EXPORT(wgtCanvasLoad) DXE_EXPORT(wgtCanvasDrawLine) DXE_EXPORT(wgtCanvasDrawRect) DXE_EXPORT(wgtCanvasFillRect) DXE_EXPORT(wgtCanvasFillCircle) DXE_EXPORT(wgtCanvasSetPixel) DXE_EXPORT(wgtCanvasGetPixel) // dvxWidget.h — ANSI terminal DXE_EXPORT(wgtAnsiTerm) DXE_EXPORT(wgtAnsiTermWrite) DXE_EXPORT(wgtAnsiTermClear) DXE_EXPORT(wgtAnsiTermSetComm) DXE_EXPORT(wgtAnsiTermSetScrollback) DXE_EXPORT(wgtAnsiTermPoll) DXE_EXPORT(wgtAnsiTermRepaint) // dvxWidget.h — operations DXE_EXPORT(wgtInvalidate) DXE_EXPORT(wgtInvalidatePaint) DXE_EXPORT(wgtSetDebugLayout) DXE_EXPORT(wgtSetText) DXE_EXPORT(wgtSetTooltip) DXE_EXPORT(wgtGetText) DXE_EXPORT(wgtGetFocused) DXE_EXPORT(wgtSetEnabled) DXE_EXPORT(wgtSetFocused) DXE_EXPORT(wgtSetReadOnly) DXE_EXPORT(wgtSetVisible) DXE_EXPORT(wgtGetContext) DXE_EXPORT(wgtSetName) DXE_EXPORT(wgtFind) DXE_EXPORT(wgtDestroy) // dvxWidget.h — list box ops DXE_EXPORT(wgtListBoxSetItems) DXE_EXPORT(wgtListBoxGetSelected) DXE_EXPORT(wgtListBoxSetSelected) DXE_EXPORT(wgtListBoxSetMultiSelect) DXE_EXPORT(wgtListBoxIsItemSelected) DXE_EXPORT(wgtListBoxSetItemSelected) DXE_EXPORT(wgtListBoxSelectAll) DXE_EXPORT(wgtListBoxClearSelection) DXE_EXPORT(wgtListBoxSetReorderable) // dvxWidget.h — layout DXE_EXPORT(wgtResolveSize) DXE_EXPORT(wgtLayout) DXE_EXPORT(wgtPaint) // taskswitch.h — only yield and query functions are exported. // tsCreate/tsKill/etc. are NOT exported because apps should not // manipulate the task system directly — the shell manages task // lifecycle through shellLoadApp/shellForceKillApp. DXE_EXPORT(tsActiveCount) DXE_EXPORT(tsCreate) DXE_EXPORT(tsCurrentId) DXE_EXPORT(tsGetName) DXE_EXPORT(tsGetPriority) DXE_EXPORT(tsGetState) DXE_EXPORT(tsKill) DXE_EXPORT(tsPause) DXE_EXPORT(tsResume) DXE_EXPORT(tsSetPriority) DXE_EXPORT(tsYield) // dvxWm.h — direct window management DXE_EXPORT(wmRaiseWindow) DXE_EXPORT(wmSetFocus) DXE_EXPORT(wmRestoreMinimized) // Shell API DXE_EXPORT(shellLog) DXE_EXPORT(shellLoadApp) DXE_EXPORT(shellGetApp) DXE_EXPORT(shellTaskMgrOpen) DXE_EXPORT(shellForceKillApp) DXE_EXPORT(shellRunningAppCount) DXE_EXPORT(shellRegisterDesktopUpdate) DXE_EXPORT(shellUnregisterDesktopUpdate) DXE_EXPORT(shellGetSystemInfo) // ================================================================ // libc / libm exports. DXE3 modules are relocatable objects, not // fully linked executables. Every C library function a DXE calls // must appear here so the loader can resolve it at dlopen time. // This is intentionally comprehensive to avoid "unresolved symbol" // surprises when apps use standard functions. // ================================================================ // --- memory --- DXE_EXPORT(calloc) DXE_EXPORT(free) DXE_EXPORT(malloc) DXE_EXPORT(realloc) // --- string / memory ops --- DXE_EXPORT(memchr) DXE_EXPORT(memcmp) DXE_EXPORT(memcpy) DXE_EXPORT(memmove) DXE_EXPORT(memset) DXE_EXPORT(strcasecmp) DXE_EXPORT(strcat) DXE_EXPORT(strchr) DXE_EXPORT(strcmp) DXE_EXPORT(strcpy) DXE_EXPORT(strcspn) DXE_EXPORT(strdup) DXE_EXPORT(strerror) DXE_EXPORT(strlen) DXE_EXPORT(strncasecmp) DXE_EXPORT(strncat) DXE_EXPORT(strncmp) DXE_EXPORT(strncpy) DXE_EXPORT(strpbrk) DXE_EXPORT(strrchr) DXE_EXPORT(strspn) DXE_EXPORT(strstr) DXE_EXPORT(strtok) // --- ctype --- DXE_EXPORT(isalnum) DXE_EXPORT(isalpha) DXE_EXPORT(isdigit) DXE_EXPORT(islower) DXE_EXPORT(isprint) DXE_EXPORT(ispunct) DXE_EXPORT(isspace) DXE_EXPORT(isupper) DXE_EXPORT(isxdigit) DXE_EXPORT(tolower) DXE_EXPORT(toupper) // --- conversion --- DXE_EXPORT(abs) DXE_EXPORT(atof) DXE_EXPORT(atoi) DXE_EXPORT(atol) DXE_EXPORT(labs) DXE_EXPORT(strtod) DXE_EXPORT(strtol) DXE_EXPORT(strtoul) // --- formatted I/O --- DXE_EXPORT(fprintf) DXE_EXPORT(fputs) DXE_EXPORT(fscanf) DXE_EXPORT(printf) DXE_EXPORT(puts) DXE_EXPORT(snprintf) DXE_EXPORT(sprintf) DXE_EXPORT(sscanf) DXE_EXPORT(vfprintf) DXE_EXPORT(vprintf) DXE_EXPORT(vsnprintf) DXE_EXPORT(vsprintf) // --- character I/O --- DXE_EXPORT(fgetc) DXE_EXPORT(fgets) DXE_EXPORT(fputc) DXE_EXPORT(getc) DXE_EXPORT(putc) DXE_EXPORT(putchar) DXE_EXPORT(ungetc) // --- file I/O --- DXE_EXPORT(fclose) DXE_EXPORT(feof) DXE_EXPORT(ferror) DXE_EXPORT(fflush) DXE_EXPORT(fopen) DXE_EXPORT(fread) DXE_EXPORT(freopen) DXE_EXPORT(fseek) DXE_EXPORT(ftell) DXE_EXPORT(fwrite) DXE_EXPORT(remove) DXE_EXPORT(rename) DXE_EXPORT(rewind) DXE_EXPORT(tmpfile) DXE_EXPORT(tmpnam) // --- directory --- DXE_EXPORT(closedir) DXE_EXPORT(mkdir) DXE_EXPORT(opendir) DXE_EXPORT(readdir) DXE_EXPORT(rmdir) // --- filesystem --- DXE_EXPORT(access) DXE_EXPORT(chdir) DXE_EXPORT(getcwd) DXE_EXPORT(stat) DXE_EXPORT(unlink) // --- time --- DXE_EXPORT(clock) DXE_EXPORT(difftime) DXE_EXPORT(gmtime) DXE_EXPORT(localtime) DXE_EXPORT(mktime) DXE_EXPORT(strftime) DXE_EXPORT(time) // --- process / environment --- DXE_EXPORT(abort) DXE_EXPORT(atexit) DXE_EXPORT(exit) DXE_EXPORT(getenv) DXE_EXPORT(system) // --- sorting / searching --- DXE_EXPORT(bsearch) DXE_EXPORT(qsort) // --- random --- DXE_EXPORT(rand) DXE_EXPORT(srand) // --- setjmp / signal --- DXE_EXPORT(longjmp) DXE_EXPORT(setjmp) DXE_EXPORT(signal) // --- libm --- DXE_EXPORT(acos) DXE_EXPORT(asin) DXE_EXPORT(atan) DXE_EXPORT(atan2) DXE_EXPORT(ceil) DXE_EXPORT(cos) DXE_EXPORT(exp) DXE_EXPORT(fabs) DXE_EXPORT(floor) DXE_EXPORT(fmod) DXE_EXPORT(frexp) DXE_EXPORT(ldexp) DXE_EXPORT(log) DXE_EXPORT(log10) DXE_EXPORT(modf) DXE_EXPORT(pow) DXE_EXPORT(sin) DXE_EXPORT(sqrt) DXE_EXPORT(tan) // --- errno --- DXE_EXPORT(errno) // --- libgcc 64-bit integer math helpers --- // GCC emits calls to these for int64_t division/modulo on 32-bit targets. // Without them, any DXE using 64-bit arithmetic gets unresolved symbols. DXE_EXPORT(__divdi3) DXE_EXPORT(__moddi3) DXE_EXPORT(__muldi3) DXE_EXPORT(__udivdi3) DXE_EXPORT(__udivmoddi4) DXE_EXPORT(__umoddi3) // --- DJGPP stdio internals --- // The stdin/stdout/stderr macros in DJGPP expand to pointers to // these FILE structs. Without them, any DXE that does printf() // or fprintf(stderr, ...) gets an unresolved symbol at load time. DXE_EXPORT(__dj_stdin) DXE_EXPORT(__dj_stdout) DXE_EXPORT(__dj_stderr) // --- stb_ds (dynamic arrays / hashmaps) --- // Internal functions called by the arrput/arrfree/hm* macros. // Implementation lives in libtasks.a. DXE_EXPORT(stbds_arrfreef) DXE_EXPORT(stbds_arrgrowf) DXE_EXPORT(stbds_hash_bytes) DXE_EXPORT(stbds_hash_string) DXE_EXPORT(stbds_hmdel_key) DXE_EXPORT(stbds_hmfree_func) DXE_EXPORT(stbds_hmget_key) DXE_EXPORT(stbds_hmget_key_ts) DXE_EXPORT(stbds_hmput_default) DXE_EXPORT(stbds_hmput_key) DXE_EXPORT(stbds_rand_seed) DXE_EXPORT(stbds_shmode_func) DXE_EXPORT(stbds_stralloc) DXE_EXPORT(stbds_strreset) // --- stb_image (image loading) --- DXE_EXPORT(stbi_failure_reason) DXE_EXPORT(stbi_image_free) DXE_EXPORT(stbi_info) DXE_EXPORT(stbi_info_from_memory) DXE_EXPORT(stbi_load) DXE_EXPORT(stbi_load_from_memory) DXE_EXPORT(stbi_set_flip_vertically_on_load) // --- stb_image_write --- DXE_EXPORT(stbi_write_bmp) DXE_EXPORT(stbi_write_png) DXE_EXPORT(stbi_write_jpg) DXE_EXPORT(stbi_write_tga) DXE_EXPORT_END // ============================================================ // shellRegisterExports // ============================================================ // dlregsym registers our export table with DJGPP's DXE3 runtime. // Must be called once before any dlopen — subsequent dlopen calls // will search this table to resolve DXE symbol references. static void shellRegisterExports(void) { dlregsym(shellExportTable); } // ============================================================ // Public init function // ============================================================ void shellExportInit(void) { shellRegisterExports(); }