Compare commits
No commits in common. "d876bc1c5516ff908b1d5a4ea3fe9d27f96a8244" and "937be903afc736e20893c0d28996dbd97a474355" have entirely different histories.
d876bc1c55
...
937be903af
12 changed files with 13 additions and 709 deletions
|
|
@ -64,7 +64,7 @@ $(BINDIR)/dvxdemo:
|
||||||
mkdir -p $(BINDIR)/dvxdemo
|
mkdir -p $(BINDIR)/dvxdemo
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
$(OBJDIR)/progman.o: progman/progman.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvxshell/shellApp.h ../dvxshell/shellInfo.h
|
$(OBJDIR)/progman.o: progman/progman.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvxshell/shellApp.h
|
||||||
$(OBJDIR)/notepad.o: notepad/notepad.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvxshell/shellApp.h
|
$(OBJDIR)/notepad.o: notepad/notepad.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvxshell/shellApp.h
|
||||||
$(OBJDIR)/clock.o: clock/clock.c ../dvx/dvxApp.h ../dvx/dvxWidget.h ../dvx/dvxDraw.h ../dvx/dvxVideo.h ../dvxshell/shellApp.h ../tasks/taskswitch.h
|
$(OBJDIR)/clock.o: clock/clock.c ../dvx/dvxApp.h ../dvx/dvxWidget.h ../dvx/dvxDraw.h ../dvx/dvxVideo.h ../dvxshell/shellApp.h ../tasks/taskswitch.h
|
||||||
$(OBJDIR)/dvxdemo.o: dvxdemo/dvxdemo.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvx/dvxVideo.h ../dvxshell/shellApp.h
|
$(OBJDIR)/dvxdemo.o: dvxdemo/dvxdemo.c ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxWm.h ../dvx/dvxVideo.h ../dvxshell/shellApp.h
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include "dvxWidget.h"
|
#include "dvxWidget.h"
|
||||||
#include "dvxWm.h"
|
#include "dvxWm.h"
|
||||||
#include "shellApp.h"
|
#include "shellApp.h"
|
||||||
#include "shellInfo.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -56,7 +55,6 @@
|
||||||
#define CMD_MIN_ON_RUN 104
|
#define CMD_MIN_ON_RUN 104
|
||||||
#define CMD_ABOUT 300
|
#define CMD_ABOUT 300
|
||||||
#define CMD_TASK_MGR 301
|
#define CMD_TASK_MGR 301
|
||||||
#define CMD_SYSINFO 302
|
|
||||||
|
|
||||||
// Task Manager column count
|
// Task Manager column count
|
||||||
#define TM_COL_COUNT 4
|
#define TM_COL_COUNT 4
|
||||||
|
|
@ -96,7 +94,6 @@ static void onPmMenu(WindowT *win, int32_t menuId);
|
||||||
static void scanAppsDir(void);
|
static void scanAppsDir(void);
|
||||||
static void scanAppsDirRecurse(const char *dirPath);
|
static void scanAppsDirRecurse(const char *dirPath);
|
||||||
static void showAboutDialog(void);
|
static void showAboutDialog(void);
|
||||||
static void showSystemInfo(void);
|
|
||||||
static void updateStatusText(void);
|
static void updateStatusText(void);
|
||||||
|
|
||||||
// Task Manager
|
// Task Manager
|
||||||
|
|
@ -165,7 +162,6 @@ static void buildPmWindow(void) {
|
||||||
|
|
||||||
MenuT *helpMenu = wmAddMenu(menuBar, "&Help");
|
MenuT *helpMenu = wmAddMenu(menuBar, "&Help");
|
||||||
wmAddMenuItem(helpMenu, "&About DVX Shell...", CMD_ABOUT);
|
wmAddMenuItem(helpMenu, "&About DVX Shell...", CMD_ABOUT);
|
||||||
wmAddMenuItem(helpMenu, "&System Information...", CMD_SYSINFO);
|
|
||||||
wmAddMenuSeparator(helpMenu);
|
wmAddMenuSeparator(helpMenu);
|
||||||
wmAddMenuItem(helpMenu, "&Task Manager\tCtrl+Esc", CMD_TASK_MGR);
|
wmAddMenuItem(helpMenu, "&Task Manager\tCtrl+Esc", CMD_TASK_MGR);
|
||||||
|
|
||||||
|
|
@ -384,10 +380,6 @@ static void onPmMenu(WindowT *win, int32_t menuId) {
|
||||||
showAboutDialog();
|
showAboutDialog();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_SYSINFO:
|
|
||||||
showSystemInfo();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_TASK_MGR:
|
case CMD_TASK_MGR:
|
||||||
buildTaskManager();
|
buildTaskManager();
|
||||||
break;
|
break;
|
||||||
|
|
@ -642,38 +634,6 @@ static void showAboutDialog(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void showSystemInfo(void) {
|
|
||||||
const char *info = shellGetSystemInfo();
|
|
||||||
|
|
||||||
if (!info || !info[0]) {
|
|
||||||
dvxMessageBox(sAc, "System Information", "No system information available.", MB_OK | MB_ICONINFO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a window with a read-only text area
|
|
||||||
int32_t screenW = sAc->display.width;
|
|
||||||
int32_t screenH = sAc->display.height;
|
|
||||||
int32_t winW = 400;
|
|
||||||
int32_t winH = 360;
|
|
||||||
int32_t winX = (screenW - winW) / 2;
|
|
||||||
int32_t winY = (screenH - winH) / 4;
|
|
||||||
|
|
||||||
WindowT *win = dvxCreateWindow(sAc, "System Information", winX, winY, winW, winH, true);
|
|
||||||
|
|
||||||
if (!win) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WidgetT *root = wgtInitWindow(sAc, win);
|
|
||||||
WidgetT *ta = wgtTextArea(root, 4096);
|
|
||||||
ta->weight = 100;
|
|
||||||
wgtSetText(ta, info);
|
|
||||||
|
|
||||||
// Mark read-only by disabling the text area
|
|
||||||
wgtSetEnabled(ta, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void updateStatusText(void) {
|
static void updateStatusText(void) {
|
||||||
if (!sStatusLabel) {
|
if (!sStatusLabel) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
43
dvx/dvxApp.c
43
dvx/dvxApp.c
|
|
@ -1096,39 +1096,6 @@ static void dispatchEvents(AppContextT *ctx) {
|
||||||
win->onMouse(win, relX, relY, buttons);
|
win->onMouse(win, relX, relY, buttons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse wheel — scroll the focused window's vertical scrollbar.
|
|
||||||
// Each notch moves MOUSE_WHEEL_STEP lines. If no vertical scrollbar,
|
|
||||||
// try horizontal (for windows with only horizontal scroll).
|
|
||||||
if (ctx->mouseWheel != 0 && ctx->stack.focusedIdx >= 0) {
|
|
||||||
WindowT *win = ctx->stack.windows[ctx->stack.focusedIdx];
|
|
||||||
ScrollbarT *sb = win->vScroll ? win->vScroll : win->hScroll;
|
|
||||||
|
|
||||||
if (sb) {
|
|
||||||
int32_t oldValue = sb->value;
|
|
||||||
sb->value += ctx->mouseWheel * MOUSE_WHEEL_STEP;
|
|
||||||
|
|
||||||
if (sb->value < sb->min) {
|
|
||||||
sb->value = sb->min;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb->value > sb->max) {
|
|
||||||
sb->value = sb->max;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb->value != oldValue) {
|
|
||||||
int32_t sbScreenX = win->x + sb->x;
|
|
||||||
int32_t sbScreenY = win->y + sb->y;
|
|
||||||
dirtyListAdd(&ctx->dirty, sbScreenX, sbScreenY,
|
|
||||||
sb->orient == ScrollbarVerticalE ? SCROLLBAR_WIDTH : sb->length,
|
|
||||||
sb->orient == ScrollbarVerticalE ? sb->length : SCROLLBAR_WIDTH);
|
|
||||||
|
|
||||||
if (win->onScroll) {
|
|
||||||
win->onScroll(win, sb->orient, sb->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1582,11 +1549,10 @@ int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_
|
||||||
ctx->cursorBg = packColor(&ctx->display, 0, 0, 0);
|
ctx->cursorBg = packColor(&ctx->display, 0, 0, 0);
|
||||||
|
|
||||||
platformMouseInit(ctx->display.width, ctx->display.height);
|
platformMouseInit(ctx->display.width, ctx->display.height);
|
||||||
ctx->hasMouseWheel = platformMouseWheelInit();
|
ctx->mouseX = ctx->display.width / 2;
|
||||||
ctx->mouseX = ctx->display.width / 2;
|
ctx->mouseY = ctx->display.height / 2;
|
||||||
ctx->mouseY = ctx->display.height / 2;
|
ctx->prevMouseX = ctx->mouseX;
|
||||||
ctx->prevMouseX = ctx->mouseX;
|
ctx->prevMouseY = ctx->mouseY;
|
||||||
ctx->prevMouseY = ctx->mouseY;
|
|
||||||
|
|
||||||
ctx->running = true;
|
ctx->running = true;
|
||||||
ctx->lastIconClickId = -1;
|
ctx->lastIconClickId = -1;
|
||||||
|
|
@ -3401,7 +3367,6 @@ static void pollMouse(AppContextT *ctx) {
|
||||||
ctx->mouseX = mx;
|
ctx->mouseX = mx;
|
||||||
ctx->mouseY = my;
|
ctx->mouseY = my;
|
||||||
ctx->mouseButtons = buttons;
|
ctx->mouseButtons = buttons;
|
||||||
ctx->mouseWheel = platformMouseWheelPoll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ typedef struct AppContextT {
|
||||||
int32_t mouseX;
|
int32_t mouseX;
|
||||||
int32_t mouseY;
|
int32_t mouseY;
|
||||||
int32_t mouseButtons;
|
int32_t mouseButtons;
|
||||||
int32_t mouseWheel; // wheel delta this frame (positive=down, negative=up)
|
|
||||||
bool hasMouseWheel; // true if CuteMouse Wheel API detected
|
|
||||||
int32_t keyModifiers; // current BIOS shift state (KEY_MOD_xxx)
|
int32_t keyModifiers; // current BIOS shift state (KEY_MOD_xxx)
|
||||||
// Previous-frame mouse state for edge detection (button press/release
|
// Previous-frame mouse state for edge detection (button press/release
|
||||||
// transitions and delta-based cursor movement).
|
// transitions and delta-based cursor movement).
|
||||||
|
|
|
||||||
|
|
@ -553,9 +553,6 @@ typedef struct {
|
||||||
#define MOUSE_RIGHT 2
|
#define MOUSE_RIGHT 2
|
||||||
#define MOUSE_MIDDLE 4
|
#define MOUSE_MIDDLE 4
|
||||||
|
|
||||||
// Scrollbar lines to scroll per mouse wheel notch
|
|
||||||
#define MOUSE_WHEEL_STEP 3
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Mouse cursor
|
// Mouse cursor
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
|
|
@ -127,18 +127,6 @@ void platformMouseInit(int32_t screenW, int32_t screenH);
|
||||||
// to detect press/release edges.
|
// to detect press/release edges.
|
||||||
void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons);
|
void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons);
|
||||||
|
|
||||||
// Detect and activate mouse wheel support. Returns true if the mouse
|
|
||||||
// driver supports the CuteMouse Wheel API (INT 33h AX=0011h). This
|
|
||||||
// call also activates wheel reporting — after it returns true, function
|
|
||||||
// 03h will return wheel delta in BH. Must be called after platformMouseInit.
|
|
||||||
bool platformMouseWheelInit(void);
|
|
||||||
|
|
||||||
// Read the accumulated wheel delta since the last call. Positive = scroll
|
|
||||||
// down, negative = scroll up. Returns 0 if no wheel movement or if wheel
|
|
||||||
// is not supported. The delta is cleared on each read (accumulated by the
|
|
||||||
// driver between polls).
|
|
||||||
int32_t platformMouseWheelPoll(void);
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Input — Keyboard
|
// Input — Keyboard
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -163,21 +151,6 @@ bool platformKeyboardRead(PlatformKeyEventT *evt);
|
||||||
// map to a printable character (e.g. Alt+F1).
|
// map to a printable character (e.g. Alt+F1).
|
||||||
char platformAltScanToChar(int32_t scancode);
|
char platformAltScanToChar(int32_t scancode);
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// System information
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
// Maximum size of the formatted system information text
|
|
||||||
#define PLATFORM_SYSINFO_MAX 4096
|
|
||||||
|
|
||||||
// Gather hardware information (CPU, clock, memory, DOS/DPMI version,
|
|
||||||
// video, mouse, disk drives) and return as a pre-formatted text string.
|
|
||||||
// The display pointer provides the current video mode info. Returns a
|
|
||||||
// pointer to a static buffer valid for the lifetime of the process.
|
|
||||||
// On DOS this uses CPUID, RDTSC, DPMI, INT 21h, INT 33h, and VBE.
|
|
||||||
// On other platforms it returns whatever the OS can report.
|
|
||||||
const char *platformGetSystemInfo(const DisplayT *display);
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// File system
|
// File system
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include "dvxPlatform.h"
|
#include "dvxPlatform.h"
|
||||||
#include "../dvxPalette.h"
|
#include "../dvxPalette.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -47,24 +46,11 @@
|
||||||
// Prototypes
|
// Prototypes
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
static uint32_t estimateClockMhz(void);
|
static int32_t findBestMode(int32_t requestedW, int32_t requestedH, int32_t preferredBpp, uint16_t *outMode, DisplayT *d);
|
||||||
static int32_t findBestMode(int32_t requestedW, int32_t requestedH, int32_t preferredBpp, uint16_t *outMode, DisplayT *d);
|
static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
|
||||||
static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
|
static int32_t mapLfb(DisplayT *d, uint32_t physAddr);
|
||||||
static bool hasCpuid(void);
|
void platformVideoEnumModes(void (*cb)(int32_t w, int32_t h, int32_t bpp, void *userData), void *userData);
|
||||||
static int32_t mapLfb(DisplayT *d, uint32_t physAddr);
|
static int32_t setVesaMode(uint16_t mode);
|
||||||
void platformVideoEnumModes(void (*cb)(int32_t w, int32_t h, int32_t bpp, void *userData), void *userData);
|
|
||||||
static int32_t setVesaMode(uint16_t mode);
|
|
||||||
static void sysInfoAppend(const char *fmt, ...);
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// Module state
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
// Wheel state: set by platformMouseWheelInit, read by platformMousePoll
|
|
||||||
// and platformGetSystemInfo. Declared here (above all functions) so
|
|
||||||
// every function in the file can see them.
|
|
||||||
static bool sHasMouseWheel = false;
|
|
||||||
static int32_t sLastWheelDelta = 0;
|
|
||||||
|
|
||||||
// Alt+key scan code to ASCII lookup table (indexed by BIOS scan code).
|
// Alt+key scan code to ASCII lookup table (indexed by BIOS scan code).
|
||||||
// INT 16h returns these scan codes with ascii=0 for Alt+key combos.
|
// INT 16h returns these scan codes with ascii=0 for Alt+key combos.
|
||||||
|
|
@ -557,449 +543,6 @@ void platformFlushRect(const DisplayT *d, const RectT *r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// System information — static buffer and helpers
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
static char sSysInfoBuf[PLATFORM_SYSINFO_MAX];
|
|
||||||
static int32_t sSysInfoPos = 0;
|
|
||||||
|
|
||||||
// Formatted append to the system info buffer (newline-terminated).
|
|
||||||
static void sysInfoAppend(const char *fmt, ...) {
|
|
||||||
if (sSysInfoPos >= PLATFORM_SYSINFO_MAX - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
int32_t written = vsnprintf(sSysInfoBuf + sSysInfoPos, PLATFORM_SYSINFO_MAX - sSysInfoPos, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (written > 0) {
|
|
||||||
sSysInfoPos += written;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sSysInfoPos < PLATFORM_SYSINFO_MAX - 1) {
|
|
||||||
sSysInfoBuf[sSysInfoPos] = '\n';
|
|
||||||
sSysInfoPos++;
|
|
||||||
sSysInfoBuf[sSysInfoPos] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// estimateClockMhz — RDTSC calibration via BIOS timer
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Measures TSC ticks over 3 BIOS timer ticks (~165 ms). The BIOS timer
|
|
||||||
// at 0040:006C increments at 18.2065 Hz (1193182 / 65536 Hz per tick).
|
|
||||||
// Using 3 ticks instead of 1 reduces jitter from interrupt latency and
|
|
||||||
// gives a more stable reading.
|
|
||||||
|
|
||||||
#define CLOCK_MEAS_TICKS 3
|
|
||||||
|
|
||||||
static uint32_t estimateClockMhz(void) {
|
|
||||||
uint32_t biosTimerAddr = 0x46C; // linear address 0000:046C = 0040:006C
|
|
||||||
|
|
||||||
// Wait for tick boundary to synchronize
|
|
||||||
uint32_t tick0 = _farpeekl(_dos_ds, biosTimerAddr);
|
|
||||||
|
|
||||||
while (_farpeekl(_dos_ds, biosTimerAddr) == tick0) {
|
|
||||||
// spin
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read TSC at tick boundary
|
|
||||||
uint32_t lo1;
|
|
||||||
uint32_t hi1;
|
|
||||||
|
|
||||||
__asm__ __volatile__ ("rdtsc" : "=a"(lo1), "=d"(hi1));
|
|
||||||
|
|
||||||
uint32_t tickStart = _farpeekl(_dos_ds, biosTimerAddr);
|
|
||||||
|
|
||||||
// Wait for CLOCK_MEAS_TICKS more ticks
|
|
||||||
while ((_farpeekl(_dos_ds, biosTimerAddr) - tickStart) < CLOCK_MEAS_TICKS) {
|
|
||||||
// spin
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read TSC at end
|
|
||||||
uint32_t lo2;
|
|
||||||
uint32_t hi2;
|
|
||||||
|
|
||||||
__asm__ __volatile__ ("rdtsc" : "=a"(lo2), "=d"(hi2));
|
|
||||||
|
|
||||||
uint64_t tsc1 = ((uint64_t)hi1 << 32) | lo1;
|
|
||||||
uint64_t tsc2 = ((uint64_t)hi2 << 32) | lo2;
|
|
||||||
uint64_t delta = tsc2 - tsc1;
|
|
||||||
|
|
||||||
// Each BIOS tick = 65536 / 1193182 seconds = 54925.4 microseconds
|
|
||||||
uint32_t mhz = (uint32_t)(delta / (CLOCK_MEAS_TICKS * 54925ULL));
|
|
||||||
|
|
||||||
return mhz;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// hasCpuid — check if CPUID instruction is available
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// The CPUID instruction exists if bit 21 (ID flag) of EFLAGS can be
|
|
||||||
// toggled. On a 386 this bit is hardwired to 0. On a 486 without
|
|
||||||
// CPUID it's also hardwired. Only if we can flip it does CPUID exist.
|
|
||||||
|
|
||||||
static bool hasCpuid(void) {
|
|
||||||
uint32_t before;
|
|
||||||
uint32_t after;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"pushfl\n\t"
|
|
||||||
"popl %%eax\n\t"
|
|
||||||
"movl %%eax, %0\n\t"
|
|
||||||
"xorl $0x200000, %%eax\n\t"
|
|
||||||
"pushl %%eax\n\t"
|
|
||||||
"popfl\n\t"
|
|
||||||
"pushfl\n\t"
|
|
||||||
"popl %%eax\n\t"
|
|
||||||
"movl %%eax, %1\n\t"
|
|
||||||
: "=r"(before), "=r"(after)
|
|
||||||
:
|
|
||||||
: "eax"
|
|
||||||
);
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"pushl %0\n\t"
|
|
||||||
"popfl"
|
|
||||||
:
|
|
||||||
: "r"(before)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (before ^ after) & 0x200000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformGetSystemInfo
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Gathers all available hardware information and formats it as a
|
|
||||||
// human-readable text string. Each section is separated by a blank
|
|
||||||
// line and headed with === Section ===.
|
|
||||||
|
|
||||||
const char *platformGetSystemInfo(const DisplayT *display) {
|
|
||||||
__dpmi_regs r;
|
|
||||||
|
|
||||||
sSysInfoPos = 0;
|
|
||||||
sSysInfoBuf[0] = '\0';
|
|
||||||
|
|
||||||
sysInfoAppend("DVX System Information");
|
|
||||||
sysInfoAppend("");
|
|
||||||
|
|
||||||
// ---- CPU ----
|
|
||||||
sysInfoAppend("=== CPU ===");
|
|
||||||
|
|
||||||
if (!hasCpuid()) {
|
|
||||||
sysInfoAppend("Processor: 386/486 (no CPUID support)");
|
|
||||||
} else {
|
|
||||||
// Vendor string (CPUID leaf 0)
|
|
||||||
uint32_t maxFunc;
|
|
||||||
uint32_t ebx;
|
|
||||||
uint32_t ecx;
|
|
||||||
uint32_t edx;
|
|
||||||
char vendor[13];
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cpuid"
|
|
||||||
: "=a"(maxFunc), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
|
||||||
: "a"(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
memcpy(vendor + 0, &ebx, 4);
|
|
||||||
memcpy(vendor + 4, &edx, 4);
|
|
||||||
memcpy(vendor + 8, &ecx, 4);
|
|
||||||
vendor[12] = '\0';
|
|
||||||
|
|
||||||
sysInfoAppend("CPU Vendor: %s", vendor);
|
|
||||||
|
|
||||||
// Family/model/stepping/features (CPUID leaf 1)
|
|
||||||
if (maxFunc >= 1) {
|
|
||||||
uint32_t eax;
|
|
||||||
uint32_t features;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cpuid"
|
|
||||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(features)
|
|
||||||
: "a"(1)
|
|
||||||
);
|
|
||||||
|
|
||||||
int32_t stepping = eax & 0x0F;
|
|
||||||
int32_t model = (eax >> 4) & 0x0F;
|
|
||||||
int32_t family = (eax >> 8) & 0x0F;
|
|
||||||
|
|
||||||
if (family == 0x0F) {
|
|
||||||
family += (eax >> 20) & 0xFF;
|
|
||||||
model += ((eax >> 16) & 0x0F) << 4;
|
|
||||||
} else if (family == 6) {
|
|
||||||
model += ((eax >> 16) & 0x0F) << 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
sysInfoAppend("Family: %ld Model: %ld Stepping: %ld", (long)family, (long)model, (long)stepping);
|
|
||||||
|
|
||||||
// Feature flags
|
|
||||||
bool hasFpu = (features & (1U << 0)) != 0;
|
|
||||||
bool hasTsc = (features & (1U << 4)) != 0;
|
|
||||||
bool hasMmx = (features & (1U << 23)) != 0;
|
|
||||||
bool hasSse = (features & (1U << 25)) != 0;
|
|
||||||
bool hasSse2 = (features & (1U << 26)) != 0;
|
|
||||||
|
|
||||||
char featureStr[128];
|
|
||||||
int32_t fpos = 0;
|
|
||||||
|
|
||||||
featureStr[0] = '\0';
|
|
||||||
|
|
||||||
if (hasFpu) {
|
|
||||||
fpos += snprintf(featureStr + fpos, sizeof(featureStr) - fpos, "FPU ");
|
|
||||||
}
|
|
||||||
if (hasTsc) {
|
|
||||||
fpos += snprintf(featureStr + fpos, sizeof(featureStr) - fpos, "TSC ");
|
|
||||||
}
|
|
||||||
if (hasMmx) {
|
|
||||||
fpos += snprintf(featureStr + fpos, sizeof(featureStr) - fpos, "MMX ");
|
|
||||||
}
|
|
||||||
if (hasSse) {
|
|
||||||
fpos += snprintf(featureStr + fpos, sizeof(featureStr) - fpos, "SSE ");
|
|
||||||
}
|
|
||||||
if (hasSse2) {
|
|
||||||
fpos += snprintf(featureStr + fpos, sizeof(featureStr) - fpos, "SSE2 ");
|
|
||||||
}
|
|
||||||
if (fpos > 0) {
|
|
||||||
featureStr[fpos - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
sysInfoAppend("Features: %s", featureStr[0] ? featureStr : "(none)");
|
|
||||||
|
|
||||||
// Clock speed via RDTSC (Pentium+ only)
|
|
||||||
if (hasTsc) {
|
|
||||||
uint32_t mhz = estimateClockMhz();
|
|
||||||
|
|
||||||
if (mhz > 0) {
|
|
||||||
sysInfoAppend("Clock: ~%lu MHz", (unsigned long)mhz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Brand string (CPUID extended leaves 0x80000002-0x80000004)
|
|
||||||
uint32_t maxExtFunc;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cpuid"
|
|
||||||
: "=a"(maxExtFunc), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
|
||||||
: "a"(0x80000000U)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (maxExtFunc >= 0x80000004U) {
|
|
||||||
char brand[49];
|
|
||||||
uint32_t *b = (uint32_t *)brand;
|
|
||||||
|
|
||||||
for (uint32_t func = 0x80000002U; func <= 0x80000004U; func++) {
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cpuid"
|
|
||||||
: "=a"(b[0]), "=b"(b[1]), "=c"(b[2]), "=d"(b[3])
|
|
||||||
: "a"(func)
|
|
||||||
);
|
|
||||||
|
|
||||||
b += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
brand[48] = '\0';
|
|
||||||
|
|
||||||
const char *p = brand;
|
|
||||||
|
|
||||||
while (*p == ' ') {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p) {
|
|
||||||
sysInfoAppend("Brand: %s", p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Memory ----
|
|
||||||
sysInfoAppend("");
|
|
||||||
sysInfoAppend("=== Memory ===");
|
|
||||||
|
|
||||||
__dpmi_free_mem_info memInfo;
|
|
||||||
|
|
||||||
if (__dpmi_get_free_memory_information(&memInfo) == 0) {
|
|
||||||
if (memInfo.largest_available_free_block_in_bytes != 0xFFFFFFFFUL) {
|
|
||||||
sysInfoAppend("Largest free block: %lu KB", (unsigned long)(memInfo.largest_available_free_block_in_bytes / 1024));
|
|
||||||
}
|
|
||||||
if (memInfo.total_number_of_physical_pages != 0xFFFFFFFFUL) {
|
|
||||||
uint32_t totalKb = memInfo.total_number_of_physical_pages * 4;
|
|
||||||
sysInfoAppend("Total physical: %lu KB (%lu MB)", (unsigned long)totalKb, (unsigned long)(totalKb / 1024));
|
|
||||||
}
|
|
||||||
if (memInfo.total_number_of_free_pages != 0xFFFFFFFFUL) {
|
|
||||||
uint32_t freeKb = memInfo.total_number_of_free_pages * 4;
|
|
||||||
sysInfoAppend("Free physical: %lu KB (%lu MB)", (unsigned long)freeKb, (unsigned long)(freeKb / 1024));
|
|
||||||
}
|
|
||||||
if (memInfo.linear_address_space_size_in_pages != 0xFFFFFFFFUL) {
|
|
||||||
uint32_t linearKb = memInfo.linear_address_space_size_in_pages * 4;
|
|
||||||
sysInfoAppend("Linear address space: %lu KB (%lu MB)", (unsigned long)linearKb, (unsigned long)(linearKb / 1024));
|
|
||||||
}
|
|
||||||
if (memInfo.size_of_paging_file_partition_in_pages != 0xFFFFFFFFUL) {
|
|
||||||
uint32_t pagingKb = memInfo.size_of_paging_file_partition_in_pages * 4;
|
|
||||||
sysInfoAppend("Paging file: %lu KB (%lu MB)", (unsigned long)pagingKb, (unsigned long)(pagingKb / 1024));
|
|
||||||
}
|
|
||||||
if (memInfo.free_linear_address_space_in_pages != 0xFFFFFFFFUL) {
|
|
||||||
uint32_t freeLinearKb = memInfo.free_linear_address_space_in_pages * 4;
|
|
||||||
sysInfoAppend("Free linear space: %lu KB", (unsigned long)freeLinearKb);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sysInfoAppend("DPMI memory info unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- DOS / DPMI ----
|
|
||||||
sysInfoAppend("");
|
|
||||||
sysInfoAppend("=== DOS ===");
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x3000;
|
|
||||||
__dpmi_int(0x21, &r);
|
|
||||||
sysInfoAppend("DOS Version: %ld.%02ld", (long)(r.x.ax & 0xFF), (long)((r.x.ax >> 8) & 0xFF));
|
|
||||||
|
|
||||||
__dpmi_version_ret ver;
|
|
||||||
|
|
||||||
if (__dpmi_get_version(&ver) == 0) {
|
|
||||||
sysInfoAppend("DPMI Version: %d.%02d", ver.major, ver.minor);
|
|
||||||
sysInfoAppend("DPMI Flags: %s%s%s",
|
|
||||||
(ver.flags & 0x01) ? "32-bit " : "16-bit ",
|
|
||||||
(ver.flags & 0x02) ? "V86 " : "",
|
|
||||||
(ver.flags & 0x04) ? "VirtMem " : "");
|
|
||||||
sysInfoAppend("CPU Type: %d86", ver.cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Video ----
|
|
||||||
sysInfoAppend("");
|
|
||||||
sysInfoAppend("=== Video ===");
|
|
||||||
|
|
||||||
// VBE controller info for version, video RAM, OEM string
|
|
||||||
_farpokeb(_dos_ds, __tb + 0, 'V');
|
|
||||||
_farpokeb(_dos_ds, __tb + 1, 'B');
|
|
||||||
_farpokeb(_dos_ds, __tb + 2, 'E');
|
|
||||||
_farpokeb(_dos_ds, __tb + 3, '2');
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x4F00;
|
|
||||||
r.x.es = __tb >> 4;
|
|
||||||
r.x.di = __tb & 0x0F;
|
|
||||||
__dpmi_int(0x10, &r);
|
|
||||||
|
|
||||||
if (r.x.ax == 0x004F) {
|
|
||||||
uint16_t vbeVersion = _farpeekw(_dos_ds, __tb + 4);
|
|
||||||
uint16_t totalMem64k = _farpeekw(_dos_ds, __tb + 18);
|
|
||||||
|
|
||||||
sysInfoAppend("VBE Version: %d.%d", vbeVersion >> 8, vbeVersion & 0xFF);
|
|
||||||
sysInfoAppend("Video memory: %lu KB", (unsigned long)(totalMem64k * 64));
|
|
||||||
|
|
||||||
// OEM string (real-mode far pointer at offset 6)
|
|
||||||
uint16_t oemOff = _farpeekw(_dos_ds, __tb + 6);
|
|
||||||
uint16_t oemSeg = _farpeekw(_dos_ds, __tb + 8);
|
|
||||||
uint32_t oemAddr = ((uint32_t)oemSeg << 4) + oemOff;
|
|
||||||
|
|
||||||
char oemStr[80];
|
|
||||||
int32_t oemLen = 0;
|
|
||||||
|
|
||||||
while (oemLen < 79) {
|
|
||||||
char c = _farpeekb(_dos_ds, oemAddr + oemLen);
|
|
||||||
|
|
||||||
if (c == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
oemStr[oemLen++] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
oemStr[oemLen] = '\0';
|
|
||||||
|
|
||||||
if (oemLen > 0) {
|
|
||||||
sysInfoAppend("VBE OEM: %s", oemStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display) {
|
|
||||||
sysInfoAppend("Resolution: %ldx%ld", (long)display->width, (long)display->height);
|
|
||||||
sysInfoAppend("Color depth: %ld bpp", (long)display->format.bitsPerPixel);
|
|
||||||
sysInfoAppend("Pitch: %ld bytes", (long)display->pitch);
|
|
||||||
|
|
||||||
uint32_t fbSize = (uint32_t)display->pitch * (uint32_t)display->height;
|
|
||||||
sysInfoAppend("Framebuffer: %lu KB", (unsigned long)(fbSize / 1024));
|
|
||||||
|
|
||||||
if (display->format.bitsPerPixel >= 15) {
|
|
||||||
sysInfoAppend("Red: %ld bits @ bit %ld", (long)display->format.redBits, (long)display->format.redShift);
|
|
||||||
sysInfoAppend("Green: %ld bits @ bit %ld", (long)display->format.greenBits, (long)display->format.greenShift);
|
|
||||||
sysInfoAppend("Blue: %ld bits @ bit %ld", (long)display->format.blueBits, (long)display->format.blueShift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Mouse ----
|
|
||||||
sysInfoAppend("");
|
|
||||||
sysInfoAppend("=== Mouse ===");
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x0000;
|
|
||||||
__dpmi_int(0x33, &r);
|
|
||||||
|
|
||||||
if (r.x.ax == 0xFFFF) {
|
|
||||||
sysInfoAppend("Mouse: Detected (%ld buttons)", (long)r.x.bx);
|
|
||||||
} else {
|
|
||||||
sysInfoAppend("Mouse: Not detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
sysInfoAppend("Wheel: %s", sHasMouseWheel ? "Yes (CuteMouse Wheel API)" : "No");
|
|
||||||
|
|
||||||
// ---- Disk Drives ----
|
|
||||||
sysInfoAppend("");
|
|
||||||
sysInfoAppend("=== Disk Drives ===");
|
|
||||||
|
|
||||||
for (int32_t drv = 3; drv <= 26; drv++) {
|
|
||||||
// INT 21h AH=36h: Get disk free space
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x3600;
|
|
||||||
r.x.dx = drv;
|
|
||||||
__dpmi_int(0x21, &r);
|
|
||||||
|
|
||||||
if (r.x.ax == 0xFFFF) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t sectPerClust = r.x.ax;
|
|
||||||
uint32_t freeClusters = r.x.bx;
|
|
||||||
uint32_t bytesPerSect = r.x.cx;
|
|
||||||
uint32_t totalClusters = r.x.dx;
|
|
||||||
|
|
||||||
uint32_t clusterSize = sectPerClust * bytesPerSect;
|
|
||||||
uint32_t totalMb = (uint32_t)((uint64_t)totalClusters * clusterSize / (1024 * 1024));
|
|
||||||
uint32_t freeMb = (uint32_t)((uint64_t)freeClusters * clusterSize / (1024 * 1024));
|
|
||||||
|
|
||||||
// INT 21h AX=4408h: Check if drive is removable
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x4408;
|
|
||||||
r.x.bx = drv;
|
|
||||||
__dpmi_int(0x21, &r);
|
|
||||||
|
|
||||||
const char *driveType = "Unknown";
|
|
||||||
|
|
||||||
if (!(r.x.flags & 0x01)) {
|
|
||||||
driveType = (r.x.ax == 0) ? "Removable" : "Fixed";
|
|
||||||
}
|
|
||||||
|
|
||||||
char letter = 'A' + (drv - 1);
|
|
||||||
sysInfoAppend("%c: %s %lu MB total %lu MB free", letter, driveType, (unsigned long)totalMb, (unsigned long)freeMb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sSysInfoBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// platformInit
|
// platformInit
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -1152,49 +695,7 @@ void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons) {
|
||||||
|
|
||||||
*mx = r.x.cx;
|
*mx = r.x.cx;
|
||||||
*my = r.x.dx;
|
*my = r.x.dx;
|
||||||
*buttons = r.x.bx & 0x07; // BL only: bits 0-2 = left/right/middle
|
*buttons = r.x.bx;
|
||||||
|
|
||||||
// BH = signed 8-bit wheel counter (cleared on read by the driver).
|
|
||||||
// Only meaningful if the wheel API was activated via platformMouseWheelInit.
|
|
||||||
if (sHasMouseWheel) {
|
|
||||||
sLastWheelDelta = (int32_t)(int8_t)(r.x.bx >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformMouseWheelInit
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Detects and activates the CuteMouse Wheel API 1.0 (INT 33h AX=0011h).
|
|
||||||
// The driver returns AX=574Dh ('WM') if supported, with CX bit 0 set if
|
|
||||||
// a wheel is physically present. Calling this function also switches the
|
|
||||||
// driver from "wheelkey" mode (faking keypresses) to real wheel reporting
|
|
||||||
// via function 03h BH. Must be called after platformMouseInit.
|
|
||||||
|
|
||||||
bool platformMouseWheelInit(void) {
|
|
||||||
__dpmi_regs r;
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x0011;
|
|
||||||
__dpmi_int(0x33, &r);
|
|
||||||
|
|
||||||
// 0x574D = 'WM' (Wheel Mouse) magic signature
|
|
||||||
sHasMouseWheel = (r.x.ax == 0x574D) && (r.x.cx & 0x0001);
|
|
||||||
return sHasMouseWheel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformMouseWheelPoll
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Returns the wheel delta captured by the last platformMousePoll call.
|
|
||||||
// Positive = scroll down, negative = scroll up. Returns 0 if no wheel
|
|
||||||
// movement or if the wheel is not supported.
|
|
||||||
|
|
||||||
int32_t platformMouseWheelPoll(void) {
|
|
||||||
return sLastWheelDelta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ OBJDIR = ../obj/dvxshell
|
||||||
BINDIR = ../bin
|
BINDIR = ../bin
|
||||||
LIBDIR = ../lib
|
LIBDIR = ../lib
|
||||||
|
|
||||||
SRCS = shellMain.c shellApp.c shellExport.c shellInfo.c
|
SRCS = shellMain.c shellApp.c shellExport.c
|
||||||
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
|
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
|
||||||
TARGET = $(BINDIR)/dvx.exe
|
TARGET = $(BINDIR)/dvx.exe
|
||||||
|
|
||||||
|
|
@ -42,7 +42,6 @@ $(BINDIR):
|
||||||
# Dependencies
|
# Dependencies
|
||||||
$(OBJDIR)/shellMain.o: shellMain.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
$(OBJDIR)/shellMain.o: shellMain.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
||||||
$(OBJDIR)/shellApp.o: shellApp.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
$(OBJDIR)/shellApp.o: shellApp.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
||||||
$(OBJDIR)/shellExport.o: shellExport.c shellApp.h shellInfo.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxDraw.h ../dvx/dvxVideo.h ../dvx/dvxWm.h ../tasks/taskswitch.h
|
$(OBJDIR)/shellExport.o: shellExport.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../dvx/dvxWidget.h ../dvx/dvxDraw.h ../dvx/dvxVideo.h ../dvx/dvxWm.h ../tasks/taskswitch.h
|
||||||
$(OBJDIR)/shellInfo.o: shellInfo.c shellInfo.h shellApp.h ../dvx/dvxApp.h ../dvx/platform/dvxPlatform.h
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS) $(TARGET) $(BINDIR)/dvx.map $(BINDIR)/dvx.log
|
rm -f $(OBJS) $(TARGET) $(BINDIR)/dvx.map $(BINDIR)/dvx.log
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
// design limitation — there's no automatic fallback to the host's libc.
|
// design limitation — there's no automatic fallback to the host's libc.
|
||||||
|
|
||||||
#include "shellApp.h"
|
#include "shellApp.h"
|
||||||
#include "shellInfo.h"
|
|
||||||
#include "dvxApp.h"
|
#include "dvxApp.h"
|
||||||
#include "dvxDialog.h"
|
#include "dvxDialog.h"
|
||||||
#include "dvxWidget.h"
|
#include "dvxWidget.h"
|
||||||
|
|
@ -395,7 +394,6 @@ DXE_EXPORT_TABLE(shellExportTable)
|
||||||
DXE_EXPORT(shellForceKillApp)
|
DXE_EXPORT(shellForceKillApp)
|
||||||
DXE_EXPORT(shellRunningAppCount)
|
DXE_EXPORT(shellRunningAppCount)
|
||||||
DXE_EXPORT(shellRegisterDesktopUpdate)
|
DXE_EXPORT(shellRegisterDesktopUpdate)
|
||||||
DXE_EXPORT(shellGetSystemInfo)
|
|
||||||
|
|
||||||
// libc exports below. DXE3 modules are compiled as relocatable objects,
|
// libc exports below. DXE3 modules are compiled as relocatable objects,
|
||||||
// not fully linked executables. Any libc function the DXE calls must be
|
// not fully linked executables. Any libc function the DXE calls must be
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
// shellInfo.c — System information wrapper for DVX Shell
|
|
||||||
//
|
|
||||||
// Delegates hardware detection to the platform layer via
|
|
||||||
// platformGetSystemInfo(), then logs the result line-by-line
|
|
||||||
// to DVX.LOG. The result pointer is cached so subsequent calls
|
|
||||||
// to shellGetSystemInfo() return instantly without re-probing.
|
|
||||||
|
|
||||||
#include "shellInfo.h"
|
|
||||||
#include "shellApp.h"
|
|
||||||
#include "platform/dvxPlatform.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// Module state
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
static const char *sCachedInfo = NULL;
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// shellGetSystemInfo — return the cached info text
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
const char *shellGetSystemInfo(void) {
|
|
||||||
return sCachedInfo ? sCachedInfo : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// shellInfoInit — gather info and log it
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
void shellInfoInit(AppContextT *ctx) {
|
|
||||||
sCachedInfo = platformGetSystemInfo(&ctx->display);
|
|
||||||
|
|
||||||
// Log each line individually so the log file is readable
|
|
||||||
shellLog("=== System Information ===");
|
|
||||||
|
|
||||||
const char *line = sCachedInfo;
|
|
||||||
|
|
||||||
while (*line) {
|
|
||||||
const char *eol = strchr(line, '\n');
|
|
||||||
|
|
||||||
if (!eol) {
|
|
||||||
shellLog("%s", line);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t len = (int32_t)(eol - line);
|
|
||||||
char tmp[256];
|
|
||||||
|
|
||||||
if (len >= (int32_t)sizeof(tmp)) {
|
|
||||||
len = sizeof(tmp) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tmp, line, len);
|
|
||||||
tmp[len] = '\0';
|
|
||||||
shellLog("%s", tmp);
|
|
||||||
line = eol + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
shellLog("=== End System Information ===");
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// shellInfo.h — System information display for DVX Shell
|
|
||||||
//
|
|
||||||
// Thin wrapper around platformGetSystemInfo(). Calls the platform
|
|
||||||
// layer to gather hardware info, logs each line to DVX.LOG, and
|
|
||||||
// caches the result for the Program Manager's "System Information"
|
|
||||||
// dialog.
|
|
||||||
#ifndef SHELL_INFO_H
|
|
||||||
#define SHELL_INFO_H
|
|
||||||
|
|
||||||
#include "dvxApp.h"
|
|
||||||
|
|
||||||
// Gather all hardware information via the platform layer, log it,
|
|
||||||
// and store for later retrieval. Call once after dvxInit.
|
|
||||||
void shellInfoInit(AppContextT *ctx);
|
|
||||||
|
|
||||||
// Return the formatted system information text. The pointer is valid
|
|
||||||
// for the lifetime of the process (static buffer in the platform layer).
|
|
||||||
const char *shellGetSystemInfo(void);
|
|
||||||
|
|
||||||
#endif // SHELL_INFO_H
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
// doesn't take down the whole system.
|
// doesn't take down the whole system.
|
||||||
|
|
||||||
#include "shellApp.h"
|
#include "shellApp.h"
|
||||||
#include "shellInfo.h"
|
|
||||||
#include "dvxDialog.h"
|
#include "dvxDialog.h"
|
||||||
#include "platform/dvxPlatform.h"
|
#include "platform/dvxPlatform.h"
|
||||||
|
|
||||||
|
|
@ -260,9 +259,6 @@ int main(void) {
|
||||||
// roughly twice as many scheduling turns as any single app.
|
// roughly twice as many scheduling turns as any single app.
|
||||||
tsSetPriority(0, TS_PRIORITY_HIGH);
|
tsSetPriority(0, TS_PRIORITY_HIGH);
|
||||||
|
|
||||||
// Gather system information (CPU, memory, drives, etc.)
|
|
||||||
shellInfoInit(&sCtx);
|
|
||||||
|
|
||||||
// Register DXE export table
|
// Register DXE export table
|
||||||
shellExportInit();
|
shellExportInit();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue