Skip to content

Releases: Darkone83/XbDiag

1.0.11 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 11 Jul 23:17
4c60fbf

XbDiag 1.0.11 Beta — Changelog

A big thank you to the original Xbox community for the feedback and testing
that helped shape this release. Your reports, suggestions, and real-world
testing on hardware are what drive XbDiag forward — it is appreciated more
than you know.


New Features

SysInfo — EOS Modchip Detection (SysInfo.cpp)

XbDiag now identifies the EOS LPC BIOS-loader modchip (Team Resurgent /
Darkone) as its own chip rather than reporting it as a Xenium.

EOS is a clean-room design that implements the Xenium banking convention on
purpose — its bank register lives at I/O 0x00EF with the same low-nibble
1-10 encoding — so the existing banking probe matches it exactly as it matches
a genuine Xenium. Banking alone cannot tell the two apart. EOS additionally
decodes I/O 0x00EE and returns a fixed 0x55 there (a Darkone signature
byte; unconditional, read-only, no side effects). A real Xenium's 0x00EE is a
two-bit LED/control field that reads 0x00-0x03 and can never return 0x55.

DetectModchip now reads 0x00EE immediately after the 0x00EF banking probe
matches: 0x55 reports EOS, anything else reports Xenium. The check is one
extra read-only port access on the LPC bus the probe already uses, and it is
the only way to distinguish the two — no other signature separates a clean-room
Xenium-banking chip from the original. A genuine Xenium is unaffected and
reports exactly as before.

SmBusScan — EOS Device and Register Map (SmBusScan.cpp)

The SMBus scanner now recognises the EOS modchip at 7-bit address 0x6E
(sw-shifted 0xDC) as a known device instead of an unidentified ACK. The grid
entry reads "EOS — EOS LPC BIOS-loader modchip (Team Resurgent / Darkone)".

A register descriptor table has been added so the [A] register read labels each
EOS register: MAGIC (0xD8 Darkone signature), firmware version major / minor /
patch, live STATUS and ENGINE state, and the two lock-mask bytes. Labels are
taken directly from the EOS firmware register map. The CRC result and
last-command registers are internal to the update flow and are intentionally
omitted from the scan view — they carry no meaning outside an active update, and
the detail panel shows at most eight registers.

Note that STATUS and ENGINE are live: they reflect what EOS is doing at scan
time, so they will read differently depending on whether the chip is idle,
preloading, or mid-update. MAGIC and the version bytes are the only constant
identifiers.

Controller Test — Configurable Drift Warn Gate (ControllerTest.cpp)

The Drift card now supports a user-adjustable warn threshold to eliminate
false positives. The pass/fail threshold was previously a fixed 4% of full
scale; it is now a configurable gate from 0 to 20%.

The intended workflow: hold a known-good controller and capture the gate from
its measured drift, then test a new or suspect controller against the same
number. A pad is only flagged when it genuinely drifts more than the reference.

Controls on the Drift card: DPAD Up / Down nudge the gate by 1% per press; [Y]
captures the gate from the current measured drift (the worse of the two sticks,
plus a small margin, clamped to the 0-20% window); [X] is unchanged and still
resets the samples. The readout shows the active gate value and its source —
captured, manual, or the fixed default. With the gate left at 0 the card
behaves exactly as before, using the standard 4% threshold, so the change is
opt-in.

The Drift card already sampled raw unfiltered stick values with automatic
baseline capture and ADC jitter nulling; the gate builds on that existing
machinery without altering it.


Files Changed

  • SysInfo.cpp
  • SmBusScan.cpp
  • ControllerTest.cpp

1.0.10 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 15 May 02:34

XbDiag 1.0.10 Beta — Changelog

A big thank you to the original Xbox community for the feedback and testing
that helped shape this release. Your reports, suggestions, and real-world
testing on hardware are what drive XbDiag forward — it is appreciated more
than you know.


Bug Fixes

SysInfo — Rev 1.6 Ambient Temperature Scaling (SysInfo.cpp)

On rev 1.6 hardware the PIC proxy returns a raw ambient reading that requires
a 0.8x scaling correction before display — the same correction applied by
TempMonitor and referenced in PrometheOS xboxConfig. SysInfo was storing the
raw averaged value directly, causing ambient temperature to read high compared
to every other tool on 1.6 hardware. The correction is applied after averaging
the 3-sample PIC read, inside the PIC-only block — rev 1.0-1.5 ADM1032
readings are unaffected.

TempMonitor — Sensor Wait Message (TempMonitor.cpp)

While the sensor path is being detected or the rev 1.6 PIC accumulator is
filling, the module previously showed raw SMBus NAK strings in red implying
a hardware fault during normal initialisation. Replaced with friendly dim grey
messages centred in the graph area: "Please wait — reading sensor..." when path
is unknown, "Please wait — reading temperature data..." when path is known but
the accumulator has not yet committed.

FileExplorer — Cache Volumes X and Y Now Visible (FileExplorer.cpp)

Cache partitions X: and Y: were silently omitted from the drive list because
FindFirstFile("X:\*") returns INVALID_HANDLE_VALUE on empty volumes. The HDD
drive probe now uses GetFileAttributesA on the root path — the same approach
already used for MU detection — which succeeds on any accessible volume
regardless of whether it contains files.

LCD — Display Detection Regression Fixed (Lcd.cpp)

A regression introduced after 1.0.3 caused the physical LCD display to never
initialise on any hardware. The CerBiosOwnsLCD() function had an
IoCreateSymbolicLink call added to mount E: before reading cerbios.ini. On
systems where E: is already correctly mounted by the kernel this call either
failed with an unexpected return code or introduced a conflicting symlink,
corrupting SMBus state before the detection probe fired. The function has been
reverted to the 1.0.3 approach of opening cerbios.ini directly with
CreateFileA, which returns false immediately on non-CerBIOS installs with no
bus interaction. The call site has also been corrected to pass
(BYTE)(LCD_ADDR >> 1) rather than the hardcoded literal 0x3C.

LCD — FTP Progress Bar (Lcd.cpp)

The PUT transfer progress bar previously used GetTickCount() % 101 to generate
a fake percentage, producing a jittery sweep that conveyed no real information.
PUT and DIR transfers now show a ping-pong spinner where a '>' character
bounces smoothly across the bar at 120ms per step, making it clear a transfer
is active without implying false progress. GET transfers retain the deterministic
fill bar with real percentage since the total file size is known.

The refresh rate values for interlaced modes in the mode table were incorrectly
set to the field rate rather than the frame rate. 480i and 1080i are now 30Hz
and 576i PAL is now 25Hz — reflecting the correct frame rate that the hardware
delivers. Progressive modes 480p and 720p remain at 60Hz and 50Hz respectively.

VideoInfo — Interlaced Mode Refresh Rates Corrected (VideoInfo.cpp)

The refresh rate values for interlaced modes in the mode table were incorrectly
set to the field rate rather than the frame rate. 480i and 1080i are now 30Hz
and 576i PAL is now 25Hz — reflecting the correct frame rate that the hardware
delivers. Progressive modes 480p and 720p remain at 60Hz and 50Hz respectively.

VideoInfo — NKPatcher Detection Path Corrected (VideoInfo.cpp)

The NKPatcher detection check was looking for C:\nkpatcher\ which lives on real
Partition2 — invisible when ShadowC is active and C:\ is remapped to a virtual
image. Detection now checks E:\NKP11, E:\NKP10, and E:\NKPatcher\ — all known
NKPatcher config directories — covering Rocky5 1.1, Rocky5 1.0, and standalone
installs across all versions.

VideoInfo — NKPatcher Warning Overlay Not Rendering (VideoInfo.cpp)

The warning overlay was not visible despite the correct code path executing.
RenderNKWarn was calling the main Render() function which completed its own
BeginScene/EndScene/Present cycle, leaving all overlay draws outside any active
scene. RenderNKWarn now manages its own full scene independently — BeginScene,
DrawPageChrome, dim backdrop, warning card, text, EndScene, Present.

FileExplorer — ShadowC Real C Partition Access (FileExplorer.cpp)

The ShadowC detection check shared the same incorrect C:\nkpatcher\ path.
Detection updated to probe E:\NKP11, E:\NKP10, and E:\NKPatcher\ for full
version coverage. After detection, IoDeleteSymbolicLink clears any stale N:
mapping then IoCreateSymbolicLink maps N: to \Device\Harddisk0\Partition14
(Rocky5 NKP11 ACTUAL_C_DRIVE) with fallback to Partition6 for older configs.
Mount is verified by checking N:\ accessibility before adding to the drive list.

About — Typo and Calibration-Aware Centering (AboutScreen.cpp)

"Bonb Bloke" corrected to "Bomb Bloke". All centred text updated to use the
calibrated area centre rather than raw SW / 2, so items remain properly centred
on displays with non-zero margin settings. Left-aligned text and horizontal rules
use g_marginL / g_marginR rather than the hardcoded LM constant.


Improvements

SysInfo — BIOS Row Removed (SysInfo.cpp / SysInfo.h / HttpRptSrv.cpp)

The BIOS row previously showed "See VideoInfo" which confused users expecting
a version string. Reliable BIOS detection requires parsing mod-chip-specific
flash layouts which differ across Evox, X2, Cerbios, and retail — not safe to
scan blindly. The row has been removed from the on-screen display, text export,
HTTP server BIOS card, and SysSnapshot struct entirely. biosVer removed from
SysData.

SysInfo — TSOP Info Button Label (SysInfo.cpp)

[X] Flash renamed to [X] TSOP Info across all hint bar states. The previous
label implied a flash write operation, causing user confusion.

SysInfo — Encoder ID Row Removed (SysInfo.cpp)

The ENC ID row showing the raw encoder chip ID byte in hex has been removed
from the VIDEO section. The encoder name already conveys the relevant
information and the raw ID byte was consuming valuable vertical space in the
right column. encId removed from SysData. The local encId variable used
internally for board revision detection and encoder name lookup is retained.

HddInfo — Security Status Display (HddInfo.cpp / HddInfo.h)

The two-row SUPPORT: YES/NO + LOCKED: YES/NO display has been replaced with a
single SECURITY row giving a meaningful status: Not Supported, Not Enabled,
Locked, or Enabled / Unlocked. Not Enabled is shown in white — it is entirely
normal for hardmodded consoles with replacement HDDs which ship without security
enabled. secEnabled (word 128 bit 1) added to HddData. Report export updated.

HddInfo — Total Partition Size in Bar (HddInfo.cpp)

The total partition size is now drawn centred inside each partition usage bar,
giving an at-a-glance capacity reference alongside the free space label.

HddInfo — Partition Size in MB Below 1GB (HddInfo.cpp)

Partitions smaller than 1GB now display their total and free values in MB rather
than as a fractional GB figure. 820 MB is clearer than 0.8 GB, particularly for
the small system partitions C, X, Y, and Z on a stock drive.

HddInfo — Partition Cluster Size Validation (HddInfo.cpp / HddInfo.h)

Each partition now displays its cluster size alongside the free space label using
XGetDiskClusterSizeA. Cluster size is validated against the partition total using
standard FATX guidance — 16KB clusters up to 256GB, 32KB up to 512GB, doubling
per power of two thereafter. Valid sizes are shown in green, undersized
configurations in amber. Cluster data is also included in the text export with an
[UNDERSIZED] flag where applicable.

VideoInfo — Xcalibur 1080i Unblocked (VideoInfo.cpp)

Rev 1.6 Xcalibur hardware previously had 1080i hard-blocked with "NO XCALIBUR
MAP". The kernel programs the Xcalibur encoder internally during mode switches
without needing userspace register writes. Xcalibur 1080i is now treated
identically to Conexant 1080i, marked EXPERIMENTAL in amber and added to the
selectable mode list.

VideoInfo — Mode Test Respects Calibration Data (VideoInfo.cpp)

The mode test overlay was drawn at a hardcoded position relative to the raw
screen edge, causing hint text and the mode list to be cut off on overscanned
displays even when calibration data was present. The overlay now anchors to
g_marginB so its position respects screen.set calibration settings.

Update — Changelog Scroll Speed Control (Update.cpp)

The changelog scroll now responds to the left thumbstick Y axis. Pushing up
increases scroll speed up to 8x, pulling down reverses scroll. [BLACK] toggles
pause and resume — the hint bar updates dynamically. [A] is unchanged.

Screen Calibration — Default Margins Corrected (ScreenCalib.cpp)

ApplyDefaults previously set g_marginL and g_marginR to LM (48px) causing the
chrome to be unnecessarily inset on modern displays and xemu. Defaults are now
zero horizontal margins and natural CONTENT_Y / BOT_BAR_Y for vertical — full
resolution out of the box. CRT users who need overscan compensation run
calibration and save their own settings.

Screen Calibration — Input Anti-Fire Guard (DiagMenu.cpp)

Returning from calibration via [A] confirm could immediately trigger a menu
selection on the next frame because the button release was not awaited. DiagMenu
now spins on PumpInput() + Sleep(10) until...

Read more

1.0.9 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 21 Apr 02:44

XbDiag 1.0.9 Beta — Changelog


New Features

HddSmart — Vendor SMART Database (HddSmartDB.hpp / HddSmart.cpp / HddSmart.h)

A self-contained vendor SMART attribute database replacing the previous flat name table. Attribute raw values are now decoded into human-readable strings instead of being displayed as raw hex bytes. The database is implemented as a single .hpp file included exclusively by HddSmart.cpp — no additional translation unit or linker entry required.

Architecture — three-layer lookup

  1. Vendor prefix table — model string prefix match, first match wins. Covers 99 prefixes across 20 vendor/controller families.
  2. Default attribute table — de facto standard attribute meanings used by the vast majority of drives regardless of vendor. 40 entries covering all commonly reported IDs.
  3. Fallback — unknown attributes display as Attr 0xXX with full 6-byte hex raw value.

Raw format decode (RawFmt enum — 12 types)

Format Output example Basis
RF_HEX 00 00 00 2B 00 00 Opaque/vendor-specific fallback
RF_COUNT32 8760 Lower 32-bit plain decimal
RF_HOURS 8760h Lower 24 bits — matches smartmontools raw24(raw8)
RF_MINUTES 146h 0m Lower 32 bits ÷ 60 — matches min2hour
RF_SECONDS 2h 3m 4s Lower 32 bits in seconds — matches sec2hour
RF_TEMP 43C (22/55) Byte[0]=current°C, bytes[2/3]=min/max with smartmontools sanity gate
RF_SECTORS 12 sct Lower 16 bits
RF_PERCENT 87% Byte[0] as percentage
RF_RAW16 4391 Lower 16 bits — Seagate error rate style
RF_RAW16_OPT16 0 (2100) Lower 16 primary + upper 16 in parens if nonzero — matches raw16(raw16)
RF_RAW16_AVG16 450ms avg:445ms Spin-up time ms + optional average — matches raw16(avg16)
RF_GIB 3200 GiB Lower 32 bits labelled GiB for SSD lifetime writes/reads

0xA8 and 0xC7 are particularly relevant on original Xbox hardware where 20-year-old IDE cables and IDE-to-SATA adapters of varying quality are the most common source of bus errors.

Vendor coverage (99 prefixes, 20 tables)

HDD families: Seagate (all ST), WD (all Caviar/colour lines), Samsung SpinPoint (SP/HD), IBM/early Hitachi Deskstar (DTLA/IC35), Hitachi/HGST (HDS/HDT/HUA/HTE), Toshiba 2.5" MK (power-on in minutes), Toshiba 3.5" DT/MD/MG (power-on in hours), Fujitsu (MHT/MHV/MHS/MHY/MHZ — original Xbox OEM), Maxtor DiamondMax (6Y/6L/7Y/7L — OEM Xbox era), Quantum Fireball.

SSD controller families: Samsung (own controller — 840/850/860/870), Intel (SSDSA/SSDSC), Crucial/Micron (CT/MTFD — Marvell/Silicon Motion), SandForce (OCZ/Kingston HyperX/Corsair Force/ADATA SP/Mushkin), Phison (Kingston A400/UV/PNY/Patriot/Team Group), Silicon Motion (ADATA SU/SPCC/Transcend/Gigabyte/KingFast/KingSpec/Intenso), Marvell (SanDisk/WD SSD/Plextor), SK Hynix (HFS/HFM).

Export updated

Column header renamed from RAW VALUE to VALUE. Decoded value shown in the export alongside the data, matching the on-screen display. Raw hex is preserved in the export for attributes using RF_HEX where the decode is intentionally opaque.


Stress Test — Fan Speed Control (StressTest.cpp / StressTestCPU.cpp / StressTest.h)

Manual fan speed override added as a step in the CPU stress test startup wizard. The SMC is fully overridden using the correct two-register PIC protocol confirmed by xboxdevwiki.

Startup wizard flow

IDLE →[A]→ THRESHOLD →[A]→ FAN →[A]→ CONFIRM →[LT+RT]→ RUNNING

Back navigation: [B] from FAN returns to THRESHOLD, [B] from THRESHOLD returns to IDLE.

Fan Speed overlay (SSTATE_FAN)

  • AUTO / MANUAL mode pills (green = auto, orange = manual) toggled with [X]
  • In MANUAL mode: [LT] / [RT] step fan target in 5% increments (0–100%)
  • Big percentage readout with left/right arrow hints when in MANUAL mode
  • AUTO mode shows "SMC controls fan speed" message
  • [A] applies and proceeds to CONFIRM; [B] cancels and returns to THRESHOLD

PIC register protocol (xboxdevwiki)

Per the xboxdevwiki PIC register table, fan override requires two writes in sequence — writing only to the speed register is silently ignored:

reg 0x05 = fan mode:  0 = automatic (SMC), 1 = custom speed from reg 0x06
reg 0x06 = fan speed: 0..50 (multiply by 2 for 0–100%)

Both registers are written every 500ms (render tick rate) during SSTATE_RUNNING to maintain the override against the SMC's continuous thermal management loop, which updates the fan registers independently and would otherwise reclaim control between writes.

On module exit ([B] from IDLE), ST_CPU_FanRelease() writes 0x05=0 and 0x06=0 to restore SMC automatic fan control.

StressTest.h — new enum value

SSTATE_FAN added between SSTATE_THRESHOLD and SSTATE_CONFIRM.

SSTATE_THRESHOLD and SSTATE_FAN added to the anythingRunning guard — card navigation is blocked while either overlay is open.

New public API (StressTestCPU.h)

void ST_CPU_FanToggleAuto();   // toggle AUTO ↔ MANUAL
void ST_CPU_FanStep(int delta);// ±1 step (5%), MANUAL only
void ST_CPU_FanApply();        // write PIC regs 0x05+0x06, proceed
void ST_CPU_FanCancel();       // revert to AUTO, no PIC write
void ST_CPU_FanRelease();      // restore SMC control on module exit
bool ST_CPU_FanIsAuto();       // query mode for input gating
int  ST_CPU_FanGetPct();       // query current target percentage

Improvements

ControllerTest — Layout (ControllerTest.cpp)

  • Trigger bars moved alongside the port status strip (same vertical band, left/right flanking) — freed space allows sticks, D-pad, and face buttons to fit without clipping below BOT_BAR_Y = 416
  • Trigger bar label moved to the right of the bar to clear the top chrome
  • All Y constants tightened to the new 358px usable height: Y_TRIG=34, Y_META=108, Y_STICK=170, Y_DPAD=Y_FACE=298
  • Diamond bottom lands at y≈408 — 8px clearance above bottom bar

AboutScreen — Credit Card Centering and Fact Ticker (AboutScreen.cpp)

  • Logo + name block now centered vertically within each credit card using a computed block height (LOGO_DISP_H + 6 + LINE_H) — previously a fixed offset from card top caused visual misalignment
  • Fact ticker repositioned from hardcoded BOT_BAR_Y - 24 (which overlapped the card bottoms at the new BOT_BAR_Y = 416) to dynamically computed center of the gap between card bottom and panel bottom

Bug Fixes

Stress Test — Fan Not Released on Thermal Abort (StressTestCPU.cpp)

When the thermal abort fired, s_state was set to SSTATE_IDLE and s_thermalAbort flagged, but ST_CPU_FanRelease() was never called. The fan remained locked at the manual PIC target (both reg 0x05 in manual mode and reg 0x06 at the set speed) while the CPU was already over threshold and the SMC could not compensate. ST_CPU_FanRelease() is now called immediately in the abort branch so the SMC resumes thermal fan control the moment the abort is detected.

Stress Test — Confirm Overlay Shows No Settings Summary (StressTestCPU.cpp)

DrawConfirmOverlay previously showed only a generic "START CPU STRESS TEST?" prompt with no recap of the wizard configuration. After stepping through two picker screens the user had no way to review their choices before committing. The overlay now shows the configured abort temperature (colour-coded green / orange / red) and fan mode (AUTO in green, MANUAL XX% in orange) above the LT+RT hold prompt.

Stress Test — AutoRun Inherits Manual Fan State (StressTest.cpp)

StressTest_AutoRun() bypasses the interactive wizard and writes directly to SSTATE_RUNNING. If a prior interactive session left s_fanAuto = false (a manual fan target active), that override would persist into the headless run with no mechanism to re-apply or release it. ST_CPU_FanRelease() is now called at the top of AutoRun to guarantee SMC fan control regardless of prior session state.

HddInfo — SMART Tab Scroll Never Resets (HddInfo.cpp)

HddSmart_ResetScroll() was declared, implemented, and documented in HddSmart.h as needing to be called from HddInfo when switching to the SMART tab, but the call was never wired. The scroll position carried over from the previous visit every time. The call is now made at the s_view = VIEW_SMART transition.

StressTestGPU — strlen Build Constraint Violation (StressTestGPU.cpp)

strlen(cs_vsSource) was used to compute the vertex shader assembly source length in CS_CreateVS(). While functionally safe on a compile-time string, this violated the no-CRT build constraint. Replaced with StrLen().

XbSet — Float-to-i...

Read more

1.0.8 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 17 Apr 17:10

XbDiag 1.0.8 Beta — Changelog


New Features

Web Dashboard — HttpRptSrv (HttpRptSrv.cpp / HttpRptSrv.h)

A background HTTP server running on port 80, started automatically at boot
alongside the FTP server. No user interaction required — the server is always
available while XbDiag is running. Access from any browser on the same network
via http://<xbox-ip>/.

Architecture

  • Single-threaded, polled once per frame via HttpRptSrv_Poll() in the main loop
  • Non-blocking select() with zero timeout — never stalls the frame loop
  • One connection served per frame. Response body sent in 4KB chunks
  • HTTP/1.0, Connection: close. Single 128KB response buffer
  • Network stack (XNet/Winsock) brought up by the update checker before
    HttpRptSrv_Start() is called — no duplicate init
  • Socket bound using SO_REUSEADDR as DWORD, INADDR_ANY — mirrors the
    FTP server socket pattern exactly
  • Settings save uses GET /save?KEY=val&... query string encoding — avoids
    HTTP/1.0 POST body parsing limitations entirely

Pages

/sysinfo — Live hardware snapshot mirroring the System Info module.
Two-column card layout on desktop, single column on mobile. Live stress test
status banner and per-test data cards (CPU temp/fan, RAM sweeps/errors,
GPU loops/FPS) appear automatically when a stress test is running. Page
auto-refreshes every 30 seconds.

/report — Report file viewer. Auto-detects the first existing report file
on D:\. Smarter empty state — checks whether XbDiag.set exists and
tailors the prompt accordingly. File switcher pills link to all text exports.

/settings — Full XbSet editor. CSS toggle switches for all 11 module and
stress toggles, hour/minute spinners for all three stress durations, loops
counter, and the two run option toggles. Sticky save bar always visible while
scrolling. Save via GET /save writes D:\XbDiag.set by calling
XbSet_SaveSettings() directly — identical format and write path to the
on-screen editor. Save result banner (green/red) shown on redirect back.
Export files section at the bottom lists all XbDiag output files with download
links for binary files (bios.bin, eeprom.bin).

/about — About page. XbDiag logo as a hero image, version string from
Update_GetLocalVersion(), platform info, tool description, and Team
Resurgent / Darkone83 / Darkone Customs branding logos embedded as base64 PNG.

/download?f=<filename> — Binary file download. Streams files of any size
in 4KB chunks with Content-Disposition: attachment. No FTP required for
binary exports.

Design

  • Dark dashboard aesthetic — #06080F background, #50DCFF cyan accents,
    #50DC64 green, #FFA028 orange
  • Inter (sans-serif) for UI chrome and labels, JetBrains Mono for values and
    report viewer
  • Animated background grid, pulsing logo ring animation, blinking ONLINE
    status indicator, glowing value text shadows, CSS-only toggle switches with
    animated knobs
  • Fully responsive — two-column card layout on desktop, single column on
    mobile. Tested on iOS Safari
  • All assets (CSS, fonts via Google Fonts CDN, images) fully self-contained
    in the HTTP response — no separate file serving required
  • Team branding logos embedded as base64 PNG — no filesystem dependency

main.cpp hooks (3 lines)

#include "HttpRptSrv.h"
HttpRptSrv_Start();    // after Update_StartBootCheck()
HttpRptSrv_Poll();     // alongside FtpServ_Tick() in main loop

SysInfo accessor added
SysInfo_GetSnapshot(SysSnapshot& out) exposes all SysData fields as const
char pointers for the web server. Returns false if data not yet loaded.


Improvements

DiagCommon — CRT Title Safe Area (DiagCommon.h / DiagCommon.cpp)

  • BOT_BAR_H increased from 30.f to 64.f; BOT_BAR_Y raised from
    450.f to 416.f
  • Places bottom bar hint text at design-space y≈443 — within the XDK-specified
    7.5% title safe boundary (y < 444 at 480 design units) on all CRT displays
  • Top and bottom bars continue to bleed to physical screen edges; only content
    positioning is affected
  • All modules using BOT_BAR_Y as their content lower limit automatically gain
    34px of additional usable vertical space — zero module code changes required
  • Title text in DrawPageChrome corrected from hardcoded SW - 10.f to
    SW - LM to respect the right content margin on all display types
  • g_overscanX / g_overscanY globals and DiagCommon_SetOverscan() removed —
    overscan compensation is now baked into the layout constants directly,
    eliminating the __ftol2_sse linker error that the runtime approach caused

HddSmart — Scrolling (HddSmart.cpp)

  • SMART attribute table now scrolls with [DPAD UP] / [DPAD DOWN]
  • Visible row count calculated dynamically from available content area:
    Ftoi((BOT_BAR_Y - firstRowY) / LH2) — currently 19 rows at the updated
    BOT_BAR_Y = 416
  • Drives with fewer than 19 attributes show no scroll indicators; behaviour
    is identical to before for those drives
  • ^ more indicator right-aligned in the header row when scrolled down from top
  • v N more indicator below the last visible row showing remaining count
  • Proportional scrollbar on the right edge (3px track + thumb)
  • s_smartScrollRst flag resets scroll to top on view entry — call
    HddSmart_ResetScroll() from HddInfo when switching to the SMART tab
  • Critical attribute rows (reallocated sectors, pending sectors, uncorrectable
    sectors with non-zero raw values) now highlight in dark red with attribute
    name drawn in COL_RED — more visually distinct than the previous grey
  • File-scope SmartRow struct and s_smartRows[] array replace the per-frame
    local allocation; all declarations hoisted to function top for C89 compliance

Update — Changelog Box Clipping (Update.cpp)

  • Fixed text bleeding above and below the changelog frame borders on scroll
  • Draw condition tightened from partial-overlap check to strict containment:
    lines only render when lineY >= CT + 2.f && lineY + LINE_H <= CT + CH
  • Prevents partial lines drawing into the box border, the title label area
    above, and the bottom bar below — clean entry and exit on both edges as the
    auto-scroll cycles

Files Changed

  • HttpRptSrv.h (new)
  • HttpRptSrv.cpp (new)
  • SysInfo.h
  • SysInfo.cpp
  • DiagCommon.h
  • DiagCommon.cpp
  • HddSmart.cpp
  • Update.cpp
  • main.cpp

1.0.7 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 16 Apr 04:24

Note: 1.0.7 Beta needs to be installed manually due to how the updater processes

XbDiag 1.0.7 Beta — Changelog


Bug Fixes

SysInfo — Softmod hardware freeze on entry (DiagCommon.cpp)

  • Fixed a 100%-reproducible hang at "Reading data..." on softmodded consoles.
  • Root cause: softmod exploits hijack execution mid-game and can leave the nForce SMBus controller with a stuck in-progress transaction. HalReadSMBusValue's internal retry loop has no hard timeout — it spins indefinitely if the controller never clears, causing a permanent freeze before any hardware data is read.
  • Fix: added SMBusControllerReset() to DiagCommon.cpp. Writes 0xFF to the nForce SMBus Global Status register at I/O 0xC000 (W1C — clears all pending/error/busy bits), then stalls 2ms for the bus to settle. Called once at the top of ReadSysData() before any SMBus probing begins. Safe and a no-op on hardware that is already idle.
  • KeStallExecutionProcessor consolidated into the shared extern "C" block in DiagCommon.cpp.

SysInfo — Hard crash on entry on 1.6 hardware (SysInfo.cpp)

  • Fixed a hard crash at "Reading hardware..." affecting all 1.6 boards regardless of boot method.
  • Root cause: DetectBoardRevision() performed a raw MMIO dereference at 0xFD101000 (NV2A PFB block) to read DRAM strap bits distinguishing 1.6 from 1.6b. D3D context teardown from the dashboard leaves the PFB block in a state where this read triggers a machine check, causing a hard reset.
  • Fix: removed the EMRS dereference entirely. All P2L boards now report "1.6". The 1.6 vs 1.6b distinction (Samsung vs Hynix DRAM) is cosmetic — both are functionally identical for all diagnostic purposes.

SysInfo — BIOS dump writing to wrong path (SysInfo.cpp)

  • Fixed DumpBios() writing bios.bin to the current drive root rather than D:.
  • CreateFileA("\\bios.bin", ...) resolves relative to the XBE launch drive which may not be D:. Changed to explicit "D:\\bios.bin" matching all other flat export paths in XbDiag.

StressTestRAM — Overscan layout issues (StressTestRAM.cpp)

  • Phase label text overflowing the left panel boundary on standard TVs — all 11 phase label strings shortened to fit within the narrowed column.
  • COL_SPLIT nudged from 300 to 310 giving the left panel additional breathing room.
  • GRID_LM offset reduced from +30 to +24 to compensate, keeping the right grid balanced.
  • Idle hint string shortened to reduce bottom bar crowding.

New Features

SysInfo — Hardware Registers panel (SysInfo.cpp)

  • New [BLACK] overlay panel: Hardware Registers. Opens on demand, [A] refreshes live, [BLACK] closes.
  • Left — IDE Bus Master (BAR4 @ 0xFF60): Reads BM Command (0xFF60), BM Status (0xFF62), and PRD table address (0xFF64). Decodes ACTIVE, INTR, D0/D1 capability bits individually. Summary uses INTR and PRD as DMA evidence — MCPX programs DMA without ATA SET FEATURES so capability bits 5/6 are unreliable.
  • Right — NVNet NIC I/O (0xE000–0xE007): Raw 8-byte read. All-zero expected without full driver init. Displayed with contextual note.
  • Right — SMBus BAR2 (0xC200–0xC21F): 32-byte raw research dump of the undocumented secondary SMBus I/O window. Values are static init-time configuration. Board-revision cross-reference note included.

SmBusScan — Controller health panel (SmBusScan.cpp)

  • New [WHITE] overlay panel: SMBus Controller Health + BAR2 Research Dump. Opens on demand, [A] refreshes, [WHITE] closes.
  • BAR1 section: Reads Global Status (0xC000) and Global Enable (0xC002). Decodes and color-codes INTER, DEV_ERR, BUS_ERR, FAILED bits individually.
  • BAR2 section: Raw 32-byte hex dump of 0xC200–0xC21F as two rows of 16. Non-zero bytes highlighted white.

Stress Test — GPU Stress card (StressTestGPU.cpp / StressTestGPU.h)

  • New third stress card: GPU. Navigate with [Left]/[Right] alongside the existing CPU and RAM cards.
  • Runs the Crystalline Grotto scene (CrystalScene) as a continuous NV2A GPU workload: ~344K crystal tri submissions per frame across 16 DOT3/cubemap render passes, ~110K cave mesh tri submissions (drawn 3x), 120 billboarded fog quads. Pushes fill-rate, texture bandwidth, and vertex throughput simultaneously.
  • Scene loops every 20 seconds. Total elapsed time, loop count, live FPS, peak FPS, min FPS, CPU temp, and fan speed displayed in a two-row overlay strip at the bottom of the screen.
  • Abort: hold [Back]+[A] for 5 seconds — same UX as CPU and RAM cards. LT+RT confirm gate before starting.
  • Textures loaded from D:\tex\ (crystal_n.dds, crystal_cube.dds, rock.dds) with procedural fallbacks if files are absent.
  • CrystalScene code is fully self-contained within StressTestGPU.cpp — no separate CrystalScene dependency.

XbSet — GPU Stress automation (XbSet.cpp / XbSet.h)

  • GPU stress test added to XbSet automation: GPUSTRESS=0/1, GPU_HRS=N, GPU_MIN=N settings.
  • GPU stress runs headlessly for the configured duration, loops the scene, and reports peak FPS, min FPS, scene loop count, and pass/fail result to D:\XbDiag.txt.
  • Settings UI updated with GPU STRESS toggle, GPU HOURS, and GPU MINS rows. Settings list now scrolls — all rows accessible regardless of screen height.

Update — XBA archive-based update delivery (Update.cpp)

  • Update flow now downloads a single update.xba archive rather than individual files.
  • Archive is extracted to D:\ via the built-in XBA engine, which handles directory creation, CRC verification, and multi-codec decompression. All assets (XBE, textures, and any future additions) are delivered in one atomic operation.
  • Temp archive (D:\update.xba) is always deleted after extraction whether it succeeds or fails.
  • XbDiag.ver is still downloaded last as a commit marker — only written on successful extraction.
  • Adding new assets to a future update requires only rebuilding update.xba on the server — no code changes needed.
  • Extraction progress displayed using the existing progress bar. Status label distinguishes download phase from extraction phase.

Improvements

SmBusScan — Known device table corrections (SmBusScan.cpp)

  • EEPROM (0x54): Chip type corrected from 93LC56 (SPI) to 24LC-compatible (I2C). MAC offsets corrected from 0xEA–0xEF to 0x40–0x45. Added 0xA8–0xAB=HDD key. Count updated 5→8.
  • PIC16L (0x10) register descriptors: Expanded from 3 to 7 entries. Added 0x09 CPU temp, 0x0A MB temp, 0x10 fan speed readback, 0x06 fan mode.
  • ADM1032 (0x4C) register descriptors: Corrected high limit registers, added fractional byte 0x10 and THERM limit 0x19. Count updated 4→8.
  • Dead code removed: s_regs_smc was defined but never wired — removed.

TempMonitor — Xyclops 1.6 SMC handling (TempMonitor.cpp)

  • The SMC on 1.6 hardware is Xyclops (8051 core), not PIC16LC63A. Xyclops does not implement temperature registers at 0x09/0x0A — confirmed NAK on all tested 1.6 hardware.
  • Previously showed a generic red "PIC NOT RESPONDING" error. Now shows an informational grey "N/A — Xyclops SMC detected" overlay with explanation. Sensor divider label updates to "XYCLOPS". Bottom bar shows "Xyclops 1.6 SMC — temp N/A".
  • OnEnter() now resets s_path, s_xyclopsNoTemp, and all PIC accumulator fields — stale state from AutoRun or a previous session no longer carries over.

StressTest — GPU overlay layout (StressTestGPU.cpp)

  • GPU stress overlay expanded to two rows to eliminate text overlap at all resolutions.
  • Row 1: ELAPSED / LOOPS / FPS / PEAK / MIN — left-anchored with TW()-based flowing spacing, resolution independent.
  • Row 2: CPU temp / FAN speed left-anchored, abort hint right-aligned.
  • Strip height increased from 26px to 38px; abort hold bar repositioned accordingly.

Research Findings

SMBus BAR2 (0xC200–0xC21F) — first public read

  • Confirmed non-trivial, static data on a 1.3 board: 0x70 at offset +0x00, 0x0E at offset +0x10. All other bytes zero.
  • Values do not change with SMBus activity — rules out a transaction log.
  • Best hypothesis: static init-time clock/timing configuration written by 2BL. 0x70 = 112 maps to approximately 297 kHz at 33 MHz PCI clock — plausible SMBus clock prescaler.
  • Cross-board validation ongoing. Community encouraged to report BAR2 values with board revision.

IDE Bus Master (BAR4 0xFF62) — MCPX DMA behaviour confirmed

  • BM Status capability bits 5/6 not set by MCPX even when DMA is active — confirms MCPX programs DMA without ATA SET FEATURES.
  • INTR bit (2) and non-zero PRD address are the reliable DMA-used indicators on Xbox hardware.

Files Changed

  • DiagCommon.cpp
  • SysInfo.cpp
  • SmBusScan.cpp
  • StressTestRAM.cpp
  • TempMonitor.cpp
  • StressTest.h
  • StressTest.cpp
  • StressTestCPU.cpp
  • StressTestGPU.h (new)
  • StressTestGPU.cpp (new)
  • XbSet.h
  • XbSet.cpp
  • Update.cpp

1.0.6 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 22 Mar 20:18

Development Note — Stress Test Thermal Soak (Research Ongoing)
CPU stress test thermal soak behaviour is under active research. Current work is focused on validating that the SSE/x87/integer compute mix combined with memory flood interleaving produces consistent platform-wide heat rather than core-local utilisation only. MEM_BURST_CYCLES has been set to 16 and MEM_BURST_MS to 30 to increase uninterrupted CPU burn time between memory flood bursts. SM_SSE_OUTER has been bumped from 128 to 256 to extend sustained FP port saturation per outer iteration. Real hardware validation of the new thermal delta is pending.

[1.0.6 Beta]

New Features

MU Utilities Card (FileExplorer.cpp)

  • [Back+Black] on a Memory Unit entry at the drive root now opens a three-item MU Utilities card instead of immediately prompting to format. Card items: Format, Create Skeleton Key, Create ENDGAME. The hint bar text and overlay hint have been updated accordingly ([Back+Black] MU Utilities).
  • Card is rendered as a centred modal overlay (300×136 px, dark blue fill, cyan top border) with a navigable cursor ([DPAD Up/Down], [A] select, [B] cancel).

Skeleton Key MU Creation (FileExplorer.cpp, FileExplorerMU.cpp, FileExplorerMU.h)

  • New end-to-end flow for writing a Skeleton Key to a Memory Unit:
    1. Checks for D:\resources\SK.xba; if absent, offers to download from server ([A] Download / [B] Cancel).
    2. Downloads SK.xba via HTTP GET /xbdiag/resource/SK.xba from darkone83.myddns.me:8008 with a live KB progress bar.
    3. Confirms format + write ([A] Create / [B] Cancel), showing a file-count progress bar during extraction and copy.
    4. Reports success ([B] Close) or a two-line error message (type on line 1, detail on line 2).

ENDGAME MU Creation (FileExplorer.cpp, FileExplorerMU.cpp, FileExplorerMU.h)

  • Identical flow to Skeleton Key using D:\resources\ENDGAME.xba / server path /xbdiag/resource/ENDGAME.xba. Both assets share the same internal download and create helpers (MU_DownloadXba, MU_CreateFromXba).

XBA Archive Extractor (xba.cpp, xba.h) — new module

  • Self-contained XBA extractor supporting v1 (XBA\x01) and v2 (XBA\x02) archive formats. No CRT; no dynamic allocation; all buffers file-scope static; MSVC 2003 / C89 declaration ordering.
  • v1 compression: LZ77 (16 KB window), LZSS (32 KB window), x86 pre-filter variants, stored fallback. CRC32 verified against original unfiltered data.
  • v2 compression: per-block scheme (block size 64 KB) with stored, LZ77, LZSS, RLE, LZ77+Huffman, and LZSS+Huffman block types; optional whole-file x86 unfilter post-decode. Canonical Huffman codes rebuilt from 256-entry code-length table at decode time.
  • Public API: Xba_Extract(xbaPath, destFolder, progressFn, detailOut, detailLen) — returns typed XbaResult enum; Xba_ResultStr() for human-readable error strings.
  • Progress callback XbaProgressFn(filesDone, filesTotal, bytesDone, bytesTotal) drives the SK/EG in-progress overlay bar.

Improvements

MU Format refactor (FileExplorerMU.cpp)

  • FE_MU_Format() now performs a proper three-step remount sequence: (1) IoDismountVolume + MU_CloseDeviceObject to flush all pending I/O, (2) MU_CreateDeviceObject + format, (3) close and reopen the device object to force a clean FAT driver remount before rebinding the drive-letter symlink. Previously skipping the dismount step could leave the volume in a dirty state after subsequent writes.
  • Extracted MU_Remount() helper that dismounts and closes the MU volume; called at the end of MU_CreateFromXba to release the write session and prevent a stale volume object returning ERROR_DISK_FULL (112) on the next operation.

Destination picker now shows Memory Units (FileExplorerOps.cpp)

  • The copy/move destination picker previously listed only HDD partitions (C/E/F/G/X/Y/Z). It now also enumerates inserted Memory Units (A–H) using GetFileAttributesA on the MU root (reliable on empty MUs where FindFirstFile fails). Each MU entry is labelled P1 MMU1P4 MMU2 and stores its drive letter in sizeLow for picker navigation.

MU drive-letter fix in destination picker (FileExplorer.cpp)

  • When opening a drive from the picker at root level, the drive letter was previously always read from pe.name[0]. MU entries now correctly read the letter from pe.sizeLow (set by the picker enumeration), falling back to pe.name[0] only for HDD entries where sizeLow is zero. Affects both directory-open and root-fallback path in FOS_PICK_DEST.

Bug Fixes

Modal input auto-fire guard (FileExplorer.cpp)

  • Added s_muModalSkipInput flag. Whenever any MU modal opens (card, SK prompt, SK confirm, etc.), the first input tick is consumed before the modal begins processing buttons. Prevents analog [A] re-assertion from immediately selecting the first item after the modal opens on the same edge.
  • [A] and [B] are masked out of s_prevBtns at the exact tick the card closes or a state transition fires, so the downstream modal or main browser does not see the button as still held.

1.0.5 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 21 Mar 01:24

XbDiag Changelog


Development Note — March 2026
The CPU stress test thermal soak behaviour is under ongoing research. Current work is focused on validating that the SSE/x87/integer compute mix combined with the memory flood interleaving produces consistent platform-wide heat rather than core-local utilisation only. MEM_BURST_CYCLES has been set to 16 and MEM_BURST_MS to 30 to increase uninterrupted CPU burn time between memory flood bursts. SM_SSE_OUTER has been bumped from 128 to 256 to extend sustained FP port saturation per outer iteration. Real hardware validation of the new thermal delta is pending.


1.0.5 Beta — March 2026

Comment Cleanup

All source file comments have been cleaned up and better aligned. Stale comments removed.

StressTestCPU.cpp — CPU MHz Detection Fixes

PCI slot encoding bug corrected and crystal reference constant unified with SysInfo.cpp.

  • PCI slot encoding bug fixed: ULONG slot was computed as (dev & 0x1F) | ((func & 0x07) << 5) — dev and func bit fields were swapped, causing HalReadWritePCISpace to target PCI device 0 instead of device 3 (the MCPX). The correct encoding is ((dev & 0x1F) << 5) | (func & 0x07). The CPUMPLL register at offset 0x6C was silently reading garbage on every boot
  • XTAL_HZ constant unified: inline (50000000.0 / 3.0) replaced with static const double XTAL_HZ = 16666666.6667 matching SysInfo.cpp exactly — both modules now use the identical bit-for-bit crystal reference
  • FSB calculation cleaned up: spurious fsb_mhz intermediate removed; calculation now flows fsb_hz → cpu_mhz in a single expression matching SysInfo::MeasureCpuMHz() exactly
  • sLabel corrected: was "ICS + PIC" / "ICS + PIC (v1.6)" — the ICS clock generator is not involved in this detection path at all. Now correctly displays "MCPX PLL + MSR"

SysInfo.cpp — CPU MHz Detection Fixes

Same class of fixes applied to SysInfo.cpp to ensure both modules agree on all hardware configurations.

  • PCI slot encoding corrected to ((dev & 0x1F) << 5) | (func & 0x07) in PciRead32() — previously the same dev/func swap bug affected OC detection and NV2A vendor checks
  • XTAL_HZ constant already present and authoritative in this module — StressTestCPU.cpp now matches it exactly

StressMath.cpp / StressMath.h — Stress Test Thermal Tuning

CPU stress kernel and memory flood timing adjusted to maximise sustained FP port saturation and improve thermal delta on upgraded systems.

  • SM_SSE_OUTER increased from 128 to 256 — doubles the number of consecutive SSE MULPS/ADDPS passes before the deadline check, keeping the FP multiplier port loaded for longer uninterrupted bursts per outer iteration
  • MEM_BURST_CYCLES set to 16 — memory flood fires less frequently, giving the CPU more uninterrupted compute time between FSB/DRAM pressure events
  • MEM_BURST_MS set to 30 — when the burst does fire it runs longer, producing a more meaningful platform heat event without dominating the CPU burn budget

AboutScreen.cpp — Special Thanks Scroller

Cracktro-style rainbow wave scroller added to the About screen.

  • Special thanks label "Special Thanks To:" added as static white text in the gap between the modules list and the lower panel divider
  • Wave scroller renders immediately below the label — each character rides an independent sine wave position (amplitude = 7px, spatial frequency 0.018 rad/px, temporal frequency 2.2 rad/s) producing a fluid per-character wave as the text scrolls
  • Rainbow colour — full HSV saturation and value, hue offset per character index with a slow time-driven drift so the rainbow animates continuously across the text
  • Credits sequence: Diego -=- Equinox -=- Andr0 -=- Haguero -=- Harcroft -=- Wolfgang von Douchenozzle -=- The XBOX-Scene Discord -=- The OG Xbox Community
  • Scroll speed 60px/sec, wraps seamlessly when the full text clears the left edge
  • All timing is delta-time driven via GetTickCount() — frame rate independent

1.0.4 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 19 Mar 19:37

XbDiag Changelog


Development Note — March 2026
CPU detection and clock speed reporting are still being dialled in. MSR-based ratio reading, PLL register interpretation, and CPUID family/model identification across retail Coppermine, Tualatin upgrade, and xemu-hosted configurations are all under active investigation. Results may not be fully accurate on all hardware combinations in this build.

The CPU stress test thermal soak behaviour is also under ongoing research. Current work is focused on validating that the SSE/x87/integer compute mix combined with the memory flood interleaving produces consistent platform-wide heat rather than core-local utilisation only. Tuning recommendations for MEM_BURST_CYCLES and MEM_BURST_MS will follow once results from real hardware are confirmed.


1.0.4 Beta — March 2026

Keyboard.cpp / Keyboard.h — QWERTY Layout and Overlay Fixes

Row stagger corrected throughout both fullscreen and overlay keyboard modes to match a real QWERTY physical layout.

  • Row 3 (ZXCV) stagger corrected from 1.5× to 1.0× indent — the previous value over-indented the bottom row relative to the ASDF row
  • Overlay fn row restructured: BKSP moved to the right of the QWERTY row, Enter moved to the right of the ASDF row, bottom strip reduced to CAPS / SPACE / DONE only
  • Fullscreen fn row reverted to four keys (CAPS / SPACE / BKSP / DONE) with no Enter — Enter is overlay-only
  • Enter label renamed from "CR" to "Enter" in overlay rendering
  • Overlay centred at OV_GRID_X = 123.f with navigation extended via OV_COL_BKSP = 10 and OV_COL_ENTER = 9 sentinel columns
  • Enter behaviour commits the current line and inserts a new empty line below — consistent with standard text editor behaviour

FileViewer.cpp / FileEdit.cpp / FileEdit.h — Save Pipeline Overhaul

Root cause of silent save failure identified and fixed: s_prev = cur on confirm box open meant BTN_A was still held from the previous frame, causing FV_Edge to fire instantly and complete the save invisibly in one tick.

  • s_confirmReady flag added: set false when the confirm box opens, set true only after A is fully released — the confirm prompt now waits for a clean A press before acting
  • Save combo changed from A (which conflicts with typing) to BACK alone, eliminating the BACK+A interaction that caused ambiguity with the keyboard overlay
  • s_editLoaded flag added: separates "keyboard visible" from "edit data alive" — dismissing the keyboard with B keeps edits alive and the UNSAVED indicator on screen without destroying the edit session

File format preservation rewritten as a complete architectural fix:

  • BuildLineInfo() runs before BuildLines(), capturing per-logical-line byte offsets and exact terminator lengths (\r\n, \n, or none) from the raw buffer into FE_LineInfo[]
  • s_rawBuf — a separate malloc'd clean copy of the file bytes allocated after ReadFile and before BuildLines() nulls terminators in-place in s_buf
  • FileEdit_Save() — unchanged lines copy raw bytes verbatim including exact terminators; edited lines write new content followed by the original terminator bytes — mixed \r\n / \n files are preserved exactly
  • FileEdit_GetLastError() returns the Win32 error code captured from a failed save for display in the hint bar

FtpServ.cpp — Client Compatibility Fixes

Several issues identified through testing with FlashFXP, FileZilla, and WinSCP.

  • EPSV reply code changed from 522 to 500 — FileZilla was not falling back to PASV on 522; 500 (unrecognised command) triggers correct fallback behaviour
  • SIZE command switched from CreateFile to GetFileAttributesExA — cheaper, no handle leak risk, consistent with how the file list already queries sizes
  • SITE → 202, XCRC/XMD5 → 502 — FlashFXP sends these before transfers; correct responses prevent unnecessary retries and connection drops
  • Data listen socket now closed after each transfer completes (LIST, RETR, STOR) — previously the socket was left open between transfers causing connection state issues on reconnect
  • STOR I/O buffer expanded from 4KB to 64KB — upload speed now symmetric with download speed
  • FEAT response cleaned up: MLSD/MLST removed (not implemented), REST STREAM added (correctly advertises resume support)

input.cpp / input.h / ControllerTest.cpp — Controller Type Detection

Duke vs Type-S identification added via XInputGetCapabilities at connect time.

  • ControllerType enum added to input.hCT_DUKE (SubType XINPUT_DEVSUBTYPE_GC_GAMEPAD), CT_TYPE_S (SubType XINPUT_DEVSUBTYPE_GC_GAMEPAD_ALT), CT_UNKNOWN for wheels, arcade sticks, or unrecognised devices
  • g_ctrlType[MAX_PORTS] — cached per-port, populated on XInputOpen and cleared to CT_UNKNOWN on disconnect
  • GetControllerType(int port) — public accessor returning the cached type for a given port
  • Controller type row added to the port status strip in ControllerTest.cpp — displays DUKE, TYPE-S, or ??? in cyan beneath each connected port box; empty ports show nothing

ControllerTest.cpp — Per-Port Disconnect Tracking and Rumble Strip

Per-port connection state tracking added across the main controller view, Stick Test card, and Rumble subcard.

  • s_wasConn[4] and s_discCount[4] added — s_wasConn tracks connection state from the previous tick for edge detection; s_discCount accumulates a running total of disconnect events seen per port since the module was opened
  • Disconnect counter increments each time a previously connected port goes away, displayed in red beneath the port status strip when non-zero
  • Both arrays reset on module entry via ControllerTest_OnEnter()
  • Port status strip added to Rumble subcard (RenderRumble) — previously the Rumble subcard had no port visibility while the motors were being tested. The same four-box strip (green = connected, dark = disconnected) and Disconnects row from the main view are now rendered at the top of the subcard. cY shifted from B+160 to B+185 and the RUMBLE MOTORS header from B+30 to B+58 to clear the new strip

Update.cpp / Update.h — Self-Hosted Update Server and Changelog Display

Update server migrated from raw.githubusercontent.com to a self-hosted endpoint, and changelog display added to the update screen.

  • Host changed to darkone83.myddns.me on port 8008 — all version checks, XBE downloads, and changelog fetches now go through the dedicated update server rather than the GitHub raw CDN
  • Update_SetPaths(const char* xbeDir) added — install path is passed in from main.cpp at launch rather than hardcoded, allowing XbDiag to write the downloaded XBE back to whatever folder it was launched from
  • Background boot check (Update_StartBootCheck(), Update_IsCheckComplete(), Update_BootFoundUpdate()) — on startup main.cpp kicks off a silent version check while the rest of the initialisation completes. If a newer version is found the app jumps directly to the Update screen instead of the main menu
  • Changelog fetch (FetchChangelog(), GET /xbdiag/log.chg) — when entering the Update screen after a successful version check (or when the boot check already has a result), the remote changelog is fetched and displayed in the lower panel with automatic scrolling at 80ms per tick. Scroll resets to the top on wrap-around
  • s_changelog[4096] — 4KB receive buffer; content is stripped of HTTP headers before display

When returning from the FileViewer, START held during exit was seen by the FileExplorer tick on the very next frame, causing an unintended FTP server toggle. Fixed by syncing s_prevBtns = GetButtons() immediately after FileViewer returns control, consuming the held state before the main input loop runs.

1.0.3 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 18 Mar 17:46

XbDiag Changelog


Development Note — March 2026 CPU detection and clock speed reporting are still being dialled in. MSR-based ratio reading, PLL register interpretation, and CPUID family/model identification across retail Coppermine, Tualatin upgrade, and xemu-hosted configurations are all under active investigation. Results may not be fully accurate on all hardware combinations in this build.

The CPU stress test thermal soak behaviour is also under ongoing research. Current work is focused on validating that the SSE/x87/integer compute mix combined with the memory flood interleaving produces consistent platform-wide heat rather than core-local utilisation only. Tuning recommendations for MEM_BURST_CYCLES and MEM_BURST_MS will follow once results from real hardware are confirmed.


1.0.3 Beta — March 2026

font.cpp / font.h — Lowercase Glyph Support

Added 26 lowercase glyph bitmaps (az) to the g_font[] array. FindGlyph() previously folded all a-z input to A-Z unconditionally — that fold is removed. Lowercase characters are now looked up directly, with a fallback to the corresponding uppercase glyph only if a lowercase entry is missing. g_fontCount recalculates automatically via sizeof. No call sites changed, no header changes, all existing uppercase strings continue to work exactly as before.

Descenders (g, j, p, q, y) use row 6 of the 5×7 grid, rendering visually shorter than cap height — standard behaviour for a small bitmap font at this resolution.


ControllerTest.cpp — Rumble Port Status Strip

The Rumble subcard (RenderRumble) was missing the port status strip that the main controller view already had. Added the same four-box strip (green = connected, dark = disconnected) plus the "Disconnects:" count row beneath it, using identical geometry (PBW=46, PGAP=6, centred at X_MID). cY shifted from B+160 to B+185 and the "RUMBLE MOTORS" section header from B+30 to B+58 to clear the new strip.


ControllerTest.cpp — Trigger Dead-Zone Card (Stick Test tab 3)

A fourth tab, TRIGGERS, added to the Stick Test card ([Left/Right] to cycle as before). Two vertical bars (left = LT, right = RT) display live pressure 0–255 with tri-colour fill (green → orange → red). The bottom portion of each bar shows a dark red dead-zone band with a bright red threshold line at 30/255.

Stats accumulated per session:

  • Live value — current raw reading displayed below each bar
  • Min / Max — lowest and highest values seen since entry or last reset
  • PASSES DZ (green) — minimum was inside dead-zone but maximum broke through
  • IN DZ (red) — maximum never exceeded threshold; trigger does not actuate

[X] resets min/max. Stats reset on re-entry to the Stick Test card. Tab strip per-tab width reduced from 100px to 88px to fit four tabs at the same screen width.


FileExplorer.cpp / FileExplorerOps.cpp — New Folder (R3)

FE_Ops_MkDir(name) added to FileExplorerOps.cpp. Builds the full path from the current directory, calls CreateDirectoryA, reloads the directory listing, and repositions the cursor to the newly created folder. FileExplorer.cpp opens the virtual keyboard on R3 press, routes the confirmed name through OnMkdirDone, and guards the tick loop while the keyboard is active. Hint string updated with [R3] New Folder.


FileExplorer.cpp / FileViewer.cpp / FileViewer.h — File Viewer (L3)

New FileViewer.cpp / FileViewer.h module — read-only viewer for .txt and .csv files, opened from the file explorer with L3 on a compatible file.

  • malloc'd buffer on open, 512KB cap, freed on exit via both normal and error paths
  • BuildLines() walks the buffer once, replaces \r\n / \n with \0 in-place, and wraps long lines by pointing segment entries into the existing buffer — no additional allocations
  • Controls: D-pad up/down = 1 line, LT/RT = page, B = exit and free
  • Scroll bar, line counter (1–21 / N), truncation warning at 512KB, continuation indent on wrapped lines
  • FileViewer_IsActive() guard added to FileExplorer_Tick alongside the keyboard guard

HddBench.cpp — Benchmark Accuracy and Label Consistency

  • Seq read path corrected: BenchStartRead() now opens with FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN. The export header already said FILE_FLAG_NO_BUFFERING but the code was using buffered I/O. Implementation and label now agree.
  • Fallback file size fix: BENCH_READ loop and progress display call GetFileSize() at the start of the case and use the result (capped at BENCH_FILE_SIZE) as the loop target. In fallback (read-only) mode a source file smaller than 64MB no longer shows incorrect progress or a distorted MB/s number.
  • CACHE renamed to BUF RD: render label, export header, and export result line all updated. The repeated-block test probes drive buffer behaviour — it is not sustained throughput.
  • FS WR export description updated: now reads buffered write + FlushFileBuffers (practical sustained write) — explicit about flush overhead being included.
  • Inline cleanup path fix: three DeleteFileA(BENCH_FILE) calls in BenchTick completion paths replaced with DeleteFileA(s_bench.readSrc[0] ? s_bench.readSrc : BENCH_FILE). BenchCleanup() was already correct; the inline paths were not.

StressMath.cpp / StressMath.h — Memory Flood Integration

CPUStress() now interleaves MemFlood_Timed() bursts to broaden the thermal soak from core-local compute to whole-platform FSB/DRAM/northbridge load.

  • Every MEM_BURST_CYCLES compute iterations a MEM_BURST_MS MemFlood_Timed() pass fires against the 2MB sm_membuf buffer — well outside L2 on all Xbox CPU variants
  • Default: MEM_BURST_CYCLES = 8, MEM_BURST_MS = 50 — targets ~70% compute / ~30% memory flood
  • Both constants declared in StressMath.h as tunable values with inline tuning guidance
  • MemFlood_Timed() four-phase rotation unchanged: sequential write, sequential read, strided read (defeats hardware prefetcher), dual-stream copy

1.0.2 Beta — March 2026

Architecture — Major Module Refactoring

All large monolithic .cpp files split into focused sub-modules.

Original file Split into
HddInfo.cpp HddInfo.cpp · HddSmart.cpp · HddBench.cpp
EepromView.cpp EepromView.cpp · EepromCrypto.cpp · EepromSettings.cpp · EepromRepair.cpp
FileExplorer.cpp FileExplorer.cpp · FileExplorerMU.cpp · FileExplorerOps.cpp
StressTest.cpp StressTest.cpp · StressTestCPU.cpp · StressTestRAM.cpp

All new files added to XbDiag.vcxproj and XbDiag.vcxproj.filters.

StressMath.cpp — CPU Stress Kernel Overhaul

Previous x87 FFT kernel achieved ~40–60% measured load. FFT butterfly dependency chains serialise the FP pipeline and fninit in FourComplexSquareSweep serialised the full FPU pipeline once per block. New kernel uses dual-chain SSE1 MULPS/ADDPS targeting the Coppermine's separate FP-MUL and FP-ADD dispatch ports simultaneously.

  • Two MULPS chains (xmm0*xmm4, xmm1*xmm5) and two ADDPS chains (xmm2+xmm6, xmm3+xmm7) dispatch in pairs each cycle
  • Working set 16KB — exactly half of Coppermine's 32KB L1, ensuring zero cache miss overhead
  • SM_SSE_OUTER = 128 passes between GetTickCount() checks (~0.9ms at 733MHz)
  • CPUStress() restructured: SSE passes dominate (~85%), followed by one x87 FFT cycle and one IntegerStress() pass per outer iteration
  • fninit removed from FourComplexSquareSweep
  • Tualatin compatible — SSE1 encoding identical on Coppermine and Tualatin

ControllerTest.cpp — Trigger Dead-Zone Card (initial add)

(See 1.0.3 — this feature was first introduced in 1.0.2 and expanded in 1.0.3.)

SD/HD Readability and Clipping Fixes

Font_SetSD(bool) and Font_GetAdvance() added. SD mode uses 6.5px advance with scanline-safe dot height and alpha-blended shadow. HD stays at 6.0px. Font_SetSD() called post-InitD3D() in main.cpp. g_isTrueInterlaced flag set for NTSC 480i and PAL 576i only. Per-module SD clipping fixes in RamTest.cpp, TempMonitor.cpp, StressTest.cpp, AboutScreen.cpp, and EepromView.cpp.


1.0.1 Beta — March 2026

SysInfo.cpp

CPU speed — TSC replaced with PLL:

Read more

1.0.2 Beta

Choose a tag to compare

@Darkone83 Darkone83 released this 17 Mar 19:06
ebcf87c

XbDiag Changelog


1.0.2 Beta — March 2026

Architecture — Major Module Refactoring

All large monolithic .cpp files have been split into focused sub-modules. This reduces per-file compile times, improves code organisation, and makes individual subsystems independently testable. The public API surface of each module is unchanged.

Original file Split into
HddInfo.cpp HddInfo.cpp · HddSmart.cpp · HddBench.cpp
EepromView.cpp EepromView.cpp · EepromCrypto.cpp · EepromSettings.cpp · EepromRepair.cpp
FileExplorer.cpp FileExplorer.cpp · FileExplorerMU.cpp · FileExplorerOps.cpp
StressTest.cpp StressTest.cpp · StressTestCPU.cpp · StressTestRAM.cpp

HddInfo split:

  • HddInfo.cpp/.h — core load, render, export, OnEnter, Tick, AutoRun
  • HddSmart.cpp/.h — SMART attribute name table and render
  • HddBench.cpp/.h — sequential read/write and random seek benchmark engine

EepromView split:

  • EepromView.cpp/.h — core hex/decoded view, state machine, EepromView_Reload()
  • EepromCrypto.cpp/.hEepCrypto_Decrypt() and EepCrypto_Encrypt() as pure functions
  • EepromSettings.cpp/.h — TZ table, field editing, EepromSettings_RecalcChecksums(), EepromSettings_GetUtcTzBlock()
  • EepromRepair.cpp/.h — validator diagnostics, EepromRepair_BuildDiag(), repair apply, restore from bin

FileExplorer split:

  • FileExplorer.cpp/.h — core directory loading, render, tick, FTP integration, GoUp()
  • FileExplorerMU.cpp/.hFE_MU_MountAll() (HDD partitions + Memory Units), FE_MU_Format()
  • FileExplorerOps.cpp/.h — clipboard, destination picker, FE_Ops_Start/Tick/Snap/DrawPicker/EnterSelected/DeleteRecursive()

StressTest split:

  • StressTest.cpp/.h — shared state, HandleInput, Tick, AutoRun coordination
  • StressTestCPU.cpp/.hST_CPU_TakeSample(), ST_CPU_ReadMHz(), ST_CPU_Render(), all CPU render functions and sensor logic
  • StressTestRAM.cpp/.h — 11-phase moving-inversions RAM engine, ST_RAM_OnStart/Stop/Step/Render(), RamStress_AutoRun()

All new files added to XbDiag.vcxproj and XbDiag.vcxproj.filters.


StressMath.cpp — CPU Stress Kernel Overhaul

Problem: The previous x87 FFT kernel achieved ~40–60% measured CPU load. FFT butterfly dependency chains serialise the FP pipeline — each output feeds the next stage input, so the Coppermine's OOO engine exhausts independent work and stalls on 4-cycle latencies. GetTickCount() was called every 8 FFT cycles introducing integer pipeline stalls inside the burn window. fninit at the start of each FourComplexSquareSweep block serialised the entire FPU pipeline once per block.

New kernel — dual-chain SSE1 MULPS/ADDPS: The Coppermine PIII has separate FP-MUL and FP-ADD dispatch ports. MULPS and ADDPS target these ports independently and can execute simultaneously when operands are independent.

  • Two MULPS chains (xmm0*xmm4, xmm1*xmm5) target FP-MUL; two ADDPS chains (xmm2+xmm6, xmm3+xmm7) target FP-ADD — all four dispatch simultaneously in pairs
  • Three rounds of 4 ops per 64-byte block hide the 5-cycle MULPS and 4-cycle ADDPS latencies across loop iterations
  • Working set: 16KB (SM_SSE_PASS) — exactly half of the Coppermine's 32KB L1 D-cache, ensuring all MOVAPS accesses hit L1 with zero miss overhead
  • SM_SSE_OUTER = 128 passes between GetTickCount() checks (~0.9ms at 733MHz); no deadline check inside the inner loop

CPUStress() restructured: SM_SSE_OUTER SSE passes dominate each outer iteration (~85% of clock budget). One complete x87 FFT cycle and one IntegerStress() pass follow. GetTickCount() is called once per outer iteration only.

fninit removed from FourComplexSquareSweep — it was serialising the full FPU pipeline once per 64-byte block with no benefit.

Tualatin compatibility: SSE1 encoding is identical on Coppermine and Tualatin. No changes needed for CPU upgrade variants from 733 MHz through 1400 MHz.


ControllerTest.cpp — Trigger Dead-Zone Card

A fourth tab, TRIGGERS, added to the Stick Test card ([Left/Right] to cycle as before).

Two large vertical bars (80×220px) display live LT and RT pressure. The bottom portion of each bar is filled with a dark red dead-zone band (threshold: 30/255) with a bright red threshold line. The fill colour transitions green → orange → red with pressure value.

Stats accumulated per session:

  • Live value — current raw reading (0–255) displayed below each bar
  • Min / Max — lowest and highest values recorded since entry or last reset
  • PASSES DZ (green) — minimum was inside dead-zone but maximum broke through cleanly
  • IN DZ (red) — maximum never exceeded the threshold; trigger does not actuate

[X] resets Min/Max. Stats reset on re-entry to the Stick Test card. The tab strip per-tab width reduced from 100px to 88px to fit four tabs at the same screen width.


SD/HD Readability and Clipping Fixes

font.h/.cpp: Font_SetSD(bool) and Font_GetAdvance() — SD mode uses 6.5px advance with scanline-safe dot height and soft shadow. HD uses 6.0px advance. Font_SetSD() called post-InitD3D() in main.cpp.

DiagCommon.h/.cpp: g_isTrueInterlaced flag (NTSC 480i and PAL 576i only). TW() uses Font_GetAdvance(). DrawPageChrome hint truncation is badge-aware.

Per-module SD clipping fixes:

  • RamTest.cpp — right-panel legend strings shortened, left-panel quick hint single-space separators
  • TempMonitor.cpp — poll hint right-aligned left of badge
  • StressTest.cpp — status text draw order fixed (drawn after MHz panel so panel background does not paint over it)
  • AboutScreen.cpp — modules list split to 3 lines
  • EepromView.cpp — HEX view column constants corrected (HEX_B8_X, HEX_ASC_X), decoded view hint strings shortened, bottom bar hint fixed

CPU/GPU MHz math: Both SysInfo.cpp and StressTest.cpp now use the exact crystal constant 50000000.0/3.0 with double-precision arithmetic. GPU PLL in SysInfo.cpp also updated to use the correct 16666667 Hz crystal reference.


1.0.1 Beta — March 2026

SysInfo.cpp

CPU speed: TSC replaced with PLL register read MeasureCpuMHz() previously used RDTSC over a 300ms Sleep() window. This blocked SysInfo load for 300ms on every entry and gave ±5–10 MHz noise at higher clock speeds on Tualatin upgrades. The new implementation reads the MCPX CPUMPLL register (PCI Bus 0, Dev 3, Fun 0, Offset 0x6C) for the FSB divider/multiplier, and MSR 0x2A bits [27:22] for the CPU ratio. The result is exact, instantaneous, and correct on all Tualatin variants (733 MHz through 1400 MHz). The 300ms startup delay is eliminated.

GPU speed: crystal constant precision fix ReadGpuMHz() was using 16666 KHz as the NV2A PRAMDAC crystal reference. Corrected to 16666667 Hz for proper precision in the (N × crystal) / (M × 2^P) formula.

StressTest.cpp

CPU speed display: ICS clock generator replaced with PLL ReadCPUMHz() was polling the ICS clock generator at SMBus 0xD2, which only reports three values (733/800/853 MHz) and NAKs on Tualatin upgrades where the ICS chip may be absent. Replaced with the same CPUMPLL + MSR 0x2A method as SysInfo. The CPUMPLL read is cached on first call.

main.cpp + Lcd.cpp/h (new)

Physical LCD display support added New Lcd.cpp / Lcd.h module drives a US2066-compatible 20×4 character OLED at SMBus 0x78 (7-bit 0x3C). Detection is silent — if no display is found the module no-ops completely.

Pages (auto-cycle every 5 seconds): Thermal, Clocks, Storage, Network. FTP status page activates automatically when the FTP server is running, showing state, IP:21, current filename, and a progress bar.

Shadow buffer tracks display state and skips SMBus writes for cells that have not changed, reducing bus traffic on stable pages to near zero.

Key combos (hold all three simultaneously):

  • [START + A + WHITE] — enable/reinitialise display
  • [START + A + BLACK] — disable display

LCD_Begin() called at startup after

Read more