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
|
||||
|
||||
# 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)/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
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "dvxWidget.h"
|
||||
#include "dvxWm.h"
|
||||
#include "shellApp.h"
|
||||
#include "shellInfo.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -56,7 +55,6 @@
|
|||
#define CMD_MIN_ON_RUN 104
|
||||
#define CMD_ABOUT 300
|
||||
#define CMD_TASK_MGR 301
|
||||
#define CMD_SYSINFO 302
|
||||
|
||||
// Task Manager column count
|
||||
#define TM_COL_COUNT 4
|
||||
|
|
@ -96,7 +94,6 @@ static void onPmMenu(WindowT *win, int32_t menuId);
|
|||
static void scanAppsDir(void);
|
||||
static void scanAppsDirRecurse(const char *dirPath);
|
||||
static void showAboutDialog(void);
|
||||
static void showSystemInfo(void);
|
||||
static void updateStatusText(void);
|
||||
|
||||
// Task Manager
|
||||
|
|
@ -165,7 +162,6 @@ static void buildPmWindow(void) {
|
|||
|
||||
MenuT *helpMenu = wmAddMenu(menuBar, "&Help");
|
||||
wmAddMenuItem(helpMenu, "&About DVX Shell...", CMD_ABOUT);
|
||||
wmAddMenuItem(helpMenu, "&System Information...", CMD_SYSINFO);
|
||||
wmAddMenuSeparator(helpMenu);
|
||||
wmAddMenuItem(helpMenu, "&Task Manager\tCtrl+Esc", CMD_TASK_MGR);
|
||||
|
||||
|
|
@ -384,10 +380,6 @@ static void onPmMenu(WindowT *win, int32_t menuId) {
|
|||
showAboutDialog();
|
||||
break;
|
||||
|
||||
case CMD_SYSINFO:
|
||||
showSystemInfo();
|
||||
break;
|
||||
|
||||
case CMD_TASK_MGR:
|
||||
buildTaskManager();
|
||||
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) {
|
||||
if (!sStatusLabel) {
|
||||
return;
|
||||
|
|
|
|||
43
dvx/dvxApp.c
43
dvx/dvxApp.c
|
|
@ -1096,39 +1096,6 @@ static void dispatchEvents(AppContextT *ctx) {
|
|||
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);
|
||||
|
||||
platformMouseInit(ctx->display.width, ctx->display.height);
|
||||
ctx->hasMouseWheel = platformMouseWheelInit();
|
||||
ctx->mouseX = ctx->display.width / 2;
|
||||
ctx->mouseY = ctx->display.height / 2;
|
||||
ctx->prevMouseX = ctx->mouseX;
|
||||
ctx->prevMouseY = ctx->mouseY;
|
||||
ctx->mouseX = ctx->display.width / 2;
|
||||
ctx->mouseY = ctx->display.height / 2;
|
||||
ctx->prevMouseX = ctx->mouseX;
|
||||
ctx->prevMouseY = ctx->mouseY;
|
||||
|
||||
ctx->running = true;
|
||||
ctx->lastIconClickId = -1;
|
||||
|
|
@ -3401,7 +3367,6 @@ static void pollMouse(AppContextT *ctx) {
|
|||
ctx->mouseX = mx;
|
||||
ctx->mouseY = my;
|
||||
ctx->mouseButtons = buttons;
|
||||
ctx->mouseWheel = platformMouseWheelPoll();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ typedef struct AppContextT {
|
|||
int32_t mouseX;
|
||||
int32_t mouseY;
|
||||
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)
|
||||
// Previous-frame mouse state for edge detection (button press/release
|
||||
// transitions and delta-based cursor movement).
|
||||
|
|
|
|||
|
|
@ -553,9 +553,6 @@ typedef struct {
|
|||
#define MOUSE_RIGHT 2
|
||||
#define MOUSE_MIDDLE 4
|
||||
|
||||
// Scrollbar lines to scroll per mouse wheel notch
|
||||
#define MOUSE_WHEEL_STEP 3
|
||||
|
||||
// ============================================================
|
||||
// Mouse cursor
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -127,18 +127,6 @@ void platformMouseInit(int32_t screenW, int32_t screenH);
|
|||
// to detect press/release edges.
|
||||
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
|
||||
// ============================================================
|
||||
|
|
@ -163,21 +151,6 @@ bool platformKeyboardRead(PlatformKeyEventT *evt);
|
|||
// map to a printable character (e.g. Alt+F1).
|
||||
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
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include "dvxPlatform.h"
|
||||
#include "../dvxPalette.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -47,24 +46,11 @@
|
|||
// 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 void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
|
||||
static bool hasCpuid(void);
|
||||
static int32_t mapLfb(DisplayT *d, uint32_t physAddr);
|
||||
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;
|
||||
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 int32_t mapLfb(DisplayT *d, uint32_t physAddr);
|
||||
void platformVideoEnumModes(void (*cb)(int32_t w, int32_t h, int32_t bpp, void *userData), void *userData);
|
||||
static int32_t setVesaMode(uint16_t mode);
|
||||
|
||||
// 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.
|
||||
|
|
@ -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
|
||||
// ============================================================
|
||||
|
|
@ -1152,49 +695,7 @@ void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons) {
|
|||
|
||||
*mx = r.x.cx;
|
||||
*my = r.x.dx;
|
||||
*buttons = r.x.bx & 0x07; // BL only: bits 0-2 = left/right/middle
|
||||
|
||||
// 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;
|
||||
*buttons = r.x.bx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ OBJDIR = ../obj/dvxshell
|
|||
BINDIR = ../bin
|
||||
LIBDIR = ../lib
|
||||
|
||||
SRCS = shellMain.c shellApp.c shellExport.c shellInfo.c
|
||||
SRCS = shellMain.c shellApp.c shellExport.c
|
||||
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
|
||||
TARGET = $(BINDIR)/dvx.exe
|
||||
|
||||
|
|
@ -42,7 +42,6 @@ $(BINDIR):
|
|||
# Dependencies
|
||||
$(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)/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)/shellInfo.o: shellInfo.c shellInfo.h shellApp.h ../dvx/dvxApp.h ../dvx/platform/dvxPlatform.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
|
||||
clean:
|
||||
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.
|
||||
|
||||
#include "shellApp.h"
|
||||
#include "shellInfo.h"
|
||||
#include "dvxApp.h"
|
||||
#include "dvxDialog.h"
|
||||
#include "dvxWidget.h"
|
||||
|
|
@ -395,7 +394,6 @@ DXE_EXPORT_TABLE(shellExportTable)
|
|||
DXE_EXPORT(shellForceKillApp)
|
||||
DXE_EXPORT(shellRunningAppCount)
|
||||
DXE_EXPORT(shellRegisterDesktopUpdate)
|
||||
DXE_EXPORT(shellGetSystemInfo)
|
||||
|
||||
// libc exports below. DXE3 modules are compiled as relocatable objects,
|
||||
// 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.
|
||||
|
||||
#include "shellApp.h"
|
||||
#include "shellInfo.h"
|
||||
#include "dvxDialog.h"
|
||||
#include "platform/dvxPlatform.h"
|
||||
|
||||
|
|
@ -260,9 +259,6 @@ int main(void) {
|
|||
// roughly twice as many scheduling turns as any single app.
|
||||
tsSetPriority(0, TS_PRIORITY_HIGH);
|
||||
|
||||
// Gather system information (CPU, memory, drives, etc.)
|
||||
shellInfoInit(&sCtx);
|
||||
|
||||
// Register DXE export table
|
||||
shellExportInit();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue