首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

VirtuaNES 0.97 源碼探究(四):調色盤查看器實現解析

     編輯:關於C語言

功能概覽

打開「工具 → 查看器 → 調色盤查看器」,可實時顯示 NES 畫面處理單元(PPU)的 32 種調色盤顏色:上 16 色為背景調色盤,下 16 色為精靈調色盤。每色佔 16×16 像素,整體位圖尺寸 256×32。

核心類:CPaletteView

文件:PaletteView.h/cpp,對象 m_PaletteView 定義於 CMainFrame 中。

1. Create():窗口與位圖頭初始化

BOOL CPaletteView::Create(HWND hWndParent) {
    HWND hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, VIRTUANES_WNDCLASS, 
        "PaletteView", WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        hWndParent, NULL, CApp::GetInstance(), (LPVOID)this);
    if (!hWnd) return FALSE;
    m_hWnd = hWnd;

    // 8-bit 位圖頭:256×32,32 色調色盤
    m_BitmapHdr.bih.biSize = sizeof(BITMAPINFOHEADER);
    m_BitmapHdr.bih.biWidth = 256;
    m_BitmapHdr.bih.biHeight = -32; // 負值表示自頂向下 DIB
    m_BitmapHdr.bih.biPlanes = 1;
    m_BitmapHdr.bih.biBitCount = 8;
    m_BitmapHdr.bih.biCompression = BI_RGB;
    m_BitmapHdr.bih.biClrUsed = 32;

    // 從 DirectDraw 獲取當前 32 色調色盤數據
    DirectDraw.GetPaletteData(m_Palette);

    // 填充 m_lpPattern:每 16×16 區塊填入對應調色盤索引 0~31
    for (INT y = 0; y < 32; y++) {
        for (INT x = 0; x < 256; x++) {
            m_lpPattern[x + y * 256] = (y >> 4) * 0x10 + (x >> 4);
        }
    }
    return TRUE;
}

2. OnTimer():定時器驅動實時繪製

WNDMSG CPaletteView::OnTimer(WNDMSGPARAM) {
    if (!Emu.IsRunning()) return TRUE;

    // 同步最新調色盤:前 16 色背景,後 16 色精靈
    for (INT i = 0; i < 16; i++) {
        m_BitmapHdr.rgb[i] = m_Palette[BGPAL[i]];
        m_BitmapHdr.rgb[i + 16] = m_Palette[SPPAL[i]];
    }

    // 拉伸繪製到客戶區
    RECT rc; GetClientRect(hWnd, &rc);
    HDC hDC = GetDC(hWnd);
    StretchDIBits(hDC, 0, 0, rc.right, rc.bottom,
        0, 0, 256, 32, m_lpPattern, 
        (BITMAPINFO*)&m_BitmapHdr, DIB_RGB_COLORS, SRCCOPY);
    ReleaseDC(hWnd, hDC);
    return TRUE;
}

關鍵技術點補充

  • DIB 結構:BITMAPINFOHEADER + RGBQUAD rgb[32] + 索引數據 m_lpPattern,屬經典 8-bit 設備無關位圖。
  • 負高度技巧:biHeight = -32 使位圖數據按從上到下順序存儲,配合 StretchDIBits 直接繪製,無需翻轉。
  • 調色盤索引映射:雙重循環 (y>>4)*0x10 + (x>>4) 將 256×32 畫布劃分為 16×16=256 個宏像素,每宏像素填單一索引值,構成 16×2 的調色盤矩陣。

作者感言

這系列文章雖屬小眾(NES 模擬器源碼分析),但堅持記錄是為了讓對復古遊戲技術感興趣的人有據可查,也為自己留下知識錨點。祝各位國慶快樂!

本文轉載自 “三人乘虎” 博客,原文地址:https://darhx.blog.51cto.com/7920146/1304059

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved