--- a/src/xiaomao.c +++ b/src/xiaomao.c @@ -6,6 +6,8 @@ * Additional terms under GPLv3 section 7(b): the author attribution "HelloSun" and this copyright * notice must be preserved in all copies and modified versions, including the notice the program * displays when it starts. See LICENSE. + * MODIFIED VERSION: adapted to the v86 emulator by the DOS LLM project (see xiaomao-v86.patch): the shadow + * text buffer is at A800:0000 instead of B800:0000. Original work: HelloSun, Copyright (C) 2026 HelloSun, first version 1.0 (2026-10-25). * * Design (the classic "Chinese system" approach): * The text screen is kept as an ordinary 80x25 text-mode shadow in memory at @@ -42,6 +44,9 @@ #define COLS 80 #define ROWS 25 +/* v86 patch: v86's VGA planes are exactly 64 KB and do not wrap the 128 KB aperture the way DOSBox does, + * so the shadow text lives at A800:0000 (plane offset 8000h, inside a 64 KB A0000 window, GC6=05h) instead of B800. */ +#define SHADOW_SEG 0xA800u #define GFX_BASE 0x0000u #define PAINT_OFF 0x6000u /* painted copy (ch/attr) in the shadow window */ #define KIND_OFF 0x7000u /* painted kinds */ @@ -92,7 +97,7 @@ #define BDA8(o) (*(u8 far *)MK_FP(0x40, (o))) #define BDA16(o) (*(u16 far *)MK_FP(0x40, (o))) -#define SHADOW ((u16 far *)MK_FP(0xB800, 0)) +#define SHADOW ((u16 far *)MK_FP(SHADOW_SEG, 0)) /* ---- VGA helpers ---- */ static void gcw(unsigned i, unsigned v) { outp(0x3CE, i); outp(0x3CF, v); } @@ -165,8 +170,8 @@ int cvis, cur_on, dirty_any; u16 cur[COLS], old[COLS]; u8 kd[COLS], ok[COLS], dr[COLS]; - u16 far *pt = (u16 far *)MK_FP(0xB800, PAINT_OFF); - u8 far *pk = (u8 far *)MK_FP(0xB800, KIND_OFF); + u16 far *pt = (u16 far *)MK_FP(SHADOW_SEG, PAINT_OFF); + u8 far *pk = (u8 far *)MK_FP(SHADOW_SEG, KIND_OFF); if (!text_active) return; if (!force && tick == last_tick) return; last_tick = tick; @@ -288,8 +293,8 @@ crtc(0x11, p); } outp(0x3C4, 2); outp(0x3C5, 0x0F); /* map mask: all planes */ - gcw(0, 0); gcw(1, 0); gcw(3, 0); gcw(4, 0); gcw(5, 0); gcw(6, 0x01); gcw(8, 0xFF); /* 128K aperture: A000 = picture, B800 = shadow */ - for (i = 0; i < COLS * ROWS; i++) { ((u16 far *)MK_FP(0xB800, PAINT_OFF))[i] = 0xFFFF; ((u8 far *)MK_FP(0xB800, KIND_OFF))[i] = 0xFF; } + gcw(0, 0); gcw(1, 0); gcw(3, 0); gcw(4, 0); gcw(5, 0); gcw(6, 0x05); gcw(8, 0xFF); /* 64K aperture at A0000: A000 = picture (0000-7CFF), A800 = shadow (8000-FFFF) */ + for (i = 0; i < COLS * ROWS; i++) { ((u16 far *)MK_FP(SHADOW_SEG, PAINT_OFF))[i] = 0xFFFF; ((u8 far *)MK_FP(SHADOW_SEG, KIND_OFF))[i] = 0xFF; } BDA8(0x49) = 3; BDA16(0x4A) = COLS; BDA16(0x4C) = 0x1000; BDA16(0x4E) = 0; BDA8(0x84) = ROWS - 1; BDA8(0x85) = 16; BDA16(0x60) = 0x0D0E; BDA16(0x10) = (BDA16(0x10) & ~0x30u) | 0x20; @@ -715,7 +720,7 @@ xms_ok = 1; save_vectors(); rom16 = (u8 far *)get_rom_font(); - for (i = 0; i < COLS * ROWS; i++) saved[i] = ((u16 far *)MK_FP(0xB800, 0))[i]; + for (i = 0; i < COLS * ROWS; i++) saved[i] = ((u16 far *)MK_FP(0xB800, 0))[i]; /* the REAL text screen before we switch to graphics */ crow = BDA8(0x51); ccol = BDA8(0x50); enter_text(); for (i = 0; i < COLS * ROWS; i++) SHADOW[i] = (saved[i] & 0xF000) ? (u16)((saved[i] & 0xFF) | 0x0700) : saved[i];