Advertisement
xiahanlu

NES用的地图编辑器.cpp

Nov 29th, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 299.86 KB | None | 0 0
  1. // NNametableEditor.cxx, NNametableEditor::2019::MS_PL::IRQ_crash
  2. //
  3. // Required: DirectX SDK 9.0c June
  4. //           Windows Template Library
  5. //
  6. // TODO: Undo op in map unit
  7. // TODO: Nametable rorate, split
  8. // TODO: PNG Pixel Mapper NES Palette
  9. // TODO: More GPU Palette Mapper .
  10. // TODO: Details BUG
  11. // TODO: Details more.
  12. // TODO: C++ Dtor
  13. // TODO: CA65 Assembler Mapper
  14.  
  15. #if defined (_MSC_VER)
  16. # pragma warning(disable:4005)
  17. #endif
  18.  
  19. #include <atlbase.h>
  20. #include <atlcoll.h>
  21. #include <atlapp.h>
  22. #include <atlframe.h>
  23. #include <atlfile.h>
  24. #include <atlctrls.h>
  25. #include <atlctrlw.h>
  26. #include <atlctrlx.h>
  27. #include <atlsplit.h>
  28. #include <atldlgs.h>
  29. #include <atlscrl.h>
  30. #include <atlstr.h>
  31. #include <atlmisc.h>
  32. #include <atlimage.h>
  33.  
  34. #include <d3dx9.h>
  35. #include <tchar.h>
  36. #include "resource.h"
  37. #include <intrin.h>
  38.  
  39. // Embedded style list
  40. #if defined (_M_IX86)
  41. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
  42. #elif defined (_M_IA64)
  43. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
  44. #elif defined (_M_X64)
  45. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
  46. #else
  47. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
  48. #endif
  49.  
  50. #if defined (_MSC_VER) || defined (__ICC) || defined (__INTEL_COMPILER) || defined (__BORLANDC__)
  51. # define FINLINE  __forceinline
  52. # define SFINLINE static __forceinline
  53. # define typeof_noref decltype
  54. #
  55. # ifndef _WIN64
  56. #  define _X86_32_WIN_INTEL_INLINE_ASM_SPEC
  57. # endif
  58. #endif
  59.  
  60. #if defined (_DEBUG) || defined (DEBUG)
  61. # define DEBUG_OUT _tprintf
  62. #else
  63. # define DEBUG_OUT(...) ((VOID) 0)
  64. #endif
  65.  
  66. #define PHOTOSHOP_COL_TOGDI16_0(col32)\
  67.   ((WORD)(col32 >> 0 & 0xFF) >> 3) << 0\
  68.   | ((WORD)(col32 >> 8 & 0xFF) >> 3)  << 5\
  69.  | ((WORD)(col32 >>16 & 0xFF) >> 3) << 10
  70.  
  71. #define PHOTOSHOP_COL_TOGDI16_1(col32)\
  72.   ((WORD)(col32 >> 16 & 0xFF) >> 3) << 0 \
  73.   | ((WORD)(col32 >> 8 & 0xFF) >> 3) << 5\
  74.  | ((WORD)(col32 >>0 & 0xFF) >> 3) << 10
  75.  
  76. #define PHOTOSHOP_COL_TOGDI16\
  77.        PHOTOSHOP_COL_TOGDI16_0
  78.  
  79. #define CTRL_IN_KEYQUEUE()\
  80.   (:: GetKeyState (VK_LCONTROL) & 0x8000) \
  81.   || (:: GetKeyState (VK_RCONTROL) & 0x8000)
  82.  
  83. // < CFileDialogFilter >==================================================
  84. // Not mine, see .https://www.codeproject.com/articles/3167/webcontrols/
  85. // License:unknown
  86. // Author:Rob Caldecott
  87. // Implementation of the CFileDialogFilter class.
  88.  
  89. // Class to support a filter list when using the WTL CFileDialog.
  90. // Allows a filter string delimited with a pipe to be used (instead of a string
  91. // delimited with '\0')
  92. class CFileDialogFilter  
  93. {
  94. private:
  95.   CString m_strFilter;
  96. public:
  97.   CFileDialogFilter()
  98.   {
  99.   }
  100.  
  101.   /// nID The ID of a resource string containing the filter
  102.   CFileDialogFilter(UINT nID)
  103.   {
  104.     SetFilter(nID);
  105.   }
  106.  
  107.   /// lpsz The filter string
  108.   CFileDialogFilter(LPCTSTR lpsz)
  109.   {
  110.     SetFilter(lpsz);
  111.   }
  112.  
  113.   ~CFileDialogFilter()
  114.   {
  115.   }
  116.  
  117.   inline LPCTSTR GetFilter() const { return m_strFilter; }
  118.   inline operator LPCTSTR() const { return m_strFilter; }
  119.  
  120.   // Set the filter string to use
  121.   // nID - The ID of a resource string containing the filter
  122.   VOID SetFilter(UINT nID)
  123.   {
  124.     if (m_strFilter.LoadString(nID) && !m_strFilter.IsEmpty())
  125.       ModifyString();
  126.   }
  127.  
  128.   // Set the filter string to use
  129.   // lpsz - The filter string
  130.   VOID SetFilter(LPCTSTR lpsz)
  131.   {    
  132.     m_strFilter = lpsz;
  133.     if (!m_strFilter.IsEmpty())
  134.       ModifyString();
  135.   }
  136. private:
  137.   // Replace '|' with '\0'
  138.   VOID ModifyString(VOID)
  139.   {
  140.     // Get a pointer to the string buffer
  141.     LPTSTR psz = m_strFilter.GetBuffer(0);
  142.     // Replace '|' with '\0'
  143.     while ((psz = _tcschr(psz, _T('|'))) != NULL)
  144.       *psz++ = _T('\0');
  145.     // Release buffer
  146.     m_strFilter.ReleaseBuffer ();
  147.   }
  148. };
  149.  
  150. // < CWindowFT >====================================================
  151. class CWindowFT : public CWindow {
  152. public:
  153.   CWindowFT(_In_opt_ HWND hWnd = NULL) throw() :
  154.      CWindow (hWnd)
  155.   {
  156.   }
  157.  
  158.   int __cdecl SetWindowTextFT (LPCTSTR format, ...) {
  159.     ATLASSERT (::IsWindow (*this));
  160.  
  161.     CString output;
  162.  
  163.     va_list va;
  164.     va_start (va, format);
  165.  
  166.     output.FormatV (format, va);
  167.  
  168.     ::SetWindowText (this->m_hWnd, output);
  169.  
  170.     va_end (va);
  171.  
  172.     return output.GetLength ();
  173.   }
  174. };
  175.  
  176. // < CListViewCtrlTS >====================================================
  177. template <class T> // (T)emplate (s)elect item for listview.
  178. class CListViewCtrlTS : public CListViewCtrl {
  179. public:
  180.   T *GetItemDataT (int index) {
  181.     auto count = GetItemCount ();
  182.     if (index >= 0 && index < count) {
  183.       return reinterpret_cast<T *> (GetItemData (index));
  184.     }
  185.     return NULL;
  186.   }
  187.   T *GetItemSelectedDataT (void) {
  188.     return GetItemDataT (GetSelectedIndex ());
  189.   }
  190.   BOOL SetItemDataT (int index, T *item) {
  191.     auto count = GetItemCount ();
  192.     if (index >= 0 && index < count) {
  193.       SetItemData (index, reinterpret_cast<DWORD_PTR> (item));
  194.       return TRUE;
  195.     }
  196.     return FALSE;
  197.   }
  198.  
  199.   // XXX:Arg must correct.
  200.   CString GetItemTextAMC (int index, int iSubItem) {
  201.     auto count = GetItemCount ();
  202.     ATLASSERT (index >= 0);
  203.     ATLASSERT (index < count);
  204.    
  205.     CString buffer;
  206.     auto p = buffer.GetBuffer (MAX_PATH);
  207.     // -----------
  208.     GetItemText (index, iSubItem, p, MAX_PATH);
  209.  
  210.     CString returnBuffer (p);
  211.  
  212.     buffer.ReleaseBuffer ();
  213.     return returnBuffer;
  214.   }
  215.   CString GetSelectedItemTextAMC (int iSubItem) {
  216.     return GetItemTextAMC (GetSelectedIndex (), iSubItem);
  217.   }
  218. };
  219.  
  220. // < CByteStream >====================================================
  221. class CByteStream {
  222. private:
  223.   INT32 m_BufferCount;
  224.   INT32 m_MaxCount;
  225.   INT32 m_ReadSeek;
  226.   INT32 m_WriteSeek;
  227.   INT32 m_ExpandSize;
  228.   PBYTE m_pBuffer;
  229. public:
  230.   static const INT32 errors_signal = 0x80000000;
  231.   static const INT32 errors_signal_failed = 0x80000000;
  232.   static const INT32 errors_signal_eof = 0x80000001;
  233.   static const INT32 errors_signal_badalloc = 0x80000002;
  234.  
  235.   CByteStream (INT32 allocRequset = -1, INT32 expandSize = 32) {
  236.     defaultInit (allocRequset, expandSize);
  237.   }
  238.  ~CByteStream (void) {
  239.    if (m_pBuffer != NULL) {
  240.      // Release buffer
  241.      CCRTAllocator::Free (m_pBuffer);
  242.    }
  243.   }
  244.  
  245.   void defaultInit (INT32 allocRequset = -1, INT32 ExpandSize = 32) {
  246.     m_ReadSeek =
  247.     m_WriteSeek = 0;
  248.     m_ExpandSize = ExpandSize;
  249.  
  250.     if (allocRequset < 0) {
  251.       m_MaxCount = 32;
  252.       m_BufferCount = 16;
  253.     } else {
  254.       m_BufferCount = allocRequset;
  255.       m_MaxCount = m_BufferCount + 15 & -16;
  256.     }
  257.     m_pBuffer = static_cast <PBYTE> (CCRTAllocator ::Allocate (m_MaxCount));
  258.     ATLASSERT (m_pBuffer != NULL);
  259.   }
  260.  
  261.   FINLINE
  262.   INT32 getExpandSize (void) {
  263.     return m_ExpandSize;
  264.   }
  265.  
  266.   FINLINE
  267.   INT32 setExpandSize (INT32 expandSize) {
  268.     if (expandSize > 0) {
  269.       m_ExpandSize = expandSize;
  270.       return 0;
  271.     } else
  272.       return errors_signal_failed;
  273.   }
  274.  
  275.   FINLINE
  276.   INT32 getSize (void) {
  277.     return m_BufferCount;
  278.   }
  279.  
  280.   FINLINE
  281.   INT32 getReadSeek (void) {
  282.     return m_ReadSeek;
  283.   }
  284.  
  285.   FINLINE
  286.   INT32 getWriteSeek (void) {
  287.     return m_WriteSeek;
  288.   }
  289.  
  290.   FINLINE
  291.   INT32 setReadSeek (INT32 readSeek = 0) {
  292.     if (readSeek >= m_MaxCount) {
  293.       return errors_signal_failed;
  294.     } else {
  295.       m_ReadSeek = readSeek;
  296.       return 0;
  297.     }
  298.   }
  299.  
  300.   FINLINE
  301.   INT32 setWriteSeek (INT32 writeSeek = 0) {
  302.     if (writeSeek >= m_MaxCount) {
  303.       return errors_signal_failed;
  304.     } else {
  305.       m_WriteSeek = writeSeek;
  306.       return 0;
  307.     }
  308.   }
  309.  
  310.   FINLINE
  311.   VOID **getBuffer (INT32 writeSeek = 0) {
  312.     return (VOID **)& m_pBuffer;
  313.   }
  314.    
  315.   // return read count.
  316.   INT32 read (void *buffer, INT32 count, BOOL bSeekCursor = TRUE) {
  317.     ATLASSERT (buffer != NULL);
  318.     ATLASSERT (count >= 0);
  319.  
  320.     if (count == 0) {
  321.       return 0;
  322.     }
  323.     if (m_ReadSeek >= m_BufferCount) {
  324.       return errors_signal_eof;
  325.     }
  326.     // focus read pos pointer .
  327.     PBYTE pReadFocus = & m_pBuffer[m_ReadSeek];
  328.     PBYTE pReadBuffer = static_cast<PBYTE> (buffer);
  329.     INT32 readCount = 0;
  330.  
  331.     while (count > 0 && m_ReadSeek + readCount < m_BufferCount) {
  332.       BYTE value = pReadFocus[readCount];
  333.       pReadBuffer[readCount] = value;
  334.       readCount ++;
  335.       count --;
  336.     }
  337.     // Adjust seek pos.
  338.     if (bSeekCursor != FALSE) {
  339.       m_ReadSeek += readCount;
  340.     }
  341.     return readCount;
  342.   }
  343.  
  344.   INT32 writeAssert (const void *buffer, INT32 count, BOOL bSeekCursor = TRUE) {
  345.     INT32 sig = write (buffer, count, bSeekCursor);
  346.     ATLASSERT ((sig & CByteStream::errors_signal) == 0);
  347.     return sig;
  348.   }
  349.  
  350.   // return exec status
  351.   INT32 write (const void *buffer, INT32 count, BOOL bSeekCursor = TRUE) {
  352.     ATLASSERT (buffer != NULL);
  353.     ATLASSERT (count >= 0);
  354.  
  355.     if (count == 0) {
  356.       return 0;
  357.     }
  358.     if (m_WriteSeek + count > m_MaxCount) {
  359.       // Alloc new buffer .
  360.       const auto allocRequset = m_WriteSeek + count + m_ExpandSize + 31 & -32;
  361.       void *allocHeap = CCRTAllocator::Reallocate (m_pBuffer, allocRequset);
  362.      
  363.       if (allocHeap == NULL) {
  364.         allocHeap = CCRTAllocator ::Allocate (allocRequset);
  365.        
  366.         if (allocHeap == NULL) {
  367.           return errors_signal_badalloc;
  368.         }
  369.         if (m_pBuffer != NULL) {
  370.           // Copy content
  371.           RtlCopyMemory (allocHeap, m_pBuffer, m_BufferCount);
  372.           // Release old buffer
  373.           CCRTAllocator::Free (m_pBuffer);
  374.         } else {
  375.           RtlZeroMemory (allocHeap, allocRequset);
  376.         }
  377.       }
  378.       // Attach it
  379.       m_pBuffer = static_cast<PBYTE> (allocHeap);
  380.       m_MaxCount = allocRequset;
  381.       m_BufferCount = m_WriteSeek + count;
  382.     }
  383.    
  384.     // focus write pos pointer .
  385.     PBYTE pWriteFocus = & m_pBuffer[m_WriteSeek];
  386.     PBYTE pWriteBuffer = static_cast< PBYTE>  (const_cast <void *>  (buffer));
  387.     INT32 writeCount = 0;
  388.  
  389.     while (count > 0) {
  390.       PBYTE pValue = & pWriteFocus[writeCount];
  391.       * pValue = pWriteBuffer[writeCount];
  392.      
  393.       writeCount++;
  394.       count --;
  395.     }
  396.     // Adjust seek pos.
  397.     if (bSeekCursor != FALSE) {
  398.       m_WriteSeek += writeCount;
  399.     }
  400.     return 0;
  401.   }
  402.  
  403.   INT32 writeDummyAssert (INT32 count, BOOL bSeekCursor = TRUE) {
  404.     INT32 sig = writeDummy (count, bSeekCursor);
  405.     ATLASSERT ((sig & CByteStream::errors_signal) == 0);
  406.     return sig;
  407.   }
  408.  
  409.   // return exec status
  410.   INT32 writeDummy (INT32 count, BOOL bSeekCursor = TRUE) {
  411.     ATLASSERT (count >= 0);
  412.  
  413.     if (count == 0) {
  414.       return 0;
  415.     }
  416.     if (m_WriteSeek + count > m_MaxCount) {
  417.       // Alloc new buffer .
  418.       const auto allocRequset = m_WriteSeek + count + m_ExpandSize + 31 & -32;
  419.       void *allocHeap = CCRTAllocator::Reallocate (m_pBuffer, allocRequset);
  420.      
  421.       if (allocHeap == NULL) {
  422.         allocHeap = CCRTAllocator ::Allocate (allocRequset);
  423.        
  424.         if (allocHeap == NULL) {
  425.           return errors_signal_badalloc;
  426.         }
  427.         if (m_pBuffer != NULL) {
  428.           // Copy content
  429.           RtlCopyMemory (allocHeap, m_pBuffer, m_BufferCount);
  430.           // Release old buffer
  431.           CCRTAllocator::Free (m_pBuffer);
  432.         } else {
  433.           RtlZeroMemory (allocHeap, allocRequset);
  434.         }
  435.       }
  436.       // Attach it
  437.       m_pBuffer = static_cast<PBYTE> (allocHeap);
  438.       m_MaxCount = allocRequset;
  439.       m_BufferCount = m_WriteSeek + count;
  440.     }
  441.     // Adjust seek pos.
  442.     if (bSeekCursor != FALSE) {
  443.       m_WriteSeek += count;
  444.     }
  445.     return 0;
  446.   }
  447.  
  448.   INT32 fillExistBufferNoreallocAssert (const void *buffer, INT32 pos, INT32 count) {
  449.     INT32 sig = fillExistBufferNorealloc (buffer, pos, count);
  450.     ATLASSERT ((sig & CByteStream::errors_signal) == 0);
  451.     return sig;
  452.   }
  453.  
  454.   INT32 fillExistBufferNorealloc (const void *buffer, INT32 pos, INT32 count) {
  455.     if (buffer == NULL
  456.       || pos >= m_BufferCount
  457.       || count < 0)
  458.       return errors_signal_failed;
  459.     else
  460.       {
  461.         auto dst = & (static_cast<PBYTE> (m_pBuffer))[pos];
  462.         auto src =    static_cast< PBYTE>  (const_cast <void *>  (buffer));
  463.         auto readCount = 0;
  464.         auto remain = m_BufferCount - pos;
  465.  
  466.         while (count > 0 && readCount < remain) {
  467.           BYTE value = src[readCount];
  468.           dst[readCount] = value;
  469.           readCount ++;
  470.           count --;
  471.         }
  472.         return readCount;
  473.       }
  474.     // Never reach here
  475.     ATLASSERT (FALSE);
  476.     return 0;
  477.   }
  478. };
  479.  
  480. #define WTL_WMSG_CALLBACK(MethodName)\
  481.   LRESULT MethodName (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  482. #define WTL_DMSG_CALLBACK(MethodName)\
  483.   LRESULT MethodName (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  484.  
  485. #define GDI_COL_TO_DRAW16 CGlobals::r32tor15_rev
  486. #define GDI_COL_TO_DRAW32 CGlobals::r15tor32_rev
  487.  
  488. CAppModule _Module;
  489.  
  490. union CPolyData64 {
  491.   UINT64 blk;
  492.   INT64 sblk;
  493.   UINT32 blk32[2];
  494.   INT32 sblk32[2];
  495.   UINT16 blk16[4];
  496.   INT16 sblk16[4];
  497.   UINT8 blk8[8];
  498.   INT8 sblk8[8];
  499. };
  500.  
  501. struct CAttr {
  502.   CAttr (VOID) {
  503.     RtlZeroMemory (attr, sizeof (attr));
  504.     comment = _T ("_");
  505.   }
  506.   BYTE attr[64];
  507.   CString comment;
  508. };
  509.  
  510. struct CPal {
  511.   static const BYTE private_palette = 0; // private palette use in nametable/clay
  512.   static const BYTE static_palette = private_palette + 1; // private palette use in whole map/ nametable/clay
  513.   static const BYTE global_palette = static_palette + 1; // global palette use in all map/ nametable/clay
  514.  
  515.   CPal (BYTE source_ = private_palette):comment (_T ("-")) {
  516.     const BYTE pal_init [] = {
  517.       0x0F, 0x00, 0x10, 0x30,
  518.       0x0F, 0x1C, 0x2B, 0x39,
  519.       0x0F, 0x06, 0x15, 0x36,
  520.       0x0C, 0x17, 0x28, 0x39 // from yychr's default palette
  521.     };
  522.     RtlCopyMemory (pal, pal_init, sizeof (pal_init));
  523.     source = source_;
  524.   }
  525.   FINLINE
  526.   void sourceAssert (void) {
  527.     ATLASSERT (source == private_palette
  528.       || source == static_palette
  529.       || source == global_palette);
  530.   }
  531.   BYTE source;
  532.   BYTE pal[16];
  533.   CString comment;
  534. };
  535.  
  536. struct CChr {
  537.   BYTE chr[0x1000];
  538.   CString comment;
  539. };
  540.  
  541. struct CUndoMapNode {
  542.   PWORD pTileBufL; // L source
  543.   PBYTE pAttrBufL;
  544.   CPoint ptStartL;
  545.   CSize szCopyL;
  546.   PWORD pTileBufR; // R target, first
  547.   PBYTE pAttrBufR;
  548.   CPoint ptStartR;
  549.   CSize szCopyR;
  550.  
  551.   CUndoMapNode (void):
  552.     pTileBufL (NULL),
  553.     pAttrBufL (NULL),
  554.     ptStartL (0, 0),
  555.     szCopyL (0, 0),
  556.     pTileBufR (NULL),
  557.     pAttrBufR (NULL),
  558.     ptStartR (0, 0),
  559.     szCopyR (0, 0) {}
  560.  
  561.   ~CUndoMapNode (void) {
  562.     if (pTileBufL != NULL) {
  563.       CCRTAllocator::Free (pTileBufL);
  564.     }
  565.     if (pAttrBufL != NULL) {
  566.       CCRTAllocator::Free (pAttrBufL);
  567.     }
  568.     if (pTileBufR != NULL) {
  569.       CCRTAllocator::Free (pTileBufR);
  570.     }
  571.     if (pAttrBufR != NULL) {
  572.       CCRTAllocator::Free (pAttrBufR);
  573.     }
  574.   }
  575. };
  576.  
  577. struct CClayUndoNode {
  578.   WORD tileSlot[0x400];
  579.   BYTE attrSlot[0x40];
  580.   CAttr *attr;
  581. };
  582.  
  583. template <BOOL t_bReadWriteMap = FALSE>
  584. struct CNametableCell {
  585.   WORD tileSlot[0x400]; // 0x8000 is trans pixel.
  586.   CAtlArray <CAttr *> attrList;
  587.   CAtlArray <CPal *> palList;
  588.   CAtlArray <CPal *> &staticPalList; // only nametable use.
  589.   CAtlArray <CPal *> &globalPalList;
  590.   CAtlList <CClayUndoNode *> *undoStack;
  591.   int undoSeek;
  592.  
  593.   CChr *chr;
  594.   CAttr *attr;
  595.   CPal *pal;
  596.   INT select; // select index, < 0 no select or empty item.
  597.   INT bank; // attr table bank.
  598.   BOOL hackChr;
  599.   BOOL hackAttr;
  600.   BOOL hackPal;
  601.   CString comment;
  602.  
  603.   struct selPaletteInfos {
  604.     int indexInTotal;
  605.     int indexInCurSource;
  606.     int sizeInCurSource;
  607.     int sizeInTotal;
  608.  
  609.     CString source; // Global | Static | Local
  610.     CPal *pal;
  611.     CAtlArray <CPal *> *srcPaletteSet;
  612.    
  613.     selPaletteInfos (void):
  614.               indexInTotal (-1),
  615.               indexInCurSource (-1),
  616.               sizeInCurSource (-1),
  617.               sizeInTotal (-1),
  618.               source (_T ("_")),
  619.               pal (NULL),
  620.               srcPaletteSet (NULL) {}
  621.   };
  622.  
  623.   // FIXME: adjust attr index in internal.
  624.   void updateCacheToMain (CClayUndoNode *node) {
  625.     ATLASSERT (node != NULL);
  626.  
  627.     auto specAttr = node->attr;
  628.  
  629.     // Copy tile id.
  630.     memcpy (tileSlot, node->tileSlot, sizeof (tileSlot));
  631.  
  632.     // Serach list .
  633.     for (SIZE_T it =0; it != attrList.GetCount (); it++) {
  634.       auto p = attrList[it];
  635.       if (p == specAttr) {
  636.         // Adjust pos.
  637.         // attr = specAttr;
  638.  
  639.         memcpy (specAttr->attr, node->attrSlot, sizeof (node->attrSlot));
  640.         return ;
  641.       }
  642.     }
  643.     node->attr = NULL;
  644.   }
  645.  
  646.   // snapshot only for clay windwos.
  647.   PVOID snapshotResume (void) {
  648.     // Next undo list.
  649.     if (undoStack != NULL) {
  650.       auto count = undoStack->GetCount ();
  651.  
  652.       if (count == 0 || undoSeek == count) {
  653.         return NULL;
  654.       }
  655.       ATLASSERT (undoSeek <=  count);
  656.       auto node = undoStack->GetAt (undoStack->FindIndex (undoSeek));
  657.       ATLASSERT (node != NULL);
  658.       undoSeek ++;
  659.       updateCacheToMain (node);
  660.       return node;
  661.     }
  662.     return NULL;
  663.   }
  664.  
  665.   PVOID snapshotUndo (void) {
  666.     if (undoStack != NULL) {
  667.       auto count = undoStack->GetCount ();
  668.  
  669.       if (count <= 1 || undoSeek <= 1) {
  670.         return NULL;
  671.       }
  672.       ATLASSERT (undoSeek <=  count);
  673.       auto node = undoStack->GetAt (undoStack->FindIndex (undoSeek - 2));
  674.       ATLASSERT (node != NULL);
  675.       undoSeek --;
  676.       updateCacheToMain (node);
  677.       return node;
  678.     }
  679.     return NULL;
  680.   }
  681.  
  682.   void snapshotToUndoStack (void) {
  683.     if (undoStack != NULL) {
  684.       // For simplicity, put the entire snapshot on the stack at once
  685.       auto newNode = new CClayUndoNode;
  686.  
  687.       // Copy tile cache.
  688.       memcpy (newNode->tileSlot, tileSlot, sizeof (tileSlot));
  689.  
  690.       newNode->attr = attr;
  691.  
  692.       if (attr != NULL) {
  693.         memcpy (newNode->attrSlot, attr->attr, sizeof (attr->attr));
  694.       }
  695.       // Clear undo pos next all node.
  696.       int nodeNums = undoStack->GetCount ();
  697.  
  698.       if (nodeNums > 0 && undoSeek != nodeNums) {
  699.         // Clear next node.
  700.         auto listPollPos = undoStack->GetHeadPosition ();
  701.  
  702.         for (int it =0; it != nodeNums; it++) {
  703.           // auto p = undoStack.Get
  704.           auto temp_pos = listPollPos;
  705.           auto p = undoStack->GetNext (listPollPos);
  706.           if (undoSeek == 0 || it >= undoSeek) {
  707.             // Remove it
  708.             undoStack->RemoveAt (temp_pos);
  709.             delete p; // XXX:
  710.           }
  711.         }
  712.       }
  713.       // Add new node.
  714.       undoStack->AddTail (newNode);
  715.       undoSeek ++;
  716.     }
  717.   }
  718.  
  719.   selPaletteInfos getSelectPal_b (int index) {
  720.  
  721.     int psize = static_cast <int> ( palList.GetCount ());
  722.     int gsize = static_cast <int> ( globalPalList.GetCount ());
  723.     int ssize ;
  724.     int total ;
  725.  
  726.     if (t_bReadWriteMap == FALSE) {
  727.       ssize = static_cast <int> ( staticPalList.GetCount ());
  728.     } else {
  729.       ssize = 0;
  730.     }
  731.     total = psize
  732.           + gsize
  733.           + ssize;
  734.  
  735.     selPaletteInfos refPal;
  736.  
  737.     refPal.sizeInTotal = total;
  738.     if (index >= 0 && index <= total) {
  739.       refPal.indexInTotal = index;
  740.  
  741.       if (t_bReadWriteMap == FALSE) {
  742.         if (total != 0 && index < total) {
  743.           if (index <  gsize) {
  744.             refPal.indexInCurSource = index;
  745.             refPal.sizeInCurSource = index;
  746.  
  747.             refPal.source = _T ("Global");
  748.             refPal.pal = globalPalList[index];
  749.             refPal.srcPaletteSet = & globalPalList;
  750.           } else {
  751.             int rvaOffset = index - gsize;
  752.             if (rvaOffset < ssize) {
  753.  
  754.               refPal.indexInCurSource = index - gsize;
  755.               refPal.sizeInCurSource = ssize;
  756.  
  757.               refPal.source = _T ("Static");
  758.               refPal.pal = staticPalList[refPal.indexInCurSource];
  759.               refPal.srcPaletteSet = & staticPalList;
  760.             } else {
  761.               refPal.indexInCurSource = index - gsize - ssize;
  762.               refPal.sizeInCurSource = psize;
  763.  
  764.               refPal.source = _T ("Local");
  765.               refPal.pal = palList[refPal.indexInCurSource];
  766.               refPal.srcPaletteSet = & palList;
  767.             }
  768.           }
  769.         }
  770.       } else {
  771.         if (total != 0 && index < total) {
  772.           if (index <  gsize) {
  773.             refPal.indexInCurSource = index;
  774.             refPal.sizeInCurSource = gsize;
  775.  
  776.             refPal.source = _T ("Global");
  777.             refPal.pal = globalPalList[index];
  778.             refPal.srcPaletteSet = & globalPalList;
  779.           } else {
  780.             refPal.indexInCurSource = index - gsize;
  781.             refPal.sizeInCurSource = psize;
  782.  
  783.             refPal.source = _T ("Local");
  784.             refPal.pal = palList[refPal.indexInCurSource];
  785.             refPal.srcPaletteSet = & palList;
  786.           }
  787.         }
  788.       }
  789.     }
  790.     return refPal;
  791.   }
  792.  
  793.   int getSelectPalSourceIndex (void) {
  794.     selPaletteInfos temp = getSelectPal_b (select);
  795.     if (temp.pal != NULL) {
  796.       return temp.pal->source;
  797.     }
  798.     return -1;
  799.   }
  800.  
  801.   CString getSelectPalSource (void) {
  802.     selPaletteInfos temp = getSelectPal_b (select);
  803.     if (temp.pal != NULL) {
  804.       return temp.source;
  805.     }
  806.     return _T ("Null");
  807.   }
  808.  
  809.   CPal *removePalette (int index) {
  810.     selPaletteInfos temp = getSelectPal_b (select);
  811.     if (temp.pal != NULL) {
  812.       temp.srcPaletteSet->RemoveAt (temp.indexInCurSource);
  813.       return temp.pal;
  814.     }
  815.     return NULL;
  816.   }
  817.  
  818.   void setIfEmptySelect0 (void) {
  819.     auto size = getPaletteTotal ();
  820.     if (size == 0) {
  821.       select = -1;
  822.       pal = NULL;
  823.     } else if (pal == NULL) {
  824.       ATLASSERT (select < 0);
  825.  
  826.       pal = getSelectPal (0);
  827.       select = 0;
  828.     } else {
  829.       // ATLASSERT (select >= 0);
  830.  
  831.       // Check current spec palette alive??
  832.       for (auto it = 0; it != size; it++) {
  833.         auto pal_temp = getSelectPal (it);
  834.         if (pal == pal_temp) {
  835.           select = it;
  836.           return ;
  837.         }
  838.       }
  839.       // Mismatch select.
  840.       // Check near index
  841.       if (select >= size) {
  842.         select = size - 1;
  843.       }
  844.       pal= getSelectPal (select);
  845.     }
  846.   }
  847.  
  848.   void readjustPos (void) {
  849.     auto size = getPaletteTotal ();
  850.     if (size == 0) {
  851.       select = -1;
  852.       pal = NULL;
  853.     } else if (pal == NULL) {
  854.       ATLASSERT (select < 0);
  855.  
  856.       select = -1;
  857.     } else {
  858.       // ATLASSERT (select >= 0);
  859.  
  860.       // Check current spec palette alive??
  861.       for (auto it = 0; it != size; it++) {
  862.         auto pal_temp = getSelectPal (it);
  863.         if (pal == pal_temp) {
  864.           select = it;
  865.           return ;
  866.         }
  867.       }
  868.       select = -1;
  869.     }
  870.   }
  871.  
  872.   FINLINE
  873.   BOOL isReadWriteMap (void) {
  874.     return t_bReadWriteMap;
  875.   }
  876.  
  877.   BOOL setSelectPalette (int sel_index = 0) {
  878.     BOOL sig = FALSE;
  879.  
  880.     if (sel_index >= 0) {
  881.       auto total = getPaletteTotal ();
  882.       if (total != 0 && sel_index < total) {
  883.         select = sel_index;
  884.         pal = getSelectPal (sel_index);
  885.         ATLASSERT (pal != NULL);
  886.  
  887.         sig = TRUE;
  888.       }
  889.     }
  890.     return sig;
  891.   }
  892.  
  893.   SIZE_T getPaletteTotal (void) {
  894.     selPaletteInfos temp = getSelectPal_b (select);
  895.     return static_cast <SIZE_T> ( temp.sizeInTotal);
  896.   }
  897.  
  898.   INT getSelectPalSourceOffset (void) {
  899.     selPaletteInfos temp = getSelectPal_b (select);
  900.     return static_cast <SIZE_T> ( temp.indexInCurSource);
  901.   }
  902.  
  903.   CPal *getSelectPal (INT select_) {
  904.     selPaletteInfos temp = getSelectPal_b (select_);
  905.     if (temp.pal != NULL) {
  906.       return temp.pal;
  907.     }
  908.     return NULL;
  909.   }
  910.  
  911.   CPal *getSelectPal (void) {
  912.     return getSelectPal (select);
  913.   }
  914.  
  915.   VOID fillId (WORD id) {
  916.      for (auto it = 0; it != 0x400; it++)
  917.      {  tileSlot [it] = id;
  918.      }
  919.   }
  920.   ~CNametableCell (void) {
  921.     if (undoStack != NULL) {
  922.       delete undoStack;
  923.       undoStack = NULL;
  924.     }
  925.     // TODO:
  926.   }
  927.   CNametableCell (CAtlArray <CPal *> &static_palList_,
  928.                CAtlArray <CPal *> &global_palList_,
  929.                BOOL bAddDefaultAttr = TRUE) :
  930.               staticPalList (static_palList_),
  931.               globalPalList (global_palList_),
  932.                      hackChr (FALSE),
  933.                    hackAttr (FALSE),
  934.                    hackPal (FALSE),
  935.                    undoStack (NULL),
  936.                    undoSeek (0),
  937.            chr (NULL), attr (NULL), pal (NULL), bank (0),select (-1) {
  938.     RtlFillMemory (tileSlot, sizeof (tileSlot), 0xFF);
  939.  
  940.     attrList.RemoveAll ();
  941.     palList.RemoveAll ();
  942.  
  943.     if (bAddDefaultAttr != FALSE) {
  944.       attr = new CAttr;
  945.       attrList.InsertAt (attrList.GetCount (), attr);
  946.     }
  947.     if (t_bReadWriteMap != FALSE) {
  948.       undoStack = new CAtlList <CClayUndoNode *>;
  949.     }
  950.   }
  951.  
  952.   // Copt methiod
  953.   VOID Copy (const CNametableCell &cObject) {
  954.      * chr = *cObject.chr;
  955.       attrList.RemoveAll ();
  956.       palList.RemoveAll ();
  957.  
  958.      for (auto it = 0; it != cObject.attrList.GetCount (); it++) {
  959.         auto p = new CAttr;
  960.         * p = * cObject.attrList[it];
  961.         attrList.InsertAt (attrList.GetCount (), p);
  962.      }
  963.      for (auto it = 0; it != cObject.palList.GetCount (); it++) {
  964.         auto p = new CPal;
  965.         * p = * cObject.palList[it];
  966.         palList.InsertAt (palList.GetCount (), p);
  967.      }
  968.      RtlCopyMemory (tileSlot, cObject.tileSlot, sizeof (tileSlot));
  969.   }
  970. };
  971.  
  972. struct CMapUnit {
  973.   INT height;
  974.   INT width;
  975.   CString comment;
  976.   CAtlArray <CNametableCell<FALSE> *> ntList;
  977.   CAtlArray <CPal *> staticPal;
  978.   CAtlArray <CPal *> &globalPal;
  979.   CAtlArray <CUndoMapNode *> undoStack;
  980.   int undoSeek;
  981.  
  982.   CMapUnit (CAtlArray <CPal *> &globalPal__):
  983.                            globalPal (globalPal__),
  984.                            height (0),
  985.                          width (0),
  986.                          undoSeek (0)
  987.   {}
  988. #if 0
  989.   // FIXME: adjust attr index in internal.
  990.   void updateCacheToMain (CClayUndoNode *node) {
  991.     ATLASSERT (node != NULL);
  992.  
  993.     auto specAttr = node->attr;
  994.  
  995.     // Copy tile id.
  996.     memcpy (tileSlot, node->tileSlot, sizeof (tileSlot));
  997.  
  998.     // Serach list .
  999.     for (SIZE_T it =0; it != attrList.GetCount (); it++) {
  1000.       auto p = attrList[it];
  1001.       if (p == specAttr) {
  1002.         // Adjust pos.
  1003.         // attr = specAttr;
  1004.  
  1005.         memcpy (specAttr->attr, node->attrSlot, sizeof (node->attrSlot));
  1006.         return ;
  1007.       }
  1008.     }
  1009.     node->attr = NULL;
  1010.   }
  1011.  
  1012.   // snapshot only for clay windwos.
  1013.   PVOID snapshotResume (void) {
  1014.     // Next undo list.
  1015.     if (undoStack != NULL) {
  1016.       auto count = undoStack->GetCount ();
  1017.  
  1018.       if (count == 0 || undoSeek == count) {
  1019.         return NULL;
  1020.       }
  1021.       ATLASSERT (undoSeek <=  count);
  1022.       auto node = undoStack->GetAt (undoStack->FindIndex (undoSeek));
  1023.       ATLASSERT (node != NULL);
  1024.       undoSeek ++;
  1025.       updateCacheToMain (node);
  1026.       return node;
  1027.     }
  1028.     return NULL;
  1029.   }
  1030.  
  1031.   PVOID snapshotUndo (void) {
  1032.     if (undoStack != NULL) {
  1033.       auto count = undoStack->GetCount ();
  1034.  
  1035.       if (count <= 1 || undoSeek <= 1) {
  1036.         return NULL;
  1037.       }
  1038.       ATLASSERT (undoSeek <=  count);
  1039.       auto node = undoStack->GetAt (undoStack->FindIndex (undoSeek - 2));
  1040.       ATLASSERT (node != NULL);
  1041.       undoSeek --;
  1042.       updateCacheToMain (node);
  1043.       return node;
  1044.     }
  1045.     return NULL;
  1046.   }
  1047.  
  1048.   void snapshotToUndoStack (void) {
  1049.     if (undoStack != NULL) {
  1050.       // For simplicity, put the entire snapshot on the stack at once
  1051.       auto newNode = new CClayUndoNode;
  1052.  
  1053.       // Copy tile cache.
  1054.       memcpy (newNode->tileSlot, tileSlot, sizeof (tileSlot));
  1055.  
  1056.       newNode->attr = attr;
  1057.  
  1058.       if (attr != NULL) {
  1059.         memcpy (newNode->attrSlot, attr->attr, sizeof (attr->attr));
  1060.       }
  1061.       // Clear undo pos next all node.
  1062.       int nodeNums = undoStack->GetCount ();
  1063.  
  1064.       if (nodeNums > 0 && undoSeek != nodeNums) {
  1065.         // Clear next node.
  1066.         auto listPollPos = undoStack->GetHeadPosition ();
  1067.  
  1068.         for (int it =0; it != nodeNums; it++) {
  1069.           // auto p = undoStack.Get
  1070.           auto temp_pos = listPollPos;
  1071.           auto p = undoStack->GetNext (listPollPos);
  1072.           if (undoSeek == 0 || it >= undoSeek) {
  1073.             // Remove it
  1074.             undoStack->RemoveAt (temp_pos);
  1075.             delete p; // XXX:
  1076.           }
  1077.         }
  1078.       }
  1079.       // Add new node.
  1080.       undoStack->AddTail (newNode);
  1081.       undoSeek ++;
  1082.     }
  1083.   }
  1084.   void snapshotToUndoStack (int xDst, int yDst, int wDst, int hDst,
  1085.                             int xSrc, int ySrc, int wSrc, int hSrc) {
  1086.     if (undoStack != NULL) {
  1087.       // For simplicity, put the entire snapshot on the stack at once
  1088.       auto newNode = new CClayUndoNode;
  1089.  
  1090.       // Copy tile cache.
  1091.       memcpy (newNode->tileSlot, tileSlot, sizeof (tileSlot));
  1092.  
  1093.       newNode->attr = attr;
  1094.  
  1095.       if (attr != NULL) {
  1096.         memcpy (newNode->attrSlot, attr->attr, sizeof (attr->attr));
  1097.       }
  1098.       // Clear undo pos next all node.
  1099.       int nodeNums = undoStack->GetCount ();
  1100.  
  1101.       if (nodeNums > 0 && undoSeek != nodeNums) {
  1102.         // Clear next node.
  1103.         auto listPollPos = undoStack->GetHeadPosition ();
  1104.  
  1105.         for (int it =0; it != nodeNums; it++) {
  1106.           // auto p = undoStack.Get
  1107.           auto temp_pos = listPollPos;
  1108.           auto p = undoStack->GetNext (listPollPos);
  1109.           if (undoSeek == 0 || it >= undoSeek) {
  1110.             // Remove it
  1111.             undoStack->RemoveAt (temp_pos);
  1112.             delete p; // XXX:
  1113.           }
  1114.         }
  1115.       }
  1116.       // Add new node.
  1117.       undoStack->AddTail (newNode);
  1118.       undoSeek ++;
  1119.     }
  1120.   }
  1121.  
  1122.   void snapshotToUndoStack (int x, int y, int w, int h) {
  1123.     // For simplicity, put the entire snapshot on the stack at once
  1124.     auto newNode = new CClayUndoNode;
  1125.  
  1126.     // Copy tile cache.
  1127.     memcpy (newNode->tileSlot, tileSlot, sizeof (tileSlot));
  1128.  
  1129.     newNode->attr = attr;
  1130.  
  1131.     if (attr != NULL) {
  1132.       memcpy (newNode->attrSlot, attr->attr, sizeof (attr->attr));
  1133.     }
  1134.     // Clear undo pos next all node.
  1135.     int nodeNums = undoStack->GetCount ();
  1136.  
  1137.     if (nodeNums > 0 && undoSeek != nodeNums) {
  1138.       // Clear next node.
  1139.       auto listPollPos = undoStack->GetHeadPosition ();
  1140.  
  1141.       for (int it =0; it != nodeNums; it++) {
  1142.         // auto p = undoStack.Get
  1143.         auto temp_pos = listPollPos;
  1144.         auto p = undoStack->GetNext (listPollPos);
  1145.         if (undoSeek == 0 || it >= undoSeek) {
  1146.           // Remove it
  1147.           undoStack->RemoveAt (temp_pos);
  1148.           delete p; // XXX:
  1149.         }
  1150.       }
  1151.     }
  1152.     // Add new node.
  1153.     undoStack->AddTail (newNode);
  1154.     undoSeek ++;
  1155.   }
  1156. #endif
  1157.  
  1158.   VOID resetMap (SIZE_T req_w, SIZE_T req_h,
  1159.                BOOL clear_data = FALSE,
  1160.                WORD fill_id = 0x8000)
  1161.   {
  1162.     if ( (req_w != 0
  1163.       && req_h != 0)
  1164.          &&
  1165.          (height != req_w
  1166.         || width != req_h))
  1167.     {
  1168.        // Adjust size
  1169.        if (width == req_h) {
  1170.          // Same pitch
  1171.          // Only Adjust y vector.
  1172.          int rva = req_h - height;
  1173.          if (rva >0) {
  1174.            // Add vector
  1175.           for (auto j = 0; j != rva; j++) {
  1176.             for (auto i = 0; i != width; i++) {
  1177.               CNametableCell<FALSE> *chunk = new CNametableCell <FALSE> (staticPal, globalPal);
  1178.               ntList.InsertAt (ntList.GetCount (), chunk);
  1179.             }
  1180.           }
  1181.          } else {
  1182.            // Sub vector
  1183.           rva = - rva;
  1184.           for (auto j = 0; j != rva; j++) {
  1185.             for (auto i = 0; i != width; i++) {
  1186.               delete ntList.GetAt (ntList.GetCount () - 1);
  1187.               ntList.RemoveAt  (ntList.GetCount () - 1);
  1188.             }
  1189.           }
  1190.          }
  1191.        } else {
  1192.          // new temp mapunit
  1193.          CAtlArray <CNametableCell<FALSE> *> ntListTemp;
  1194.          
  1195.          ntList.Copy (ntListTemp);
  1196.  
  1197.          // Allco new size.
  1198.          ntList.SetCount (0);
  1199.  
  1200.          for (auto j = 0; j != req_h; j++) {
  1201.            for (auto i = 0; i != req_w; i++) {
  1202.              auto p = new CNametableCell<FALSE> (staticPal, globalPal);
  1203.              ntList.InsertAt (ntList.GetCount (), p);
  1204.              // Check is old data???
  1205.              if (j < height
  1206.                && i < width)
  1207.              {
  1208.                 p->Copy (* ntListTemp[j * width + i]);
  1209.              }
  1210.            }
  1211.          }
  1212.          // Release old data
  1213.          for (auto it =0; it != ntListTemp.GetCount (); it++) {
  1214.            delete ntListTemp[it];
  1215.          }
  1216.          ntListTemp.RemoveAll ();
  1217.        }
  1218.        width = req_w;
  1219.        height = req_h;
  1220.     }
  1221.     if (clear_data != FALSE) {
  1222.         for (auto it = 0; it != ntList.GetCount (); it++) {
  1223.           ntList[it]->fillId (fill_id);
  1224.         }
  1225.     }
  1226.   }
  1227. };
  1228.  
  1229. class CMemoryPaint16 {
  1230. private:
  1231.   HGDIOBJ m_PrevBitmap;
  1232.   HDC m_MemoryDC;
  1233.   PWORD m_SurfacePtr;
  1234.   DWORD m_SurfaceWidth;
  1235.   DWORD m_SurfaceHeight;
  1236.   HWND m_AttachWindow;
  1237.   DWORD m_PitchBaseBit;
  1238.   DWORD m_Pitch;
  1239.  
  1240. public:
  1241.   struct DirectWrite {
  1242.     PWORD pBits;
  1243.     DWORD Pitch16;
  1244.     DWORD Pitch;
  1245.   };
  1246.   FINLINE
  1247.   HDC& getMemoryDC (VOID) {
  1248.     return m_MemoryDC;
  1249.   }
  1250.   CMemoryPaint16 (VOID):
  1251.     m_PrevBitmap (NULL),
  1252.     m_MemoryDC (NULL),
  1253.     m_SurfacePtr (NULL),
  1254.     m_SurfaceWidth (0),
  1255.     m_SurfaceHeight (0) {}
  1256.   ~CMemoryPaint16 (VOID) { destroy (); }
  1257.  
  1258.   VOID destroy (VOID) {
  1259.    if (m_SurfacePtr!= NULL) {
  1260.      m_SurfacePtr = NULL;
  1261.      if (m_MemoryDC != NULL) {
  1262.        HGDIOBJ prev = SelectObject (m_MemoryDC, m_PrevBitmap);
  1263.        DeleteObject (prev);
  1264.        DeleteDC (m_MemoryDC);
  1265.      }
  1266.    }
  1267.   }
  1268.  
  1269.   VOID fillColor (int x_pos, int y_pos, int width , int height, WORD color) {
  1270.     PWORD vptr = & m_SurfacePtr[x_pos+y_pos*m_PitchBaseBit];
  1271.     DWORD rva = m_PitchBaseBit - width;
  1272.     DWORD wblk_8 = width >> 3;
  1273.     DWORD wmod_8 = width & 7;
  1274.     DWORD u, v;
  1275.  
  1276.     for (u = height; u != 0; u--) { // XXX: height must >= 0
  1277.       for (v = wblk_8; v != 0; v--) {
  1278.         vptr[0] = color;
  1279.         vptr[1] = color;
  1280.         vptr[2] = color;
  1281.         vptr[3] = color;
  1282.         vptr[4] = color;
  1283.         vptr[5] = color;
  1284.         vptr[6] = color;
  1285.         vptr[7] = color;
  1286.         vptr += 8;
  1287.       }
  1288.       for (v = wmod_8; v != 0; v--) {
  1289.         *vptr++ = color;
  1290.       }
  1291.       vptr += rva;
  1292.     }
  1293.   }
  1294.  
  1295.   VOID fillColor (CPoint &pt, CSize &vec, WORD color) {
  1296.     return fillColor (pt.x, pt.y, vec.cx, vec.cy, color);
  1297.   }
  1298.  
  1299.   VOID fillFullClient (WORD color) {
  1300.     CRect rcClient;
  1301.     :: GetClientRect (m_AttachWindow, & rcClient);
  1302.  
  1303.     if (rcClient.Width () > 0
  1304.       && rcClient.Height () > 0)
  1305.     {
  1306.       fillColor (rcClient.TopLeft (), rcClient.Size (), color);
  1307.     }
  1308.   }
  1309.  
  1310.   SFINLINE
  1311.   VOID fillColor (const CMemoryPaint16::DirectWrite &dirwrite, int x_pos, int y_pos, int width , int height, WORD color) {
  1312.     PWORD vptr = & dirwrite.pBits[x_pos+y_pos*dirwrite.Pitch16];
  1313.     DWORD rva = dirwrite.Pitch16 - width;
  1314.     DWORD wblk_8 = width >> 3;
  1315.     DWORD wmod_8 = width & 7;
  1316.     DWORD u, v;
  1317.  
  1318.     for (u = height; u != 0; u--) { // XXX: height must >= 0
  1319.       for (v = wblk_8; v != 0; v--) {
  1320.         vptr[0] = color;
  1321.         vptr[1] = color;
  1322.         vptr[2] = color;
  1323.         vptr[3] = color;
  1324.         vptr[4] = color;
  1325.         vptr[5] = color;
  1326.         vptr[6] = color;
  1327.         vptr[7] = color;
  1328.         vptr += 8;
  1329.       }
  1330.       for (v = wmod_8; v != 0; v--) {
  1331.         *vptr++ = color;
  1332.       }
  1333.       vptr += rva;
  1334.     }
  1335.   }
  1336.  
  1337.   SFINLINE
  1338.   VOID fillColor (const CMemoryPaint16::DirectWrite &dirwrite, CPoint &pt, CSize &vec, WORD color) {
  1339.     return fillColor (dirwrite, pt.x, pt.y, vec.cx, vec.cy, color);
  1340.   }
  1341.  
  1342.   VOID fillFullClient (const CMemoryPaint16::DirectWrite &dirwrite, WORD color) {
  1343.     CRect rcClient;
  1344.     :: GetClientRect (m_AttachWindow, & rcClient);
  1345.  
  1346.     if (rcClient.Width () > 0
  1347.       && rcClient.Height () > 0)
  1348.     {
  1349.       fillColor (dirwrite, rcClient.TopLeft (), rcClient.Size (), color);
  1350.     }
  1351.   }
  1352.  
  1353.   VOID blit (int dst_x, int dst_y, int src_x, int src_y, int width, int height) {
  1354.     HDC dc = GetDC (m_AttachWindow);
  1355.     :: BitBlt (dc, dst_x, dst_y, width, height, m_MemoryDC, src_x, src_y, SRCCOPY);
  1356.     :: ReleaseDC (m_AttachWindow, dc);
  1357.   }
  1358.  
  1359.   VOID blit (CPoint &dst, CPoint &src, CSize &vec) {
  1360.     blit (dst.x, dst.y, src.x, src.y, vec.cx, vec.cy);
  1361.   }
  1362.  
  1363.   VOID blitClientBaseALL0 (VOID) {
  1364.     CRect rcClient;
  1365.     :: GetClientRect (m_AttachWindow, & rcClient);
  1366.  
  1367.     if (rcClient.Width () > 0
  1368.       && rcClient.Height () > 0)
  1369.     {
  1370.       blit (CPoint (0, 0), CPoint (0, 0), rcClient.Size ());
  1371.     }
  1372.   }
  1373.  
  1374.   VOID blitStretch (int dst_x, int dst_y, int dst_w, int dst_h, int src_x, int src_y, int src_w, int src_h) {
  1375.     HDC dc = GetDC (m_AttachWindow);
  1376.     :: StretchBlt (dc, dst_x, dst_y, dst_w, dst_h, m_MemoryDC, src_x, src_y, src_w, src_h, SRCCOPY);
  1377.     :: ReleaseDC (m_AttachWindow, dc);
  1378.   }
  1379.  
  1380.   VOID blitStretch (CPoint &dst_point, CSize &dst_vec, CPoint &src_point, CSize &src_vec) {
  1381.     blitStretch (dst_point.x, dst_point.y, dst_vec.cx, dst_vec.cy,
  1382.               src_point.x, src_point.y, src_vec.cx, src_vec.cy);
  1383.   }
  1384.  
  1385.   VOID getBackSurface (DirectWrite &ref) {
  1386.     ref.pBits = m_SurfacePtr;
  1387.     ref.Pitch = m_Pitch;
  1388.     ref.Pitch16 = m_PitchBaseBit;
  1389.   }
  1390.  
  1391.   BOOL resetMemoryDC (HWND attachWindow) {
  1392.     CRect rcClient;
  1393.     ::GetClientRect (attachWindow, & rcClient);
  1394.     return resetMemoryDC (attachWindow, rcClient.Width (), rcClient.Height ());
  1395.   }
  1396.  
  1397.   BOOL resetMemoryDC (HWND attachWindow, int backSurfaceWidth, int backSurfaceHeight) {
  1398.  
  1399.     ATLASSERT (attachWindow != NULL);
  1400.  
  1401.     if (backSurfaceWidth <= 0) {
  1402.       backSurfaceWidth = GetSystemMetrics(SM_CXFULLSCREEN) + 32;
  1403.     }
  1404.     if (backSurfaceHeight <= 0) {
  1405.       backSurfaceHeight = GetSystemMetrics(SM_CYFULLSCREEN) + 32;
  1406.     }
  1407.  
  1408.     ATLASSERT (backSurfaceWidth > 0);
  1409.     ATLASSERT (backSurfaceHeight > 0);
  1410.  
  1411.     auto Pitch = backSurfaceWidth + 31 & -32;
  1412.  
  1413.     HDC dc = GetDC (attachWindow);
  1414.     HDC mdc = CreateCompatibleDC (dc);
  1415.  
  1416.     ATLASSERT (dc != NULL);
  1417.     ATLASSERT (mdc != NULL);
  1418.  
  1419.     BITMAPINFO bmpinfos;
  1420.     RtlZeroMemory (& bmpinfos, sizeof (bmpinfos));
  1421.  
  1422.     bmpinfos.bmiHeader.biSize        =  sizeof (bmpinfos);
  1423.     bmpinfos.bmiHeader.biWidth       =  Pitch;
  1424.     bmpinfos.bmiHeader.biHeight      = -(backSurfaceHeight + 32); // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
  1425.     bmpinfos.bmiHeader.biPlanes      =  1;
  1426.     bmpinfos.bmiHeader.biBitCount    =  16;
  1427.     bmpinfos.bmiHeader.biCompression =  BI_RGB;
  1428.  
  1429.     PVOID pDIB;
  1430.     HBITMAP bitmap = :: CreateDIBSection    (mdc, & bmpinfos,
  1431.                                   DIB_RGB_COLORS, (VOID* *)& pDIB, NULL, 0);
  1432.     ATLASSERT (bitmap != NULL);
  1433.  
  1434.     HGDIOBJ GdiObj = SelectObject (mdc, bitmap);
  1435.     ATLASSERT (GdiObj != NULL && (GdiObj != HGDI_ERROR));
  1436.  
  1437.     BOOL sig = ReleaseDC (attachWindow, dc);
  1438.     ATLASSERT (sig != FALSE);    
  1439.  
  1440.     m_PrevBitmap = GdiObj;
  1441.     m_MemoryDC = mdc;
  1442.     m_SurfacePtr = (PWORD) pDIB;
  1443.     m_SurfaceWidth = backSurfaceWidth;
  1444.     m_SurfaceHeight = backSurfaceHeight;
  1445.     m_AttachWindow = attachWindow;
  1446.     m_PitchBaseBit = Pitch;
  1447.     m_Pitch = Pitch << 1;
  1448.  
  1449.     return TRUE;
  1450.   }
  1451. };
  1452.  
  1453. namespace CGlobals {
  1454.  
  1455.   CString getLastErrorString (void) {
  1456.     CString error_string;
  1457.  
  1458.     HRESULT error_code = AtlHresultFromLastError ();
  1459.     LPTSTR pszMsg = NULL;
  1460.     ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, (LPTSTR)&pszMsg, 0, NULL);
  1461.  
  1462.     error_string.Format (_T("Error code: 0x%x - %s"), error_code, pszMsg);
  1463.     ::LocalFree(pszMsg);
  1464.  
  1465.     return error_string;
  1466.   }
  1467.  
  1468.   static WORD virtuanes[64];
  1469.   static WORD nesterj[64];
  1470.   static WORD nestopia[64];
  1471.   static WORD fceux[64];
  1472.  
  1473.   static PWORD nespal;
  1474.   static UINT64 chrmixer[256];
  1475.  
  1476.   // NES Final Fansty Font.
  1477.   // From The VG Resource web.
  1478.   static WORD attrFont0_x2[256]; // 16x16
  1479.   static WORD attrFont1_x2[256]; // 16x16
  1480.   static WORD attrFont2_x2[256]; // 16x16
  1481.   static WORD attrFont3_x2[256]; // 16x16
  1482.  
  1483.   struct TilePaste {
  1484.     WORD tileSlot[0x400];
  1485.     BYTE attrSlot[64];
  1486.     BYTE palSlot[16];
  1487.     CSize copySize;
  1488.     BOOL lock;
  1489.     CChr *chr;
  1490.     BOOL hackChr;
  1491.     BOOL hackPal;
  1492.     BOOL hackAttr;
  1493.   };
  1494.  
  1495.   static TilePaste pasteTile;
  1496.   static CChr *pasteChr;
  1497.   static CAttr *pasteAttr;
  1498.   static CPal *pastePal;
  1499.  
  1500.   SFINLINE
  1501.   BYTE getAttrBit (PBYTE attrBuffer,  BYTE x, BYTE y) {
  1502.     auto xslot = x >> 2;
  1503.     auto yslot = y >> 2;
  1504.     auto attrbit = attrBuffer[(yslot << 3) + xslot];
  1505.     auto shift = (y & 2) << 1 | x & 2;
  1506.     return attrbit >> shift & 3;
  1507.   }
  1508.  
  1509.   SFINLINE
  1510.   VOID setAttrBit (PBYTE attrBuffer,  BYTE x, BYTE y, BYTE bit) {
  1511.     auto setbit = bit & 3;
  1512.     auto xslot = x >> 2;
  1513.     auto yslot = y >> 2;
  1514.     auto &attrbit = attrBuffer[(yslot << 3) + xslot];
  1515.     auto shift = (y & 2) << 1 | x & 2;
  1516.     attrbit &= ~(3 << shift);
  1517.     attrbit |= setbit << shift;
  1518.   }
  1519.  
  1520.   SFINLINE
  1521.   BOOL pasteAlive (VOID) {
  1522.     return pasteTile.lock != FALSE
  1523.        && pasteTile.copySize.cx > 0
  1524.        && pasteTile.copySize.cy > 0
  1525.        && pasteTile.chr != NULL;
  1526.   }
  1527.  
  1528.   SFINLINE
  1529.   VOID makePasteDead (VOID) {
  1530.     pasteTile.lock = FALSE;
  1531.     pasteTile.copySize.cx = 0;
  1532.     pasteTile.copySize.cy = 0;
  1533.     pasteTile.chr = NULL;
  1534.   }
  1535.  
  1536.   SFINLINE
  1537.   VOID setDefaultListViewColor (CListViewCtrl &ctrl) {
  1538.     ctrl.SetBkColor (0);
  1539.     ctrl.SetTextBkColor (0);
  1540.     ctrl.SetTextColor (0xff00);
  1541.   }
  1542.  
  1543.   static
  1544.   VOID lockPaste (PWORD tileSlot, /* base 0, no offset */
  1545.                   CPoint &ptCopyStart_,
  1546.                   CSize &copySize_,
  1547.                   CSize &maxRange_,
  1548.                   BOOL hackChr = FALSE,
  1549.                   CChr *chr = NULL,
  1550.                   BOOL hackPal = FALSE,
  1551.                   PBYTE palSlot = NULL,
  1552.                   BOOL hackAttr = FALSE,
  1553.                   PBYTE attrSlot = NULL/* base 0, no offset */)
  1554.   {
  1555.     if (copySize_.cx >= 0
  1556.       && copySize_.cy >= 0
  1557.       && chr != NULL)
  1558.     {
  1559.       pasteTile.lock = TRUE;
  1560.       pasteTile.hackChr = hackChr &&chr != NULL ;
  1561.       pasteTile.hackPal = hackPal != FALSE && palSlot != NULL;
  1562.       pasteTile.hackAttr = hackAttr != FALSE && attrSlot != NULL;
  1563.       pasteTile.copySize = copySize_;
  1564.  
  1565.       BYTE palT[] = {
  1566.         0x0F, 0x00, 0x10, 0x30,
  1567.         0x0F, 0x1C, 0x2B, 0x39,
  1568.         0x0F, 0x06, 0x15, 0x36,
  1569.         0x0F, 0x17, 0x28, 0x39
  1570.       };
  1571.  
  1572.       RtlCopyMemory (pasteTile.palSlot, palT, sizeof (pasteTile.palSlot));
  1573.       RtlZeroMemory (pasteTile.attrSlot, sizeof (pasteTile.attrSlot));
  1574.       RtlFillMemory (pasteTile.tileSlot, sizeof (pasteTile.tileSlot), 0x80);
  1575.  
  1576.       if (ptCopyStart_.x + pasteTile.copySize.cx > maxRange_.cx)
  1577.         pasteTile.copySize.cx = maxRange_.cx - ptCopyStart_.x ;
  1578.       if (ptCopyStart_.y + pasteTile.copySize.cy > maxRange_.cy)
  1579.         pasteTile.copySize.cy = maxRange_.cy - ptCopyStart_.y ;
  1580.  
  1581.       // Copy tile id.
  1582.       for (auto y = 0; y != pasteTile.copySize.cy; y++) {
  1583.         const auto y_src = y + ptCopyStart_.y;
  1584.         for (auto x = 0; x != pasteTile.copySize.cx; x++) {
  1585.           const auto x_src = x + ptCopyStart_.x;
  1586.           const auto pos = y*32+x;
  1587.           const auto dst_pos = y_src*32+x_src;
  1588.           if (tileSlot != NULL)
  1589.             pasteTile.tileSlot[pos] = tileSlot[dst_pos];
  1590.         }
  1591.       }
  1592.       // Copy palette
  1593.       if  (pasteTile.hackPal != FALSE) {
  1594.         RtlCopyMemory (pasteTile.palSlot, palSlot, sizeof (pasteTile.palSlot));
  1595.  
  1596.         pasteTile.palSlot[12] =
  1597.         pasteTile.palSlot[8] =
  1598.         pasteTile.palSlot[4] =
  1599.         pasteTile.palSlot[0];
  1600.       }
  1601.       if  (pasteTile.hackAttr != FALSE) {
  1602.         // Copy attr table
  1603.         for (auto y = 0; y != pasteTile.copySize.cy; y++) {
  1604.           const auto y_src = y + ptCopyStart_.y;
  1605.           for (auto x = 0; x != pasteTile.copySize.cx; x++) {
  1606.             const auto x_src = x + ptCopyStart_.x;
  1607.            
  1608.             setAttrBit (pasteTile.attrSlot, x, y,
  1609.                getAttrBit (attrSlot, x_src, y_src));
  1610.           }
  1611.         }
  1612.       }
  1613.       pasteTile.chr = chr;
  1614.     }
  1615.   }
  1616.  
  1617.   template <typename T>
  1618.   static VOID adjustCommentUnique (CAtlArray<T *> &list, T *add_ptr, BOOL bPushtolist = TRUE) {
  1619.     for (int it = 0; it != list.GetCount (); it++) {
  1620.       T *ptr = list[it];
  1621.       if (ptr->comment == add_ptr->comment
  1622.         && ptr != add_ptr) {
  1623.         add_ptr->comment += _T ("_");
  1624.         it = 0;
  1625.       }
  1626.     }
  1627.     if (bPushtolist != FALSE) {
  1628.       list.InsertAt (list.GetCount (), add_ptr);
  1629.     }
  1630.   }
  1631.  
  1632.   enum GridType {
  1633.     GRID_TYPE_FIXED = 0,
  1634.     GRID_TYPE_INTERLACING
  1635.   };
  1636.  
  1637.   SFINLINE
  1638.   VOID limitPoint (CPoint &point, LONG x_lim, LONG  y_lim) {
  1639.     if (point.x < 0)
  1640.       point.x = 0;
  1641.     if (point.x >= x_lim)
  1642.       point.x = x_lim - 1;
  1643.     if (point.y < 0)
  1644.       point.y = 0;
  1645.     if (point.y >= y_lim)
  1646.       point.y = y_lim - 1;
  1647.   }
  1648.  
  1649.   SFINLINE
  1650.   VOID dividerLimitPoint (CPoint &point, int div_x, int div_y,  LONG x_lim, LONG  y_lim) {
  1651.     if (div_x != 0)
  1652.       point.x /= div_x;
  1653.     else
  1654.       point.x = 0;
  1655.     if (div_y != 0)
  1656.       point.y /= div_y;
  1657.     else
  1658.       point.y = 0;
  1659.     if (point.x < 0)
  1660.       point.x = 0;
  1661.     if (point.x >= x_lim)
  1662.       point.x = x_lim - 1;
  1663.     if (point.y < 0)
  1664.       point.y = 0;
  1665.     if (point.y >= y_lim)
  1666.       point.y = y_lim - 1;
  1667.   }
  1668.  
  1669.   SFINLINE
  1670.   VOID limitSize (CSize &size, LONG x_lim, LONG  y_lim) {
  1671.     if (size.cx < 0)
  1672.       size.cx = 0;
  1673.     if (size.cx >= x_lim)
  1674.       size.cx = x_lim - 1;
  1675.     if (size.cy < 0)
  1676.       size.cy = 0;
  1677.     if (size.cy >= y_lim)
  1678.       size.cy = y_lim - 1;
  1679.   }
  1680.  
  1681.   SFINLINE
  1682.   VOID translateVecPointToltrb (CPoint &lefttop, CPoint &rightbottom) {
  1683.    
  1684.     if (lefttop.x < 0)
  1685.       lefttop.x = 0;
  1686.     if (lefttop.y < 0)
  1687.       lefttop.y = 0;
  1688.     if (rightbottom.x < 0)
  1689.       rightbottom.x = 0;
  1690.     if (rightbottom.y < 0)
  1691.       rightbottom.y = 0;
  1692.     if (lefttop.x >=rightbottom.x) {
  1693.       auto t = lefttop.x;
  1694.       lefttop.x = rightbottom.x;
  1695.       rightbottom.x = t;
  1696.     }
  1697.     if (lefttop.y >= rightbottom.y) {
  1698.       auto t = lefttop.y;
  1699.       lefttop.y = rightbottom.y;
  1700.       rightbottom.y = t;
  1701.     }
  1702.   }
  1703.  
  1704.   SFINLINE
  1705.   VOID translateVecPointToltrbLimitRange (CPoint &lefttop, CPoint &rightbottom, CSize range) {
  1706.    
  1707.     if (lefttop.x < 0)
  1708.       lefttop.x = 0;
  1709.     if (lefttop.y < 0)
  1710.       lefttop.y = 0;
  1711.     if (rightbottom.x < 0)
  1712.       rightbottom.x = 0;
  1713.     if (rightbottom.y < 0)
  1714.       rightbottom.y = 0;
  1715.     if (lefttop.x >=rightbottom.x) {
  1716.       auto t = lefttop.x;
  1717.       lefttop.x = rightbottom.x;
  1718.       rightbottom.x = t;
  1719.     }
  1720.     if (lefttop.y >= rightbottom.y) {
  1721.       auto t = lefttop.y;
  1722.       lefttop.y = rightbottom.y;
  1723.       rightbottom.y = t;
  1724.     }
  1725.     if (rightbottom.x - lefttop.x > range.cx)
  1726.       rightbottom.x = lefttop.x + range.cx ;
  1727.     if (rightbottom.y - lefttop.y > range.cy)
  1728.       rightbottom.y = lefttop.y + range.cy;
  1729.   }
  1730.  
  1731.   SFINLINE
  1732.   WORD r32tor15 (DWORD color) {
  1733.  
  1734.     BYTE c = color >> 0 & 0xFF;
  1735.     BYTE v = color >> 8 & 0xFF;
  1736.     BYTE b = color >>16 & 0xFF;
  1737.  
  1738.     c >>= 3;
  1739.     v >>= 3;
  1740.     b >>= 3;
  1741.  
  1742.     return c | v << 5 | b << 10;
  1743.   }
  1744.  
  1745.   SFINLINE
  1746.   WORD r32tor15_rev (DWORD color) {
  1747.  
  1748.     BYTE c = color >> 0 & 0xFF;
  1749.     BYTE v = color >> 8 & 0xFF;
  1750.     BYTE b = color >>16 & 0xFF;
  1751.  
  1752.     c >>= 3;
  1753.     v >>= 3;
  1754.     b >>= 3;
  1755.  
  1756.     return b | v << 5 | c << 10;
  1757.   }
  1758.  
  1759.   SFINLINE
  1760.   DWORD r15tor32_rev (WORD color) {
  1761.  
  1762.     BYTE c = color >> 0 & 0x1F;
  1763.     BYTE v = color >> 5 & 0x1F;
  1764.     BYTE b = color >>10 & 0x1F;
  1765.  
  1766.     c <<= 3;
  1767.     v <<= 3;
  1768.     b <<= 3;
  1769.  
  1770.     return b | v << 8 | c << 16;
  1771.   }
  1772.  
  1773.   SFINLINE
  1774.   WORD r15_rev (WORD color) {
  1775.  
  1776.     BYTE c = color >> 0 & 0x1F;
  1777.     BYTE v = color >> 5 & 0x1F;
  1778.     BYTE b = color >>10 & 0x1F;
  1779.  
  1780.     return b | v << 5 | c << 10;
  1781.   }
  1782.  
  1783.   SFINLINE
  1784.   WORD alpha16 (WORD tilePixel, WORD backdrop, WORD coeff1, WORD coeff2) {
  1785.  
  1786.     DWORD u_out;
  1787.     DWORD v_out;
  1788.     DWORD   out;
  1789.  
  1790.     u_out = tilePixel | tilePixel << 16;
  1791.     u_out&= 0x3E07C1F;
  1792.     u_out*= coeff1;
  1793.     v_out = backdrop | backdrop << 16;
  1794.     v_out&= 0x3E07C1F;
  1795.     v_out*= coeff2;
  1796.     /* 0000 0011 1110 0000 0111 1100 0001 1111*/
  1797.     out = v_out +u_out >> 4;
  1798.     /* Check pixel saturation */
  1799.   #if 0
  1800.     if (out & 0x20)
  1801.       out |= 0x1F; /* mod:1 */
  1802.     if (out & 0x8000)
  1803.       out |= 0x7C00;/* mod:4 */
  1804.     if (out & 0x4000000)/* mod:2 */
  1805.       out |=   0x3E00000;
  1806.   #else
  1807.       out |= 0x4008020 - (out >> 5 & 0x200401);
  1808.   #endif
  1809.     out&=    0x3E07C1F;
  1810.     return out | out >> 16;
  1811.   }
  1812.   static VOID alphaClr (CMemoryPaint16::DirectWrite &dwrite,
  1813.                                        WORD color ,
  1814.                                        WORD colorAlphaCnt,
  1815.                                         CPoint &ptStart,
  1816.                                         CSize &scanLen)
  1817.   {
  1818.     const DWORD pitch_x = scanLen.cx;
  1819.               PWORD vptr_y = & dwrite.pBits[ptStart.x + ptStart.y*dwrite.Pitch16];
  1820.  
  1821.     for (DWORD j = 0; j != scanLen.cy; j++)  {
  1822.       for (DWORD i = 0; i != scanLen.cx; i++)  {
  1823.         vptr_y[i] = CGlobals::alpha16 (vptr_y[i], color, 15 - colorAlphaCnt, colorAlphaCnt);;
  1824.         }
  1825.       vptr_y += dwrite.Pitch16;
  1826.     }
  1827.   }
  1828.  
  1829.   static VOID drawGrid (CMemoryPaint16::DirectWrite &dwrite,
  1830.                                        GridType gtype,
  1831.                                         CPoint &ptStart,
  1832.                                         CSize &elemVec,
  1833.                                         CSize &scanLen,
  1834.                                         WORD color)
  1835.  
  1836.   {
  1837.     const DWORD pitch_y = elemVec.cy * dwrite.Pitch16;
  1838.     const DWORD pitch_x = elemVec.cx;
  1839.               PWORD vptr_y = & dwrite.pBits[ptStart.x + ptStart.y*dwrite.Pitch16];
  1840.               PWORD vptr_y2 = vptr_y;
  1841.  
  1842.     if(gtype == GRID_TYPE_FIXED) {
  1843.          for (DWORD j = 0; j != scanLen.cy; j++)  {
  1844.            PWORD vptr_yt = vptr_y;
  1845.            PWORD vptr_x = vptr_yt;
  1846.            for (DWORD i = 0; i != scanLen.cx; i++)  {
  1847.              PWORD vptr_v = vptr_x;
  1848.              PWORD vptr_v2 = vptr_x;
  1849.             for (DWORD x = 0; x != elemVec.cx; x++) {
  1850.               vptr_v[x] = color;
  1851.             }
  1852.             for (DWORD x = 0; x != elemVec.cy; x++) {
  1853.               vptr_v2[0] = color;
  1854.               vptr_v2 += dwrite.Pitch16;
  1855.             }
  1856.             vptr_x += pitch_x;
  1857.            }
  1858.            vptr_y += pitch_y;
  1859.          }
  1860.          // draw final
  1861.         PWORD vptr_t = & vptr_y2[elemVec.cy * scanLen.cy * dwrite.Pitch16];
  1862.         DWORD vec = elemVec.cx * scanLen.cx + 1;
  1863.  
  1864.         for (DWORD it = 0; it != vec; it++) {
  1865.           vptr_t[it] = color;
  1866.         }
  1867.         vptr_t = & vptr_y2[elemVec.cx * scanLen.cx];
  1868.         vec = elemVec.cy * scanLen.cy + 1;
  1869.  
  1870.         for (DWORD it = 0; it != vec; it++) {
  1871.           vptr_t[0] = color;
  1872.           vptr_t += dwrite.Pitch16;
  1873.         }
  1874.     } else if (gtype == GRID_TYPE_INTERLACING) {
  1875.          for (DWORD j = 0; j != scanLen.cy; j++)  {
  1876.            PWORD vptr_yt = vptr_y;
  1877.            PWORD vptr_x = vptr_yt;
  1878.            for (DWORD i = 0; i != scanLen.cx; i++)  {
  1879.              PWORD vptr_v = vptr_x;
  1880.              PWORD vptr_v2 = vptr_x;
  1881.             for (DWORD x = 0; x != elemVec.cx; x++) {
  1882.               if (x & 1)
  1883.               vptr_v[x] = color;
  1884.             }
  1885.             for (DWORD x = 0; x != elemVec.cy; x++) {
  1886.               if (x & 1)
  1887.               vptr_v2[0] = color;
  1888.               vptr_v2 += dwrite.Pitch16;
  1889.             }
  1890.             vptr_x += pitch_x;
  1891.            }
  1892.            vptr_y += pitch_y;
  1893.          }
  1894.         PWORD vptr_t = & vptr_y2[elemVec.cy * scanLen.cy * dwrite.Pitch16];
  1895.         DWORD vec = elemVec.cx * scanLen.cx + 1;
  1896.  
  1897.         for (DWORD it = 0; it != vec; it++) {
  1898.           if (it & 1)
  1899.           vptr_t[it] = color;
  1900.         }
  1901.         vptr_t = & vptr_y2[elemVec.cx * scanLen.cx];
  1902.         vec = elemVec.cy * scanLen.cy + 1;
  1903.  
  1904.         for (DWORD it = 0; it != vec; it++) {
  1905.           if (it & 1)
  1906.           vptr_t[it] = color;
  1907.           vptr_t += dwrite.Pitch16;
  1908.         }
  1909.     }
  1910.   }
  1911.  
  1912.   static VOID loadFontPixel (LPDIRECT3DDEVICE9 device) {
  1913.     LPDIRECT3DTEXTURE9 texture;
  1914.     HRESULT sig;
  1915.     D3DLOCKED_RECT lockrect;
  1916.  
  1917.     RtlZeroMemory (attrFont0_x2, sizeof (attrFont0_x2));
  1918.     RtlZeroMemory (attrFont1_x2, sizeof (attrFont1_x2));
  1919.     RtlZeroMemory (attrFont2_x2, sizeof (attrFont2_x2));
  1920.     RtlZeroMemory (attrFont3_x2, sizeof (attrFont3_x2));
  1921.  
  1922.  
  1923.     sig = D3DXCreateTextureFromResourceEx (device,
  1924.         ModuleHelper::GetResourceInstance (),
  1925.         MAKEINTRESOURCE (IDB_ATTRFONT),
  1926.         64,
  1927.         16,
  1928.         D3DX_DEFAULT,
  1929.         0,
  1930.         D3DFMT_UNKNOWN,
  1931.         D3DPOOL_MANAGED,
  1932.         D3DX_DEFAULT,
  1933.         D3DX_DEFAULT,
  1934.         0,
  1935.         NULL,
  1936.         NULL, & texture);
  1937.  
  1938.     ATLASSERT (SUCCEEDED (sig));
  1939.  
  1940.     // Make font infos.
  1941.     sig = texture->LockRect (0, & lockrect, NULL, D3DLOCK_READONLY);
  1942.     ATLASSERT (SUCCEEDED (sig));
  1943.  
  1944.     PDWORD lockrect_v = (PDWORD) lockrect.pBits;
  1945.     DWORD lockrect_p = lockrect.Pitch >> 2;
  1946.  
  1947.     for (auto i = 0; i != 16; i++) {
  1948.       auto v = & lockrect_v[i*lockrect_p];
  1949.       auto y = i << 4;
  1950.       for (auto j = 0; j != 16; j++) {
  1951.          attrFont0_x2[y+j] = r32tor15 ( v[j]);
  1952.          attrFont1_x2[y+j] = r32tor15 ( v[j+16]);
  1953.          attrFont2_x2[y+j] = r32tor15 ( v[j+32]);
  1954.          attrFont3_x2[y+j] = r32tor15 ( v[j+48]);
  1955.       }
  1956.     }
  1957.     texture->UnlockRect (0);
  1958.     texture->Release ();
  1959.     texture = NULL;
  1960.   }
  1961.  
  1962.   static VOID globalInit (VOID) {
  1963.  
  1964.      // init global nes palette
  1965.      static DWORD virtuaNESPal[] = {
  1966.        0x007F7F7F,0x002000B0,0x002800B8,0x006010A0,
  1967.        0x00982078,0x00B01030,0x00A03000,0x00784000,
  1968.        0x00485800,0x00386800,0x00386C00,0x00306040,
  1969.        0x00305080,0x00000000,0x00000000,0x00000000,
  1970.        0x00BCBCBC,0x004060F8,0x004040FF,0x009040F0,
  1971.        0x00D840C0,0x00D84060,0x00E05000,0x00C07000,
  1972.        0x00888800,0x0050A000,0x0048A810,0x0048A068,
  1973.        0x004090C0,0x00000000,0x00000000,0x00000000,
  1974.        0x00FFFFFF,0x0060A0FF,0x005080FF,0x00A070FF,
  1975.        0x00F060FF,0x00FF60B0,0x00FF7830,0x00FFA000,
  1976.        0x00E8D020,0x0098E800,0x0070F040,0x0070E090,
  1977.        0x0060D0E0,0x00606060,0x00000000,0x00000000,
  1978.        0x00FFFFFF,0x0090D0FF,0x00A0B8FF,0x00C0B0FF,
  1979.        0x00E0B0FF,0x00FFB8E8,0x00FFC8B8,0x00FFD8A0,
  1980.        0x00FFF090,0x00C8F080,0x00A0F0A0,0x00A0FFC8,
  1981.        0x00A0FFF0,0x00A0A0A0,0x00000000,0x00000000
  1982.      };
  1983.      static DWORD nesterjPal[] = {
  1984.        0x00757575,0x00271B8F,0x000000AB,0x0047009F,
  1985.        0x008F0077,0x00AB0013,0x00A70000,0x007F0B00,
  1986.        0x00432F00,0x00004700,0x00005100,0x00003F17,
  1987.        0x001B3F5F,0x00000000,0x00050505,0x00050505,
  1988.        0x00BCBCBC,0x000073EF,0x00233BEF,0x008300F3,
  1989.        0x00BF00BF,0x00E7005B,0x00DB2B00,0x00CD4F0F,
  1990.        0x008B7300,0x00009700,0x0000AB00,0x0000933B,
  1991.        0x0000838B,0x00111111,0x00090909,0x00090909,
  1992.        0x00FFFFFF,0x003FBFFF,0x005F97FF,0x00A78BFD,
  1993.        0x00F77BFF,0x00FF77B7,0x00FF7763,0x00FF9B3B,
  1994.        0x00F3BF3F,0x0083D313,0x004FDF4B,0x0058F898,
  1995.        0x0000EBDB,0x00666666,0x000D0D0D,0x000D0D0D,
  1996.        0x00FFFFFF,0x00ABE7FF,0x00C7D7FF,0x00D7CBFF,
  1997.        0x00FFC7FF,0x00FFC7DB,0x00FFBFB3,0x00FFDBAB,
  1998.        0x00FFE7A3,0x00E3FFA3,0x00ABF3BF,0x00B3FFCF,
  1999.        0x009FFFF3,0x00DDDDDD,0x00111111,0x00111111
  2000.      };
  2001.      for (auto It = 0; It != 64; It++) {
  2002.        virtuanes[It] = r32tor15 (virtuaNESPal[It]);
  2003.        nesterj[It] = r32tor15 (nesterjPal[It]);
  2004.      }
  2005.      nespal = virtuanes;
  2006.  
  2007.      // Make chr mixer ;
  2008.      for (WORD It = 0; It != 256; It++) {
  2009.        CPolyData64 cpd64;
  2010.  
  2011.        cpd64.blk8[0] = It >> 7 & 1;
  2012.        cpd64.blk8[1] = It >> 6 & 1;
  2013.        cpd64.blk8[2] = It >> 5 & 1;
  2014.        cpd64.blk8[3] = It >> 4 & 1;
  2015.        cpd64.blk8[4] = It >> 3 & 1;
  2016.        cpd64.blk8[5] = It >> 2 & 1;
  2017.        cpd64.blk8[6] = It >> 1 & 1;
  2018.        cpd64.blk8[7] = It >> 0 & 1;
  2019.  
  2020.        chrmixer[It] = cpd64.blk;
  2021.      }
  2022.      pasteChr = NULL;
  2023.      pasteAttr = NULL;
  2024.      pastePal = NULL;
  2025.   }
  2026.   static
  2027.   DWORD crc32_intel (DWORD init_crc, void *buffer, int len) {
  2028.     auto crc_calc = init_crc;
  2029.  
  2030.     if (len > 0) {
  2031.       auto crc_block4 = len >> 4;
  2032.       auto crc_block1 = len & 15;
  2033.       auto crc_ptr = (DWORD *) buffer;
  2034.  
  2035.       // calc align buffer
  2036.       for (auto it = 0; it != crc_block4; it++) {
  2037.         crc_calc =
  2038.            _mm_crc32_u32
  2039.             ( _mm_crc32_u32
  2040.              ( _mm_crc32_u32
  2041.                ( _mm_crc32_u32 (crc_calc,
  2042.                          crc_ptr[0])
  2043.                       , crc_ptr[1])
  2044.                      , crc_ptr[2])
  2045.                     , crc_ptr[3]);
  2046.         crc_ptr += 4;
  2047.       }
  2048.       // calc remain
  2049.       auto crc_ptr8 = (BYTE *)crc_ptr;
  2050.       for (auto it = 0; it != crc_block1; it++) {
  2051.         crc_calc = _mm_crc32_u8 (crc_calc, crc_ptr8[it]);
  2052.       }
  2053.     }
  2054.     return crc_calc;
  2055.   }
  2056. };
  2057.  
  2058. class CMainFrame : public CFrameWindowImpl<CMainFrame>
  2059.                  , public CMessageFilter
  2060.                  , public CIdleHandler
  2061. {
  2062.   class CValidateALL {
  2063.     BOOL m_bValidateMain;
  2064.     HWND m_window;
  2065.     BOOL m_FlushFrame;
  2066.     CMainFrame &m_frame;
  2067.  
  2068.  public:  
  2069.     void operator=(BOOL bFlushFrame)
  2070.     {
  2071.      m_FlushFrame = !! bFlushFrame;
  2072.     }
  2073.  
  2074.     void setMainValidateStatus(BOOL bValidateMain)
  2075.     {
  2076.      m_bValidateMain = !! bValidateMain;
  2077.     }
  2078.  
  2079.     CValidateALL (CMainFrame &hostFrame, HWND window, BOOL bFlushFrame = TRUE, BOOL bValidateMain = TRUE):
  2080.       m_FlushFrame (bFlushFrame),
  2081.       m_frame (hostFrame),
  2082.       m_bValidateMain (bValidateMain),
  2083.       m_window (window)
  2084.     {
  2085.     }
  2086.     ~CValidateALL (VOID)
  2087.     {
  2088.        if (m_FlushFrame != FALSE)
  2089.        {
  2090.          m_frame.allViewUpdate ();
  2091.        }
  2092.        if (m_window != NULL
  2093.            && m_bValidateMain != FALSE)
  2094.        {
  2095.           :: ValidateRect (m_window, NULL);
  2096.        }
  2097.     }
  2098.   };
  2099.  
  2100.   struct CNNEFile {
  2101.     CNNEFile (void) {
  2102.       //  Same as namespace
  2103.       //  Does not contain actual code and memory space
  2104.       ATLASSERT (FALSE);
  2105.     }
  2106.     // nne files      0123456789ABCDEF
  2107.     // magic number - moecmks  nes-nne:char
  2108.     // files crc32 without header : dword (use _mm_crc32_u8)
  2109.     //
  2110.     // chr-chain section offset | chr number : dword  | dword  
  2111.     // gloabl-palette-chain section offset | palette number : dword | dword
  2112.     // clay-chain section offset| clay number  : dword  | dword  
  2113.     // map-chain section offset | map number : dword  | dword  
  2114.     //
  2115.     // chr-pixel- pool section offset :dword    -> per elem 4K bytes
  2116.     // attr table- pool section offset :dword    -> per elem 64 bytes
  2117.     // palette- pool section offset :dword    -> per elem 16 bytes
  2118.     // nametable/clay-pool section offset : dword -> per elem 2K bytes 32x32 tile word
  2119.     // string-pool section offset : dword
  2120.     //
  2121.     // gloabl-palette-chain section >========================================
  2122.     //    array : comment length | offset  :qword + index : qword
  2123.     // chr-chain section >========================================
  2124.     //    array : comment length | offset  :qword + index : qword
  2125.     // clay-chain section >=======================================
  2126.     //    header -> elem offset array
  2127.     //
  2128.     //    elem -> comment length | offset : qword
  2129.     //         -> chr-index : qword
  2130.     //         -> nametable/clay-pool index : dword
  2131.     //         -> attr-count : dword
  2132.     //         -> palette-count : dword
  2133.     //         -> attr-select : dword (DWORD_MAX := empty)
  2134.     //         -> palette-select : dword (DWORD_MAX := empty)
  2135.     //         -> attr chunk set
  2136.     //               |
  2137.     //               -> comment length | offset : qword
  2138.     //               -> attr index
  2139.     //         -> pal chunk set
  2140.     //               |
  2141.     //               -> comment length | offset : qword
  2142.     //               -> pal index
  2143.     //
  2144.     // map-chain section >=======================================
  2145.     //    header -> elem offset array
  2146.     //
  2147.     //    elem -> comment length | offset : qword
  2148.     //         -> width : dword
  2149.     //         -> height : dword
  2150.     //         -> static palette -chain count: dword
  2151.     //         -> static-palette -array : comment length | offset  :qword + index : qword
  2152.     //         |
  2153.     //         -> page elem
  2154.     //                | header -> page elem offset array
  2155.     //                |
  2156.     //                |  -> chr-index : qword (DWORD_MAX := empty)
  2157.     //                |  -> nametable/clay-pool index : dword
  2158.     //                |  -> attr-count : dword
  2159.     //                |  -> palette-count : dword
  2160.     //                |  -> attr-select : dword (DWORD_MAX := empty)
  2161.     //                |  -> palette-select : dword (DWORD_MAX := empty)
  2162.     //                |  -> attr chunk set
  2163.     //                      |  
  2164.     //                      |-------> comment length | offset : qword
  2165.     //                      |-------> attr index
  2166.     //                |  -> pal chunk set
  2167.     //                      |      
  2168.     //                      |-------> comment length | offset : qword
  2169.     //                      |-------> pal index    
  2170.     struct NNEHeader {
  2171.       BYTE magic[16];
  2172.       DWORD crc32_intel;
  2173.       DWORD chrChainOffset;
  2174.       DWORD chrCount;
  2175.       DWORD gPaletteCount;
  2176.       DWORD gPaletteChainOffset;  
  2177.       DWORD clayChainOffset;
  2178.       DWORD clayCount;
  2179.       DWORD mapChainOffset;
  2180.       DWORD mapCount;
  2181.       DWORD attrPoolOffset;
  2182.       DWORD chrPoolOffset;
  2183.       DWORD palettePoolOffset;
  2184.       DWORD nclayPoolOffset;
  2185.       DWORD stringPoolOffset;
  2186.     };
  2187.     struct chrSectionChunk {
  2188.       DWORD commentLength;
  2189.       DWORD commentOffset;
  2190.       UINT64 chrIndex;
  2191.     };
  2192.     struct attrChunk {
  2193.       DWORD commentLength;
  2194.       DWORD commentOffset;
  2195.       UINT64 attrIndex;
  2196.     };
  2197.     struct palChunk {
  2198.       DWORD commentLength;
  2199.       DWORD commentOffset;
  2200.       UINT64 palIndex;
  2201.     };
  2202.     struct claySectionChunkHeader {
  2203.       DWORD commentLength;
  2204.       DWORD commentOffset;
  2205.       DWORD chrIndex;
  2206.       DWORD clayIndex;
  2207.       DWORD attrCount;
  2208.       DWORD paletteCount;
  2209.       DWORD attrSel;
  2210.       DWORD paletteSel;
  2211.       /* attrCount  attrChunk */
  2212.       /* paletteCount  palChunk */
  2213.     };
  2214.     struct claySection {
  2215.       /* NNEHeader :: clayCount offset:DWORD */
  2216.       /* NNEHeader :: clayCount claySectionChunkHeader */
  2217.     };
  2218.     struct mapSectionPageChunk {
  2219.       DWORD chrIndex;
  2220.       DWORD nametableIndex;
  2221.       DWORD attrCount;
  2222.       DWORD paletteCount;
  2223.       DWORD attrSel;
  2224.       DWORD paletteSel;
  2225.       /* attrCount  attrChunk */
  2226.       /* paletteCount  palChunk */  
  2227.     };
  2228.     struct mapSectionChunk {
  2229.       DWORD commentLength;
  2230.       DWORD commentOffset;
  2231.       DWORD width;
  2232.       DWORD height;
  2233.       DWORD sPaletteCount;
  2234.       /* sPaletteCount  palChunk */  
  2235.       /* width* height  mapSectionPageChunk offset   */
  2236.     };
  2237.   };
  2238.  
  2239. // <CViewNametablePage> =========================================
  2240. template <BOOL t_bReadWriteMap>
  2241. struct CViewNametablePage : public CDialogImpl<CViewNametablePage<t_bReadWriteMap>, CWindowFT>
  2242. {
  2243. // Some global settings.
  2244.   enum { IDD = IDD_NAMETABLE_PAGE };
  2245.  
  2246.   static const DWORD tileUnitSize = 16;
  2247.   static const DWORD attrUnitSize = 16;
  2248.   static const DWORD gpalUnitWidth = 19;
  2249.   static const DWORD gpalUnitHeight = 25;
  2250.   static const DWORD cpalUnitWidth = 46;
  2251.   static const DWORD cpalUnitHeight = 23;
  2252.   static const WORD meshClr = 12 | 12 << 5 | 12 << 10;
  2253.   static const WORD spalCatchClr = 0x1f << 10;
  2254.   static const WORD alphaClr = 0x7f00;
  2255.   static const WORD alphaCnt = 7;
  2256.   static const WORD attrFontclr= 0x7fff;
  2257.   static const WORD attrFontbgclr = 0;
  2258.   static const WORD spalCatchBakClr = 0x1f << 5;
  2259.   static const WORD attrSelMoveClr = 0x1f;
  2260.   static const WORD attrSelEndClr = 0x1f << 5;
  2261.   static const WORD claySelMovClr = 0x1f << 10;
  2262.   static const WORD attrMeshClr = PHOTOSHOP_COL_TOGDI16 (0xaaaaaa);
  2263.   static const WORD transShadowMark = PHOTOSHOP_COL_TOGDI16 (0xffffff);
  2264.   static const WORD transHitMark = PHOTOSHOP_COL_TOGDI16 (0xcecece);
  2265.  
  2266.   static const size_t MAP_CONTROL_LV_CHR = 1;
  2267.   static const size_t MAP_CONTROL_LV_ATTR = MAP_CONTROL_LV_CHR + 1;
  2268.   static const size_t MAP_CONTROL_LV_GPAL = MAP_CONTROL_LV_ATTR + 1;
  2269.   static const size_t MAP_CONTROL_LV_SPAL = MAP_CONTROL_LV_GPAL + 1;
  2270.   static const size_t MAP_CONTROL_LV_ATTRLIST = MAP_CONTROL_LV_SPAL + 1;
  2271.   static const size_t MAP_CONTROL_LV_PALLIST = MAP_CONTROL_LV_ATTRLIST + 1;
  2272.  
  2273.   typedef CDialogImpl<CViewNametablePage<t_bReadWriteMap>> baseClass;
  2274.   typedef CViewNametablePage thisClass;
  2275.  
  2276.   CMainFrame *m_atthis;
  2277.   CContainedWindowT<CListViewCtrl> m_GuiLV_Chr;
  2278.   CContainedWindowT<CListViewCtrl> m_GuiLV_Attr;
  2279.   CContainedWindowT<CListViewCtrl> m_GuiLV_GlobalPalette;
  2280.   CContainedWindowT<CListViewCtrl> m_GuiLV_SelectPalette;
  2281.   CContainedWindowT<CListViewCtrlTS<CAttr>> m_GuiLV_AttrList;
  2282.   CContainedWindowT<CListViewCtrlTS<CPal>> m_GuiLV_PalList;
  2283.  
  2284.   CMemoryPaint16 m_MemoryPaintChr;
  2285.   CMemoryPaint16 m_MemoryPaintAttr;
  2286.   CMemoryPaint16 m_MemoryPaintGPal;
  2287.   CMemoryPaint16 m_MemoryPaintSPal;
  2288.   CButton m_GuiGB_Chr;
  2289.  
  2290.   BOOL m_bClaywindow;
  2291.   BOOL m_bAttrEditMode;
  2292.  
  2293.   BEGIN_MSG_MAP(thisClass)
  2294.     MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  2295.     MESSAGE_HANDLER (WM_PAINT, OnPaint)
  2296.     MESSAGE_HANDLER (WM_NCLBUTTONDBLCLK, OnChangeShowMode)
  2297.     MESSAGE_HANDLER (WM_CLOSE, OnClose)
  2298.     MESSAGE_HANDLER (WM_DESTROY, OnDestroy)
  2299.     COMMAND_ID_HANDLER (IDCK_TILEGRID, OnCheckUpdate)
  2300.     COMMAND_ID_HANDLER (IDCK_ATTRGRID, OnCheckUpdate)
  2301.     ALT_MSG_MAP(MAP_CONTROL_LV_CHR)
  2302.       MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT<MAP_CONTROL_LV_CHR>)
  2303.       MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMoveT<MAP_CONTROL_LV_CHR>)
  2304.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_CHR>)
  2305.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT<MAP_CONTROL_LV_CHR>)
  2306.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_CHR>)
  2307.     ALT_MSG_MAP(MAP_CONTROL_LV_ATTR)
  2308.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_ATTR>)
  2309.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_ATTR>)
  2310.       MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMoveT<MAP_CONTROL_LV_ATTR>)
  2311.       MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT<MAP_CONTROL_LV_ATTR>)
  2312.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT<MAP_CONTROL_LV_ATTR>)
  2313.     ALT_MSG_MAP(MAP_CONTROL_LV_ATTRLIST)
  2314.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_ATTRLIST>)
  2315.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_ATTRLIST>)
  2316.       MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclk <MAP_CONTROL_LV_ATTRLIST>)
  2317.     ALT_MSG_MAP(MAP_CONTROL_LV_SPAL)
  2318.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_SPAL>)
  2319.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_SPAL>)
  2320.       MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT<MAP_CONTROL_LV_SPAL>)
  2321.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT<MAP_CONTROL_LV_SPAL>)
  2322.     ALT_MSG_MAP(MAP_CONTROL_LV_GPAL)
  2323.       MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT<MAP_CONTROL_LV_GPAL>)
  2324.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_GPAL>)
  2325.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT<MAP_CONTROL_LV_GPAL>)
  2326.     ALT_MSG_MAP(MAP_CONTROL_LV_PALLIST)
  2327.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_PALLIST>)
  2328.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_PALLIST>)
  2329.       MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclk <MAP_CONTROL_LV_PALLIST>)
  2330.   END_MSG_MAP()
  2331.  
  2332.   CNametableCell<t_bReadWriteMap> *m_pNametableCell;
  2333.  
  2334.   DWORD m_dwStateAttr; // 0: no copy 1:copy it
  2335.                                       // 0x8000 mask : ing...
  2336.   DWORD m_dwStateChr; // 0: no copy 1:copy it
  2337.                                       // 0x8000 mask : ing...
  2338.   // adjust by ptr.
  2339.   void sMutViewAttr_reset (BOOL bDeleteListViewFirst = FALSE) {
  2340.     if (bDeleteListViewFirst != FALSE) {
  2341.       m_GuiLV_Attr.DeleteAllItems ();
  2342.     }
  2343.     if (m_pNametableCell != NULL) {
  2344.       auto &attr_list = m_pNametableCell->attrList;
  2345.       auto attr_sel_t = m_pNametableCell->attr;
  2346.  
  2347.       m_GuiLV_Attr.DeleteAllItems ();
  2348.  
  2349.       for (auto it = 0; it != attr_list.GetCount (); it++) {
  2350.         auto p = attr_list[it];
  2351.         ATLASSERT (p != NULL);
  2352.  
  2353.         m_GuiLV_AttrList.InsertItem (it, p->comment, 0);
  2354.         m_GuiLV_AttrList.SetItemData (it, reinterpret_cast <DWORD_PTR> ( p));
  2355.  
  2356.         if (p== attr_sel_t) {
  2357.           m_GuiLV_AttrList.SelectItem (it);
  2358.         }
  2359.       }
  2360.     }
  2361.   }
  2362.  
  2363.   // adjust by ptr.
  2364.   void sMutViewPal_reset (BOOL bDeleteListViewFirst = FALSE) {
  2365.     if (bDeleteListViewFirst != FALSE) {
  2366.       m_GuiLV_PalList.DeleteAllItems ();
  2367.     }
  2368.     if (m_pNametableCell != NULL) {
  2369.       auto &pal_list = m_pNametableCell->palList;
  2370.       auto pal_sel_t = m_pNametableCell->pal;
  2371.       auto total = m_pNametableCell->getPaletteTotal ();
  2372.  
  2373.       m_GuiLV_PalList.DeleteAllItems ();
  2374.  
  2375.       for (SIZE_T it = 0; it != total; it++) {
  2376.         auto p = m_pNametableCell->getSelectPal (it);
  2377.         ATLASSERT (p != NULL);
  2378.  
  2379.         m_GuiLV_PalList.InsertItem (it, p->comment, p->source);
  2380.         m_GuiLV_PalList.SetItemData (it, reinterpret_cast <DWORD_PTR> ( p));
  2381.  
  2382.         if (p== pal_sel_t) {
  2383.           m_GuiLV_AttrList.SelectItem (it);
  2384.         }
  2385.       }
  2386.     }
  2387.   }
  2388.  
  2389.   void resetListViewPalette (void) {
  2390.     auto total =m_pNametableCell->getPaletteTotal ();
  2391.  
  2392.     m_GuiLV_PalList.DeleteAllItems ();
  2393.  
  2394.     if (total > 0) {
  2395.       BOOL bSelect =FALSE;
  2396.  
  2397.       for (typeof_noref(total) it = 0; it != total; it++) {
  2398.         auto pal = m_pNametableCell->getSelectPal (it);
  2399.         ATLASSERT (pal != NULL);
  2400.        
  2401.         m_GuiLV_PalList.InsertItem (it, pal->comment, pal->source);  // XXX: enum series.
  2402.         m_GuiLV_PalList.SetItemDataT (it, pal);
  2403.  
  2404.         if (pal == m_pNametableCell->pal) {
  2405.           m_pNametableCell->select = it;
  2406.           m_GuiLV_PalList.SelectItem (it);
  2407.           bSelect = TRUE;
  2408.         }
  2409.       }
  2410.       // Item remove. select default index 0 palette.
  2411.       if (bSelect == FALSE) {
  2412.         m_GuiLV_PalList.SelectItem (0);
  2413.         m_pNametableCell->pal = m_pNametableCell->getSelectPal (0);
  2414.         m_pNametableCell->select = 0;
  2415.       }
  2416.     } else {
  2417.       m_pNametableCell->pal = NULL;
  2418.       m_pNametableCell->select = -1;
  2419.     }
  2420.   }
  2421.  
  2422.   BOOL alive (void) {
  2423.     return m_pNametableCell != NULL;
  2424.   }
  2425.  
  2426.   void setDead  (void) {
  2427.     m_pNametableCell = NULL;
  2428.   }
  2429.  
  2430.   void setAttach (CMainFrame *attachhtis0) {
  2431.     m_atthis = attachhtis0;
  2432.   }
  2433.   VOID setNtCell  (CNametableCell<t_bReadWriteMap> *cell) {
  2434.     if (cell == m_pNametableCell)
  2435.       return ;
  2436.  
  2437.     m_GuiLV_AttrList.DeleteAllItems ();
  2438.     m_GuiLV_PalList.DeleteAllItems ();
  2439.  
  2440.     m_pNametableCell = cell;
  2441.  
  2442.     if (cell != NULL) {
  2443.       auto &attr_list = cell->attrList;
  2444.       auto attr_sel_t = cell->attr;
  2445.       auto attr_sel = - 1;
  2446.  
  2447.       for (auto it = 0; it != attr_list.GetCount (); it++) {
  2448.         auto p = attr_list[it];
  2449.         if (p != NULL) {
  2450.           m_GuiLV_AttrList.InsertItem (it, p->comment, 0);
  2451.           m_GuiLV_AttrList.SetItemData (it, reinterpret_cast <DWORD_PTR> ( p));
  2452.           if (p== attr_sel_t) {
  2453.             attr_sel = it;
  2454.           }
  2455.         }
  2456.       }
  2457.       if (attr_sel >= 0) {
  2458.         m_GuiLV_AttrList.SelectItem (attr_sel);
  2459.       }
  2460.       resetListViewPalette ();
  2461.  
  2462.       // Update draw infos.
  2463.       UpdateInfos (TRUE);
  2464.     }
  2465.   }
  2466.   INT m_bShowMinMode; // 0:std 1:only chr 2:chr + attr 3: chr + paleetee
  2467.  
  2468.   PBYTE m_pTrackSPal;
  2469.  
  2470.   CPoint m_ptTrackChrStartZ;
  2471.  
  2472.   CPoint m_ptTrackAttrStart;
  2473.   CPoint m_ptTrackAttrEnd;
  2474.  
  2475.   CPoint m_ptTrackChrStart;
  2476.   CPoint m_ptTrackChrEnd;
  2477.  
  2478.   CPoint m_ptTrackerAttrStartY;
  2479.   CSize m_szTrackerAttrVectorY;
  2480.   CRect m_rcStdClient;
  2481.  
  2482.   CPoint m_ptTrackerChrStartY;
  2483.   CSize m_szTrackerChrVectorY;
  2484.  
  2485.   CPoint m_ptTrackGPal;
  2486.   CPoint m_ptTrackSPal;
  2487.   CImageListManaged m_ImgListAttr;
  2488.   CImageListManaged m_ImgListPal;
  2489.  
  2490.   // <CAttrSettings> =========================================
  2491.   struct CAttrSettings : public CDialogImpl<CAttrSettings>
  2492.   {
  2493.     typedef CAttrSettings thisClass;
  2494.     typedef CDialogImpl<CAttrSettings> baseClass;
  2495.  
  2496.     CViewNametablePage &m_attthis;
  2497.     CAttr *m_newattr;
  2498.  
  2499.     CAttrSettings (CViewNametablePage &psthis):
  2500.         m_attthis (psthis),
  2501.         m_newattr (NULL) {}
  2502.  
  2503.     enum { IDD = IDD_ATTR_LIST_SETTINGS };
  2504.  
  2505.     BEGIN_MSG_MAP(thisClass)
  2506.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  2507.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  2508.       COMMAND_ID_HANDLER (IDBT_ATTR_RESET, OnSet)
  2509.     END_MSG_MAP()
  2510.  
  2511.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2512.       bHandled = FALSE;
  2513.       EndDialog (IDCANCEL);
  2514.  
  2515.       return 0;
  2516.     }
  2517.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2518.    
  2519.       CEdit etComment = GetDlgItem (IDET_ATTRCOMMENT);
  2520.  
  2521.       if (m_newattr != NULL) {
  2522.          // Fill current pal infos.
  2523.         etComment.SetWindowText (m_newattr->comment);
  2524.       }
  2525.    
  2526.       bHandled = FALSE;
  2527.        return 0;
  2528.     }
  2529.  
  2530.     LRESULT OnSet (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  2531.  
  2532.       CEdit etComment = GetDlgItem (IDET_ATTRCOMMENT);
  2533.       CButton ckFill = GetDlgItem (IDCK_ATTRFILL);
  2534.       CEdit etInitFill = GetDlgItem (IDET_INITFILL);
  2535.       CString content;
  2536.  
  2537.       etComment.GetWindowText (content);
  2538.       BOOL bpushnewItem  = m_newattr == NULL;
  2539.  
  2540.       if (bpushnewItem != FALSE
  2541.         && m_newattr == NULL)
  2542.       {
  2543.          m_newattr= new CAttr;
  2544.       }
  2545.       m_newattr->comment = content;
  2546.       if (ckFill.GetCheck () == BST_CHECKED)
  2547.       {
  2548.         etInitFill.GetWindowText (content);
  2549.  
  2550.         int fillByte                 =
  2551.         _tcstol (content, NULL, 16)
  2552.         & 255;
  2553.  
  2554.         RtlFillMemory (m_newattr->attr, sizeof (m_newattr->attr), fillByte);
  2555.       }
  2556.       EndDialog (IDOK);
  2557.  
  2558.       CGlobals::adjustCommentUnique<CAttr> (m_attthis.m_pNametableCell->attrList, m_newattr, bpushnewItem);
  2559.  
  2560.       bHandled = FALSE;
  2561.       return 0;
  2562.     }
  2563.  
  2564.     INT_PTR DoModal (CAttr *attr = NULL)
  2565.     {
  2566.       m_newattr = attr;
  2567.  
  2568.       // Modal it.
  2569.       return baseClass::DoModal ();
  2570.     }
  2571.   };
  2572.   // <CPalSettings> =========================================
  2573.   template <BOOL t_bReadWriteMap>
  2574.   struct CPalSettings : public CDialogImpl<CPalSettings<t_bReadWriteMap>>
  2575.   {
  2576.     typedef CPalSettings thisClass;
  2577.     typedef CDialogImpl<CPalSettings<t_bReadWriteMap>> baseClass;
  2578.  
  2579.     CViewNametablePage &m_attchthis;
  2580.     CPal *m_attachpal;
  2581.  
  2582.     CPalSettings (CViewNametablePage &atthis):
  2583.       m_attchthis (atthis),
  2584.       m_attachpal (NULL) {}
  2585.  
  2586.     enum { IDD = IDD_PAL_LIST_SETTINGS };
  2587.  
  2588.     BEGIN_MSG_MAP(thisClass)
  2589.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  2590.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  2591.       COMMAND_ID_HANDLER (IDBT_PAL_RESET, OnSet)
  2592.     END_MSG_MAP()
  2593.  
  2594.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2595.       bHandled = FALSE;
  2596.       EndDialog (IDCANCEL);
  2597.  
  2598.       return 0;
  2599.     }
  2600.  
  2601.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2602.    
  2603.       CEdit etComment = GetDlgItem (IDET_PALCOMMENT);
  2604.       CButton btReset = GetDlgItem (IDBT_PAL_RESET);
  2605.  
  2606.       SetWindowText (_T ("palette insert"));
  2607.         btReset.SetWindowText (_T ("Insert"));
  2608.  
  2609.         if (t_bReadWriteMap != FALSE) {
  2610.            // Remove static palette option.
  2611.           :: EnableWindow (GetDlgItem (IDRD_PAL_STATIC), FALSE);
  2612.         }
  2613.  
  2614.       if (m_attachpal != NULL) {
  2615.          // Fill current pal infos.
  2616.         etComment.SetWindowText (m_attachpal->comment);
  2617.         btReset.SetWindowText (_T ("Reset"));
  2618.         SetWindowText (_T ("palette reset"));
  2619.  
  2620.         m_attachpal->sourceAssert ();
  2621.  
  2622.         if (m_attachpal->source == CPal::private_palette) {
  2623.           CheckDlgButton (IDRD_PAL_PRIVATE, BST_CHECKED);
  2624.         } else if (m_attachpal->source == CPal::static_palette){
  2625.           CheckDlgButton (IDRD_PAL_STATIC, BST_CHECKED);
  2626.         } else if (m_attachpal->source == CPal::global_palette){
  2627.           CheckDlgButton (IDRD_PAL_GLOBAL, BST_CHECKED);
  2628.         }
  2629.       } else {
  2630.         CheckDlgButton (IDRD_PAL_PRIVATE, BST_CHECKED);
  2631.       }
  2632.       bHandled = FALSE;
  2633.        return 0;
  2634.     }
  2635.  
  2636.     LRESULT OnSet (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  2637.  
  2638.       CEdit etComment = GetDlgItem (IDET_PALCOMMENT);
  2639.       CString content;
  2640.       CButton ckSourcePrivate = GetDlgItem (IDRD_PAL_PRIVATE);
  2641.       CButton ckSourceStatic = GetDlgItem (IDRD_PAL_STATIC);
  2642.       CButton ckSourceGlobal = GetDlgItem (IDRD_PAL_GLOBAL);
  2643.  
  2644.       etComment    .GetWindowText (content);
  2645.  
  2646.       if (m_attachpal == NULL) {
  2647.         if (ckSourcePrivate.GetCheck () == BST_CHECKED) {
  2648.           m_attachpal = new CPal (CPal::private_palette);
  2649.           CGlobals::adjustCommentUnique<CPal> (m_attchthis.m_pNametableCell->palList, m_attachpal, TRUE);
  2650.         } else if (ckSourceStatic.GetCheck () == BST_CHECKED) {
  2651.           m_attachpal = new CPal (CPal::static_palette);
  2652.           CGlobals::adjustCommentUnique<CPal> (m_attchthis.m_pNametableCell->staticPalList, m_attachpal, TRUE);
  2653.         } else if (ckSourceGlobal.GetCheck () == BST_CHECKED) {
  2654.           m_attachpal = new CPal (CPal::global_palette);
  2655.           CGlobals::adjustCommentUnique<CPal> (m_attchthis.m_pNametableCell->globalPalList, m_attachpal, TRUE);
  2656.         }
  2657.         m_attachpal->sourceAssert ();
  2658.         m_attachpal->comment = content;
  2659.       } else {
  2660.         // Adjust exist attr infos.
  2661.         m_attachpal->sourceAssert ();
  2662.         m_attachpal->comment = content;
  2663.  
  2664.         auto prevsource = m_attachpal->source;
  2665.         auto cursource =prevsource;
  2666.  
  2667.         if (ckSourcePrivate.GetCheck () == BST_CHECKED) {
  2668.           m_attachpal->source = CPal::private_palette;
  2669.         } else if (ckSourceStatic.GetCheck () == BST_CHECKED) {
  2670.           m_attachpal->source = CPal::static_palette;
  2671.         } else if (ckSourceGlobal.GetCheck () == BST_CHECKED) {
  2672.           m_attachpal->source = CPal::global_palette;
  2673.         }
  2674.  
  2675.         if (m_attachpal->source != prevsource) {
  2676.           // vector move.
  2677.           CAtlArray <CPal *> *palvec;
  2678.           if (prevsource == CPal::private_palette) {
  2679.             palvec = & m_attchthis.m_pNametableCell->palList;
  2680.           } else if (prevsource == CPal::static_palette) {
  2681.             palvec = & m_attchthis.m_pNametableCell->staticPalList;
  2682.           } else if (prevsource == CPal::global_palette) {
  2683.             palvec = & m_attchthis.m_pNametableCell->globalPalList;
  2684.           }
  2685.           for (auto it = 0; it != palvec->GetCount (); it++) {
  2686.             auto p = (*palvec)[it];
  2687.             if (p == m_attachpal) {
  2688.               palvec->RemoveAt (it);
  2689.               break;
  2690.             }
  2691.           }
  2692.           if (m_attachpal->source == CPal::private_palette) {
  2693.             palvec = & m_attchthis.m_pNametableCell->palList;
  2694.           } else if (m_attachpal->source == CPal::static_palette) {
  2695.             palvec = & m_attchthis.m_pNametableCell->staticPalList;
  2696.           } else if (m_attachpal->source == CPal::global_palette) {
  2697.             palvec = & m_attchthis.m_pNametableCell->globalPalList;
  2698.           }
  2699.           palvec->InsertAt (palvec->GetCount(), m_attachpal);
  2700.         }
  2701.       }
  2702.  
  2703.       m_attchthis.m_atthis->updateItemPalette ();
  2704.  
  2705.       EndDialog (IDOK);
  2706.  
  2707.       bHandled = FALSE;
  2708.       return 0;
  2709.     }
  2710.  
  2711.     INT_PTR DoModal ( CPal *pal = NULL)
  2712.     {
  2713.       m_attachpal = pal;
  2714.  
  2715.       // Modal it.
  2716.       return baseClass::DoModal ();
  2717.     }
  2718.   };
  2719.  
  2720.   CViewNametablePage (CNametableCell<t_bReadWriteMap> *nt_cell = NULL):
  2721.                     m_bClaywindow (t_bReadWriteMap),
  2722.                     m_bAttrEditMode (FALSE),
  2723.                     m_dwStateChr (0),
  2724.                     m_dwStateAttr (0),
  2725.                     m_bShowMinMode (0),
  2726.                     m_pNametableCell (nt_cell),
  2727.                     m_pTrackSPal (NULL),
  2728.                     m_GuiLV_Chr (this, MAP_CONTROL_LV_CHR),
  2729.                     m_GuiLV_Attr (this, MAP_CONTROL_LV_ATTR),
  2730.                     m_GuiLV_GlobalPalette (this, MAP_CONTROL_LV_GPAL),
  2731.                     m_GuiLV_SelectPalette (this, MAP_CONTROL_LV_SPAL),
  2732.                     m_GuiLV_AttrList (this, MAP_CONTROL_LV_ATTRLIST),
  2733.                     m_GuiLV_PalList (this, MAP_CONTROL_LV_PALLIST),
  2734.                     m_ptTrackGPal (0, 0),
  2735.                     m_ptTrackSPal (0, 0)
  2736.   {
  2737.   }
  2738.   ~CViewNametablePage (VOID)  {
  2739.  
  2740.     // m_GuiLV_PalList.Remov
  2741.     // m_GuiLV_PalList.SetImageList (m_ImgListPal, LVSIL_SMALL);
  2742.     // m_GuiLV_AttrList.SetImageList (m_ImgListAttr, LVSIL_SMALL);
  2743.     m_ImgListPal.RemoveAll ();
  2744.     m_ImgListAttr.RemoveAll ();
  2745.   }
  2746.   LRESULT OnChangeShowMode (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2747.       // 0:std 1:only chr 2:chr + attr 3: chr + paleetee
  2748.     m_bShowMinMode ++;
  2749.     m_bShowMinMode &= 3;
  2750.  
  2751.     switch (m_bShowMinMode) {
  2752.     case 0:
  2753.       ResizeClient (m_rcStdClient.Width (), m_rcStdClient.Height (), TRUE);
  2754.       break;
  2755.     case 1:
  2756.       ResizeClient (282, 282, TRUE);
  2757.       break;
  2758.     case 2:
  2759.       ResizeClient (m_rcStdClient.Width (), 282, TRUE);
  2760.       break;
  2761.     case 3:
  2762.       ResizeClient (282, m_rcStdClient.Height (), TRUE);
  2763.       break;
  2764.     default:
  2765.       break;
  2766.     }
  2767.     return 0;
  2768.   }
  2769.   LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  2770.  
  2771.     // Subclass/Attach it
  2772.     m_GuiLV_Chr.SubclassWindow (GetDlgItem (IDLV_4KCHR));
  2773.     m_GuiLV_Attr.SubclassWindow (GetDlgItem (IDLV_ATTR));
  2774.     m_GuiLV_GlobalPalette.SubclassWindow (GetDlgItem (IDLV_GLOBAL_PALETTE));
  2775.     m_GuiLV_SelectPalette.SubclassWindow (GetDlgItem (IDLV_SELPALETTE));
  2776.     m_GuiLV_AttrList.SubclassWindow (GetDlgItem (IDLV_ATTR_LIST));
  2777.     m_GuiLV_PalList.SubclassWindow (GetDlgItem (IDLV_PAL_LIST));
  2778.  
  2779.     m_GuiGB_Chr.Attach (GetDlgItem (IDGB_4KCHR));
  2780.  
  2781.     m_MemoryPaintChr.resetMemoryDC (m_GuiLV_Chr);
  2782.     m_MemoryPaintAttr.resetMemoryDC (m_GuiLV_Attr);
  2783.     m_MemoryPaintGPal.resetMemoryDC (m_GuiLV_GlobalPalette);
  2784.     m_MemoryPaintSPal.resetMemoryDC (m_GuiLV_SelectPalette);
  2785.  
  2786.     CGlobals::setDefaultListViewColor (m_GuiLV_AttrList);
  2787.     CGlobals::setDefaultListViewColor (m_GuiLV_PalList);
  2788.  
  2789.     m_ImgListAttr.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  2790.     m_ImgListPal.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  2791.  
  2792.     m_ImgListAttr.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_ATTRLIST)));
  2793.     m_ImgListPal.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_PRIVATE_PAL)));
  2794.     m_ImgListPal.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_STATIC_PAL)));
  2795.     m_ImgListPal.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_GLOBAL_PAL)));
  2796.    
  2797.     // Get init view rect..
  2798.     GetClientRect (m_rcStdClient);
  2799.    
  2800.     m_GuiLV_PalList.SetImageList (m_ImgListPal, LVSIL_SMALL);
  2801.     m_GuiLV_AttrList.SetImageList (m_ImgListAttr, LVSIL_SMALL);
  2802.  
  2803.     if (t_bReadWriteMap != FALSE) {
  2804.       m_GuiGB_Chr.SetWindowText (_T ("Clay-stdmode"));
  2805.     } else {
  2806.       // Hide item .
  2807.       ::ShowWindow (GetDlgItem (IDCK_OVERWRITE_ATTR), SW_HIDE);
  2808.       ::ShowWindow (GetDlgItem (IDCK_OVERWRITE_CHR), SW_HIDE);
  2809.       ::ShowWindow (GetDlgItem (IDCK_OVERWRITE_PAL), SW_HIDE);
  2810.     }
  2811.     bHandled = FALSE;
  2812.     return 0;
  2813.   }
  2814.  
  2815.   VOID UpdateInfos (BOOL postToScreen = FALSE) {
  2816.      CMemoryPaint16::DirectWrite dwriteChr;
  2817.      CMemoryPaint16::DirectWrite dwriteAttr;
  2818.      CMemoryPaint16::DirectWrite dwriteGPal;
  2819.      CMemoryPaint16::DirectWrite dwriteSPal;
  2820.  
  2821.      m_MemoryPaintChr.getBackSurface (dwriteChr);
  2822.      m_MemoryPaintAttr.getBackSurface (dwriteAttr);
  2823.      m_MemoryPaintGPal.getBackSurface (dwriteGPal);
  2824.      m_MemoryPaintSPal.getBackSurface (dwriteSPal);
  2825.  
  2826.      if (m_pNametableCell == NULL) {
  2827.        // No attach item.
  2828.        m_MemoryPaintChr.fillFullClient (dwriteChr, 0);
  2829.        m_MemoryPaintAttr.fillFullClient (dwriteAttr, 0);
  2830.        m_MemoryPaintGPal.fillFullClient (dwriteGPal, 0);
  2831.        m_MemoryPaintSPal.fillFullClient (dwriteSPal, 0);
  2832.      } else {
  2833.        auto &rNamtable = *m_pNametableCell;
  2834.        if (rNamtable.chr == NULL) {
  2835.          m_MemoryPaintChr.fillFullClient (dwriteChr, 0);
  2836.        } else {
  2837.          if (t_bReadWriteMap == FALSE) {
  2838.            // Scan tiles. in chr mode  (2bit + fixed palette bank)
  2839.            static const BYTE palT[] = { 0, 0 << 0, 0 << 5, 0 << 10 };
  2840.          
  2841.            auto pPal = palT;
  2842.            auto pChr = rNamtable.chr->chr;
  2843.            auto pGloablNESPal = CGlobals::nespal;
  2844.  
  2845.            if (rNamtable.pal != NULL) {
  2846.              pPal = & rNamtable.pal->pal[(rNamtable.bank & 3) * 4];
  2847.            }
  2848.  
  2849.            WORD palFast[] = {
  2850.              pGloablNESPal[rNamtable.pal? rNamtable.pal->pal[0] : palT[0]],
  2851.              pGloablNESPal[pPal[1]],
  2852.              pGloablNESPal[pPal[2]],
  2853.              pGloablNESPal[pPal[3]]
  2854.            };
  2855.  
  2856.            for (auto j = 0; j != 16; j++)  {
  2857.              for (auto i = 0; i != 16; i++)  {
  2858.                DWORD x_pos=  i << 4;
  2859.                DWORD y_pos = j << 4;
  2860.                PWORD vramT  = & dwriteChr.pBits[x_pos + y_pos *dwriteChr.Pitch16];
  2861.                PWORD vramT2  = & vramT[dwriteChr.Pitch16];
  2862.                PBYTE pChrT = pChr;
  2863.                CPolyData64 chr;
  2864.  
  2865.                for (DWORD v = 0; v != 8; v++) {
  2866.                  chr.blk = CGlobals::chrmixer[pChrT[0]]
  2867.                        | CGlobals::chrmixer[pChrT[8]] << 1;
  2868.  
  2869.                  vramT[0] = vramT[1] =
  2870.                  vramT2[0] = vramT2[1] = palFast[chr.blk8[0]];
  2871.                  vramT[2] = vramT[3] =
  2872.                  vramT2[2] = vramT2[3] = palFast[chr.blk8[1]];
  2873.                  vramT[4] = vramT[5] =
  2874.                  vramT2[4] = vramT2[5] = palFast[chr.blk8[2]];
  2875.                  vramT[6] = vramT[7] =
  2876.                  vramT2[6] = vramT2[7] = palFast[chr.blk8[3]];
  2877.                  vramT[8] = vramT[9] =
  2878.                  vramT2[8] = vramT2[9] = palFast[chr.blk8[4]];
  2879.                  vramT[10] = vramT[11] =
  2880.                  vramT2[10] = vramT2[11] = palFast[chr.blk8[5]];
  2881.                  vramT[12] = vramT[13]  =
  2882.                  vramT2[12] = vramT2[13] = palFast[chr.blk8[6]];
  2883.                  vramT[14] = vramT[15]  =
  2884.                  vramT2[14] = vramT2[15] = palFast[chr.blk8[7]];          
  2885.  
  2886.                  vramT += dwriteChr.Pitch16;
  2887.                  vramT += dwriteChr.Pitch16;
  2888.                  vramT2 += dwriteChr.Pitch16;
  2889.                  vramT2 += dwriteChr.Pitch16;
  2890.  
  2891.                  pChrT++;
  2892.                }
  2893.                pChr += 16;
  2894.              }
  2895.            }
  2896.          } else {
  2897.            // Scan tiles. in nes mode  (2bit + attr palette bank)
  2898.            BYTE palT[] = {
  2899.               0x0F, 0x00, 0x10, 0x30,
  2900.               0x0F, 0x1C, 0x2B, 0x39,
  2901.               0x0F, 0x06, 0x15, 0x36,
  2902.               0x0C, 0x17, 0x28, 0x39
  2903.            };
  2904.            static  BYTE attrT[64];
  2905.  
  2906.            auto pPal = palT;
  2907.            auto pAttr = attrT;
  2908.            auto pChr = rNamtable.chr->chr;
  2909.            auto &rNametableT = rNamtable.tileSlot;
  2910.            auto &rGloablNESPal = CGlobals::nespal;
  2911.  
  2912.            BYTE transTile[16];
  2913.            RtlZeroMemory (transTile, sizeof (transTile));
  2914.  
  2915.            if (rNamtable.pal != NULL) {
  2916.              RtlCopyMemory (palT, & rNamtable.pal->pal[0], sizeof (palT));
  2917.  
  2918.              palT[12] =
  2919.              palT[8] =
  2920.              palT[4] = palT[0];
  2921.            }
  2922.            if (rNamtable.attr != NULL) {
  2923.              pAttr = rNamtable.attr->attr;
  2924.            }
  2925.  
  2926.            for (auto j = 0; j != 32; j++)  {
  2927.              for (auto i = 0; i != 32; i++)  {
  2928.                DWORD x_pos=  i << 3;
  2929.                DWORD y_pos = j << 3;
  2930.                PWORD vramT  = & dwriteChr.pBits[x_pos + y_pos *dwriteChr.Pitch16];
  2931.                WORD tileSlot = rNametableT[i+ (j << 5)];
  2932.  
  2933.                if ( (tileSlot & 0x8000) == 0) {  
  2934.                  PBYTE pChrT = tileSlot & 0x8000 ? transTile : & pChr[(tileSlot & 255) << 4];
  2935.                  PBYTE pBank = & palT[CGlobals::getAttrBit (pAttr, i, j) << 2];
  2936.  
  2937.                  for (DWORD v = 0; v != 8; v++) {
  2938.                    CPolyData64 chr;
  2939.                    chr.blk = CGlobals::chrmixer[pChrT[0]]
  2940.                          | CGlobals::chrmixer[pChrT[8]] << 1;
  2941.  
  2942.                    vramT[0] = rGloablNESPal[pBank[chr.blk8[0]]];
  2943.                    vramT[1] = rGloablNESPal[pBank[chr.blk8[1]]];
  2944.                    vramT[2] = rGloablNESPal[pBank[chr.blk8[2]]];
  2945.                    vramT[3] = rGloablNESPal[pBank[chr.blk8[3]]];      
  2946.                    vramT[4] = rGloablNESPal[pBank[chr.blk8[4]]];
  2947.                    vramT[5] = rGloablNESPal[pBank[chr.blk8[5]]];
  2948.                    vramT[6] = rGloablNESPal[pBank[chr.blk8[6]]];
  2949.                    vramT[7] = rGloablNESPal[pBank[chr.blk8[7]]];      
  2950.  
  2951.                    vramT += dwriteChr.Pitch16;
  2952.  
  2953.                    pChrT++;
  2954.                  }
  2955.                } else {
  2956.                  // Draw transparent
  2957.                  WORD transMarkClr[4] = { transHitMark, transShadowMark,
  2958.                                           transShadowMark, transHitMark };
  2959.  
  2960.                  for (DWORD v = 0; v != 8; v++) {
  2961.                    PWORD clrVPhase = & transMarkClr[v & 2];
  2962.  
  2963.                    vramT[0] =
  2964.                    vramT[1] = clrVPhase[0];
  2965.                    vramT[2] =
  2966.                    vramT[3] = clrVPhase[1];
  2967.                    vramT[4] =
  2968.                    vramT[5] = clrVPhase[0];
  2969.                    vramT[6] =
  2970.                    vramT[7] = clrVPhase[1];
  2971.  
  2972.                    vramT += dwriteChr.Pitch16;
  2973.                  }
  2974.                }
  2975.              }
  2976.            }
  2977.            // Tracker movse infos...
  2978.            // FIXME: more case.
  2979.            if (CGlobals::pasteAlive () != FALSE) {
  2980.              
  2981.              int copy_x = CGlobals::pasteTile.copySize.cx;
  2982.              int copy_y = CGlobals::pasteTile.copySize.cy;
  2983.              int mouse_x = m_ptTrackChrStartZ.x;
  2984.              int mouse_y = m_ptTrackChrStartZ.y;
  2985.  
  2986.              if (mouse_x + copy_x > 32)
  2987.                copy_x = 32 - mouse_x;
  2988.              if (mouse_y + copy_y > 32)
  2989.                copy_y = 32 - mouse_y;
  2990.  
  2991.              auto &rNametableS = CGlobals::pasteTile.tileSlot;
  2992.  
  2993.              for (auto j = 0; j != copy_y; j++)  {
  2994.                for (auto i = 0; i != copy_x; i++)  {
  2995.                  DWORD x2_pos = i + mouse_x << 3;
  2996.                  DWORD y2_pos = j + mouse_y << 3;
  2997.                  DWORD x_pos=  i << 3;
  2998.                  DWORD y_pos = j << 3;
  2999.                  WORD tileSlot = rNametableS[i+ (j << 5)];
  3000.                  PWORD vramT  = & dwriteChr.pBits[x2_pos + y2_pos *dwriteChr.Pitch16];
  3001.                  PBYTE pChrT = tileSlot & 0x8000 ? transTile : & CGlobals::pasteTile.chr->chr[(tileSlot & 255) << 4];
  3002.  
  3003.                  if ((tileSlot & 0x8000) == 0) {
  3004.                    auto pBank = & palT[CGlobals::getAttrBit (pAttr, i, j) << 2];
  3005.  
  3006.                    for (DWORD v = 0; v != 8; v++) {
  3007.                      CPolyData64 chr;
  3008.                      chr.blk = CGlobals::chrmixer[pChrT[0]]
  3009.                            | CGlobals::chrmixer[pChrT[8]] << 1;
  3010.  
  3011.                      vramT[0] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[0]]], vramT[0], alphaCnt, 15 - alphaCnt);
  3012.                      vramT[1] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[1]]], vramT[1], alphaCnt, 15 - alphaCnt);
  3013.                      vramT[2] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[2]]], vramT[2], alphaCnt, 15 - alphaCnt);
  3014.                      vramT[3] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[3]]], vramT[3], alphaCnt, 15 - alphaCnt);      
  3015.                      vramT[4] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[4]]], vramT[4], alphaCnt, 15 - alphaCnt);
  3016.                      vramT[5] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[5]]], vramT[5], alphaCnt, 15 - alphaCnt);
  3017.                      vramT[6] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[6]]], vramT[6], alphaCnt, 15 - alphaCnt);
  3018.                      vramT[7] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[7]]], vramT[7], alphaCnt, 15 - alphaCnt);      
  3019.  
  3020.                      vramT += dwriteChr.Pitch16;
  3021.  
  3022.                      pChrT++;
  3023.                    }
  3024.                  }
  3025.                }
  3026.              }
  3027.            }
  3028.          }
  3029.  
  3030.          // Check draw chr mesh
  3031.          if (CButton (GetDlgItem (IDCK_TILEGRID)).GetCheck () == BST_CHECKED) {
  3032.            if (t_bReadWriteMap != FALSE) {
  3033.            CGlobals::drawGrid (dwriteChr,
  3034.                    CGlobals::GRID_TYPE_FIXED,
  3035.                    CPoint (0, 0),
  3036.                    CSize (8, 8),
  3037.                    CSize (32, 32),
  3038.                    meshClr);
  3039.            } else {
  3040.            CGlobals::drawGrid (dwriteChr,
  3041.                    CGlobals::GRID_TYPE_FIXED,
  3042.                    CPoint (0, 0),
  3043.                    CSize (16, 16),
  3044.                    CSize (16, 16),
  3045.                    meshClr);
  3046.            }
  3047.  
  3048.          }
  3049.          // Check draw attr mesh
  3050.          if (CButton (GetDlgItem (IDCK_ATTRGRID)).GetCheck () == BST_CHECKED
  3051.            && t_bReadWriteMap != FALSE) {
  3052.            CGlobals::drawGrid (dwriteChr,
  3053.                    CGlobals::GRID_TYPE_FIXED,
  3054.                    CPoint (0, 0),
  3055.                    CSize (16, 16),
  3056.                    CSize (16, 16),
  3057.                    attrMeshClr);
  3058.          }
  3059.         // Tracker chr
  3060.         if (m_dwStateChr != 0)
  3061.         {
  3062.           if (t_bReadWriteMap != FALSE && m_bAttrEditMode == FALSE) {
  3063.         CGlobals::drawGrid (dwriteChr,
  3064.                 CGlobals::GRID_TYPE_FIXED,
  3065.                 CPoint (m_ptTrackerChrStartY.x * 8, m_ptTrackerChrStartY.y * 8),
  3066.                 CSize (m_szTrackerChrVectorY.cx * 8, m_szTrackerChrVectorY.cy * 8),
  3067.                 CSize (1, 1),
  3068.                 m_dwStateChr & 0x8000 ? attrSelMoveClr : attrSelEndClr );
  3069.           } else {
  3070.            CGlobals::drawGrid (dwriteChr,
  3071.                    CGlobals::GRID_TYPE_FIXED,
  3072.                    CPoint (m_ptTrackerChrStartY.x * 16, m_ptTrackerChrStartY.y * 16),
  3073.                    CSize (m_szTrackerChrVectorY.cx * 16, m_szTrackerChrVectorY.cy * 16),
  3074.                    CSize (1, 1),
  3075.                    m_dwStateChr & 0x8000 ? attrSelMoveClr : attrSelEndClr );
  3076.           }
  3077.         }
  3078.                       if (CGlobals::pasteAlive () != FALSE) {
  3079.                           CGlobals::drawGrid (dwriteChr,
  3080.                    CGlobals::GRID_TYPE_FIXED,
  3081.                    CPoint (m_ptTrackChrStartZ.x << 3, m_ptTrackChrStartZ.y << 3),
  3082.                    CSize (8, 8),
  3083.                    CSize (1, 1),
  3084.                    spalCatchClr);
  3085.                       }
  3086.        }
  3087.        // Draw Attr table
  3088.        if (rNamtable.attr == NULL) {
  3089.          m_MemoryPaintAttr.fillFullClient (dwriteChr, 0);
  3090.        } else {
  3091.          PWORD pGloablNESPal = CGlobals::nespal;
  3092.          PBYTE pAttr = rNamtable.attr->attr;
  3093.  
  3094.          for (auto j = 0; j != 16; j++)  {
  3095.            for (auto i = 0; i != 16; i++)  {
  3096.              auto x_pos=  i << 4;
  3097.              auto y_pos = j << 4;
  3098.              auto vramT  = & dwriteAttr.pBits[x_pos + y_pos *dwriteAttr.Pitch16];
  3099.              auto attrX = i >> 1;
  3100.              auto attrY = j >> 1;
  3101.              auto attrByte = pAttr[attrX+(attrY<<3)];
  3102.  
  3103.              if (j & 1)
  3104.                if (i & 1)
  3105.                  attrByte = attrByte >> 6 & 3;
  3106.                else
  3107.                  attrByte = attrByte >> 4 & 3;
  3108.              else
  3109.                if (i & 1)
  3110.                  attrByte = attrByte >> 2 & 3;
  3111.                else
  3112.                  attrByte &= 3;
  3113.  
  3114.              PWORD pFontpix;
  3115.              switch (attrByte) {
  3116.              case 0: pFontpix = CGlobals::attrFont0_x2; break;          
  3117.              case 1: pFontpix = CGlobals::attrFont1_x2; break;    
  3118.              case 2: pFontpix = CGlobals::attrFont2_x2; break;    
  3119.              case 3: pFontpix = CGlobals::attrFont3_x2; break;    
  3120.              default:
  3121.                ATLASSERT (FALSE);
  3122.                break;
  3123.              }
  3124.              for (DWORD v = 0; v != 16; v++) {
  3125.   #define CHECK_SET(index)\
  3126.   vramT[index] = pFontpix[index];
  3127.                  CHECK_SET (0)
  3128.                  CHECK_SET (1)
  3129.                  CHECK_SET (2)
  3130.                  CHECK_SET (3)
  3131.                  CHECK_SET (4)
  3132.                  CHECK_SET (5)
  3133.                  CHECK_SET (6)
  3134.                  CHECK_SET (7)
  3135.                  CHECK_SET (8)
  3136.                  CHECK_SET (9)
  3137.                  CHECK_SET (10)
  3138.                  CHECK_SET (11)
  3139.                  CHECK_SET (12)
  3140.                  CHECK_SET (13)
  3141.                  CHECK_SET (14)
  3142.                  CHECK_SET (15)
  3143.   #undef CHECK_SET
  3144.                vramT += dwriteAttr.Pitch16;
  3145.  
  3146.                pFontpix += 16;
  3147.              }
  3148.            }
  3149.          }
  3150.          // Check draw mesh
  3151.         CGlobals::drawGrid (dwriteAttr,
  3152.                 CGlobals::GRID_TYPE_FIXED,
  3153.                 CPoint (0, 0),
  3154.                 CSize (16, 16),
  3155.                 CSize (16, 16),
  3156.                 meshClr);
  3157.  
  3158.          // Tracker atrtr
  3159.          if (m_dwStateAttr != 0)
  3160.          {
  3161.          CGlobals::drawGrid (dwriteAttr,
  3162.                  CGlobals::GRID_TYPE_FIXED,
  3163.                  CPoint (m_ptTrackerAttrStartY.x * 16, m_ptTrackerAttrStartY.y * 16),
  3164.                  CSize (m_szTrackerAttrVectorY.cx * 16, m_szTrackerAttrVectorY.cy * 16),
  3165.                  CSize (1, 1),
  3166.                  m_dwStateAttr & 0x8000 ? attrSelMoveClr : attrSelEndClr );
  3167.          }
  3168.           if (t_bReadWriteMap != FALSE && m_bAttrEditMode != FALSE
  3169.                  && m_dwStateChr != 0) {
  3170.            CGlobals::drawGrid (dwriteAttr,
  3171.                    CGlobals::GRID_TYPE_FIXED,
  3172.                    CPoint (m_ptTrackerChrStartY.x * 16, m_ptTrackerChrStartY.y * 16),
  3173.                    CSize (m_szTrackerChrVectorY.cx * 16, m_szTrackerChrVectorY.cy * 16),
  3174.                    CSize (1, 1),
  3175.                    attrMeshClr );
  3176.           }
  3177.        }
  3178.        // Draw GPal palette
  3179.        // 16 *4 item.
  3180.        if (rNamtable.pal != NULL) {
  3181.          for (auto j = 0; j != 4; j++) {
  3182.            for (auto i = 0; i != 16; i++) {
  3183.              auto clr = CGlobals::nespal[(j<<4)+i];
  3184.              auto pix = & dwriteGPal.pBits [j*gpalUnitHeight*dwriteGPal.Pitch16+i*gpalUnitWidth];
  3185.  
  3186.              for (auto y = 0; y != gpalUnitHeight; y++) {
  3187.                for (auto x = 0; x != gpalUnitWidth; x++) {
  3188.                  pix[x+y*dwriteGPal.Pitch16] = clr;
  3189.                }
  3190.              }
  3191.            }
  3192.          }
  3193.          // Draw SPal palette
  3194.          // 4 *4 item.
  3195.          for (auto j = 0; j != 4; j++) {
  3196.            for (auto i = 0; i != 4; i++) {
  3197.              auto clr = CGlobals::nespal[rNamtable.pal->pal[(j<<2)+i] & 0x3F];
  3198.              auto pix = & dwriteSPal.pBits [j*cpalUnitHeight*dwriteSPal.Pitch16+i*cpalUnitWidth];
  3199.  
  3200.              for (auto y = 0; y != cpalUnitHeight; y++) {
  3201.                for (auto x = 0; x != cpalUnitWidth; x++) {
  3202.                  pix[x+y*dwriteSPal.Pitch16] = clr;
  3203.                }
  3204.              }
  3205.            }
  3206.          }
  3207.          CGlobals::drawGrid (dwriteGPal,
  3208.                  CGlobals::GRID_TYPE_FIXED,
  3209.                  CPoint (0, 0),
  3210.                  CSize (gpalUnitWidth, gpalUnitHeight),
  3211.                  CSize (16, 4),
  3212.                  meshClr);
  3213.      
  3214.          CGlobals::drawGrid (dwriteSPal,
  3215.                  CGlobals::GRID_TYPE_FIXED,
  3216.                  CPoint (0, 0),
  3217.                  CSize (cpalUnitWidth, cpalUnitHeight),
  3218.                  CSize (4, 4),
  3219.                  meshClr);
  3220.          CGlobals::drawGrid (dwriteSPal,
  3221.                  CGlobals::GRID_TYPE_FIXED,
  3222.                  CPoint (0, (rNamtable.bank & 3) * cpalUnitHeight),
  3223.                  CSize (cpalUnitWidth, cpalUnitHeight),
  3224.                  CSize (4, 1),
  3225.                  spalCatchBakClr);
  3226.          if (m_pTrackSPal != NULL) {
  3227.          CGlobals::drawGrid (dwriteSPal,
  3228.                  CGlobals::GRID_TYPE_FIXED,
  3229.                  CPoint (m_ptTrackSPal.x * cpalUnitWidth, m_ptTrackSPal.y * cpalUnitHeight),
  3230.                  CSize (cpalUnitWidth, cpalUnitHeight),
  3231.                  CSize (1, 1),
  3232.                  spalCatchClr);
  3233.          CGlobals::drawGrid (dwriteGPal,
  3234.                  CGlobals::GRID_TYPE_FIXED,
  3235.                  CPoint (m_ptTrackGPal.x * gpalUnitWidth, m_ptTrackGPal.y * gpalUnitHeight),
  3236.                  CSize (gpalUnitWidth, gpalUnitHeight),
  3237.                  CSize (1, 1),
  3238.                  spalCatchClr);
  3239.          }
  3240.        } else {
  3241.          m_MemoryPaintGPal.fillFullClient (dwriteGPal, 0);
  3242.          m_MemoryPaintSPal.fillFullClient (dwriteSPal, 0);
  3243.        }
  3244.      }
  3245.      m_MemoryPaintChr.blitClientBaseALL0 ();
  3246.      m_MemoryPaintAttr.blitClientBaseALL0 ();
  3247.      m_MemoryPaintGPal.blitClientBaseALL0 ();
  3248.      m_MemoryPaintSPal.blitClientBaseALL0 ();
  3249.   }
  3250.  
  3251.   LRESULT OnPaint (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3252.     CPaintDC dc (*this);
  3253.  
  3254.     UpdateInfos (TRUE);
  3255.  
  3256.     bHandled= FALSE;
  3257.     return 0;
  3258.   }
  3259.  
  3260.   template <DWORD t_dwControlId>
  3261.   LRESULT OnRButtonUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3262.     switch (t_dwControlId) {
  3263.     case MAP_CONTROL_LV_ATTR:
  3264.       if (m_dwStateAttr == 1
  3265.           && m_pNametableCell != NULL
  3266.           && m_pNametableCell->attr != NULL)
  3267.       {
  3268.         for (auto j= 0; j != m_szTrackerAttrVectorY.cy; j++) {
  3269.           const auto yvec= j + m_ptTrackerAttrStartY.y << 1;
  3270.           for (auto i= 0; i != m_szTrackerAttrVectorY.cx; i++) {
  3271.             const auto xvec = i + m_ptTrackerAttrStartY.x << 1;
  3272.             CGlobals::setAttrBit (m_pNametableCell->attr->attr, xvec, yvec,
  3273.               CGlobals::getAttrBit (m_pNametableCell->attr->attr, xvec, yvec) + 1);
  3274.           }
  3275.         }
  3276.         // Exec undo status save.
  3277.         m_pNametableCell->snapshotToUndoStack ();
  3278.       }
  3279.       m_atthis->m_GuiSWin_Nesmap.nesPixelGenerator ();
  3280.       UpdateInfos (TRUE);
  3281.       bHandled = FALSE;
  3282.       break;
  3283.     case MAP_CONTROL_LV_CHR: // Case listview-chr
  3284.       if (  t_bReadWriteMap != FALSE
  3285.           && m_bAttrEditMode != FALSE
  3286.           && (m_dwStateChr & 0x7FFF) != 0)
  3287.       {
  3288.         for (auto j= 0; j != m_szTrackerChrVectorY.cy; j++) {
  3289.           const auto yvec= j + m_ptTrackerChrStartY.y << 1;
  3290.           for (auto i= 0; i != m_szTrackerChrVectorY.cx; i++) {
  3291.             const auto xvec = i + m_ptTrackerChrStartY.x << 1;
  3292.             CGlobals::setAttrBit (m_pNametableCell->attr->attr, xvec, yvec,
  3293.               CGlobals::getAttrBit (m_pNametableCell->attr->attr, xvec, yvec) + 1);
  3294.           }
  3295.         }
  3296.                 // Exec undo status save.
  3297.         m_pNametableCell->snapshotToUndoStack ();
  3298.       } else if (CGlobals::pasteAlive () != FALSE) {
  3299.           CGlobals::makePasteDead ();
  3300.           m_dwStateChr = 0;
  3301.       } else if (m_pNametableCell != NULL) {
  3302.         m_pNametableCell->bank ++;
  3303.         m_pNametableCell->bank &= 3;
  3304.       }
  3305.       UpdateInfos (TRUE);
  3306.       break;
  3307.     case MAP_CONTROL_LV_SPAL: // Case select palette.
  3308.     case MAP_CONTROL_LV_GPAL:
  3309.       m_pTrackSPal = NULL; // Cancel select.
  3310.     default:
  3311.       break;
  3312.     }
  3313.     return 0;
  3314.   }
  3315.   template <DWORD t_dwControlId>
  3316.   LRESULT OnMouseMoveT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3317.     CPoint pt (GET_X_LPARAM(lParam),
  3318.                        GET_Y_LPARAM(lParam));
  3319.     switch (t_dwControlId) {
  3320.     case MAP_CONTROL_LV_CHR:
  3321.       if (t_bReadWriteMap != FALSE
  3322.         && CGlobals::pasteAlive () != FALSE
  3323.         && m_bAttrEditMode == FALSE)
  3324.       {
  3325.          // in clay mode and pasting..!
  3326.         m_ptTrackChrStartZ.x = pt.x / 8;
  3327.         m_ptTrackChrStartZ.y = pt.y / 8;
  3328.  
  3329.         CGlobals::limitPoint (m_ptTrackChrStartZ, 32, 32);
  3330.       }
  3331.       else if (m_dwStateChr & 0x8000) {
  3332.         // Calc rect
  3333.         if (t_bReadWriteMap != FALSE && m_bAttrEditMode == FALSE) {
  3334.           pt.x /= 8;
  3335.           pt.y /= 8;
  3336.           CGlobals::limitPoint (pt, 32, 32);
  3337.  
  3338.           if (1/*m_bInitTrackAttr == FALSE
  3339.             ||  (m_ptTrackAttrEnd.x != pt.x
  3340.                      || m_ptTrackAttrEnd.y != pt.y)*/)
  3341.           {
  3342.             // First refresh /or cross a unit (per 16 pixels )
  3343.             // m_bInitTrackAttr = TRUE;
  3344.  
  3345.             m_ptTrackChrEnd.x =  pt.x ;
  3346.             m_ptTrackChrEnd.y =  pt.y ;
  3347.  
  3348.             CPoint ptStart = m_ptTrackChrStart;
  3349.             CPoint ptEnd = m_ptTrackChrEnd;
  3350.             CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3351.  
  3352.             m_ptTrackerChrStartY = ptStart;
  3353.             m_szTrackerChrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3354.             m_szTrackerChrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3355.           }
  3356.         } else {
  3357.           pt.x /= 16;
  3358.           pt.y /= 16;
  3359.           CGlobals::limitPoint (pt, 16, 16);
  3360.  
  3361.           if (1/*m_bInitTrackAttr == FALSE
  3362.             ||  (m_ptTrackAttrEnd.x != pt.x
  3363.                      || m_ptTrackAttrEnd.y != pt.y)*/)
  3364.           {
  3365.             // First refresh /or cross a unit (per 16 pixels )
  3366.             // m_bInitTrackAttr = TRUE;
  3367.  
  3368.             m_ptTrackChrEnd.x =  pt.x ;
  3369.             m_ptTrackChrEnd.y =  pt.y ;
  3370.  
  3371.             CPoint ptStart = m_ptTrackChrStart;
  3372.             CPoint ptEnd = m_ptTrackChrEnd;
  3373.             CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3374.  
  3375.             m_ptTrackerChrStartY = ptStart;
  3376.             m_szTrackerChrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3377.             m_szTrackerChrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3378.           }
  3379.         }
  3380.       }
  3381.       break;
  3382.     case MAP_CONTROL_LV_ATTR:
  3383.       if (m_dwStateAttr & 0x8000) {
  3384.         // Calc rect
  3385.         pt.x /= 16;
  3386.         pt.y /= 16;
  3387.         CGlobals::limitPoint (pt, 16, 16);
  3388.  
  3389.         if (1/*m_bInitTrackAttr == FALSE
  3390.           ||  (m_ptTrackAttrEnd.x != pt.x
  3391.                    || m_ptTrackAttrEnd.y != pt.y)*/)
  3392.         {
  3393.           // First refresh /or cross a unit (per 16 pixels )
  3394.           // m_bInitTrackAttr = TRUE;
  3395.  
  3396.           m_ptTrackAttrEnd.x =  pt.x ;
  3397.           m_ptTrackAttrEnd.y =  pt.y ;
  3398.  
  3399.           CPoint ptStart = m_ptTrackAttrStart;
  3400.           CPoint ptEnd = m_ptTrackAttrEnd;
  3401.           CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3402.  
  3403.           m_ptTrackerAttrStartY = ptStart;
  3404.           m_szTrackerAttrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3405.           m_szTrackerAttrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3406.         }
  3407.       }
  3408.       bHandled = FALSE;
  3409.       break;
  3410.     case MAP_CONTROL_LV_ATTRLIST: // Case Global paleete
  3411.       m_ptTrackGPal.x = pt.x / gpalUnitWidth;
  3412.       m_ptTrackGPal.y = pt.y / gpalUnitHeight;
  3413.       CGlobals::limitPoint (m_ptTrackGPal, 16, 4);
  3414.       // Check Lock ptr.
  3415.       if (m_pTrackSPal != NULL) {
  3416.         m_pTrackSPal[0] = (BYTE)(m_ptTrackGPal.x+m_ptTrackGPal.y*16 & 0xFF);
  3417.       }
  3418.     default:
  3419.       break;
  3420.     }
  3421.     UpdateInfos (TRUE);
  3422.     return 0;
  3423.   }
  3424.   template <DWORD t_dwControlId>
  3425.   LRESULT OnLButtonDblclk (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3426.     CPoint pt (GET_X_LPARAM(lParam),
  3427.                        GET_Y_LPARAM(lParam));
  3428.     CValidateALL flush (*m_atthis,  *this);
  3429.  
  3430.     switch (t_dwControlId) {
  3431.     case MAP_CONTROL_LV_ATTRLIST:
  3432.       if (m_GuiLV_AttrList.GetSelectedIndex () >= 0){
  3433.         auto index = m_GuiLV_AttrList.GetSelectedIndex ();
  3434.         CAttr *attr = m_GuiLV_AttrList.GetItemSelectedDataT ();
  3435.         ATLASSERT (attr != NULL);
  3436.         CAttrSettings dlgSettings (*this);
  3437.         if (dlgSettings.DoModal (attr) == IDOK) {
  3438.           // Append to new.
  3439.           //m_Attrsel = attr;
  3440.           m_GuiLV_AttrList.SetItemText (index, 0, attr->comment);
  3441.           m_atthis->setCPListViewItemWithImg <t_bReadWriteMap> ( m_pNametableCell, 3, attr->comment, 5);
  3442.           m_atthis->allViewUpdate ();
  3443.         }
  3444.         bHandled = FALSE;
  3445.       }
  3446.       break;
  3447.     case MAP_CONTROL_LV_PALLIST:
  3448.       if (m_GuiLV_PalList.GetSelectedIndex () >= 0){
  3449.           auto index = m_GuiLV_PalList.GetSelectedIndex ();
  3450.           CPal *pal = (CPal *) m_GuiLV_PalList.GetItemData (index);
  3451.           ATLASSERT (pal != NULL);
  3452.          CPalSettings<t_bReadWriteMap> dlgSettings (*this);
  3453.              if (dlgSettings.DoModal (pal) == IDOK) {
  3454.                // Append to new.
  3455. //                 m_Palsel = pal;
  3456.                m_GuiLV_PalList.SetItemText (index, 0, pal->comment);
  3457.                m_atthis->allViewUpdate ();
  3458.              }
  3459.          bHandled = FALSE;
  3460.       }
  3461.     default:
  3462.       break;
  3463.     }
  3464.     return 0;
  3465.   }
  3466.  
  3467.   template <DWORD t_dwControlId>
  3468.   LRESULT OnLButtonDownT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3469.     CPoint pt (GET_X_LPARAM(lParam),
  3470.                        GET_Y_LPARAM(lParam));
  3471.     CValidateALL flush (*m_atthis,  *this);
  3472.  
  3473.     switch (t_dwControlId) {
  3474.     case MAP_CONTROL_LV_ATTRLIST: // Case Global paleete , Process default message first
  3475.       m_GuiLV_AttrList.DefWindowProc (uMsg, wParam, lParam);
  3476.  
  3477.       if (m_GuiLV_AttrList.GetSelectedIndex () >= 0) {
  3478.         m_pNametableCell->attr = m_GuiLV_AttrList.GetItemSelectedDataT ();
  3479.         ATLASSERT (m_pNametableCell->attr != NULL);
  3480.  
  3481.         m_atthis->setCPListViewItemWithImg <t_bReadWriteMap> ( m_pNametableCell, 3, m_pNametableCell->attr->comment, 5);
  3482.       }
  3483.       break;
  3484.  
  3485.     case MAP_CONTROL_LV_PALLIST:
  3486.       // Process default message first
  3487.       m_GuiLV_PalList.DefWindowProc (uMsg, wParam, lParam);
  3488.  
  3489.       if (m_GuiLV_PalList.GetSelectedIndex () >= 0) {
  3490.         m_pNametableCell->pal = m_GuiLV_PalList.GetItemSelectedDataT ();
  3491.         m_pNametableCell->readjustPos ();
  3492.         ATLASSERT (m_pNametableCell->pal != NULL);
  3493.  
  3494.         m_atthis->setCPListViewItemWithImg <t_bReadWriteMap> ( m_pNametableCell, 2, m_pNametableCell->pal->comment, 2 + m_pNametableCell->pal->source);
  3495.       }
  3496.       break;
  3497.     case MAP_CONTROL_LV_CHR:
  3498.       if (t_bReadWriteMap != FALSE && m_bAttrEditMode == FALSE) {
  3499.         m_ptTrackChrStart.x =  pt.x / 8;
  3500.         m_ptTrackChrStart.y =  pt.y / 8;
  3501.  
  3502.         CGlobals::limitPoint (m_ptTrackChrStart, 32, 32);
  3503.       } else {
  3504.         m_ptTrackChrStart.x =  pt.x / 16;
  3505.         m_ptTrackChrStart.y =  pt.y / 16;
  3506.  
  3507.         CGlobals::limitPoint (m_ptTrackChrStart, 16, 16);
  3508.       }
  3509.       m_ptTrackChrEnd = m_ptTrackChrStart;
  3510.       m_dwStateChr = 0x8000 | 1;
  3511.  
  3512.       m_ptTrackerChrStartY = m_ptTrackChrStart;
  3513.       m_szTrackerChrVectorY.cx = 1;
  3514.       m_szTrackerChrVectorY.cy = 1;
  3515.       bHandled = FALSE;
  3516.       break;
  3517.     case MAP_CONTROL_LV_ATTR:
  3518.       m_ptTrackAttrStart.x =  pt.x / 16;
  3519.       m_ptTrackAttrStart.y =  pt.y / 16;
  3520.  
  3521.       CGlobals::limitPoint (m_ptTrackAttrStart, 16, 16);
  3522.  
  3523.       m_ptTrackAttrEnd = m_ptTrackAttrStart;
  3524.       m_dwStateAttr = 0x8000 | 1;
  3525.  
  3526.       m_ptTrackerAttrStartY = m_ptTrackAttrStart;
  3527.       m_szTrackerAttrVectorY.cx = 1;
  3528.       m_szTrackerAttrVectorY.cy = 1;
  3529.       bHandled = FALSE;
  3530.       break;
  3531.  
  3532.     case MAP_CONTROL_LV_GPAL:
  3533.       m_ptTrackGPal.x = pt.x / gpalUnitWidth;
  3534.       m_ptTrackGPal.y = pt.y / gpalUnitHeight;
  3535.       CGlobals::limitPoint (m_ptTrackSPal, 4, 4);
  3536.       break;
  3537.     case MAP_CONTROL_LV_SPAL: // Case select palette.
  3538.       // Catch select palette
  3539.       // do rect clip and lockit
  3540.       m_ptTrackSPal.x = pt.x / cpalUnitWidth;
  3541.       m_ptTrackSPal.y = pt.y / cpalUnitHeight;
  3542.       CGlobals::limitPoint (m_ptTrackSPal, 4, 4);
  3543.       // Lock ptr.
  3544.       if (m_pNametableCell != NULL
  3545.         && m_pNametableCell->pal != NULL)
  3546.        m_pTrackSPal = & m_pNametableCell->pal->pal[m_ptTrackSPal.x+m_ptTrackSPal.y*4];
  3547.  
  3548.       bHandled = FALSE;
  3549.     default:
  3550.       break;
  3551.     }
  3552.     return 0;
  3553.   }
  3554.   template <DWORD t_dwControlId>
  3555.   LRESULT OnLButtonUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3556.     CPoint pt (GET_X_LPARAM(lParam),
  3557.                        GET_Y_LPARAM(lParam));
  3558.     switch (t_dwControlId) {
  3559.     case MAP_CONTROL_LV_CHR:
  3560.       if (CGlobals::pasteAlive () != FALSE
  3561.         && m_bAttrEditMode == FALSE) {
  3562.  
  3563.         auto copySize = CGlobals::pasteTile.copySize;
  3564.         auto mouse = m_ptTrackChrStartZ;
  3565.         auto &rNametableS = CGlobals::pasteTile.tileSlot;
  3566.         auto &rNametableT = m_pNametableCell->tileSlot;
  3567.  
  3568.         if (mouse.x + copySize.cx > 32)
  3569.           copySize.cx = 32 - mouse.x;
  3570.         if (mouse.y + copySize.cy > 32)
  3571.           copySize.cy = 32 - mouse.y;
  3572.  
  3573.         for (auto j = 0; j != copySize.cy; j++)  {
  3574.           for (auto i = 0; i != copySize.cx; i++)  {
  3575.             if ( (rNametableS[i+ (j << 5)] & 0x8000) == 0) {
  3576.               rNametableT[ i + mouse.x + (j + mouse.y << 5)] = rNametableS[i+ (j << 5)];
  3577.             }
  3578.           }
  3579.         }
  3580.         // Exec undo status save.
  3581.         m_pNametableCell->snapshotToUndoStack ();
  3582.       }
  3583.       else if (m_dwStateChr & 0x8000)
  3584.       {
  3585.         m_dwStateChr &= ~0x8000;
  3586.  
  3587.         if (t_bReadWriteMap != FALSE && m_bAttrEditMode == FALSE) {
  3588.           m_ptTrackChrEnd.x =  pt.x / 8;
  3589.           m_ptTrackChrEnd.y =  pt.y / 8;
  3590.  
  3591.           CGlobals::limitPoint (m_ptTrackChrEnd, 32, 32);
  3592.  
  3593.           CPoint ptStart = m_ptTrackChrStart;
  3594.           CPoint ptEnd = m_ptTrackChrEnd;
  3595.           CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3596.  
  3597.           m_ptTrackerChrStartY = ptStart;
  3598.           m_szTrackerChrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3599.           m_szTrackerChrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3600.           // Copy from clay/nametable
  3601.           if (m_pNametableCell->chr != NULL) {
  3602.           CGlobals::lockPaste (
  3603.              & m_pNametableCell->tileSlot[0],
  3604.              ptStart,
  3605.              m_szTrackerChrVectorY,
  3606.              CSize (32, 32),
  3607.               IsDlgButtonChecked (IDCK_OVERWRITE_CHR) == BST_CHECKED,
  3608.              m_pNametableCell->chr,
  3609.              IsDlgButtonChecked (IDCK_OVERWRITE_PAL) == BST_CHECKED,
  3610.               m_pNametableCell->pal != NULL ?
  3611.                      m_pNametableCell->pal->pal
  3612.                      : NULL,
  3613.                      IsDlgButtonChecked (IDCK_OVERWRITE_ATTR) == BST_CHECKED,
  3614.               m_pNametableCell->attr != NULL ?
  3615.                      m_pNametableCell->attr->attr
  3616.                      : NULL);
  3617.           }
  3618.         } else {
  3619.           m_ptTrackChrEnd.x =  pt.x / 16;
  3620.           m_ptTrackChrEnd.y =  pt.y / 16;
  3621.  
  3622.           CGlobals::limitPoint (m_ptTrackChrEnd, 16, 16);
  3623.  
  3624.           CPoint ptStart = m_ptTrackChrStart;
  3625.           CPoint ptEnd = m_ptTrackChrEnd;
  3626.           CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3627.  
  3628.           m_ptTrackerChrStartY = ptStart;
  3629.           m_szTrackerChrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3630.           m_szTrackerChrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3631.  
  3632.           if (m_bAttrEditMode == FALSE) {
  3633.             // Copy from chr-
  3634.             static WORD chrTile[1024];
  3635.             RtlFillMemory (chrTile, sizeof (chrTile), 0x80);
  3636.  
  3637.             // init chr tiles
  3638.             for (auto y = 0; y != 16; y++) {
  3639.               for (auto x = 0; x != 16; x++) {
  3640.                 chrTile[y * 32 + x] = y * 16 + x;
  3641.               }
  3642.             }
  3643.             CGlobals::lockPaste (
  3644.                  & chrTile[0],
  3645.                               ptStart,
  3646.              m_szTrackerChrVectorY,
  3647.              CSize (16, 16),
  3648.              IsDlgButtonChecked (IDCK_OVERWRITE_CHR) == BST_CHECKED,
  3649.              m_pNametableCell->chr,
  3650.              IsDlgButtonChecked (IDCK_OVERWRITE_PAL) == BST_CHECKED,
  3651.               m_pNametableCell->pal != NULL ?
  3652.                      m_pNametableCell->pal->pal
  3653.                      : NULL);
  3654.           }
  3655.         }
  3656.       }
  3657.       UpdateInfos (TRUE);
  3658.       break;
  3659.     case MAP_CONTROL_LV_ATTR:
  3660.       if (m_dwStateAttr & 0x8000)
  3661.       {
  3662.         m_dwStateAttr &= ~0x8000;
  3663.  
  3664.         m_ptTrackAttrEnd.x =  pt.x / 16;
  3665.         m_ptTrackAttrEnd.y =  pt.y / 16;
  3666.  
  3667.         CGlobals::limitPoint (m_ptTrackAttrEnd, 16, 16);
  3668.  
  3669.         CPoint ptStart = m_ptTrackAttrStart;
  3670.         CPoint ptEnd = m_ptTrackAttrEnd;
  3671.         CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  3672.  
  3673.         m_ptTrackerAttrStartY = ptStart;
  3674.         m_szTrackerAttrVectorY.cx = ptEnd.x -ptStart.x + 1;
  3675.         m_szTrackerAttrVectorY.cy = ptEnd.y -ptStart.y + 1;
  3676.       }
  3677.       Invalidate ();
  3678.       bHandled = FALSE;
  3679.       break;
  3680.     case MAP_CONTROL_LV_ATTRLIST: // Case attr select end
  3681.        // m_bSelAttrtable = TRUE;
  3682.        break;
  3683.  
  3684.     case MAP_CONTROL_LV_GPAL: // Case Global paleete
  3685.       m_ptTrackGPal.x = pt.x / gpalUnitWidth;
  3686.       m_ptTrackGPal.y = pt.y / gpalUnitHeight;
  3687.       CGlobals::limitPoint (m_ptTrackGPal, 16, 4);
  3688.       // Check Lock ptr.
  3689.       if (m_pTrackSPal != NULL) {
  3690.         m_pTrackSPal[0] = (BYTE) (m_ptTrackGPal.x+m_ptTrackGPal.y*16 & 0xFF);
  3691.         m_atthis->adjustSpecPalette (m_atthis->m_ShowMap);
  3692.         m_atthis->allViewUpdate ();
  3693.       }
  3694.       Invalidate ();
  3695.     default:
  3696.       break;
  3697.     }
  3698.     return 0;
  3699.   }
  3700.   template <DWORD t_dwControlId>
  3701.   LRESULT OnKeyUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  3702.     CValidateALL flush (*m_atthis,  *this);
  3703.     ATLASSERT (m_pNametableCell != NULL);
  3704.  
  3705.     switch (t_dwControlId) {
  3706.     case MAP_CONTROL_LV_CHR:
  3707.             switch (wParam) {
  3708.             case 'Z': // Undo
  3709.                       if (CTRL_IN_KEYQUEUE ()) {
  3710.                         if (m_pNametableCell->snapshotUndo () != NULL) {
  3711.                           int id = 0;
  3712.  
  3713.                         }
  3714.                       }
  3715.                       break;
  3716.             case 'Y': // Resume
  3717.                       if (CTRL_IN_KEYQUEUE ()) {
  3718.                         if (m_pNametableCell->snapshotResume () != NULL) {
  3719.                           int id = 0;
  3720.  
  3721.                         }
  3722.                       }
  3723.                       break;
  3724.  
  3725.       case 96:
  3726.       case 97:
  3727.       case 98:
  3728.       case 99:
  3729.       case '0':
  3730.       case '1':
  3731.       case '2':
  3732.       case '3':
  3733.           if (  t_bReadWriteMap != FALSE
  3734.           && m_bAttrEditMode != FALSE
  3735.           && (m_dwStateChr & 0x7FFF) != 0)
  3736.           {
  3737.           const DWORD attr2bit = (wParam >= 96 && wParam <= 99)
  3738.                                  ? (wParam - 96 & 3)
  3739.                       : (wParam - '0' & 3);
  3740.  
  3741.           for (auto j= 0; j != m_szTrackerChrVectorY.cy; j++) {
  3742.             const auto yvec= j + m_ptTrackerChrStartY.y << 1;
  3743.             for (auto i= 0; i != m_szTrackerChrVectorY.cx; i++) {
  3744.               const auto xvec = i + m_ptTrackerChrStartY.x << 1;
  3745.               CGlobals::setAttrBit (m_pNametableCell->attr->attr, xvec, yvec, attr2bit);
  3746.             }
  3747.           }
  3748.                   // Exec undo status save.
  3749.         m_pNametableCell->snapshotToUndoStack ();
  3750.           UpdateInfos (TRUE);
  3751.           }
  3752.         break;
  3753.               case VK_RETURN:
  3754.                    if  (t_bReadWriteMap != FALSE) {
  3755.                      m_bAttrEditMode = ! m_bAttrEditMode;
  3756.                      if (m_bAttrEditMode != FALSE) {
  3757.                        m_GuiGB_Chr.SetWindowText (_T ("Clay-attr mode"));
  3758.                      } else {
  3759.                        m_GuiGB_Chr.SetWindowText (_T ("Clay-std mode"));
  3760.                      }
  3761.                      m_dwStateAttr = 0;
  3762.                      m_dwStateChr = 0;
  3763.  
  3764.                    }
  3765.                    break;
  3766.         case 'C':
  3767.  
  3768.  
  3769.  
  3770.  
  3771.       if (t_bReadWriteMap != FALSE
  3772.         && (m_dwStateChr != 0
  3773.         && (m_dwStateChr & 0x8000) == 0))
  3774.       {
  3775.         for (DWORD j= 0; j != m_szTrackerChrVectorY.cy; j++) {
  3776.           DWORD yvec = j + m_ptTrackerChrStartY.y;
  3777.           PWORD pByteY = & m_pNametableCell->tileSlot[yvec << 5];
  3778.           for (DWORD i= 0; i != m_szTrackerChrVectorY.cx; i++) {
  3779.             DWORD xvec = i + m_ptTrackerChrStartY.x;
  3780.             pByteY[xvec] = 0x8000;
  3781.           }
  3782.         }
  3783.                 // Exec undo status save.
  3784.         m_pNametableCell->snapshotToUndoStack ();
  3785.  
  3786.         UpdateInfos (TRUE);
  3787.       }
  3788.       default:
  3789.       break;
  3790.             }
  3791.       break;
  3792.     case MAP_CONTROL_LV_ATTRLIST:
  3793.       switch (wParam) {
  3794.       case 'C':
  3795.         if (CTRL_IN_KEYQUEUE ()) {
  3796.           auto attr = m_GuiLV_AttrList.GetItemSelectedDataT ();
  3797.           if (attr != NULL) {
  3798.             CGlobals::pasteAttr = attr;
  3799.             m_atthis->setStatusText (4, _T ("attr cache:%s %s"), m_pNametableCell->comment,  attr->comment);
  3800.           }
  3801.         }
  3802.         break;
  3803.       case 'V':
  3804.         if (CTRL_IN_KEYQUEUE ()) {
  3805.           auto attr = m_GuiLV_AttrList.GetItemSelectedDataT ();
  3806.           if (attr != NULL && CGlobals::pasteAttr != NULL) {
  3807.             RtlCopyMemory (attr->attr, CGlobals::pasteAttr->attr, sizeof (CGlobals::pasteAttr->attr));
  3808.             // Update view
  3809.             m_atthis->allViewUpdate ();
  3810.           }
  3811.         }
  3812.         break;
  3813.  
  3814.       case VK_INSERT:
  3815.         // Attr table insert new item.
  3816.         //
  3817.         {
  3818.           CAttrSettings dlgSettings (*this);
  3819.           if (dlgSettings.DoModal (NULL) == IDOK) {
  3820.             // Append to new.
  3821.             auto index = m_GuiLV_AttrList.InsertItem (m_GuiLV_AttrList.GetItemCount (), dlgSettings.m_newattr->comment, 0);    
  3822.             ATLASSERT (index >= 0);
  3823.  
  3824.             m_GuiLV_AttrList.SetItemData (index, reinterpret_cast <DWORD_PTR> ( dlgSettings.m_newattr));
  3825.            
  3826.             if (m_pNametableCell->attr == NULL) {
  3827.               // No sel attr table pointer. set default
  3828.               m_pNametableCell->attr = dlgSettings.m_newattr;
  3829.               m_atthis->setCPListViewItemWithImg <t_bReadWriteMap> ( m_pNametableCell, 3, m_pNametableCell->attr->comment, 5);
  3830.             }
  3831.             m_atthis->m_GuiSWin_Nesmap.nesPixelGenerator ();
  3832.           }
  3833.           return 0;
  3834.         }
  3835.         break;
  3836.       case VK_DELETE:
  3837.         // Attr table delete select item.
  3838.         //
  3839.         {
  3840.           auto index = m_GuiLV_AttrList.GetSelectedIndex ();
  3841.           if (index >= 0) {
  3842.              auto *attr = m_GuiLV_AttrList.GetItemDataT (index);
  3843.              for (auto It = 0; It != m_pNametableCell->attrList   .GetCount (); It++) {
  3844.                auto *temp = m_pNametableCell->attrList[It];
  3845.                if (temp == attr) {
  3846.                  m_pNametableCell->attrList.RemoveAt (It);
  3847.                  m_GuiLV_AttrList.DeleteItem (index);  
  3848.                  m_atthis->setCPListViewItemWithImg <t_bReadWriteMap> ( m_pNametableCell, 3, _T ("null"), 5);
  3849.                  m_pNametableCell->attr = NULL;
  3850.  
  3851.                  if (attr == CGlobals::pasteAttr) {
  3852.                    // Remove paste object
  3853.                    CGlobals::pasteAttr = NULL;
  3854.  
  3855.                    m_atthis->setStatusText (4, _T ("attr cache:empty"));
  3856.                  }
  3857.                  delete temp;
  3858.                  break;
  3859.                }
  3860.              }
  3861.           }
  3862.         }
  3863.       default:
  3864.         break;
  3865.       }
  3866.        bHandled  = FALSE;
  3867.        break;
  3868.  
  3869.     case MAP_CONTROL_LV_PALLIST:
  3870.       switch (wParam) {
  3871.       case 'C':
  3872.         if (CTRL_IN_KEYQUEUE ()) {
  3873.           auto pal = m_GuiLV_PalList.GetItemSelectedDataT ();
  3874.           if (pal != NULL) {
  3875.             CGlobals::pastePal = pal;
  3876.             m_atthis->setStatusText (3, _T ("pal cache:%s %s %s"),
  3877.                      m_pNametableCell->comment,
  3878.                      m_pNametableCell->getSelectPalSource (), pal->comment);
  3879.           }
  3880.         }
  3881.         break;
  3882.       case 'V':
  3883.         if (CTRL_IN_KEYQUEUE ()) {
  3884.           auto pal = m_GuiLV_PalList.GetItemSelectedDataT ();
  3885.           if (pal != NULL && CGlobals::pastePal != NULL) {
  3886.             RtlCopyMemory (pal->pal, CGlobals::pastePal->pal, sizeof (CGlobals::pastePal->pal));
  3887.             // Update view
  3888.             m_atthis->allViewUpdate ();
  3889.           }
  3890.         }
  3891.         break;
  3892.  
  3893.       case VK_INSERT:
  3894.         {
  3895.            CPalSettings<t_bReadWriteMap> dlgSettings (*this);
  3896.            if (dlgSettings.DoModal () == IDOK) {
  3897.              resetListViewPalette ();
  3898.  
  3899.              m_atthis->updateCPViewListInfos<FALSE> ();
  3900.              m_atthis->allViewUpdate ();
  3901.            }
  3902.         }
  3903.         break;
  3904.       case VK_DELETE:
  3905.         {
  3906.           auto index = m_GuiLV_PalList.GetSelectedIndex ();
  3907.           if (index >= 0) {
  3908.             // Delete select palette item.
  3909.             // Check global/static palette, remove it in all view. (nt and clay)
  3910.             // Update CMainFrame::Page view
  3911.             // Update all link's nt and clay view.
  3912.             // Update NEX pixel output.
  3913.             ATLASSERT (m_pNametableCell != NULL);
  3914.             CPal *pal = m_pNametableCell->removePalette (index);
  3915.             ATLASSERT (pal != NULL);
  3916.  
  3917.             // Check global/static palette, remove it in all CAtlArray. (nt and clay)
  3918.             m_atthis->removeAllSpecRefMapPaletteGS (pal);
  3919.             m_atthis->updateCPViewListInfos<FALSE>();
  3920.             m_atthis->updateCPViewListInfos<TRUE> ();    
  3921.             m_atthis->allViewUpdate ();
  3922.  
  3923.             if (pal == CGlobals::pastePal) {
  3924.               // Remove paste object
  3925.               CGlobals::pastePal = NULL;
  3926.  
  3927.               m_atthis->setStatusText (3, _T ("pal cache:empty"));
  3928.             }
  3929.             delete pal;
  3930.           }
  3931.         }
  3932.       default:
  3933.         break;
  3934.       }
  3935.  
  3936.        bHandled  = FALSE;
  3937.        break;
  3938.  
  3939.     case MAP_CONTROL_LV_ATTR:
  3940.       switch (wParam) {
  3941.             case 'Z': // Undo
  3942.                       if (CTRL_IN_KEYQUEUE ()) {
  3943.                         if (m_pNametableCell->snapshotUndo () != NULL) {
  3944.                           int id = 0;
  3945.  
  3946.                         }
  3947.                       }
  3948.                       break;
  3949.             case 'Y': // Resume
  3950.                       if (CTRL_IN_KEYQUEUE ()) {
  3951.                         if (m_pNametableCell->snapshotResume () != NULL) {
  3952.                           int id = 0;
  3953.  
  3954.                         }
  3955.                       }
  3956.                       break;
  3957.       case 96:
  3958.       case 97:
  3959.       case 98:
  3960.       case 99:
  3961.       case '0':
  3962.       case '1':
  3963.       case '2':
  3964.       case '3':
  3965.         // Scan rect.
  3966.         if (m_dwStateAttr == 1
  3967.             && m_pNametableCell != NULL
  3968.             && m_pNametableCell->attr != NULL)
  3969.         {
  3970.           const DWORD attr2bit = (wParam >= 96 && wParam <= 99)
  3971.                                  ? (wParam - 96 & 3)
  3972.                       : (wParam - '0' & 3);
  3973.                  for (auto j= 0; j != m_szTrackerAttrVectorY.cy; j++) {
  3974.           const auto yvec= j + m_ptTrackerAttrStartY.y << 1;
  3975.           for (auto i= 0; i != m_szTrackerAttrVectorY.cx; i++) {
  3976.             const auto xvec = i + m_ptTrackerAttrStartY.x << 1;
  3977.             CGlobals::setAttrBit (m_pNametableCell->attr->attr, xvec, yvec, attr2bit);
  3978.           }
  3979.         }
  3980.          UpdateInfos (TRUE);
  3981.          m_atthis->m_GuiSWin_Nesmap.nesPixelGenerator ();
  3982.         }
  3983.         break;
  3984.       }
  3985.     default:
  3986.       break;
  3987.     }
  3988.     return 0;
  3989.   }
  3990.  
  3991.   LRESULT OnCheckUpdate (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  3992.     Invalidate (NULL);
  3993.     return 0;
  3994.   }
  3995.   LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  3996.  
  3997.     m_GuiLV_PalList.RemoveImageList (LVSIL_SMALL);
  3998.     m_GuiLV_AttrList.RemoveImageList (LVSIL_SMALL);
  3999.  
  4000.     bHandled = FALSE;
  4001.     return 0;
  4002.   }
  4003.   LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  4004.  
  4005.     ShowWindow (SW_HIDE);
  4006.    
  4007.     bHandled = FALSE;
  4008.     return 0;
  4009.   }
  4010. };
  4011.  
  4012.   static const WORD clrMeshMainOne = PHOTOSHOP_COL_TOGDI16 (0x0000cc);
  4013.   static const WORD clrMeshMainTwo = PHOTOSHOP_COL_TOGDI16 (0x00cc00);
  4014.   static const WORD clrMeshAttr = PHOTOSHOP_COL_TOGDI16 (0x555555);
  4015.   static const WORD clrMeshCatching = PHOTOSHOP_COL_TOGDI16 (0xcc0000);
  4016.   static const WORD clrMeshSet = PHOTOSHOP_COL_TOGDI16 (0xebf90a);
  4017.  
  4018.   static const SIZE_T MAP_CONTROL_LV_MAP = 1;
  4019.   static const SIZE_T MAP_CONTROL_LV_PAGE = MAP_CONTROL_LV_MAP + 1;
  4020.   static const SIZE_T MAP_CONTROL_LV_CHR = MAP_CONTROL_LV_PAGE + 1;
  4021.   static const SIZE_T MAP_CONTROL_LV_CLAY = MAP_CONTROL_LV_CHR + 1;
  4022.  
  4023.   static const SIZE_T NTPAGE_SHOW_TOG_MAX = 4;
  4024.   static const SIZE_T CLAYPAGE_SHOW_TOG_MAX = 4;
  4025.  
  4026.   CImageListManaged m_IconMaplist;
  4027.   CImageListManaged m_IconClaylist;
  4028.   CImageListManaged m_IconChrlist;
  4029.   CImageListManaged m_IconPagelist;
  4030.  
  4031.   CPoint m_ptRenderStart;
  4032.   CPoint m_ptRenderEnd;
  4033.  
  4034.   CPoint m_ptRenderStartY;
  4035.   CSize m_szRenderStartY;
  4036.  
  4037.   CPoint m_ptPastePoint;
  4038.  
  4039.   BOOL m_bShowGridMain;
  4040.   BOOL m_bShowGridAttr;
  4041.   // Panel bar settings
  4042.   // --------------------------------------------------------------------------------
  4043.   //    Map view  | Chr list | Clay list
  4044.   // ---------------| ----------------------------------------
  4045.   //    Page view | real map view
  4046.   // --------------------------------------------------------------------------------
  4047.   CSplitterWindowT <true> m_SWinSplitterMain;
  4048.   CSplitterWindowT <false> m_SWinSplitterLeft;
  4049.   CSplitterWindowT <false> m_SWinSplitterRight;
  4050.   CSplitterWindowT <true> m_SWinSplitterList;
  4051.  
  4052.   CContainedWindowT <CListViewCtrlTS<CMapUnit>> m_GuiLV_Map;
  4053.   CContainedWindowT <CListViewCtrlTS<CNametableCell <FALSE>>> m_GuiLV_Page;
  4054.   CContainedWindowT <CListViewCtrlTS<CChr>> m_GuiLV_Chr;
  4055.   CContainedWindowT <CListViewCtrlTS<CNametableCell <TRUE>>> m_GuiLV_Clay;
  4056.   // CToolTipCtrl
  4057.   // CToolTipCtrlT
  4058.   // CToolInfo
  4059.   // CToolBarCtrlT <CWindow> m_GuiTB_main;
  4060.   // CStatusBarCtrlT <CWindow> m_GuiSB_main;
  4061.   //
  4062.   // CToolTipCtrlT
  4063.   CToolBarCtrlT <CWindow> m_GuiTB_main;
  4064.   CMenuT <true> m_GuiMenu_MapAttach;
  4065. public:
  4066.   DECLARE_FRAME_WND_CLASS_EX(NULL, IDR_MAINFRAME, 0, -1)
  4067.  
  4068.   CCommandBarCtrl m_CmdBar;
  4069.  
  4070.   BOOL m_bShowAttrShadow;
  4071.  
  4072.   LPDIRECT3D9 m_Direct3D9;
  4073.   LPDIRECT3DDEVICE9 m_Direct3D9Deivce;
  4074.   LPDIRECT3DSURFACE9 m_Direct3D9Surface;
  4075.   CPoint m_Tracker;
  4076.  
  4077.   CMapUnit *m_ShowMap;
  4078.   INT m_ntpWindowPoll;
  4079.  
  4080.   DWORD m_dwStateAttr; // 0: no copy 1:copy it
  4081.                                       // 0x8000 mask : ing...
  4082.   DWORD m_dwStateChr; // 0: no copy 1:copy it
  4083.                                       // 0x8000 mask : ing...
  4084.   DWORD m_dwStateRorate; // 0: no copy 1:copy it
  4085.                                       // 0x4000 : action 2:raote else action 1:select rect
  4086.                                       // 0x8000 mask : ing...
  4087.   CPoint m_ptTrackChrStartZ;
  4088.  
  4089.   CPoint m_ptTrackAttrStart;
  4090.   CPoint m_ptTrackAttrEnd;
  4091.  
  4092.   CPoint m_ptTrackChrStart;
  4093.   CPoint m_ptTrackChrEnd;
  4094.  
  4095.   CPoint m_ptTrackerAttrStartY;
  4096.   CSize m_szTrackerAttrVectorY;
  4097.  
  4098.   CPoint m_ptTrackerChrStartY;
  4099.   CSize m_szTrackerChrVectorY;
  4100.  
  4101.   INT m_subFunc; // 0: paste 1:attr adjust 2: vector rorate
  4102.   CViewNametablePage<FALSE> m_ntwCell[NTPAGE_SHOW_TOG_MAX];
  4103.   CViewNametablePage<TRUE> m_ClayCell[CLAYPAGE_SHOW_TOG_MAX];
  4104.  
  4105.   CAtlArray <CMapUnit *> m_MapVec;
  4106.   CAtlArray <CChr *> m_ChrVec;
  4107.   CAtlArray <CNametableCell<TRUE> *> m_VnpVec;
  4108.  
  4109.   CAtlArray <CPal *> m_globalPal;
  4110.  
  4111.   template <BOOL t_bReadWriteMap>
  4112.   struct CCPObjectHelper {
  4113.     CMainFrame &m_athis;
  4114.  
  4115.     CCPObjectHelper (CMainFrame &ttthis___):m_athis (ttthis___) {}
  4116.  
  4117.     BOOL isReadWriteMap (void) {
  4118.       return t_bReadWriteMap;
  4119.     }
  4120.  
  4121.     CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *
  4122.     getCPListViewObject (void) {
  4123.       return t_bReadWriteMap
  4124.         ? reinterpret_cast  <CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *> ( & m_athis.m_GuiLV_Clay)
  4125.         : reinterpret_cast  <CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *> ( & m_athis.m_GuiLV_Page);
  4126.     }
  4127.  
  4128.     const SIZE_T getCellViewMax (void) {
  4129.       return t_bReadWriteMap ? CLAYPAGE_SHOW_TOG_MAX
  4130.         : NTPAGE_SHOW_TOG_MAX;
  4131.     }
  4132.  
  4133.     CViewNametablePage<t_bReadWriteMap> *
  4134.     getCPCellView (void) {
  4135.       return t_bReadWriteMap
  4136.         ? reinterpret_cast  <CViewNametablePage<t_bReadWriteMap> *> ( m_athis.m_ClayCell)
  4137.         : reinterpret_cast  <CViewNametablePage<t_bReadWriteMap> *> ( m_athis.m_ntwCell);
  4138.     }
  4139.  
  4140.     CAtlArray <CNametableCell<t_bReadWriteMap> *> *
  4141.     getCPArrayObject (void) {
  4142.       if (t_bReadWriteMap == FALSE) {
  4143.         if (m_athis.m_ShowMap != NULL)
  4144.           return reinterpret_cast <CAtlArray <CNametableCell<t_bReadWriteMap> *> *> (& m_athis.m_ShowMap->ntList);
  4145.         return NULL;
  4146.       } else {
  4147.         return reinterpret_cast <CAtlArray <CNametableCell<t_bReadWriteMap> *> *> (& m_athis.m_VnpVec);
  4148.       }
  4149.       // Never reach here..
  4150.       ATLASSERT (FALSE);
  4151.       return NULL;
  4152.     }
  4153.  
  4154.     VOID allCPCellViewSMutUpdate () {
  4155.       auto cellmax=  getCellViewMax ();
  4156.       auto pAllocT = getCPCellView ();
  4157.  
  4158.       for (SIZE_T it = 0; it !=  cellmax; it++) {
  4159.         auto &refcc = pAllocT[it];
  4160.  
  4161.         if (refcc.alive () != FALSE) {
  4162.           refcc.sMutViewPal_reset ();
  4163.           refcc.UpdateInfos ();
  4164.         }
  4165.       }
  4166.     }
  4167.   };
  4168.  
  4169.   template <BOOL t_bReadWriteMap>
  4170.   CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *
  4171.   getCPListViewObject (void) {
  4172.     return t_bReadWriteMap
  4173.       ? reinterpret_cast  <CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *> ( & m_GuiLV_Clay)
  4174.       : reinterpret_cast  <CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *> ( & m_GuiLV_Page);
  4175.   }
  4176.  
  4177.   void setItem (CListViewCtrl &listview,  int iIndex, int iSubIndex, CString comment) {
  4178.     listview.SetItem (iIndex, iSubIndex, LVIF_TEXT, comment, 0, 0, 0, 0);
  4179.   }
  4180.  
  4181.   void setItemWithImg (CListViewCtrl &listview,  int iIndex, int iSubIndex, CString comment, int iImage) {
  4182.     listview.SetItem (iIndex, iSubIndex, LVIF_IMAGE | LVIF_TEXT, comment, iImage, 0, 0, 0);
  4183.   }
  4184.  
  4185.   template <BOOL t_bReadWriteMap>
  4186.   void setCPListViewItemWithImg (int iIndex, int iSubIndex, CString comment, int iImage) {
  4187.     setItemWithImg (*getCPListViewObject <t_bReadWriteMap> (), iIndex, iSubIndex, comment, iImage);
  4188.   }
  4189.  
  4190.   template <BOOL t_bReadWriteMap>
  4191.   void setCPListViewItemWithImg (CNametableCell<t_bReadWriteMap> *nt_cell, int iSubIndex, CString comment, int iImage) {
  4192.     // Serach index.
  4193.     CListViewCtrlTS<CNametableCell <t_bReadWriteMap>> *
  4194.     CPObject  = getCPListViewObject <t_bReadWriteMap> ();
  4195.  
  4196.     int index = -1;
  4197.     for (int it =0; it != CPObject->GetItemCount (); it++) {
  4198.       auto p = CPObject->GetItemDataT (it);
  4199.       ATLASSERT (p != NULL);
  4200.  
  4201.       if (p == nt_cell) {
  4202.         index = it;
  4203.         break;
  4204.       }
  4205.     }
  4206.     ATLASSERT (index >= 0);
  4207.     setItemWithImg (*CPObject, index, iSubIndex, comment, iImage);
  4208.   }
  4209.  
  4210.   template <BOOL t_bReadWriteMap>
  4211.   VOID updateCPViewListInfos (VOID) {
  4212.     CCPObjectHelper<t_bReadWriteMap> helper (*this);
  4213.     auto &lvPage = *helper.getCPListViewObject ();
  4214.     auto arrayT = helper.getCPArrayObject ();
  4215.  
  4216.     if (arrayT != NULL) {
  4217.       for (SIZE_T it = 0; it != arrayT->GetCount (); it++) {
  4218.         auto nt = (*arrayT)[it];
  4219.         ATLASSERT (nt != NULL);
  4220.  
  4221.         lvPage.SetItem (it, 0, LVIF_IMAGE | LVIF_TEXT, nt->comment, 0, 0, 0, 0);
  4222.         lvPage.SetItem (it, 1, LVIF_IMAGE | LVIF_TEXT, nt->chr ? nt->chr->comment : _T ("null"), 1, 0, 0, 0);
  4223.         lvPage.SetItem (it, 3, LVIF_IMAGE | LVIF_TEXT, nt->attr ? nt->attr->comment : _T ("null"), 5, 0, 0, 0);
  4224.  
  4225.         if (nt->pal != NULL) {
  4226.           lvPage.SetItem (it, 2, LVIF_IMAGE | LVIF_TEXT, nt->pal->comment, 2 + nt->pal->source, 0, 0, 0);
  4227.         } else {
  4228.           // use old clay palette ico.
  4229.           LVITEM lvtemp;
  4230.           RtlZeroMemory (& lvtemp, sizeof (LVITEM));
  4231.  
  4232.           lvtemp.iItem = it;
  4233.           lvtemp.iSubItem = 2;
  4234.           lvtemp.mask = LVIF_IMAGE;
  4235.  
  4236.           BOOL sig = lvPage.GetItem (& lvtemp);
  4237.           ATLASSERT (sig != FALSE);
  4238.  
  4239.           lvPage.SetItem (it, 2, LVIF_IMAGE | LVIF_TEXT,  _T ("null"), lvtemp.iImage, 0, 0, 0);
  4240.         }
  4241.       }
  4242.     }
  4243.   }
  4244.  
  4245.   VOID removeAllSpecRefMapPaletteGS (CPal *pal) {
  4246.  
  4247.     if (pal != NULL
  4248.         && m_ShowMap != NULL) {
  4249.  
  4250.       for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4251.         auto &r  = m_ntwCell[it];
  4252.         if (r.alive () != FALSE && r.m_pNametableCell != NULL) {
  4253.           for (int it =0; it != r.m_GuiLV_PalList.GetItemCount (); it++) {
  4254.             auto p = r.m_GuiLV_PalList.GetItemDataT (it);
  4255.             ATLASSERT (p != NULL);
  4256.             if (p == pal) {
  4257.               // Delete this item.
  4258.               r.m_GuiLV_PalList.DeleteItem (it);
  4259.               // Check current is select.???
  4260.               if (r.m_GuiLV_PalList.GetSelectedIndex () == it) {
  4261.                 // empty it.
  4262.                 r.m_GuiLV_PalList.SetItemState (it, 0, 0);
  4263.               }
  4264.               break;
  4265.             }
  4266.           }
  4267.         }
  4268.       }
  4269.  
  4270.       for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4271.         auto &r  = m_ClayCell[it];
  4272.         if (r.alive () != FALSE && r.m_pNametableCell != NULL) {
  4273.           for (int it =0; it != r.m_GuiLV_PalList.GetItemCount (); it++) {
  4274.             auto p = r.m_GuiLV_PalList.GetItemDataT (it);
  4275.             ATLASSERT (p != NULL);
  4276.             if (p == pal) {
  4277.               // Delete this item.
  4278.               r.m_GuiLV_PalList.DeleteItem (it);
  4279.               // Check current is select.???
  4280.               if (r.m_GuiLV_PalList.GetSelectedIndex () == it) {
  4281.                 // empty it.
  4282.                 r.m_GuiLV_PalList.SetItemState (it, 0, 0);
  4283.               }
  4284.               break;
  4285.             }
  4286.           }
  4287.         }
  4288.       }
  4289.  
  4290.       // Check nt-
  4291.       for (size_t it = 0; it != m_ShowMap->ntList.GetCount (); it++) {
  4292.         auto p = m_ShowMap->ntList[it];
  4293.         ATLASSERT (p != NULL);
  4294.  
  4295.         if (p->pal == pal) {
  4296.           // remove it.
  4297.           p->pal = NULL;
  4298.           p->select = -1;
  4299.         }
  4300.       }
  4301.  
  4302.       // Check clay-
  4303.       for (size_t it = 0; it != m_VnpVec.GetCount (); it++) {
  4304.         auto p = m_VnpVec[it];
  4305.         ATLASSERT (p != NULL);
  4306.  
  4307.         if (p->pal == pal) {
  4308.           // remove it.
  4309.           p->pal = NULL;
  4310.           p->select = -1;
  4311.         }
  4312.       }
  4313.     }
  4314.   }
  4315.  
  4316.   VOID allViewUpdate (void) {
  4317.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4318.       auto &r  = m_ntwCell[it];
  4319.       if (r.alive () != FALSE) {
  4320.         r.UpdateInfos ();
  4321.       }
  4322.     }
  4323.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4324.       auto &r  = m_ClayCell[it];
  4325.       if (r.alive () != FALSE) {
  4326.         r.UpdateInfos ();
  4327.       }
  4328.     }
  4329.     m_GuiSWin_Nesmap.nesPixelGenerator ();
  4330.   }
  4331.  
  4332.   VOID adjustSpecPalette (void) {
  4333.     for (auto it = 0; it != m_MapVec.GetCount (); it++) {
  4334.       adjustSpecPalette (m_MapVec[it]);
  4335.     }
  4336.   }
  4337.  
  4338.   VOID adjustSpecPalette (CMapUnit *map_unit) {
  4339.     if  (map_unit != NULL) {
  4340.       for (auto it =0; it != map_unit->ntList.  GetCount (); it++) {
  4341.         auto p = map_unit->ntList[it];
  4342.         p->setIfEmptySelect0 ();
  4343.       }
  4344.     }
  4345.   }
  4346.  
  4347.   VOID updateItemPalette (BOOL bUpdateScreen = FALSE) {
  4348.  
  4349.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4350.       auto &r  = m_ntwCell[it];
  4351.       if (r.alive () != FALSE)
  4352.         r.resetListViewPalette ();
  4353.     }
  4354.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4355.       auto &r  = m_ClayCell[it];
  4356.       if (r.alive () != FALSE)
  4357.       r.resetListViewPalette ();
  4358.     }
  4359.     if (bUpdateScreen != FALSE) {
  4360.       for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4361.         auto &r  = m_ntwCell[it];
  4362.       if (r.alive () != FALSE)
  4363.         r.UpdateInfos ();
  4364.       }
  4365.       for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4366.         auto &r  = m_ClayCell[it];
  4367.       if (r.alive () != FALSE)
  4368.         r.UpdateInfos ();
  4369.       }
  4370.     }
  4371.   }
  4372.  
  4373.   VOID allocNtpWindow (VOID) {
  4374.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4375.       auto &r  = m_ntwCell[it];
  4376.       r.setAttach (this);
  4377.       r.Create (*this);
  4378.       r.ShowWindow (SW_HIDE);
  4379.     }
  4380.   }
  4381.   VOID clearNtpWindow (VOID) {
  4382.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4383.       auto &r  = m_ntwCell[it];
  4384.       r.setNtCell (NULL);
  4385.       r.ShowWindow (SW_HIDE);
  4386.     }
  4387.   }
  4388.   CWindowFT &tryAddNtpWindow (CNametableCell<FALSE> *nt_cell) {
  4389.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4390.       auto &r  = m_ntwCell[it];
  4391.       if (r.m_pNametableCell == nt_cell) {
  4392.         r.ShowWindow (SW_HIDE);
  4393.         r.ShowWindow (SW_SHOWNORMAL);
  4394.         return r;
  4395.       }
  4396.     }
  4397.     //
  4398.     auto &r = m_ntwCell[m_ntpWindowPoll++ % NTPAGE_SHOW_TOG_MAX];
  4399.     r.setNtCell (nt_cell);
  4400.     r.ShowWindow  (SW_HIDE);
  4401.     r.ShowWindow (SW_SHOWNORMAL);
  4402.     return r;
  4403.   }
  4404.  
  4405.   CWindowFT *tryUpdateNtpWindow (CNametableCell<FALSE> *nt_cell) {
  4406.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4407.       auto &r  = m_ntwCell[it];
  4408.       if (r.m_pNametableCell == nt_cell) {
  4409.         r.UpdateInfos ();
  4410.         return &r;
  4411.       }
  4412.     }
  4413.     return NULL;
  4414.   }
  4415.  
  4416.   VOID tryCloseNtpWindow (VOID) {
  4417.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4418.       auto &r  = m_ntwCell[it];
  4419.       r.ShowWindow (SW_HIDE);
  4420.     }
  4421.   }
  4422.  
  4423.   VOID allocClayWindow (VOID) {
  4424.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4425.       auto &r  = m_ClayCell[it];
  4426.       r.setAttach (this);
  4427.       r.Create (*this);
  4428.       r.ShowWindow (SW_HIDE);
  4429.     }
  4430.   }
  4431.  
  4432.   VOID clearClayWindow (VOID) {
  4433.     for (auto it =0 ; it != NTPAGE_SHOW_TOG_MAX; it++) {
  4434.       auto &r  = m_ClayCell[it];
  4435.       r.setNtCell (NULL);
  4436.       r.ShowWindow (SW_HIDE);
  4437.     }
  4438.   }
  4439.  
  4440.   CWindowFT &tryAddClayWindow (CNametableCell<TRUE> *nt_cell) {
  4441.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4442.       auto &r  = m_ClayCell[it];
  4443.       if (r.m_pNametableCell == nt_cell) {
  4444.         r.ShowWindow (SW_HIDE);
  4445.         r.ShowWindow (SW_SHOWNORMAL);
  4446.         return r;
  4447.       }
  4448.     }
  4449.     //
  4450.     auto &r = m_ClayCell[m_ntpWindowPoll++ % CLAYPAGE_SHOW_TOG_MAX];
  4451.     r.setNtCell (nt_cell);
  4452.     r.ShowWindow  (SW_HIDE);
  4453.     r.ShowWindow (SW_SHOWNORMAL);
  4454.     return r;
  4455.   }
  4456.  
  4457.   CWindowFT *tryUpdateClayWindow (CNametableCell<TRUE> *nt_cell) {
  4458.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4459.       auto &r  = m_ClayCell[it];
  4460.       if (r.m_pNametableCell == nt_cell) {
  4461.         r.UpdateInfos ();
  4462.         return &r;
  4463.       }
  4464.     }
  4465.     return NULL;
  4466.   }
  4467.   VOID tryCloseClayWindow (VOID) {
  4468.     for (auto it =0 ; it != CLAYPAGE_SHOW_TOG_MAX; it++) {
  4469.       auto &r  = m_ClayCell[it];
  4470.       r.ShowWindow (SW_HIDE);
  4471.     }
  4472.   }
  4473.  
  4474.   template <BOOL t_bAddvec>
  4475.   SFINLINE void adjustAttrVecBaseNtAddress (CNametableCell<FALSE> *nt_cell, CPoint &point, BYTE vec) {
  4476.     ATLASSERT (nt_cell != NULL);
  4477.     ATLASSERT (point.x <= 31);
  4478.     ATLASSERT (point.y <= 29);
  4479.  
  4480.     if (nt_cell->attr != NULL) {
  4481.       PBYTE p = nt_cell->attr ->attr;
  4482.       if (t_bAddvec != FALSE)
  4483.         CGlobals::setAttrBit (p, point.x, point.y,
  4484.                     CGlobals::getAttrBit (p, point.x, point.y) + vec);
  4485.       else
  4486.         CGlobals::setAttrBit (p, point.x, point.y, vec);
  4487.     }
  4488.   }
  4489.  
  4490.   template <BOOL t_bAddvec>
  4491.   void adjustAttrVecBaseNtAddress (CNametableCell<FALSE> *nt_cell, CPoint &point /* base 8 */, CSize  &vec /* base 8 */, BYTE pulseOrSet) {
  4492.     ATLASSERT (mapUnit != NULL);
  4493.  
  4494.     if (point.x < xMax
  4495.       && point.y < yMax )
  4496.     {
  4497.        // Do clip.
  4498.        if (point.x + vec.cx > 32)
  4499.          vec.cx = 32 - point.x;
  4500.        if (point.y + vec.cy > 32)
  4501.          vec.cy = 32 - point.x;
  4502.  
  4503.        for (auto y = 0; y < vec.cy; y+= 2) {
  4504.          const vtotal = point.y + y;
  4505.          for (auto x = 0; x < vec.cx; x+=2) {
  4506.            const htotal = point.x + x;
  4507.  
  4508.            adjustAttrVecBaseNtAddress <t_bAddvec> (nt_cell, CPoint (htotal, vtotal), pulseOrSet);
  4509.          }
  4510.        }
  4511.     }
  4512.   }
  4513.  
  4514.   template <BOOL t_bAddvec>
  4515.   void adjustAttrVecBaseNtAddress (CMapUnit *mapUnit, CPoint &point /* base 8 */, CSize  &vec /* base 8 */, BYTE pulseOrSet) {
  4516.     ATLASSERT (mapUnit != NULL);
  4517.  
  4518.     const auto xMax = mapUnit->width << 5;
  4519.     const auto yMax = mapUnit->height * 30;
  4520.     // Check range.
  4521.  
  4522.     if (point.x < xMax
  4523.       && point.y < yMax )
  4524.     {
  4525.        // Do clip.
  4526.        if (point.x + vec.cx > xMax)
  4527.          vec.cx = xMax - point.x;
  4528.        if (point.y + vec.cy > yMax)
  4529.          vec.cy = yMax - point.x;
  4530.  
  4531.        for (auto y = 0; y < vec.cy; y+=2) {
  4532.          const auto vtotal = point.y + y;
  4533.          const auto vpage = vtotal / 30;
  4534.          const auto vmod = vtotal % 30;
  4535.          const auto vpage_y = vpage * mapUnit->width;
  4536.          for (auto x = 0; x < vec.cx; x+=2) {
  4537.            const auto htotal = point.x + x;
  4538.            const auto hpage = htotal >> 5;
  4539.            const auto hmod = htotal & 31;
  4540.  
  4541.            adjustAttrVecBaseNtAddress <t_bAddvec> (mapUnit->ntList[vpage_y+hpage], CPoint (hmod, vmod), pulseOrSet);
  4542.          }
  4543.        }
  4544.     }
  4545.   }
  4546.   template <BOOL t_bAddvec>
  4547.   void adjustAttrVecBaseNtAddress (CMapUnit *mapUnit, CPoint &ptStart /* base 8 */, CPoint  &ptEnd /* base 8 */, BYTE pulseOrSet) {
  4548.     CPoint ptStart_ = ptStart;
  4549.     CPoint ptEnd_ = ptEnd;
  4550.  
  4551.     CGlobals::translateVecPointToltrb (ptStart_, ptEnd_);
  4552.     adjustAttrVecBaseNtAddress <t_bAddvec> (mapUnit, ptStart_, CSize (ptEnd_.x - ptStart_.x + 1, ptEnd_.y - ptStart_.y + 1), pulseOrSet);
  4553.   }
  4554.   // <Map scan class > =========================================
  4555.   struct CNesMapGenerator: public CScrollWindowImpl <CNesMapGenerator> {
  4556.     typedef CNesMapGenerator thisClass;
  4557.     typedef CScrollWindowImpl <CNesMapGenerator> baseClass;
  4558.  
  4559.     static const WORD alphaCnt = 7;
  4560.     static const WORD transShadowMark = PHOTOSHOP_COL_TOGDI16 (0xffffff);
  4561.     static const WORD transHitMark = PHOTOSHOP_COL_TOGDI16 (0xcecece);
  4562.  
  4563.     CMainFrame &m_attframe;
  4564.     CNesMapGenerator (CMainFrame &attframe):
  4565.       m_attframe (attframe) {}
  4566.  
  4567.     VOID nesPixelGenerator (VOID) {
  4568.       // tile mesh, nt mesh
  4569.       // switch, tile paste mode | attr adjust mode.
  4570.       // unto/ next
  4571.       // y - 0~29
  4572.       // x - 0~31
  4573.       D3DLOCKED_RECT vramLock;
  4574.       HRESULT sig;
  4575.       CMemoryPaint16::DirectWrite vramWrite;
  4576.       CRect rcClient;
  4577.       CMainFrame &rFrame = m_attframe;
  4578.       CPoint ptPastePoint (m_attframe.m_ptPastePoint);
  4579.       BOOL ret = GetClientRect (rcClient);
  4580.       ATLASSERT (ret != FALSE);
  4581.       CSize szDrawElem  (rcClient.Width ()/ 8, rcClient.Height ()/ 8);
  4582.       // To align the attr table, I will align a 2 * 2 grid offset
  4583.       CPoint ptOffsetAlign (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  4584.       CPoint ptScrStart (ptOffsetAlign.x >> 3, ptOffsetAlign.y >> 3);
  4585.  
  4586.       // Try lock direct3d surface...
  4587.       sig = rFrame.m_Direct3D9Surface->LockRect (& vramLock, NULL, D3DLOCK_DONOTWAIT | D3DLOCK_DISCARD);
  4588.       ATLASSERT (SUCCEEDED (sig));
  4589.  
  4590.       vramWrite.pBits = (PWORD)vramLock.pBits;
  4591.       vramWrite.Pitch = vramLock.Pitch;
  4592.       vramWrite.Pitch16 = vramWrite.Pitch >> 1;
  4593.  
  4594.       if (rcClient.Width () >= 128
  4595.         && rcClient.Height () >= 128
  4596.         && IsWindowVisible () != FALSE
  4597.         && rFrame.m_ShowMap != NULL
  4598.         && ptScrStart.x < rFrame.m_ShowMap->width * 256
  4599.         && ptScrStart.y < rFrame.m_ShowMap->height * 240)
  4600.       {
  4601.         CSize szSizeMax (rFrame.m_ShowMap->width << 5, rFrame.m_ShowMap->height * 30);
  4602.  
  4603.         auto &rGloablNESPal = CGlobals::nespal;
  4604.  
  4605.         static BYTE transTile[16];
  4606.         static BYTE attrT[64];
  4607.  
  4608.         RtlZeroMemory (transTile, sizeof (transTile));
  4609.  
  4610.         // Check overflow.
  4611.         if (ptScrStart.x + szDrawElem.cx > szSizeMax.cx)
  4612.           szDrawElem.cx = szSizeMax.cx - ptScrStart.x;
  4613.         if (ptScrStart.y + szDrawElem.cy > szSizeMax.cy)
  4614.           szDrawElem.cy = szSizeMax.cy - ptScrStart.y;
  4615.  
  4616.         // Draw main nametable buffer
  4617.         for (auto j= 0; j != szDrawElem.cy; j++) {
  4618.           auto vi = j + ptScrStart.y;
  4619.           auto ntp_vi = vi / 30;
  4620.           auto mod_y = vi % 30;
  4621.           auto vramyT = & vramWrite.pBits[vramWrite.Pitch16 *j<<3];
  4622.           if (vi >= szSizeMax.cy) {
  4623.             break;
  4624.           }
  4625.           for (auto i= 0; i != szDrawElem.cx; i++) {
  4626.             auto hi = i + ptScrStart.x;
  4627.             auto ntp_hi = hi >> 5;
  4628.             auto mod_x = hi & 31;
  4629.             auto vramT = & vramyT[i << 3];
  4630.             if (hi >= szSizeMax.cx) {
  4631.               break;
  4632.             }
  4633.             // fetch namtpage page
  4634.             CNametableCell<FALSE> &cell = *rFrame.m_ShowMap->ntList[ntp_hi + rFrame.m_ShowMap->width * ntp_vi];
  4635.             // draw tile chunk.
  4636.             if (cell.chr != NULL) {
  4637.               BYTE palT[] = {
  4638.                 0x0F, 0x00, 0x10, 0x30,
  4639.                 0x0F, 0x1C, 0x2B, 0x39,
  4640.                 0x0F, 0x06, 0x15, 0x36,
  4641.                 0x0C, 0x17, 0x28, 0x39
  4642.               };
  4643.              
  4644.               auto pAttr = attrT;
  4645.               auto pPal = palT;
  4646.  
  4647.               if (cell.attr != NULL) {
  4648.                 pAttr = cell.attr->attr;
  4649.               }
  4650.               if (cell.pal != NULL) {
  4651.                 RtlCopyMemory (palT, & cell.pal->pal[0], sizeof (palT));
  4652.  
  4653.                 palT[12] =
  4654.                 palT[8] =
  4655.                 palT[4] = palT[0];
  4656.               }
  4657.               WORD tileSlot = cell.tileSlot[mod_x + (mod_y << 5)];
  4658.              
  4659.               PBYTE chrptr;
  4660.               if (tileSlot & 0x8000) {
  4661.                 // Transpant
  4662.                 chrptr = transTile;
  4663.               } else {
  4664.                 chrptr = & cell.chr->chr[(tileSlot & 255) * 16];
  4665.               }
  4666.               BYTE attrBank = pAttr [(mod_x >> 2) + (mod_y >> 2 << 3)];
  4667.               // calc palette bank
  4668.               PBYTE palBank;
  4669.              
  4670.               if (mod_y & 2)
  4671.                 if (mod_x & 2)
  4672.                   palBank = & pPal[attrBank >> 4 & 0x0C];
  4673.                 else
  4674.                   palBank = & pPal[attrBank >> 2 & 0x0C];
  4675.               else
  4676.                 if (mod_x & 2)
  4677.                   palBank = & pPal[attrBank << 0 & 0x0C];
  4678.                 else
  4679.                   palBank = & pPal[attrBank << 2 & 0x0C];
  4680.  
  4681.               if ((tileSlot & 0x8000) == 0) {
  4682.                 for (auto vec = 0; vec != 8; vec++) {
  4683.                   CPolyData64 cpd64;
  4684.  
  4685.                   cpd64.blk = CGlobals::chrmixer[chrptr[0]];
  4686.                   cpd64.blk|= CGlobals::chrmixer[chrptr[8]] << 1;
  4687.  
  4688.                   vramT[0] = rGloablNESPal[palBank[cpd64.blk8[0]]];
  4689.                   vramT[1] = rGloablNESPal[palBank[cpd64.blk8[1]]];
  4690.                   vramT[2] = rGloablNESPal[palBank[cpd64.blk8[2]]];
  4691.                   vramT[3] = rGloablNESPal[palBank[cpd64.blk8[3]]];
  4692.                   vramT[4] = rGloablNESPal[palBank[cpd64.blk8[4]]];
  4693.                   vramT[5] = rGloablNESPal[palBank[cpd64.blk8[5]]];
  4694.                   vramT[6] = rGloablNESPal[palBank[cpd64.blk8[6]]];
  4695.                   vramT[7] = rGloablNESPal[palBank[cpd64.blk8[7]]];
  4696.  
  4697.                   vramT += vramWrite.Pitch16;
  4698.                   chrptr++;
  4699.                 }
  4700.               } else {
  4701.                  // Draw transparent
  4702.                  WORD transMarkClr[4] = { transHitMark, transShadowMark,
  4703.                                           transShadowMark, transHitMark };
  4704.  
  4705.                  for (DWORD v = 0; v != 8; v++) {
  4706.                    PWORD clrVPhase = & transMarkClr[v & 2];
  4707.  
  4708.                    vramT[0] =
  4709.                    vramT[1] = clrVPhase[0];
  4710.                    vramT[2] =
  4711.                    vramT[3] = clrVPhase[1];
  4712.                    vramT[4] =
  4713.                    vramT[5] = clrVPhase[0];
  4714.                    vramT[6] =
  4715.                    vramT[7] = clrVPhase[1];
  4716.  
  4717.                    vramT += vramWrite.Pitch16;
  4718.                  }
  4719.               }
  4720.             } else {
  4721.               // No chr pixel
  4722.               // draw trans
  4723.               WORD transCol;
  4724.  
  4725.               if (cell.pal != NULL)
  4726.                 transCol = CGlobals::nespal[cell.pal->pal[0]];
  4727.               else
  4728.                 transCol = CGlobals::nespal[0x0F];
  4729.  
  4730.               for (auto vec = 0; vec != 8; vec++) {
  4731.                 vramT[0] = transCol;
  4732.                 vramT[1] = transCol;
  4733.                 vramT[2] = transCol;
  4734.                 vramT[3] = transCol;
  4735.                 vramT[4] = transCol;
  4736.                 vramT[5] = transCol;
  4737.                 vramT[6] = transCol;
  4738.                 vramT[7] = transCol;
  4739.  
  4740.                 vramT += vramWrite.Pitch16;
  4741.               }
  4742.             }
  4743.           }
  4744.         }
  4745.  
  4746.         // Draw attr table number shadow
  4747.         if (m_attframe.m_bShowAttrShadow != FALSE) {
  4748.            // Draw attr grid alpha
  4749.           for (auto j= 0; j != szDrawElem.cy; j++) {
  4750.             auto vi = j + ptScrStart.y;
  4751.             auto ntp_vi = vi / 30;
  4752.             auto mod_y = vi % 30;
  4753.             auto vramyT = & vramWrite.pBits[vramWrite.Pitch16 *j<<3];
  4754.             if (vi >= szSizeMax.cy) {
  4755.               break;
  4756.             }
  4757.             for (auto i= 0; i != szDrawElem.cx; i++) {
  4758.               auto hi = i + ptScrStart.x;
  4759.               auto ntp_hi = hi >> 5;
  4760.               auto mod_x = hi & 31;
  4761.               auto vramT = & vramyT[i << 3];
  4762.               if (hi >= szSizeMax.cx) {
  4763.                 break;
  4764.               }
  4765.               // fetch namtpage page
  4766.               CNametableCell<FALSE> &cell = *rFrame.m_ShowMap->ntList[ntp_hi + rFrame.m_ShowMap->width * ntp_vi];
  4767.               // draw tile chunk.
  4768.               if (cell.chr != NULL) {
  4769.              
  4770.                 auto pAttr = attrT;
  4771.  
  4772.                 if (cell.attr != NULL) {
  4773.                   pAttr = cell.attr->attr;
  4774.                 }
  4775.  
  4776.                 BYTE attrBank = pAttr [(mod_x >> 2) + (mod_y >> 2 << 3)];
  4777.                 // calc palette bank
  4778.                 BYTE attrIndex;
  4779.  
  4780.                 if (mod_y & 2)
  4781.                   if (mod_x & 2)
  4782.                     attrIndex = attrBank >> 6 & 3;
  4783.                   else
  4784.                     attrIndex = attrBank >> 4 & 3;
  4785.                 else
  4786.                   if (mod_x & 2)
  4787.                     attrIndex = attrBank >> 2 & 3;
  4788.                   else
  4789.                     attrIndex = attrBank >> 0 & 3;
  4790.  
  4791.                 PWORD attrPtr;
  4792.                 switch (attrIndex) {
  4793.                 case 0: attrPtr = CGlobals::attrFont0_x2; break;
  4794.                 case 1: attrPtr = CGlobals::attrFont1_x2; break;
  4795.                 case 2: attrPtr = CGlobals::attrFont2_x2; break;
  4796.                 case 3: attrPtr = CGlobals::attrFont3_x2; break;
  4797.                 default:
  4798.                   ATLASSERT (FALSE);
  4799.                   break;
  4800.                 }
  4801.                 attrPtr = & attrPtr[ (mod_y & 1) ? 8 * 16 : 0];
  4802.                 attrPtr = & attrPtr[ (mod_x & 1) ? 8  : 0];
  4803.  
  4804.                 for (auto vec = 0; vec != 8; vec++) {
  4805.                    vramT[0] = CGlobals::alpha16 (  attrPtr[0], vramT[0], alphaCnt, 15 - alphaCnt);
  4806.                    vramT[1] = CGlobals::alpha16 (  attrPtr[1], vramT[1], alphaCnt, 15 - alphaCnt);
  4807.                    vramT[2] = CGlobals::alpha16 (  attrPtr[2], vramT[2], alphaCnt, 15 - alphaCnt);
  4808.                    vramT[3] = CGlobals::alpha16 (  attrPtr[3], vramT[3], alphaCnt, 15 - alphaCnt);      
  4809.                    vramT[4] = CGlobals::alpha16 (  attrPtr[4], vramT[4], alphaCnt, 15 - alphaCnt);
  4810.                    vramT[5] = CGlobals::alpha16 (  attrPtr[5], vramT[5], alphaCnt, 15 - alphaCnt);
  4811.                    vramT[6] = CGlobals::alpha16 (  attrPtr[6], vramT[6], alphaCnt, 15 - alphaCnt);
  4812.                    vramT[7] = CGlobals::alpha16 (  attrPtr[7], vramT[7], alphaCnt, 15 - alphaCnt);    
  4813.  
  4814.                   vramT += vramWrite.Pitch16;
  4815.                   attrPtr += 16;
  4816.                 }
  4817.               }
  4818.             }
  4819.           }
  4820.         }
  4821.         // Draw paste infos..
  4822.         // Tracker movse infos...
  4823.         // FIXME: more case.
  4824.         CPoint ptMouse;
  4825.         :: GetCursorPos (& ptMouse);
  4826.         ScreenToClient (& ptMouse);
  4827.  
  4828.         auto &tilePaste = CGlobals::pasteTile;
  4829.         if (CGlobals::pasteAlive () != FALSE
  4830.           && ptMouse.x >= 0
  4831.           && ptMouse.y >= 0) {
  4832.           CSize copySize = tilePaste.copySize;
  4833.           auto &rNametableS = tilePaste.tileSlot;
  4834.           auto &palT = tilePaste.palSlot;
  4835.           auto &attrT = tilePaste.attrSlot;
  4836.           auto &chrT = tilePaste.chr->chr;
  4837.  
  4838.           ptMouse.x >>= 3;
  4839.           ptMouse.y >>= 3;
  4840.           for (auto j = 0; j != copySize.cy; j++)  {
  4841.             for (auto i = 0; i != copySize.cx; i++)  {
  4842.               DWORD x2_pos = i + ptMouse.x << 3;
  4843.               DWORD y2_pos = j + ptMouse.y << 3;
  4844.               DWORD x_pos=  i << 3;
  4845.               DWORD y_pos = j << 3;
  4846.               WORD tileSlot = rNametableS[i+ (j << 5)];
  4847.               PWORD vramT  = & vramWrite.pBits[x2_pos + y2_pos *vramWrite.Pitch16];
  4848.               PBYTE pChrT = tileSlot & 0x8000 ? transTile :  & chrT[(tileSlot & 255) << 4];
  4849.               auto attrByte = attrT[(i >> 2)+(j >> 2<<3)];
  4850.  
  4851.               if (j & 2)
  4852.                 if (i & 2)
  4853.                   attrByte = attrByte >> 6 & 3;
  4854.                 else
  4855.                   attrByte = attrByte >> 4 & 3;
  4856.               else
  4857.                 if (i & 2)
  4858.                   attrByte = attrByte >> 2 & 3;
  4859.                 else
  4860.                   attrByte &= 3;
  4861.  
  4862.               auto pBank = & palT[attrByte << 2];
  4863.  
  4864.               if ((tileSlot & 0x8000) == 0) {
  4865.                 for (DWORD v = 0; v != 8; v++) {
  4866.                   CPolyData64 chr;
  4867.                   chr.blk = CGlobals::chrmixer[pChrT[0]]
  4868.                         | CGlobals::chrmixer[pChrT[8]] << 1;
  4869.  
  4870.                   vramT[0] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[0]]], vramT[0], alphaCnt, 15 - alphaCnt);
  4871.                   vramT[1] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[1]]], vramT[1], alphaCnt, 15 - alphaCnt);
  4872.                   vramT[2] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[2]]], vramT[2], alphaCnt, 15 - alphaCnt);
  4873.                   vramT[3] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[3]]], vramT[3], alphaCnt, 15 - alphaCnt);      
  4874.                   vramT[4] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[4]]], vramT[4], alphaCnt, 15 - alphaCnt);
  4875.                   vramT[5] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[5]]], vramT[5], alphaCnt, 15 - alphaCnt);
  4876.                   vramT[6] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[6]]], vramT[6], alphaCnt, 15 - alphaCnt);
  4877.                   vramT[7] = CGlobals::alpha16 (  rGloablNESPal[pBank[chr.blk8[7]]], vramT[7], alphaCnt, 15 - alphaCnt);      
  4878.  
  4879.                   vramT += vramWrite.Pitch16;
  4880.  
  4881.                   pChrT++;
  4882.                 }
  4883.               }
  4884.             }
  4885.           }
  4886.         }      
  4887.  
  4888.         // Draw grid attr..
  4889.         if (m_attframe.m_bShowGridAttr != FALSE) {
  4890.           CMemoryPaint16::DirectWrite vramOffset = vramWrite;
  4891.           CPoint ptStart = ptScrStart;
  4892.           CSize copySize = szDrawElem;
  4893.  
  4894.           // Check copy align
  4895.           if (copySize.cx & 1) {
  4896.             copySize.cx ++;
  4897.           }
  4898.           if (copySize.cy & 1) {
  4899.             copySize.cy ++;
  4900.           }
  4901.           CSize szCopy ( copySize.cx / 2, copySize.cy / 2);
  4902.           for (auto scanY = 0; scanY != szCopy.cy; scanY++) {
  4903.             for (auto scanX = 0; scanX != szCopy.cx; scanX++) {
  4904.                       CGlobals::drawGrid (vramOffset,
  4905.                 CGlobals::GRID_TYPE_FIXED,
  4906.                 CPoint (scanX << 4, scanY << 4),
  4907.                 CSize (16, 16),
  4908.                 CSize (1, 1),
  4909.                 clrMeshAttr);
  4910.             }
  4911.           }
  4912.         }
  4913.         // Draw grid main...
  4914.         CPoint ptStart = ptScrStart;
  4915.         if (m_attframe.m_bShowGridMain != FALSE) {
  4916.           CSize szCopy = szDrawElem;
  4917.           szCopy.cx = szCopy.cx/ 32 + 1;
  4918.           szCopy.cy = szCopy.cy/ 30 + 1;
  4919.  
  4920.           const WORD mixerClr[] =
  4921.             { CMainFrame::clrMeshMainOne,
  4922.               CMainFrame::clrMeshMainTwo,
  4923.               CMainFrame::clrMeshMainTwo,
  4924.               CMainFrame::clrMeshMainOne };
  4925.  
  4926.           DWORD yRectPos = 0;
  4927.           for (auto scanY = 0; scanY != szCopy.cy; scanY++) {
  4928.             const WORD  *mixerClrY = & mixerClr[ (ptStart.y + yRectPos) / 30 << 1 & 2];
  4929.             DWORD copyYSize;
  4930.             if ( (scanY == 0 || scanY == szCopy.cy - 1)
  4931.             && (ptStart.y % 30) != 0){
  4932.               // first/final check.. do unaign copy.
  4933.               copyYSize = scanY == 0
  4934.                              ? 30 - ptStart.y % 30
  4935.                              : szDrawElem.cy - yRectPos;
  4936.               if (copyYSize > 30) {
  4937.                 copyYSize = 30;
  4938.                 szCopy.cy ++;
  4939.               }
  4940.             } else {
  4941.               copyYSize = 30;
  4942.             }
  4943.             DWORD xRectPos = 0;
  4944.             for (auto scanX = 0; scanX != szCopy.cx; scanX++) {
  4945.               const WORD clrset = mixerClrY[ptStart.x + xRectPos >> 5 & 1];
  4946.               DWORD copyXSize;
  4947.               if ( (scanX == 0 || scanX ==  szCopy.cx - 1)
  4948.               && (ptStart.x % 32) != 0){
  4949.                 // first/final check.. do unaign copy.
  4950.                 copyXSize = scanX == 0
  4951.                                ? 32 - ptStart.x % 32
  4952.                                : szDrawElem.cx - xRectPos;
  4953.                 if (copyXSize > 32) {
  4954.                   copyXSize = 32;
  4955.                   szCopy.cx ++;
  4956.                 }
  4957.               } else {
  4958.                 copyXSize = 32;
  4959.               }
  4960.                       CGlobals::drawGrid (vramWrite,
  4961.                 CGlobals::GRID_TYPE_FIXED,
  4962.                 CPoint (xRectPos << 3, yRectPos << 3),
  4963.                 CSize (copyXSize * 8, copyYSize * 8),
  4964.                 CSize (1, 1),
  4965.                 clrset);
  4966.               xRectPos += copyXSize;
  4967.               if (xRectPos >= szDrawElem.cx) {
  4968.                  break;
  4969.               }
  4970.             }
  4971.             yRectPos += copyYSize;
  4972.               if (yRectPos >= szDrawElem.cy) {
  4973.                  break;
  4974.               }
  4975.           }
  4976.         }
  4977.         // x, y coord push 32 offset
  4978.         // vramWrite.pBits = & vramWrite.pBits[32+vramWrite.Pitch16*32];
  4979.         if (  m_attframe.m_subFunc == 1
  4980.           && m_attframe.m_dwStateAttr != 0)
  4981.         {
  4982.           // Max size
  4983.           // 256 x 240
  4984.           // 128 x 120
  4985.           // 16 x 15
  4986.           CPoint ptStart = m_attframe.  m_ptTrackAttrStart ;
  4987.           CPoint ptEnd = m_attframe. m_ptTrackAttrEnd;
  4988.           CPoint ptScr8 ( ptOffsetAlign.x >> 3, ptOffsetAlign.y >> 3);
  4989.  
  4990.           CGlobals::translateVecPointToltrb (ptStart, ptEnd);
  4991.  
  4992.           ptStart.x >>= 3;
  4993.           ptStart.y >>= 3;
  4994.           ptEnd.x >>= 3;
  4995.           ptEnd.y >>= 3;
  4996.  
  4997.           CMemoryPaint16::DirectWrite vramOffset = vramWrite;
  4998.           CSize copySize;
  4999.  
  5000.           if (ptScr8.x & 1) vramOffset.pBits = vramOffset.pBits - 8;
  5001.           if (ptScr8.y & 1) vramOffset.pBits = vramOffset.pBits - 8 * vramOffset.Pitch16;
  5002.           if (ptStart.x & 1) ptStart.x &= ~1;
  5003.           if (ptStart.y & 1) ptStart.y &= ~1;
  5004.           if (ptEnd.x & 1) ptEnd.x &= ~1;
  5005.           if (ptEnd.y & 1) ptEnd.y &= ~1;
  5006.  
  5007.           copySize.cx = ptEnd.x - ptStart.x  + 2<< 3;
  5008.           copySize.cy = ptEnd.y - ptStart.y  + 2<< 3;
  5009.  
  5010.           if ( copySize.cx > 256)
  5011.             copySize.cx = 256;
  5012.           if ( copySize.cy > 240)
  5013.             copySize.cy = 240;
  5014.           if ( copySize.cx == 0)
  5015.             copySize.cx = 16;
  5016.           if ( copySize.cy == 0)
  5017.             copySize.cy = 16;
  5018.  
  5019.           CGlobals::drawGrid (vramOffset,
  5020.     CGlobals::GRID_TYPE_FIXED,
  5021.     CPoint (ptStart.x << 3, ptStart.y << 3) ,
  5022.     copySize,
  5023.     CSize (1, 1),
  5024.     m_attframe.m_dwStateAttr & 0x8000
  5025.         ? CMainFrame::clrMeshCatching
  5026.         : CMainFrame::clrMeshSet);  
  5027.         }
  5028.       } else {
  5029.         // fill clear color .....
  5030.         CMemoryPaint16::fillColor (vramWrite,
  5031.            CPoint (0, 0),
  5032.            rcClient.Size (), 0);
  5033.       }
  5034.       LPDIRECT3DSURFACE9 vsurf;
  5035.  
  5036.       sig = rFrame.m_Direct3D9Deivce->Clear (0, NULL, D3DCLEAR_TARGET, 0, 0.0, 0);
  5037.       ATLASSERT (SUCCEEDED (sig));
  5038.  
  5039.       sig = rFrame.m_Direct3D9Deivce->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, & vsurf);
  5040.       ATLASSERT (SUCCEEDED (sig));
  5041.  
  5042.       sig = rFrame.m_Direct3D9Surface->UnlockRect ();
  5043.       ATLASSERT (SUCCEEDED (sig));
  5044.  
  5045.       sig = rFrame.m_Direct3D9Deivce->UpdateSurface (rFrame.m_Direct3D9Surface,
  5046.                        & CRect (0, 0, szDrawElem.cx << 3, szDrawElem.cy << 3),
  5047.                        vsurf,
  5048.                        & CPoint (0, 0));
  5049.       ATLASSERT (SUCCEEDED (sig));
  5050.  
  5051.       sig = vsurf->Release ();
  5052.       ATLASSERT (SUCCEEDED (sig));
  5053.  
  5054.       // Copy rect to vram...
  5055.       // FIXME: Maybe the device will be lost when other programs are using the full screen Direct3D program
  5056.       sig = rFrame.m_Direct3D9Deivce->Present (
  5057.                      & CRect (0, 0, rcClient.Width (), rcClient.Height ()),
  5058.                      & CRect (0, 0, rcClient.Width (), rcClient.Height ()), NULL, NULL);
  5059.       ATLASSERT (SUCCEEDED (sig));
  5060.     }
  5061.  
  5062.     VOID DoPaint(CDCHandle dc)
  5063.     {
  5064.      // must be implemented in a derived class
  5065.      // ATLASSERT(FALSE);
  5066.        // int is = 0;
  5067.       nesPixelGenerator ();
  5068.     }
  5069.     LRESULT OnPaint (UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) {
  5070.       :: ValidateRect (*this, NULL);
  5071.       nesPixelGenerator ();
  5072.       bHandled = TRUE;
  5073.       return 0;
  5074.     }
  5075.  
  5076.     LRESULT OnLButtonDbclk (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
  5077.       CPoint pt (GET_X_LPARAM(lParam),
  5078.                          GET_Y_LPARAM(lParam));
  5079.       // Show spec page window.
  5080.  
  5081.       bHandled = FALSE;
  5082.       return 0;
  5083.     }
  5084.     LRESULT OnLButtonUp (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
  5085.             CPoint pt (GET_X_LPARAM(lParam),
  5086.                          GET_Y_LPARAM(lParam));
  5087.             if (m_attframe.m_subFunc == 1
  5088.         && (m_attframe.m_dwStateAttr & 0x8001 ) == 0x8001) {
  5089.           m_attframe.m_dwStateAttr &= ~0x8000;
  5090.         m_attframe.   m_ptTrackAttrEnd.x =  pt.x ;
  5091.           m_attframe.  m_ptTrackAttrEnd.y =  pt.y ;
  5092.  
  5093.       }
  5094.             nesPixelGenerator ();
  5095.  
  5096.       bHandled = FALSE;
  5097.       return 0;
  5098.     }
  5099.  
  5100.     LRESULT OnLButtonDown (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
  5101.       bHandled = FALSE;
  5102.       CPoint pt (GET_X_LPARAM(lParam),
  5103.                          GET_Y_LPARAM(lParam));
  5104.  
  5105.       CRect rcClient;
  5106.       CMainFrame &rFrame = m_attframe;
  5107.       CPoint ptPastePoint (pt);
  5108.       CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5109.       BOOL ret = GetClientRect (rcClient);
  5110.       ATLASSERT (ret != FALSE);
  5111.       CSize szDrawElem  (rcClient.Width () >> 3, rcClient.Height () >> 3);
  5112.  
  5113.       if (m_attframe.m_subFunc == 0
  5114.         && CGlobals::pasteAlive () != FALSE
  5115.         && CGlobals::pasteTile.chr != NULL
  5116.         && m_attframe.m_ShowMap != NULL
  5117.          && ptPastePoint.x < rFrame.m_ShowMap->width * 256
  5118.         && ptPastePoint.y < rFrame.m_ShowMap->height * 240
  5119.          && ptScrStart.x < rFrame.m_ShowMap->width * 256
  5120.         && ptScrStart.y < rFrame.m_ShowMap->height * 240) {
  5121.         // Paste/ edit.
  5122.        // overwrite tile id, natadssa
  5123.  
  5124.         CSize szSizeMax (rFrame.m_ShowMap->width << 5, rFrame.m_ShowMap->height * 30);
  5125.         CSize scanVec (CGlobals::pasteTile.copySize);
  5126.         CPoint ptScroll (ptScrStart.x >> 3, ptScrStart.y >> 3);
  5127.         CPoint ptPaste (GET_X_LPARAM(lParam) >> 3, GET_Y_LPARAM(lParam) >> 3);
  5128.         //  Scroll + paste point .
  5129.         CPoint ptOffsetCorrentBaseT = ptScroll + ptPaste;
  5130.  
  5131.         if (ptOffsetCorrentBaseT.x + scanVec.cx > szSizeMax.cx)
  5132.           scanVec.cx = szSizeMax.cx - ptOffsetCorrentBaseT.x;
  5133.         if (ptOffsetCorrentBaseT.y + scanVec.cy > szSizeMax.cy)
  5134.           scanVec.cy = szSizeMax.cy - ptOffsetCorrentBaseT.y;
  5135.         if (ptOffsetCorrentBaseT.x < szSizeMax.cx
  5136.           && ptOffsetCorrentBaseT.y < szSizeMax.cy)
  5137.         {
  5138.           auto &srcTile = CGlobals::pasteTile;
  5139.  
  5140.           // Adjust attr and tile id
  5141.           for (auto j = 0; j != scanVec.cy; j++) {
  5142.             auto vi = j + ptOffsetCorrentBaseT.y;
  5143.             auto ntp_vi = vi / 30;
  5144.             auto mod_y = vi % 30;
  5145.  
  5146.             for (auto i = 0; i != scanVec.cx; i++) {
  5147.               auto hi = i + ptOffsetCorrentBaseT.x;
  5148.               auto ntp_hi = hi >> 5;
  5149.               auto mod_x = hi & 31;
  5150.  
  5151.               // fetch namtpage page
  5152.               CNametableCell<FALSE> &cell = *rFrame.m_ShowMap->ntList[ntp_hi + rFrame.m_ShowMap->width * ntp_vi];
  5153.  
  5154.               WORD dstTileId = srcTile.tileSlot[(j << 5) + i];
  5155.               if ((dstTileId & 0x8000) == 0) {
  5156.                 cell.tileSlot[(mod_y << 5) + mod_x] = dstTileId;
  5157.  
  5158.                 if (srcTile.hackAttr != FALSE
  5159.                   && cell.attr != NULL)
  5160.                 {
  5161.                   BYTE srcAttr = srcTile.attrSlot[(i>>2) + (j>>2<<3)];
  5162.                   PBYTE dstAttr = & cell.attr->attr[(mod_x>>2) + (mod_y>>2<<3)];
  5163.  
  5164.                   if (j & 2)
  5165.                     if (i& 2) srcAttr = srcAttr >> 6 & 3;
  5166.                     else srcAttr = srcAttr >> 4 & 3;
  5167.                   else
  5168.                     if (i& 2)srcAttr = srcAttr >> 2 & 3;
  5169.                     else srcAttr = srcAttr >> 0 & 3;
  5170.  
  5171.                   if (mod_y & 2)
  5172.                     if (mod_x& 2) dstAttr[0] = dstAttr[0] & ~0xC0 | srcAttr << 6;
  5173.                     else dstAttr[0] = dstAttr[0] & ~0x30 | srcAttr << 4;
  5174.                   else
  5175.                     if (mod_x& 2)dstAttr[0] = dstAttr[0] & ~0x0C | srcAttr << 2;
  5176.                     else dstAttr[0] = dstAttr[0] & ~0x03 | srcAttr << 0;
  5177.                 }
  5178.               }
  5179.               if (srcTile.hackPal != FALSE
  5180.                 && cell.pal != NULL)
  5181.               {
  5182.                  // TODO: more copy ..
  5183.                 RtlCopyMemory (cell.pal->pal, srcTile.palSlot,  sizeof (cell.pal->pal));
  5184.               }
  5185.             }
  5186.           }
  5187.         }
  5188.       } else if (m_attframe.m_subFunc == 1) {
  5189.         // Attr edit
  5190.         m_attframe.  m_ptTrackAttrStart.x =  pt.x ;
  5191.         m_attframe. m_ptTrackAttrStart.y =  pt.y ;
  5192.  
  5193.         m_attframe. m_ptTrackAttrEnd = m_attframe. m_ptTrackAttrStart;
  5194.         m_attframe. m_dwStateAttr = 0x8000 | 1;
  5195.       } else if (m_attframe.m_subFunc == 2) {
  5196.       }
  5197.       nesPixelGenerator ();
  5198.       SetFocus ();
  5199.       return 0;
  5200.     }
  5201.     LRESULT OnRButtonDbclk (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
  5202.       CPoint pt (GET_X_LPARAM(lParam),
  5203.                          GET_Y_LPARAM(lParam));
  5204.       // Show spec page window.
  5205.       CRect rcClient;
  5206.       CMainFrame &rFrame = m_attframe;
  5207.       CPoint ptPastePoint (pt);
  5208.       CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5209.       BOOL ret = GetClientRect (rcClient);
  5210.       ATLASSERT (ret != FALSE);
  5211.       CSize szDrawElem  (rcClient.Width () >> 3, rcClient.Height () >> 3);
  5212.  
  5213.       if (m_attframe.m_subFunc == 0
  5214.         && m_attframe.m_ShowMap != NULL
  5215.         && rcClient.Width () > 0
  5216.         && rcClient.Height () > 0
  5217.         && m_attframe.m_GuiLV_Page.GetItemCount () > 0
  5218.          && ptPastePoint.x < rFrame.m_ShowMap->width * 256
  5219.         && ptPastePoint.y < rFrame.m_ShowMap->height * 240) {
  5220.         // Paste/ edit.
  5221.        // overwrite tile id, natadssa
  5222.  
  5223.         CSize szSizeMax (rFrame.m_ShowMap->width << 5, rFrame.m_ShowMap->height * 30);
  5224.         CSize scanVec (CGlobals::pasteTile.copySize);
  5225.         CPoint ptScroll (ptScrStart.x >> 3, ptScrStart.y >> 3);
  5226.         CPoint ptPaste (GET_X_LPARAM(lParam) >> 3, GET_Y_LPARAM(lParam) >> 3);
  5227.         //  Scroll + paste point .
  5228.         CPoint ptOffsetCorrentBaseT = ptScroll + ptPaste;
  5229.  
  5230.         if (ptOffsetCorrentBaseT.x < szSizeMax.cx
  5231.           && ptOffsetCorrentBaseT.y < szSizeMax.cy)
  5232.         {
  5233.           auto v = ptOffsetCorrentBaseT.y / 30;
  5234.           auto h = ptOffsetCorrentBaseT.x / 32;
  5235.  
  5236.           // fetch namtpage page
  5237.           CNametableCell<FALSE> *nt_cell = rFrame.m_ShowMap->ntList[h + rFrame.m_ShowMap->width * v];
  5238.           ATLASSERT (nt_cell != NULL);
  5239.  
  5240.           m_attframe.  tryAddNtpWindow (nt_cell).
  5241.                 SetWindowTextFT (_T ("%s-%s"), nt_cell->comment, nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5242.  
  5243.             }
  5244.       } else if (m_attframe.m_subFunc == 1) {
  5245.         // Attr edit
  5246.       } else if (m_attframe.m_subFunc == 2) {
  5247.       }
  5248.       bHandled = FALSE;
  5249.       return 0;
  5250.     }
  5251.     LRESULT OnRButtonUp (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5252.       if (CGlobals::pasteAlive ()  != FALSE) {
  5253.         CGlobals::makePasteDead ();
  5254.       }
  5255.                   if (m_attframe.m_subFunc == 1
  5256.         && (m_attframe.m_dwStateAttr & 0x8001 ) == 0x0001) {
  5257.           // Adjust attr table vector .
  5258.                 CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5259.                
  5260.           CPoint ptStart ( (m_attframe.  m_ptTrackAttrStart.x & ~7)+ (ptScrStart.x & ~7) >> 4 << 1,
  5261.                                       (m_attframe.  m_ptTrackAttrStart.y & ~7)+ (ptScrStart.y & ~7) >> 4 << 1);
  5262.  
  5263.           CPoint ptEnd ( (m_attframe.  m_ptTrackAttrEnd.x & ~7)+ (ptScrStart.x & ~7) >> 4 << 1,
  5264.                                       (m_attframe.  m_ptTrackAttrEnd.y & ~7)+ (ptScrStart.y & ~7) >> 4 << 1);
  5265.  
  5266.           CGlobals::
  5267.           translateVecPointToltrbLimitRange
  5268.              ( ptStart, ptEnd, CSize (31, 29));
  5269.  
  5270.  
  5271.           m_attframe.adjustAttrVecBaseNtAddress<TRUE>
  5272.               (m_attframe.m_ShowMap, ptStart, ptEnd, 1);
  5273.           m_attframe.allViewUpdate ();
  5274.       }
  5275.  
  5276.  
  5277.       bHandled = FALSE;
  5278.       return 0;
  5279.     }
  5280.     LRESULT OnRButtonDown (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5281.       bHandled = FALSE;
  5282.       return 0;
  5283.     }
  5284.     LRESULT OnMouseMove (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
  5285.       CPoint pt (GET_X_LPARAM(lParam),
  5286.                          GET_Y_LPARAM(lParam));
  5287.       CRect rcClient;
  5288.  
  5289.       BOOL ret = GetClientRect (rcClient);
  5290.       ATLASSERT (ret != FALSE);
  5291.  
  5292.       if (rcClient.Width () >= 0
  5293.         && rcClient.Height () >= 0
  5294.         && m_attframe.m_ShowMap != 0
  5295.         /* && CGlobals::bLockPaste != FALSE */ )
  5296.       {
  5297.         CSize szDrawElem  (rcClient.Width ()/ 8, rcClient.Height ()/ 8);
  5298.         CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5299.         CSize szSizeMax (m_attframe.m_ShowMap->width * 32, m_attframe.m_ShowMap->height * 30);
  5300.  
  5301.         m_attframe.m_ptPastePoint.x = pt.x / 8;
  5302.         m_attframe.m_ptPastePoint.y = pt.y / 8;
  5303.       }
  5304.       if (m_attframe.m_subFunc == 1
  5305.         && (m_attframe.m_dwStateAttr & 0x8001 ) == 0x8001) {
  5306.         m_attframe.   m_ptTrackAttrEnd.x =  pt.x ;
  5307.           m_attframe.  m_ptTrackAttrEnd.y =  pt.y ;
  5308.  
  5309.       }
  5310.       CPoint ptStart = pt + m_ptOffset ;
  5311.  
  5312.       m_attframe.setStatusText (1, _T ("page-%d, %d index- %d, %d")
  5313.               , ptStart.x / 256, ptStart.y / 240
  5314.               , ptStart.x % 256 >> 3
  5315.               , ptStart.y % 240 >> 3);
  5316.              
  5317.       nesPixelGenerator ();
  5318.       bHandled = FALSE;
  5319.       return 0;
  5320.     }
  5321.     LRESULT OnKeyUp (UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) {
  5322.       switch (wParam) {
  5323.       case 96:
  5324.       case 97:
  5325.       case 98:
  5326.       case 99:
  5327.       case '0':
  5328.       case '1':
  5329.       case '2':
  5330.       case '3':
  5331.           if (   m_attframe. m_subFunc == 1
  5332.           && (m_attframe.m_dwStateAttr & 0x7FFF) != 0)
  5333.           {
  5334.                 CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5335.                     CPoint ptStart ( (m_attframe.  m_ptTrackAttrStart.x & ~7)+ (ptScrStart.x & ~7) >> 4 << 1,
  5336.                                       (m_attframe.  m_ptTrackAttrStart.y & ~7)+ (ptScrStart.y & ~7) >> 4 << 1);
  5337.  
  5338.           CPoint ptEnd ( (m_attframe.  m_ptTrackAttrEnd.x & ~7)+ (ptScrStart.x & ~7) >> 4 << 1,
  5339.                                       (m_attframe.  m_ptTrackAttrEnd.y & ~7)+ (ptScrStart.y & ~7) >> 4 << 1);
  5340.           CGlobals::
  5341.           translateVecPointToltrbLimitRange
  5342.              ( ptStart, ptEnd, CSize (31, 29));
  5343.  
  5344.           m_attframe.adjustAttrVecBaseNtAddress<FALSE>
  5345.               (m_attframe.m_ShowMap, ptStart, ptEnd,  (wParam >= 96 && wParam <= 99)
  5346.                                  ? (wParam - 96 & 3)
  5347.                       : (wParam - '0' & 3));
  5348.           m_attframe.allViewUpdate ();
  5349.           }
  5350.           break;
  5351.       case 'M':
  5352.         m_attframe.m_bShowAttrShadow = ! m_attframe.m_bShowAttrShadow;
  5353.         nesPixelGenerator ();
  5354.         break;
  5355.  
  5356.       case VK_RETURN:
  5357.         {
  5358.           m_attframe.m_subFunc ++;
  5359.           m_attframe.m_subFunc %= 2;
  5360.  
  5361.           m_attframe.m_dwStateAttr = 0;
  5362.           m_attframe.m_dwStateChr = 0;
  5363.           m_attframe.m_dwStateRorate = 0;
  5364.          
  5365.           if (m_attframe.m_subFunc == 0) {
  5366.             m_attframe.setStatusText (0, CString (_T ("map:paste mode")));
  5367.           } else {
  5368.             m_attframe.setStatusText (0, CString (_T ("map:attr mode")));
  5369.           }
  5370.           nesPixelGenerator ();
  5371.         }
  5372.         break;
  5373.  
  5374.       case ' ':
  5375.         {
  5376.       CPoint pt ;
  5377.       GetCursorPos (& pt);
  5378.       ScreenToClient (& pt);
  5379.       pt.x = abs (pt.x);
  5380.       pt.y = abs (pt.y);
  5381.  
  5382.       // Show spec page window.
  5383.       CRect rcClient;
  5384.       CMainFrame &rFrame = m_attframe;
  5385.       CPoint ptPastePoint (pt);
  5386.       CPoint ptScrStart (m_ptOffset.x & ~0x0F, m_ptOffset.y & ~0x0F);
  5387.      
  5388.       BOOL ret = GetClientRect (rcClient);
  5389.       ATLASSERT (ret != FALSE);
  5390.       CSize szDrawElem  (rcClient.Width () >> 3, rcClient.Height () >> 3);
  5391.  
  5392.       if (m_attframe.m_ShowMap != NULL
  5393.         && rcClient.Width () > 0
  5394.         && rcClient.Height () > 0
  5395.         && m_attframe.m_GuiLV_Page.GetItemCount () > 0
  5396.          && ptPastePoint.x < rFrame.m_ShowMap->width * 256
  5397.         && ptPastePoint.y < rFrame.m_ShowMap->height * 240) {
  5398.         // Paste/ edit.
  5399.        // overwrite tile id, natadssa
  5400.  
  5401.         CSize szSizeMax (rFrame.m_ShowMap->width << 5, rFrame.m_ShowMap->height * 30);
  5402.         CSize scanVec (CGlobals::pasteTile.copySize);
  5403.         CPoint ptScroll (ptScrStart.x >> 3, ptScrStart.y >> 3);
  5404.         CPoint ptPaste (ptPastePoint.x >> 3, ptPastePoint.y >> 3);
  5405.         //  Scroll + paste point .
  5406.         CPoint ptOffsetCorrentBaseT = ptScroll + ptPaste;
  5407.  
  5408.         if (ptOffsetCorrentBaseT.x < szSizeMax.cx
  5409.           && ptOffsetCorrentBaseT.y < szSizeMax.cy)
  5410.         {
  5411.           auto v = ptOffsetCorrentBaseT.y / 30;
  5412.           auto h = ptOffsetCorrentBaseT.x / 32;
  5413.  
  5414.           // fetch namtpage page
  5415.           CNametableCell<FALSE> *nt_cell = rFrame.m_ShowMap->ntList[h + rFrame.m_ShowMap->width * v];
  5416.           ATLASSERT (nt_cell != NULL);
  5417.  
  5418.                     auto &r = m_attframe.  tryAddNtpWindow (nt_cell);
  5419.  
  5420.           r.SetWindowTextFT (_T ("%s-%s"), nt_cell->comment, nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5421.             }
  5422.       }
  5423.         }
  5424.         break;
  5425.       case 'Q':
  5426.         m_attframe.m_bShowGridMain = !m_attframe.m_bShowGridMain;
  5427.         nesPixelGenerator ();
  5428.         break;
  5429.       case 'Z':
  5430.         m_attframe.m_bShowGridAttr = !m_attframe.m_bShowGridAttr;
  5431.         nesPixelGenerator ();
  5432.       default:
  5433.         break;
  5434.       }
  5435.       bHandled = FALSE;
  5436.       return 0;
  5437.     }
  5438.     DECLARE_WND_CLASS (_T ("CNesmapGenerator"))
  5439.  
  5440.     BEGIN_MSG_MAP(thisClass)
  5441.       MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDbclk)
  5442.       MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUp)
  5443.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDown)
  5444.       MESSAGE_HANDLER (WM_RBUTTONDBLCLK, OnRButtonDbclk)
  5445.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUp)
  5446.       MESSAGE_HANDLER (WM_RBUTTONDOWN, OnRButtonDown)
  5447.       MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMove)
  5448.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUp)
  5449.       // MESSAGE_HANDLER (WM_PAINT, OnPaint)
  5450.       CHAIN_MSG_MAP(baseClass)
  5451.     END_MSG_MAP()
  5452.  
  5453.   } m_GuiSWin_Nesmap;
  5454.  
  5455.   // <CClaySettings> =========================================
  5456.   struct CClaySettings : public CDialogImpl<CClaySettings>
  5457.   {
  5458.     typedef CClaySettings thisClass;
  5459.     typedef CDialogImpl<CClaySettings> baseClass;
  5460.  
  5461.     CMainFrame &m_attchthis;
  5462.     CNametableCell<TRUE> *m_attachcell;
  5463.  
  5464.     CClaySettings (CMainFrame &atthis):
  5465.       m_attchthis (atthis),
  5466.       m_attachcell (NULL) {}
  5467.  
  5468.     enum { IDD = IDD_CLAY_LIST_SETTINGS };
  5469.  
  5470.     BEGIN_MSG_MAP(thisClass)
  5471.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  5472.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  5473.       COMMAND_ID_HANDLER (IDBT_CLAY_RESET, OnSet)
  5474.     END_MSG_MAP()
  5475.  
  5476.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5477.       bHandled = FALSE;
  5478.       EndDialog (IDCANCEL);
  5479.  
  5480.       return 0;
  5481.     }
  5482.  
  5483.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5484.    
  5485.       if (m_attachcell != NULL) {
  5486.          // Fill current pal infos.
  5487.         CWindowFT (GetDlgItem (IDET_CLAYCOMMENT))
  5488.           .SetWindowTextFT  (m_attachcell->comment);
  5489.       }
  5490.    
  5491.       bHandled = FALSE;
  5492.        return 0;
  5493.     }
  5494.  
  5495.     LRESULT OnSet (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  5496.  
  5497.       CEdit etComment = GetDlgItem (IDET_CLAYCOMMENT);
  5498.       CString content;
  5499.  
  5500.       BOOL bpushNewItem = m_attachcell == NULL;
  5501.  
  5502.       if (bpushNewItem != FALSE) {
  5503.         m_attachcell = new CNametableCell<TRUE> (  
  5504.                       m_attchthis.m_globalPal
  5505.                       ,  m_attchthis.m_globalPal);
  5506.       }
  5507.    
  5508.       etComment    .GetWindowText (content);
  5509.       m_attachcell->comment = content;
  5510.  
  5511.       CGlobals::adjustCommentUnique<CNametableCell<TRUE>> (m_attchthis.m_VnpVec, m_attachcell, bpushNewItem);
  5512.       EndDialog (IDOK);
  5513.  
  5514.       bHandled = FALSE;
  5515.       return 0;
  5516.     }
  5517.  
  5518.     INT_PTR DoModal ( CNametableCell<TRUE> *nt_cell = NULL)
  5519.     {
  5520.       m_attachcell = nt_cell;
  5521.  
  5522.       // Modal it.
  5523.       return baseClass::DoModal ();
  5524.     }
  5525.   };
  5526.   // <CMainFrame::CMapSettings Start> =========================================
  5527.   struct CMapSettings : public CDialogImpl<CMapSettings>
  5528.   {
  5529.     typedef CMapSettings thisClass;
  5530.     typedef CDialogImpl<CMapSettings> baseClass;
  5531.  
  5532.     CEditT<CWindowFT> m_GuiET_ReqW;
  5533.     CEditT<CWindowFT> m_GuiET_ReqH;
  5534.     CButtonT<CWindowFT> m_GuiBT_Cleardata;
  5535.     CEditT<CWindowFT> m_GuiET_Fillid;
  5536.     CEditT<CWindowFT> m_GuiET_Comment;
  5537.     CButtonT<CWindowFT> m_GuiBT_Settings;
  5538.  
  5539.     CMainFrame &m_attthis;
  5540.     CMapUnit *m_newmap;
  5541.  
  5542.     CMapSettings (CMainFrame &psthis):
  5543.         m_attthis (psthis),
  5544.         m_newmap (NULL) {}
  5545.  
  5546.     enum { IDD = IDD_NAMETABLE_PAGE_SETTINGS };
  5547.  
  5548.     BEGIN_MSG_MAP(thisClass)
  5549.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  5550.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  5551.       COMMAND_ID_HANDLER (IDET_NTS_SETTINGS, OnSet)
  5552.     END_MSG_MAP()
  5553.  
  5554.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5555.       bHandled = FALSE;
  5556.       EndDialog (IDCANCEL);
  5557.  
  5558.       return 0;
  5559.     }
  5560.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  5561.  
  5562.       m_GuiET_ReqW.Attach (GetDlgItem (IDET_NTS_WSIZE));
  5563.       m_GuiET_ReqH.Attach (GetDlgItem (IDET_NTS_HSIZE));
  5564.       m_GuiBT_Cleardata.Attach (GetDlgItem (IDCK_NTS_CLEARDATA));
  5565.       m_GuiET_Fillid.Attach (GetDlgItem (IDET_NTS_FILL));
  5566.       m_GuiET_Comment.Attach (GetDlgItem (IDET_NTS_COMMENT));
  5567.       m_GuiBT_Settings.Attach (GetDlgItem (IDET_NTS_SETTINGS));
  5568.  
  5569.       if (m_newmap != NULL) {
  5570.          // Fill current pal infos.
  5571.       //  etComment.SetWindowText (m_newmap->comment);
  5572.          m_GuiET_ReqW.SetWindowTextFT (_T ("%d"), m_newmap->width);
  5573.          m_GuiET_ReqH.SetWindowTextFT (_T ("%d"), m_newmap->height);
  5574.          m_GuiET_Fillid.SetWindowTextFT (_T ("8000"));
  5575.          m_GuiET_Comment.SetWindowTextFT (m_newmap->comment);
  5576.       }
  5577.       bHandled = FALSE;
  5578.        return 0;
  5579.     }
  5580.  
  5581.     LRESULT OnSet (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  5582.  
  5583.       // Get dialog pos infos.
  5584.       CString string;
  5585.  
  5586.       auto req_w = GetDlgItemInt (IDET_NTS_WSIZE, NULL, FALSE);
  5587.       auto req_h = GetDlgItemInt (IDET_NTS_HSIZE, NULL, FALSE);
  5588.       BOOL clear = m_GuiBT_Cleardata.GetCheck () == BST_CHECKED;
  5589.       BOOL bpushnewItem  = m_newmap == NULL;
  5590.       m_GuiET_Fillid.GetWindowText (string);
  5591.  
  5592.       WORD fillId = _tcstol (string.GetString (), NULL, 16) & 0xFFFF;
  5593.  
  5594.       if (req_w == 0
  5595.         || req_h == 0)
  5596.       {
  5597.          AtlMessageBox (NULL, _T ("Request w | h := 0!"), _T ("Map settings"), MB_ICONERROR);
  5598.          return 0;
  5599.       }
  5600. #if 1
  5601.       if (req_w > 64
  5602.         || req_h > 64)
  5603.       {
  5604.          AtlMessageBox (NULL, _T ("Request w | h > 64!"), _T ("Map settings"), MB_ICONERROR);
  5605.          return 0;
  5606.       }
  5607. #endif
  5608.  
  5609.       if (bpushnewItem != FALSE
  5610.         && m_newmap == NULL)
  5611.       {
  5612.          m_newmap= new CMapUnit (m_attthis.m_globalPal);
  5613.       }
  5614.       // reset map.
  5615.       m_GuiET_Comment.  GetWindowText (m_newmap->comment);
  5616.       m_newmap->resetMap (req_w, req_h,
  5617.                      clear, fillId);
  5618.  
  5619.       CGlobals::adjustCommentUnique
  5620.                (m_attthis.m_MapVec,
  5621.                  m_newmap,
  5622.                  bpushnewItem);
  5623.  
  5624.       EndDialog (IDOK);
  5625.  
  5626.       bHandled = FALSE;
  5627.       return 0;
  5628.     }
  5629.  
  5630.     INT_PTR DoModal (CMapUnit *map = NULL)
  5631.     {
  5632.       m_newmap = map;
  5633.  
  5634.       // Modal it.
  5635.       return baseClass::DoModal ();
  5636.     }
  5637.   };
  5638.  
  5639.   template <DWORD t_dwControlId>
  5640.   LRESULT OnLButtonDblclk (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  5641.     switch (t_dwControlId) {
  5642.     case MAP_CONTROL_LV_CLAY:
  5643.       {
  5644.         // Process default message first
  5645.         m_GuiLV_Clay.DefWindowProc (uMsg, wParam, lParam);
  5646.  
  5647.         int itemSel = m_GuiLV_Clay.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
  5648.  
  5649.         if (itemSel >= 0) {
  5650.           auto nt_cell = m_GuiLV_Clay.GetItemDataT (itemSel);
  5651.           if (nt_cell != NULL) {
  5652.  
  5653.             tryAddClayWindow (nt_cell).
  5654.               SetWindowTextFT (_T ("%s-%s"),
  5655.                        m_GuiLV_Clay.GetItemTextAMC (itemSel, 0),
  5656.                                    nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5657.           }
  5658.         }
  5659.       }
  5660.       break;
  5661.     case MAP_CONTROL_LV_PAGE:
  5662.       {
  5663.         // Process default message first
  5664.        
  5665.         m_GuiLV_Page.DefWindowProc (uMsg, wParam, lParam);
  5666.  
  5667.         int itemSel = m_GuiLV_Page.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
  5668.  
  5669.         if (itemSel >= 0) {
  5670.           auto nt_cell = m_GuiLV_Page.GetItemDataT (itemSel);
  5671.           if (nt_cell != NULL) {
  5672.  
  5673.             tryAddNtpWindow (nt_cell).
  5674.               SetWindowTextFT (_T ("%s-%s"),
  5675.                        m_GuiLV_Page.GetItemTextAMC (itemSel, 0),
  5676.                                    nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5677.           }
  5678.         }
  5679.       }
  5680.     default:
  5681.       break;
  5682.     }
  5683.     return 0;
  5684.   }
  5685.   template <DWORD t_dwControlId>
  5686.   LRESULT OnRButtonDownT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  5687.     CPoint pt (GET_X_LPARAM(lParam),
  5688.                        GET_Y_LPARAM(lParam));
  5689.     switch (t_dwControlId) {
  5690.     // case MAP_CONTROL_LV_MAP:
  5691.     case MAP_CONTROL_LV_PAGE:
  5692.       if (m_GuiLV_Page.GetNextItem (-1, LVNI_SELECTED) >= 0) {
  5693.         bHandled = TRUE;
  5694.  
  5695.         m_GuiLV_Page.ClientToScreen (& pt);  
  5696.  
  5697.         m_GuiMenu_MapAttach.EnableMenuItem (ID_SETPAGE_SPAL, MF_ENABLED  | MF_BYCOMMAND);
  5698.         m_GuiMenu_MapAttach.TrackPopupMenu (0, pt.x, pt.y, m_GuiLV_Page);
  5699.       }
  5700.       break;
  5701.     case MAP_CONTROL_LV_CLAY:
  5702.       if (m_GuiLV_Clay.GetNextItem (-1, LVNI_SELECTED) >= 0) {
  5703.         bHandled = TRUE;
  5704.  
  5705.         m_GuiLV_Clay.ClientToScreen (& pt);  
  5706.  
  5707.         m_GuiMenu_MapAttach.EnableMenuItem (ID_SETPAGE_SPAL, MF_GRAYED | MF_BYCOMMAND);
  5708.         m_GuiMenu_MapAttach.TrackPopupMenu (0, pt.x, pt.y, m_GuiLV_Clay);
  5709.       }
  5710.     default:
  5711.       break;
  5712.     }
  5713.     return 0;
  5714.   }
  5715.   template <DWORD t_dwControlId>
  5716.   LRESULT OnRButtonUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  5717.     CPoint pt (GET_X_LPARAM(lParam),
  5718.                        GET_Y_LPARAM(lParam));
  5719.     switch (t_dwControlId) {
  5720.     // case MAP_CONTROL_LV_MAP:
  5721.     case MAP_CONTROL_LV_PAGE:
  5722.       bHandled = TRUE;
  5723.     default:
  5724.       break;
  5725.     }
  5726.     return 0;
  5727.   }
  5728.   template <DWORD t_dwControlId>
  5729.   LRESULT OnLButtonDownT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  5730.     switch (t_dwControlId) {
  5731.     case MAP_CONTROL_LV_MAP:
  5732.       {
  5733.       // Process default message first
  5734.       m_GuiLV_Map.DefWindowProc (uMsg, wParam, lParam);
  5735.  
  5736.       auto index = m_GuiLV_Map.GetSelectedIndex ();
  5737.       auto *poldname =m_ShowMap;
  5738.       // m_GuiLV_PalList.Pro
  5739.       if (index >= 0) {
  5740.         CMapUnit *map = (CMapUnit *) m_GuiLV_Map.GetItemData (index);
  5741.         if (map != NULL) {
  5742.           m_ShowMap = map;
  5743.           // Destroy all namepage list-view's sub item
  5744.           m_GuiLV_Page.DeleteAllItems ();
  5745.        
  5746.           for (auto j = 0; j != map->height; j++) {
  5747.             for (auto i = 0; i != map->width; i++) {
  5748.               const auto it  = j*map->width+i;
  5749.               auto nt = map->ntList[it];
  5750.  
  5751.               nt->comment.Format (_T ("%d-%d"),  j, i);
  5752.               m_GuiLV_Page.InsertItem (it, nt->comment, 0);
  5753.               m_GuiLV_Page.SetItemData (it, reinterpret_cast  <DWORD_PTR> ( nt));
  5754.               /*
  5755.                 BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
  5756.         int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
  5757.     */
  5758.               m_GuiLV_Page.SetItem (it, 1, LVIF_IMAGE | LVIF_TEXT, nt->chr ? nt->chr->comment : _T ("null"), 1, 0, 0, 0);
  5759.               m_GuiLV_Page.SetItem (it, 2, LVIF_IMAGE | LVIF_TEXT, nt->pal ? nt->pal->comment : _T ("null"), 2 + nt->getSelectPalSourceIndex (), 0, 0, 0);
  5760.               m_GuiLV_Page.SetItem (it, 3, LVIF_IMAGE | LVIF_TEXT, nt->attr ? nt->attr->comment : _T ("null"), 5, 0, 0, 0);
  5761.             }
  5762.           }
  5763.           // reset scroll...
  5764.           m_GuiSWin_Nesmap.SetScrollPos (0, SB_VERT);
  5765.           m_GuiSWin_Nesmap.SetScrollPos (0, SB_HORZ);
  5766.           m_GuiSWin_Nesmap.SetScrollSize (map->width * 32 * 8 + 32, map->height * 30 * 8 + 32);
  5767.           m_GuiSWin_Nesmap.nesPixelGenerator ();
  5768.         }
  5769.         tryCloseNtpWindow ();
  5770.       }
  5771.       }
  5772.     default:
  5773.       break;
  5774.     }
  5775.     return 0;
  5776.   }
  5777.   template <DWORD t_dwControlId>
  5778.   LRESULT OnKeyUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  5779.     switch (t_dwControlId) {
  5780.     case MAP_CONTROL_LV_CLAY:
  5781.       switch (wParam) {
  5782.       case 'P':
  5783.         if (CTRL_IN_KEYQUEUE ()) {
  5784.           auto indexChr = m_GuiLV_Chr.GetSelectedIndex ();
  5785.           auto indexClay = m_GuiLV_Clay.GetSelectedIndex ();
  5786.  
  5787.           if (indexChr >= 0
  5788.             && indexClay >= 0) {
  5789.               auto chr = (CChr *) m_GuiLV_Chr.GetItemData (indexChr);
  5790.               auto nt_cell =  (CNametableCell<TRUE> *) m_GuiLV_Clay.GetItemData (indexClay);
  5791.               ATLASSERT (chr != NULL);
  5792.               ATLASSERT (nt_cell != NULL);
  5793.               nt_cell->chr = chr;
  5794.               m_GuiLV_Clay.SetItemText (indexClay, 1, chr->comment);
  5795.               auto p = tryUpdateClayWindow (nt_cell);
  5796.               if (p != NULL) {
  5797.                   p->SetWindowTextFT (_T ("clay %s-%s"),
  5798.                          m_GuiLV_Clay.GetItemTextAMC (indexChr, 0),
  5799.                       nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5800.               }
  5801.           }
  5802.         }
  5803.         break;
  5804.       case 'V':
  5805.         if (CTRL_IN_KEYQUEUE ()) {
  5806.           auto indexChr = m_GuiLV_Chr.GetSelectedIndex ();
  5807.           auto indexClay = m_GuiLV_Clay.GetSelectedIndex ();
  5808.  
  5809.           if (indexChr >= 0
  5810.             && indexClay >= 0) {
  5811.               auto chr = (CChr *) m_GuiLV_Chr.GetItemData (indexChr);
  5812.               auto nt_cell =  (CNametableCell<TRUE> *) m_GuiLV_Clay.GetItemData (indexClay);
  5813.               ATLASSERT (chr != NULL);
  5814.               ATLASSERT (nt_cell != NULL);
  5815.               nt_cell->chr = chr;
  5816.               // m_GuiLV_Clay.SetItemText (indexClay, 1, chr->comment);
  5817.               auto p = tryUpdateClayWindow (nt_cell);
  5818.               if (p != NULL) {
  5819.                   TCHAR buf[256];
  5820.                   m_GuiLV_Chr.GetItemText (indexChr, 0, buf, sizeof (buf) / sizeof (buf[0]));
  5821.  
  5822.                   p->SetWindowTextFT (_T ("clay %s-%s"), buf, nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5823.               }
  5824.           }
  5825.         }
  5826.         break;
  5827.       case VK_RETURN:
  5828.         {
  5829.           auto index = m_GuiLV_Clay.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
  5830.           if (index >= 0) {
  5831.             auto clay  = (CNametableCell<TRUE> *) m_GuiLV_Clay.GetItemData (index);
  5832.             ATLASSERT (clay != NULL);
  5833.  
  5834.             CClaySettings    dlgSettings (*this);
  5835.             if (dlgSettings.DoModal (clay) == IDOK) {
  5836.                 // Append to new.
  5837.               m_GuiLV_Clay.SetItemText (index, 0, clay->comment);
  5838.             }
  5839.  
  5840.           }
  5841.         }
  5842.         break;
  5843.       case VK_INSERT:
  5844.         {
  5845.           CClaySettings    dlgSettings (*this);
  5846.           if (dlgSettings.DoModal (NULL) == IDOK) {
  5847.              // Append to new.
  5848.              auto index = m_GuiLV_Clay.InsertItem (m_GuiLV_Clay.GetItemCount (), dlgSettings.m_attachcell->comment, 0);
  5849.              ATLASSERT (index >= 0);
  5850.              m_GuiLV_Clay.SetItemData (index,   reinterpret_cast  <DWORD_PTR> ( dlgSettings.m_attachcell));
  5851.           }
  5852.         }
  5853.       default:
  5854.         break;
  5855.       }
  5856.       break;
  5857.     case MAP_CONTROL_LV_PAGE:
  5858.       bHandled = FALSE;
  5859.  
  5860.       switch (wParam) {
  5861.       case 'A': // Check select all ...
  5862.         if (CTRL_IN_KEYQUEUE ()) {
  5863.           m_GuiLV_Page.SetItemState (-1, /* LVIS_FOCUSED | */LVIS_SELECTED, /* LVIS_FOCUSED | */LVIS_SELECTED);
  5864.         }
  5865.         break;
  5866.       case 'P':
  5867.         if (CTRL_IN_KEYQUEUE ()) {
  5868.           auto indexChr = m_GuiLV_Chr.GetSelectedIndex ();
  5869.           auto indexPage = m_GuiLV_Page.GetSelectedIndex ();
  5870.           // ::TrackPopupMenu
  5871.           if (indexChr >= 0
  5872.             && indexPage >= 0) {
  5873.               auto chr =  m_GuiLV_Chr.GetItemSelectedDataT ();
  5874.               ATLASSERT (chr != NULL);
  5875.               for (int it = 0; it != m_GuiLV_Page.GetItemCount (); it++) {
  5876.                 auto nt_cell =  m_GuiLV_Page.GetItemDataT (it);
  5877.                 ATLASSERT (nt_cell != NULL);
  5878.                 nt_cell->chr = chr;
  5879.                 m_GuiLV_Page.SetItemText (it, 1, chr->comment);
  5880.                 auto p = tryUpdateNtpWindow (nt_cell);
  5881.                 if (p != NULL) {
  5882.                   p->SetWindowTextFT (_T ("nt %s-%s"),
  5883.                          m_GuiLV_Page.GetItemTextAMC (it, 0),
  5884.                            nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5885.                 }
  5886.               }
  5887.           }
  5888.         }
  5889.         break;
  5890.       case 'V':
  5891.         if (CTRL_IN_KEYQUEUE ()) {
  5892.           auto indexChr = m_GuiLV_Chr.GetSelectedIndex ();
  5893.           auto indexPage = m_GuiLV_Page.GetSelectedIndex ();
  5894.  
  5895.           if (indexChr >= 0
  5896.             && indexPage >= 0) {
  5897.               auto chr = (CChr *) m_GuiLV_Chr.GetItemData (indexChr);
  5898.               auto nt_cell =  (CNametableCell<FALSE> *) m_GuiLV_Page.GetItemData (indexPage);
  5899.               ATLASSERT (chr != NULL);
  5900.               ATLASSERT (nt_cell != NULL);
  5901.               nt_cell->chr = chr;
  5902.               m_GuiLV_Page.SetItemText (indexPage, 1, chr->comment);
  5903.               auto p = tryUpdateNtpWindow (nt_cell);
  5904.               if (p != NULL) {
  5905.                 p->SetWindowTextFT (_T ("nt %s-%s"),
  5906.                         m_GuiLV_Page.GetSelectedItemTextAMC (0),
  5907.                           nt_cell->chr ? nt_cell->chr->comment : _T ("null"));
  5908.               }
  5909.           }
  5910.         }
  5911.       default:
  5912.         break;
  5913.       }
  5914.       break;
  5915.  
  5916.     case MAP_CONTROL_LV_CHR:
  5917.       switch (wParam) {
  5918.       case 'C': // Copy chr cache.
  5919.         if (CTRL_IN_KEYQUEUE ()) {
  5920.           auto chr = m_GuiLV_Chr.GetItemSelectedDataT ();
  5921.           if (chr != NULL) {
  5922.             CGlobals::pasteChr = chr;
  5923.             setStatusText (2, _T ("chr cache:%s"), chr->comment);
  5924.           }
  5925.         }
  5926.         break;
  5927.  
  5928.       case VK_DELETE:
  5929.         {
  5930.           auto index = m_GuiLV_Chr.GetSelectedIndex ();
  5931.           if (index >= 0) {
  5932.             removeChr ((CChr *) m_GuiLV_Chr.GetItemData (index));
  5933.             m_GuiLV_Chr.DeleteItem (index);
  5934.             if (m_GuiLV_Chr.GetItemCount () > 0) {
  5935.               m_GuiLV_Chr.SelectItem (0);
  5936.             }
  5937.           }
  5938.         }
  5939.         break;
  5940.       case VK_INSERT:
  5941.         {
  5942.           CChrSettings dlgSettings (*this);
  5943.           dlgSettings.DoModal (NULL);
  5944.  
  5945.           // Show chr infos.
  5946.           m_GuiLV_Chr.DeleteAllItems ();
  5947.  
  5948.           for (size_t it = 0; it != m_ChrVec.GetCount (); it++) {
  5949.             m_GuiLV_Chr.InsertItem (it, m_ChrVec[it]->comment, 0);
  5950.             m_GuiLV_Chr.SetItemData (it, reinterpret_cast  <DWORD_PTR> ( m_ChrVec[it]));
  5951.           }
  5952.         }
  5953.       default:
  5954.         break;
  5955.       }
  5956.       break;
  5957.     case MAP_CONTROL_LV_MAP:
  5958.       switch (wParam) {
  5959.       case VK_INSERT:
  5960.         {
  5961.           CMapSettings dlgSettings (*this);
  5962.           if (dlgSettings.DoModal (NULL) == IDOK) {
  5963.              int index = m_GuiLV_Map.InsertItem (m_GuiLV_Map.GetItemCount (), dlgSettings.m_newmap->comment, 0);
  5964.              ATLASSERT (index >= 0);
  5965.              m_ShowMap = dlgSettings.m_newmap;
  5966.              m_GuiLV_Map.SetItemData (index, reinterpret_cast  <DWORD_PTR> (m_ShowMap));
  5967.              m_GuiLV_Map.SelectItem  (index);
  5968.              // TODO::::!!!!!!!!!
  5969.             // Enum list infos. show page window (case type)
  5970.             // Frisr derstroy  all old window. and
  5971.  
  5972.  
  5973.  
  5974.           }
  5975.         }
  5976.         break;
  5977.       case VK_DECIMAL:
  5978.         break;
  5979.       }
  5980.     }
  5981.     return 0;
  5982.   }
  5983.  
  5984.   // <CMainFrame::CChrSettings Start> =========================================
  5985.   struct CChrSettings : public CDialogImpl<CChrSettings>
  5986.   {
  5987.     typedef CChrSettings thisClass;
  5988.     typedef CDialogImpl<CChrSettings> baseClass;
  5989.  
  5990.     static const WORD copying_clr = 0x1f << 5;
  5991.     static const WORD copy_clr = 0x1f;
  5992.     static const WORD paste_clr = 0x1f << 10;
  5993.     static const WORD blend_cnt = 10;
  5994.  
  5995.     static const SIZE_T MAP_CONTROL_LV_DRAWMAIN = 1;
  5996.     static const SIZE_T MAP_CONTROL_LV_DRAWROM = MAP_CONTROL_LV_DRAWMAIN + 1;
  5997.     static const SIZE_T MAP_CONTROL_LV_DRAWRAM = MAP_CONTROL_LV_DRAWROM + 1;
  5998.     static const SIZE_T MAP_CONTROL_LV_DRAWCHR0PIX = MAP_CONTROL_LV_DRAWRAM + 1;
  5999.     static const SIZE_T MAP_CONTROL_LV_DRAWCHR1PIX = MAP_CONTROL_LV_DRAWCHR0PIX + 1;
  6000.     static const SIZE_T MAP_CONTROL_LV_DRAWCHR2PIX = MAP_CONTROL_LV_DRAWCHR1PIX + 1;
  6001.     static const SIZE_T MAP_CONTROL_LV_DRAWCHR3PIX = MAP_CONTROL_LV_DRAWCHR2PIX + 1;
  6002.     static const SIZE_T MAP_CONTROL_LV_DRAWCHRLIST = MAP_CONTROL_LV_DRAWCHR3PIX + 1;
  6003.  
  6004.     WORD m_chrclr[4];
  6005.  
  6006.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawchr;
  6007.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawrom;
  6008.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawram;
  6009.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawchr0pix;
  6010.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawchr1pix;
  6011.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawchr2pix;
  6012.     CContainedWindowT <CListViewCtrl> m_GuiLV_Drawchr3pix;
  6013.     CContainedWindowT <CListViewCtrl> m_GuiLV_Chrlist;
  6014.  
  6015.     CMemoryPaint16 m_MemoryPaintChrpix0;
  6016.     CMemoryPaint16 m_MemoryPaintChrpix1;
  6017.     CMemoryPaint16 m_MemoryPaintChrpix2;
  6018.     CMemoryPaint16 m_MemoryPaintChrpix3;
  6019.     CMemoryPaint16 m_MemoryPaintDrawpreview;
  6020.     CMemoryPaint16 m_MemoryPaintRom;
  6021.     CMemoryPaint16 m_MemoryPaintRam;
  6022.  
  6023.     CScrollBar m_GuiSCR_VDraw;
  6024.     CEdit m_GuiET_Comment;
  6025.  
  6026.     CPoint m_ptDrawStart;
  6027.     CPoint m_ptDrawEnd;
  6028.     CPoint m_ptDrawDstStartY;
  6029.     CPoint m_ptDrawStartY;
  6030.     CSize m_szDrawSizeY;
  6031.  
  6032.     CMainFrame &m_attthis;
  6033.     CChr m_tmpchr;
  6034.     CChr *m_selchr;
  6035.     CImageListManaged m_IconChrlist;
  6036.  
  6037.     CChr m_copychr;
  6038.  
  6039.     DWORD m_dwState; // 0: no copy 1:from chr-main 2: from chr-single 4: from edit-self
  6040.                                 // 0x8000 mask : ing...
  6041.  
  6042.     CChr m_tmpchr2;
  6043.  
  6044.     VOID copyToCache (VOID) {
  6045.       auto sig  = m_dwState & 0x7FFF;
  6046.       auto mask = m_dwState & 0x8000;
  6047.       auto &dstchr= m_copychr;
  6048.  
  6049.       auto pt_y = m_ptDrawStartY.y;
  6050.       auto pt_x = m_ptDrawStartY.x;
  6051.       auto ptd_y = pt_y + m_szDrawSizeY.cy;
  6052.       auto ptd_x = pt_x + m_szDrawSizeY.cx;
  6053.  
  6054.       auto *_pchr = & m_tmpchr;
  6055.  
  6056.       switch  (sig) {
  6057.       case 1:
  6058.         // Show main-chr infos.
  6059.         if (m_pchrpool != NULL) {
  6060.  
  6061.           auto y_base = m_GuiSCR_VDraw.GetScrollPos ();
  6062.           auto align = m_align;
  6063.           int x_block_sft;
  6064.           int g_per_sft;
  6065.           int g_per_mod;
  6066.           int vec_block_sft;
  6067.  
  6068.           switch (align) {
  6069.           case 16:
  6070.             x_block_sft = 2;
  6071.             g_per_sft = 4;
  6072.             g_per_mod = 15;
  6073.             vec_block_sft = 12;
  6074.             break;
  6075.           case 32:
  6076.             x_block_sft = 1;
  6077.             g_per_sft = 5;
  6078.             g_per_mod = 31;
  6079.             vec_block_sft = 14;
  6080.             break;
  6081.           case 64:
  6082.             x_block_sft = 0;
  6083.             g_per_sft = 6;
  6084.             g_per_mod = 63;
  6085.             vec_block_sft = 16;
  6086.             break;
  6087.           default:
  6088.             ATLASSERT (FALSE);
  6089.             break;
  6090.           }
  6091.  
  6092.           for (auto j= pt_y; j != ptd_y; j++) {
  6093.             auto coo_y = j + y_base;
  6094.             auto sr_v = coo_y >> g_per_sft;
  6095.             auto sr_vt = sr_v << x_block_sft; // TODO:add+loop replace .
  6096.             auto sr_mod_y = coo_y & g_per_mod;
  6097.             auto j0 = j - pt_y << 8; // 16 tiles
  6098.             for (auto i = pt_x; i != ptd_x; i++) {
  6099.               // Cut child range
  6100.               auto sr_total = (i >> g_per_sft) + sr_vt;
  6101.               auto sr_mod_x = i & g_per_mod;
  6102.               auto p = & m_pchrpool[sr_total << vec_block_sft];
  6103.               auto chrptr = (PUINT64) & p[(sr_mod_x << 4) + ((sr_mod_y << g_per_sft) << 4)];
  6104.               auto i0 = i - pt_x << 4;
  6105.               auto dstptr = (PUINT64) & dstchr.chr[j0+i0];
  6106.  
  6107.               dstptr[0] = chrptr[0];
  6108.               dstptr[1] = chrptr[1];
  6109.             }
  6110.           }
  6111.         }
  6112.         break;
  6113.       case 2:
  6114.         if (m_selchr != NULL) {
  6115.           _pchr = m_selchr;
  6116.       case 4:
  6117.           for (auto j= pt_y; j != ptd_y; j++) {
  6118.             auto j0 = j - pt_y << 8; // 16 tiles
  6119.             for (auto i = pt_x; i != ptd_x; i++) {
  6120.               auto chrptr = (PUINT64) & _pchr->chr[(i  << 4)+ (j << 8)];
  6121.               auto i0 = i - pt_x << 4;
  6122.               auto dstptr = (PUINT64) & dstchr.chr[j0+i0];
  6123.  
  6124.               dstptr[0] = chrptr[0];
  6125.               dstptr[1] = chrptr[1];
  6126.             }
  6127.           }
  6128.         }
  6129.       default:
  6130.         break;
  6131.       }
  6132.     }
  6133.  
  6134.     VOID UpdateInfos (BOOL bUpdatePostto = TRUE) {
  6135.       // return ;
  6136.       CMemoryPaint16::DirectWrite dwrite_chr0;
  6137.       CMemoryPaint16::DirectWrite dwrite_chr1;
  6138.       CMemoryPaint16::DirectWrite dwrite_chr2;
  6139.       CMemoryPaint16::DirectWrite dwrite_chr3;
  6140.       CMemoryPaint16::DirectWrite dwrite_main;
  6141.       CMemoryPaint16::DirectWrite dwrite_rom;
  6142.       CMemoryPaint16::DirectWrite dwrite_ram;
  6143.  
  6144.       m_MemoryPaintDrawpreview.getBackSurface (dwrite_main);
  6145.  
  6146.       m_MemoryPaintChrpix0.getBackSurface (dwrite_chr0);
  6147.       m_MemoryPaintChrpix1.getBackSurface (dwrite_chr1);
  6148.       m_MemoryPaintChrpix2.getBackSurface (dwrite_chr2);
  6149.       m_MemoryPaintChrpix3.getBackSurface (dwrite_chr3);
  6150.       m_MemoryPaintRom.getBackSurface (dwrite_rom);
  6151.       m_MemoryPaintRam.getBackSurface (dwrite_ram);
  6152.  
  6153.       m_MemoryPaintChrpix0.fillFullClient (dwrite_chr0, m_chrclr[0]);
  6154.       m_MemoryPaintChrpix1.fillFullClient (dwrite_chr1, m_chrclr[1]);
  6155.       m_MemoryPaintChrpix2.fillFullClient (dwrite_chr2, m_chrclr[2]);
  6156.       m_MemoryPaintChrpix3.fillFullClient (dwrite_chr3, m_chrclr[3]);
  6157.  
  6158.       const auto &r_pal = m_chrclr;
  6159.  
  6160.       // Show main-chr infos.
  6161.       if (m_pchrpool != NULL) {
  6162.  
  6163.         auto y_base = m_GuiSCR_VDraw.GetScrollPos ();
  6164.         auto align = m_align;
  6165.         int x_block_sft;
  6166.         int g_per_sft;
  6167.         int g_per_mod;
  6168.         int vec_block_sft;
  6169.  
  6170.         switch (align) {
  6171.         case 16:
  6172.           x_block_sft = 2;
  6173.           g_per_sft = 4;
  6174.           g_per_mod = 15;
  6175.           vec_block_sft = 12;
  6176.           break;
  6177.         case 32:
  6178.           x_block_sft = 1;
  6179.           g_per_sft = 5;
  6180.           g_per_mod = 31;
  6181.           vec_block_sft = 14;
  6182.           break;
  6183.         case 64:
  6184.           x_block_sft = 0;
  6185.           g_per_sft = 6;
  6186.           g_per_mod = 63;
  6187.           vec_block_sft = 16;
  6188.           break;
  6189.         default:
  6190.           ATLASSERT (FALSE);
  6191.           break;
  6192.         }
  6193.  
  6194.         const auto vpit = dwrite_main.Pitch16 << 3;
  6195.        
  6196.         for (auto j= 0; j != 64; j++) {
  6197.           auto coo_y = j + y_base;
  6198.           auto sr_v = coo_y >> g_per_sft;
  6199.           auto sr_vt = sr_v << x_block_sft; // TODO:add+loop replace .
  6200.           auto sr_mod_y = coo_y & g_per_mod;
  6201.           auto vptr_y = & dwrite_main.pBits[ j * vpit];
  6202.           for (auto i = 0; i != 64; i++) {
  6203.             // Cut child range
  6204.             auto sr_total = (i >> g_per_sft) + sr_vt;
  6205.             auto sr_mod_x = i & g_per_mod;
  6206.             auto p = & m_pchrpool[sr_total << vec_block_sft];
  6207.             auto chrptr = & p[(sr_mod_x << 4) + ((sr_mod_y << g_per_sft) << 4)];
  6208.             auto vptr = & vptr_y[i << 3];
  6209.  
  6210.             CPolyData64 cpd64;
  6211.  
  6212.             for (auto vec = 0; vec != 8; vec++) {
  6213.               cpd64.blk = CGlobals::chrmixer[chrptr[0]];
  6214.               cpd64.blk|= CGlobals::chrmixer[chrptr[8]] << 1;
  6215.  
  6216.               vptr[0] = r_pal[cpd64.blk8[0]];
  6217.               vptr[1] = r_pal[cpd64.blk8[1]];
  6218.               vptr[2] = r_pal[cpd64.blk8[2]];
  6219.               vptr[3] = r_pal[cpd64.blk8[3]];
  6220.               vptr[4] = r_pal[cpd64.blk8[4]];
  6221.               vptr[5] = r_pal[cpd64.blk8[5]];
  6222.               vptr[6] = r_pal[cpd64.blk8[6]];
  6223.               vptr[7] = r_pal[cpd64.blk8[7]];
  6224.  
  6225.               chrptr ++;
  6226.               vptr += dwrite_main.Pitch16;
  6227.             }
  6228.           }
  6229.         }
  6230.       }
  6231.       // Draw attach/temp chr pixel
  6232.       CChr *chrt[2] = { m_selchr, & m_tmpchr };
  6233.       CMemoryPaint16::DirectWrite *dwirte_gp[2] = { & dwrite_rom, & dwrite_ram};
  6234.  
  6235.       for (auto it = 0; it != 2; it++) {
  6236.         if (chrt[it] != NULL) {
  6237.           auto &chr = *(chrt[it]);
  6238.           auto &vram = *(dwirte_gp[it]);
  6239.           auto pChr = chr.chr;
  6240.  
  6241.           for (auto j = 0; j != 16; j++)  {
  6242.             for (auto i = 0; i != 16; i++)  {
  6243.               auto x_pos=  i << 3;
  6244.               auto y_pos = j << 3;
  6245.               auto tv  = & vram.pBits[x_pos + y_pos *vram.Pitch16];
  6246.               auto pChrT = pChr;
  6247.               CPolyData64 chr;
  6248.  
  6249.               for (auto v = 0; v != 8; v++) {
  6250.                 chr.blk = CGlobals::chrmixer[pChrT[0]]
  6251.                       | CGlobals::chrmixer[pChrT[8]] << 1;
  6252.  
  6253.                 tv[0] = r_pal[chr.blk8[0]];
  6254.                 tv[1] = r_pal[chr.blk8[1]];
  6255.                 tv[2] = r_pal[chr.blk8[2]];
  6256.                 tv[3] = r_pal[chr.blk8[3]];
  6257.                 tv[4] = r_pal[chr.blk8[4]];
  6258.                 tv[5] = r_pal[chr.blk8[5]];
  6259.                 tv[6] = r_pal[chr.blk8[6]];
  6260.                 tv[7] = r_pal[chr.blk8[7]];
  6261.  
  6262.                 tv += vram.Pitch16;
  6263.                 pChrT++;
  6264.               }
  6265.               pChr += 16;
  6266.             }
  6267.           }
  6268.         }
  6269.       }
  6270.       if (m_dwState != 0) {
  6271.         // Darw attach infos.
  6272.         CMemoryPaint16::DirectWrite *dwrite = NULL;
  6273.         if (m_dwState & 1) {
  6274.           dwrite = & dwrite_main;
  6275.         } else if (m_dwState & 2) {
  6276.           dwrite = & dwrite_rom;
  6277.         } else if (m_dwState & 4) {
  6278.           dwrite = & dwrite_ram;
  6279.         }
  6280.         if (dwrite != NULL) {
  6281.           CPoint pt = m_ptDrawDstStartY;
  6282.           CSize sz= m_szDrawSizeY;
  6283.           if (pt.x + sz.cx > 16)
  6284.             sz.cx = 16 - pt.x;
  6285.           if (pt.y + sz.cy > 16)
  6286.             sz.cy = 16 - pt.y;
  6287.  
  6288.           if ((m_dwState & 0x8000) == 0) {
  6289.             // draw link chr.
  6290.             auto &chr = m_copychr.chr;
  6291.             const auto &r_pal = m_chrclr;
  6292.  
  6293.             for (auto j = 0; j != sz.cy; j++) {
  6294.               auto coo_y = j + pt.y << 3;
  6295.               for (auto i = 0; i != sz.cx; i++) {
  6296.                 auto coo_x = i + pt.x << 3;
  6297.                 auto vdst = & dwrite_ram.pBits[coo_x + coo_y * dwrite_ram.Pitch16];
  6298.                 auto vsrcchr = & chr [(i << 4) + (j << 8)];
  6299.                 for (auto vec = 0; vec != 8; vec++) {
  6300.                   CPolyData64 cpd64;
  6301.  
  6302.                   cpd64.blk = CGlobals::chrmixer[vsrcchr[0]];
  6303.                   cpd64.blk|= CGlobals::chrmixer[vsrcchr[8]] << 1;
  6304.  
  6305.                   vdst[0] = CGlobals::alpha16  (r_pal[cpd64.blk8[0]], vdst[0], blend_cnt, 15 - blend_cnt);
  6306.                   vdst[1] = CGlobals::alpha16  (r_pal[cpd64.blk8[1]], vdst[1], blend_cnt, 15 - blend_cnt);
  6307.                   vdst[2] = CGlobals::alpha16  (r_pal[cpd64.blk8[2]], vdst[2], blend_cnt, 15 - blend_cnt);
  6308.                   vdst[3] = CGlobals::alpha16  (r_pal[cpd64.blk8[3]], vdst[3], blend_cnt, 15 - blend_cnt);
  6309.                   vdst[4] = CGlobals::alpha16  (r_pal[cpd64.blk8[4]], vdst[4], blend_cnt, 15 - blend_cnt);
  6310.                   vdst[5] = CGlobals::alpha16  (r_pal[cpd64.blk8[5]], vdst[5], blend_cnt, 15 - blend_cnt);
  6311.                   vdst[6] = CGlobals::alpha16  (r_pal[cpd64.blk8[6]], vdst[6], blend_cnt, 15 - blend_cnt);
  6312.                   vdst[7] = CGlobals::alpha16  (r_pal[cpd64.blk8[7]], vdst[7], blend_cnt, 15 - blend_cnt);
  6313.  
  6314.                   vdst += dwrite_ram.Pitch16;
  6315.                   vsrcchr++;
  6316.                 }
  6317.               }
  6318.  
  6319.             }
  6320.           }
  6321.  
  6322.        CGlobals::drawGrid (*dwrite,
  6323.                CGlobals::GRID_TYPE_FIXED,
  6324.                CPoint (m_ptDrawStartY.x << 3, m_ptDrawStartY.y << 3),
  6325.                CSize (m_szDrawSizeY.cx << 3, m_szDrawSizeY.cy << 3),
  6326.                CSize (1, 1),
  6327.                m_dwState & 0x8000 ? copying_clr : copy_clr);
  6328.  
  6329.         // tracker dst .
  6330.           if ((m_dwState & 0x8000) == 0) {
  6331.  
  6332.             pt.x <<= 3;
  6333.             pt.y <<= 3;
  6334.             sz.cx <<= 3;
  6335.             sz.cy <<= 3;
  6336.  
  6337.            CGlobals::drawGrid (dwrite_ram,
  6338.                    CGlobals::GRID_TYPE_FIXED,
  6339.                    pt,
  6340.                    sz,
  6341.                    CSize (1, 1),
  6342.                    paste_clr);
  6343.           }
  6344.         }
  6345.       }
  6346.       m_MemoryPaintChrpix0.blitClientBaseALL0 ();
  6347.       m_MemoryPaintChrpix1.blitClientBaseALL0 ();
  6348.       m_MemoryPaintChrpix2.blitClientBaseALL0 ();
  6349.       m_MemoryPaintChrpix3.blitClientBaseALL0 ();
  6350.  
  6351.       m_MemoryPaintDrawpreview.blitClientBaseALL0 ();
  6352.       m_MemoryPaintRom.blitClientBaseALL0 ();
  6353.       m_MemoryPaintRam.blitClientBaseALL0 ();
  6354.     }
  6355.  
  6356.     // 512 * 512 pixel
  6357.     // :=
  6358.     //
  6359.     // 128 * 128 pixel := 4K
  6360.     // if <= 512 >= 512
  6361.     // other limit 256 base
  6362.     PBYTE m_pchrpool; // XXX: must align 64K chr
  6363.     INT m_64k_page;
  6364.     INT m_align;
  6365.     BOOL m_bhflip;
  6366.     BOOL m_bvflip;
  6367.  
  6368.     ~CChrSettings (VOID) {
  6369.  
  6370.       // When I use subclass to intercept control message processing inside dialog,
  6371.       // And execute the unsubclass control enddialog inside the WM_CLOSE message.
  6372.       // After the operation, the
  6373.       // ATL: object deleted before window was destroyed
  6374.       // Assertion will be triggered, but sometimes there are no exception assertions
  6375.       // I don't know what I did wrong
  6376.       // This may be a bug of WTL/ATL ??
  6377.       this->m_hWnd = NULL;
  6378.     }
  6379.     CChrSettings (CMainFrame &psthis):
  6380.         m_dwState (0),
  6381.         m_bhflip (FALSE),
  6382.         m_bvflip (FALSE),
  6383.         m_attthis (psthis),
  6384.         m_pchrpool (NULL),
  6385.         m_selchr (NULL),
  6386.         m_64k_page (0),
  6387.         m_align (16),
  6388.         m_GuiLV_Drawchr (this, MAP_CONTROL_LV_DRAWMAIN),
  6389.         m_GuiLV_Drawrom (this, MAP_CONTROL_LV_DRAWROM),
  6390.         m_GuiLV_Drawram (this, MAP_CONTROL_LV_DRAWRAM),
  6391.         m_GuiLV_Drawchr0pix (this, MAP_CONTROL_LV_DRAWCHR0PIX),
  6392.         m_GuiLV_Drawchr1pix (this, MAP_CONTROL_LV_DRAWCHR1PIX),
  6393.         m_GuiLV_Drawchr2pix (this, MAP_CONTROL_LV_DRAWCHR2PIX),
  6394.         m_GuiLV_Drawchr3pix (this, MAP_CONTROL_LV_DRAWCHR3PIX),
  6395.         m_GuiLV_Chrlist (this, MAP_CONTROL_LV_DRAWCHRLIST)
  6396.     {
  6397.        m_chrclr[0] = CGlobals::nespal[0x0F];
  6398.        m_chrclr[1] = CGlobals::nespal[0x1C];
  6399.        m_chrclr[2] = CGlobals::nespal[0x2B];
  6400.        m_chrclr[3] = CGlobals::nespal[0x39];
  6401.  
  6402.        m_IconChrlist.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  6403.        m_IconChrlist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_CHR)));
  6404.     }
  6405.  
  6406.     enum { IDD = IDD_CHR_ADD };
  6407.  
  6408.     template <DWORD t_dwAlign>
  6409.     LRESULT OnAlignT  (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  6410.       m_align = t_dwAlign;
  6411.  
  6412.       UpdateInfos (TRUE);
  6413.       return 0;
  6414.     }
  6415.  
  6416.     template <DWORD t_dwControlId>
  6417.     LRESULT OnRButtonUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6418.       CPoint pt (GET_X_LPARAM(lParam),
  6419.                          GET_Y_LPARAM(lParam));
  6420.  
  6421.       switch (t_dwControlId) {
  6422.       case MAP_CONTROL_LV_DRAWMAIN:
  6423.       case MAP_CONTROL_LV_DRAWROM:
  6424.       case MAP_CONTROL_LV_DRAWRAM:
  6425.         m_dwState = 0;
  6426.         break;
  6427.       default:
  6428.         break;
  6429.       }
  6430.       UpdateInfos (TRUE);
  6431.       bHandled = FALSE;
  6432.       return 0;
  6433.     }
  6434.  
  6435.     template <DWORD t_dwControlId>
  6436.     LRESULT OnLButtonDownT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6437.       CPoint pt (GET_X_LPARAM(lParam),
  6438.                          GET_Y_LPARAM(lParam));
  6439.  
  6440.       switch (t_dwControlId) {
  6441.       case MAP_CONTROL_LV_DRAWCHRLIST: // Case Global paleete
  6442.         {
  6443.           // Process default message first
  6444.           m_GuiLV_Chrlist.DefWindowProc (uMsg, wParam, lParam);
  6445.  
  6446.           auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  6447.  
  6448.           // m_GuiLV_PalList.Pro
  6449.           if (index >= 0) {
  6450.             CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  6451.             if (chr != NULL) {
  6452.               m_selchr = chr;
  6453.               m_GuiET_Comment.SetWindowText (chr->comment);
  6454.             }
  6455.           }
  6456.         }
  6457.         break;
  6458.       case MAP_CONTROL_LV_DRAWMAIN:
  6459.       case MAP_CONTROL_LV_DRAWROM:
  6460.       case MAP_CONTROL_LV_DRAWRAM:
  6461.         {
  6462.            // click . draw rect.
  6463.           BOOL bInitrect = TRUE;
  6464.           auto oldState = m_dwState;
  6465.           auto limsize = 16;
  6466.  
  6467.           m_dwState = 0x8000;
  6468.  
  6469.           if (t_dwControlId == MAP_CONTROL_LV_DRAWMAIN) {
  6470.             m_dwState |= 1;
  6471.             limsize = 64;
  6472.           } else if (t_dwControlId == MAP_CONTROL_LV_DRAWROM) {
  6473.             m_dwState |= 2;
  6474.           } else if (t_dwControlId == MAP_CONTROL_LV_DRAWRAM) {
  6475.             if (oldState != 0
  6476.               && (oldState & 0x8000) == 0)
  6477.             {
  6478.                // Copy paste tiles...
  6479.               // Resume old state
  6480.               auto pt_y = m_ptDrawDstStartY.y;
  6481.               auto pt_x = m_ptDrawDstStartY.x;
  6482.               auto ptd_y = pt_y + m_szDrawSizeY.cy;
  6483.               auto ptd_x = pt_x + m_szDrawSizeY.cx;
  6484.  
  6485.               if (ptd_y > 16)
  6486.                 ptd_y = 16;
  6487.               if (ptd_x > 16)
  6488.                 ptd_x = 16;
  6489.  
  6490.               for (auto j= pt_y; j != ptd_y; j++) {
  6491.                 auto j0 = j - pt_y << 8; // 16 tiles
  6492.                 for (auto i = pt_x; i != ptd_x; i++) {
  6493.                   auto i0 = i - pt_x << 4;
  6494.                   auto chrptr = (PUINT64) & m_copychr  .chr[j0+i0];
  6495.                   auto dstptr = (PUINT64) & m_tmpchr.chr[(i << 4) + (j << 8)];
  6496.  
  6497.                   dstptr[0] = chrptr[0];
  6498.                   dstptr[1] = chrptr[1];
  6499.                 }
  6500.               }
  6501.  
  6502.               m_dwState = oldState;
  6503.               bInitrect = FALSE;
  6504.             }
  6505.             else
  6506.             {
  6507.               m_dwState |= 4;
  6508.             }
  6509.           }
  6510.           if (bInitrect != FALSE) {
  6511.             // Init rect.
  6512.             m_ptDrawStart.x = pt.x / 8;
  6513.             m_ptDrawStart.y = pt.y / 8;
  6514.  
  6515.             CGlobals::limitPoint (m_ptDrawStart, limsize, limsize);
  6516.  
  6517.             m_ptDrawEnd = m_ptDrawStart;
  6518.             m_ptDrawStartY = m_ptDrawStart;
  6519.             m_szDrawSizeY= ( 1, 1);
  6520.           }
  6521.         }
  6522.       default:
  6523.         break;
  6524.       }
  6525.       UpdateInfos (TRUE);
  6526.       return 0;
  6527.     }
  6528.  
  6529.     template <DWORD t_dwControlId>
  6530.     LRESULT OnLButtonUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6531.       CPoint pt (GET_X_LPARAM(lParam),
  6532.                          GET_Y_LPARAM(lParam));
  6533.       switch (t_dwControlId) {
  6534.       case MAP_CONTROL_LV_DRAWMAIN:
  6535.       case MAP_CONTROL_LV_DRAWROM:
  6536.       case MAP_CONTROL_LV_DRAWRAM:
  6537.         if (m_dwState & 0x8000) {
  6538.           const auto limsize = t_dwControlId == MAP_CONTROL_LV_DRAWMAIN ? 64 : 16;
  6539.           pt.x /= 8;
  6540.           pt.y/= 8;
  6541.           CGlobals ::limitPoint (pt, limsize, limsize);
  6542.  
  6543.           m_ptDrawEnd = pt;
  6544.           if (t_dwControlId == MAP_CONTROL_LV_DRAWRAM) {
  6545.             m_ptDrawDstStartY = pt;
  6546.           }
  6547.           CPoint ptLT = m_ptDrawStart;
  6548.           CPoint ptBR = m_ptDrawEnd;
  6549.  
  6550.           CGlobals::translateVecPointToltrb (ptLT, ptBR);
  6551.           m_ptDrawStartY = ptLT;
  6552.           m_szDrawSizeY.cx = ptBR.x -ptLT.x + 1;
  6553.           m_szDrawSizeY.cy = ptBR.y -ptLT.y + 1;
  6554.  
  6555.           if (m_szDrawSizeY.cx > 16)
  6556.             m_szDrawSizeY.cx = 16;
  6557.           if (m_szDrawSizeY.cy > 16)
  6558.             m_szDrawSizeY.cy = 16;
  6559.  
  6560.           m_bhflip =FALSE;
  6561.           m_bvflip = FALSE;
  6562.  
  6563.           copyToCache ();
  6564.  
  6565.           m_dwState &= ~0x8000;
  6566.         }
  6567.         break;
  6568.  
  6569.         case MAP_CONTROL_LV_DRAWCHRLIST: // Case Global paleete
  6570.         {
  6571.           // Process default message first
  6572.           m_GuiLV_Chrlist.DefWindowProc (uMsg, wParam, lParam);
  6573.  
  6574.           auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  6575.  
  6576.           // m_GuiLV_PalList.Pro
  6577.           if (index >= 0) {
  6578.             CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  6579.             if (chr != NULL) {
  6580.               m_selchr = chr;
  6581.               m_GuiET_Comment.SetWindowText (chr->comment);
  6582.             }
  6583.           }
  6584.         }
  6585.         break;
  6586.  
  6587.       default:
  6588.         break;
  6589.       }
  6590.       UpdateInfos (TRUE);
  6591.       return 0;
  6592.     }
  6593.  
  6594.     template <DWORD t_dwControlId>
  6595.     LRESULT OnMouseMoveT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6596.       CPoint pt (GET_X_LPARAM(lParam),
  6597.                          GET_Y_LPARAM(lParam));
  6598.  
  6599.       switch (t_dwControlId) {
  6600.       case MAP_CONTROL_LV_DRAWMAIN:
  6601.       case MAP_CONTROL_LV_DRAWROM:
  6602.       case MAP_CONTROL_LV_DRAWRAM:
  6603.         if (m_dwState & 0x8000) {
  6604.             const auto limsize = t_dwControlId == MAP_CONTROL_LV_DRAWMAIN ? 64 : 16;
  6605.             pt.x /= 8;
  6606.             pt.y/= 8;
  6607.             CGlobals ::limitPoint (pt, limsize, limsize);
  6608.  
  6609.             m_ptDrawEnd = pt;
  6610.             CPoint ptLT = m_ptDrawStart;
  6611.             CPoint ptBR = m_ptDrawEnd;
  6612.  
  6613.             CGlobals::translateVecPointToltrb (ptLT, ptBR);
  6614.             m_ptDrawStartY = ptLT;
  6615.             m_szDrawSizeY.cx = ptBR.x -ptLT.x + 1;
  6616.             m_szDrawSizeY.cy = ptBR.y -ptLT.y + 1;
  6617.  
  6618.             if (m_szDrawSizeY.cx > 16)
  6619.               m_szDrawSizeY.cx = 16;
  6620.             if (m_szDrawSizeY.cy > 16)
  6621.               m_szDrawSizeY.cy = 16;
  6622.         } else if (m_dwState != 0 && t_dwControlId == MAP_CONTROL_LV_DRAWRAM) {
  6623.             m_ptDrawDstStartY.x  = pt.x / 8;
  6624.             m_ptDrawDstStartY.y  = pt.y / 8;
  6625.             CGlobals ::limitPoint (m_ptDrawDstStartY, 16, 16);
  6626.         }
  6627.         break;
  6628.  
  6629.         case MAP_CONTROL_LV_DRAWCHRLIST: // Case Global paleete
  6630.         {
  6631.           // Process default message first
  6632.           m_GuiLV_Chrlist.DefWindowProc (uMsg, wParam, lParam);
  6633.  
  6634.           auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  6635.  
  6636.           // m_GuiLV_PalList.Pro
  6637.           if (index >= 0) {
  6638.             CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  6639.             if (chr != NULL) {
  6640.               m_selchr = chr;
  6641.               m_GuiET_Comment.SetWindowText (chr->comment);
  6642.             }
  6643.           }
  6644.         }
  6645.         break;
  6646.  
  6647.       default:
  6648.         break;
  6649.       }
  6650.       UpdateInfos (TRUE);
  6651.       return 0;
  6652.     }
  6653.  
  6654.     template <DWORD t_dwControlId>
  6655.     LRESULT OnLButtonDblclkT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6656.       PWORD pclr = NULL;
  6657.  
  6658.       switch (t_dwControlId) {
  6659.       case MAP_CONTROL_LV_DRAWCHR0PIX: pclr = & m_chrclr[0]; break;
  6660.       case MAP_CONTROL_LV_DRAWCHR1PIX: pclr = & m_chrclr[1]; break;
  6661.       case MAP_CONTROL_LV_DRAWCHR2PIX: pclr = & m_chrclr[2]; break;
  6662.       case MAP_CONTROL_LV_DRAWCHR3PIX: pclr = & m_chrclr[3]; break;
  6663.       case MAP_CONTROL_LV_DRAWCHRLIST: break;
  6664.       default:
  6665.         ATLASSERT (FALSE);
  6666.         break;
  6667.       }
  6668.       if (t_dwControlId != MAP_CONTROL_LV_DRAWCHRLIST) {
  6669.         CColorDialog coldlg (GDI_COL_TO_DRAW32 (*pclr));
  6670.         if (coldlg.DoModal () == IDOK) {
  6671.           *pclr = GDI_COL_TO_DRAW16 (coldlg.GetColor ());
  6672.         }
  6673.       }else {
  6674.        auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  6675.  
  6676.        // m_GuiLV_PalList.Pro
  6677.        if (index >= 0) {
  6678.          CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  6679.          if (chr != NULL) {
  6680.            m_selchr = chr;
  6681.            m_GuiET_Comment.SetWindowText (chr->comment);
  6682.            m_tmpchr = *chr;
  6683.          }
  6684.        }
  6685.       }
  6686.       UpdateInfos (TRUE);
  6687.       bHandled = FALSE;
  6688.       return 0;
  6689.     }
  6690.  
  6691.     LRESULT OnVScroll (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6692.  
  6693.       SCROLLINFO scrInfos;
  6694.       WORD scrCommand = LOWORD (wParam);
  6695.  
  6696.       scrInfos.fMask = SIF_ALL;
  6697.       scrInfos.cbSize = sizeof (scrInfos);
  6698.       m_GuiSCR_VDraw.  GetScrollInfo (& scrInfos);
  6699.  
  6700.       INT vec = scrInfos.nPos;
  6701.  
  6702.       switch (scrCommand) {
  6703.       case SB_THUMBPOSITION:
  6704.       case SB_THUMBTRACK:
  6705.         vec = scrInfos.nTrackPos;
  6706.         break;
  6707.  
  6708.       case SB_LINEUP:
  6709.         vec --;
  6710.         break;
  6711.  
  6712.       case SB_LINEDOWN:
  6713.         vec ++;
  6714.         break;
  6715.  
  6716.       case SB_PAGEDOWN:
  6717.         vec += 64;
  6718.         break;
  6719.  
  6720.       case SB_PAGEUP:
  6721.         vec -= 64;
  6722.         break;
  6723.  
  6724.       case SB_TOP:
  6725.       case SB_BOTTOM:
  6726.       default:
  6727.         // ATLASSERT (FALSE);
  6728.         break;
  6729.       }
  6730.       if (vec < 0)
  6731.         vec = 0;
  6732.       if (vec+ 64 > scrInfos.nMax)
  6733.         vec = scrInfos.nMax - 64;
  6734.  
  6735.       m_GuiSCR_VDraw.SetScrollPos (vec);
  6736.       // Re-pos .
  6737.       UpdateInfos (TRUE);
  6738.       return 0;
  6739.     }
  6740.  
  6741.     template <DWORD t_dwControlId>
  6742.     LRESULT OnKeyUpT (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6743.       switch (t_dwControlId) {
  6744.       case MAP_CONTROL_LV_DRAWRAM:
  6745.         switch (wParam) {
  6746.         case 'H': // h-swap @TODO:
  6747.           m_bhflip = !m_bhflip;
  6748.           break;
  6749.         case 'V': // v-swap @TODO:
  6750.           m_bvflip = !m_bvflip;
  6751.           break;
  6752.         case ' ': // clear all elem
  6753.           RtlZeroMemory (m_tmpchr.chr, sizeof (m_tmpchr.chr));
  6754.           break;
  6755.         default:
  6756.           break;
  6757.         }
  6758.         break;
  6759.       case MAP_CONTROL_LV_DRAWCHRLIST:
  6760.         switch (wParam) {
  6761.         case VK_DELETE:
  6762.           {
  6763.             auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  6764.             auto &vec = m_attthis.m_ChrVec;
  6765.             auto &vec2 = m_attthis.m_VnpVec;
  6766.  
  6767.             if (index >= 0) {
  6768.                CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  6769.                for (auto It = 0; It != vec.GetCount (); It++) {
  6770.                  if (vec[It] == chr) {
  6771.                    // delete nametable page's attach link
  6772.                    for (auto Iz = 0; Iz != m_attthis.m_MapVec.GetCount (); Iz++) {
  6773.                      auto &vec3 = m_attthis.m_MapVec[Iz]->ntList;
  6774.                      for (auto Iq = 0; Iq != vec3.GetCount (); Iq++) {
  6775.                        if (vec3[Iq]->chr == chr) {
  6776.                          // empty it.
  6777.                          vec3[Iq]->chr = NULL;
  6778.                        }
  6779.                      }
  6780.                    }
  6781.                    // Delete clay class.
  6782.                     for (auto Iq = 0; Iq != vec2.GetCount (); Iq++) {
  6783.                       if (vec2[Iq]->chr == chr) {
  6784.                         // empty it.
  6785.                         vec2[Iq]->chr = NULL;
  6786.                       }
  6787.                     }
  6788.  
  6789.                     m_attthis.updateCPViewListInfos <TRUE> ();
  6790.                     m_attthis.updateCPViewListInfos <FALSE> ();
  6791.                     m_attthis.allViewUpdate ();
  6792.  
  6793.  
  6794.  
  6795.  
  6796.  
  6797.                    m_attthis.m_ChrVec.RemoveAt (It);
  6798.                    delete chr;
  6799.  
  6800.                   m_GuiLV_Chrlist.DeleteItem (index);
  6801.                   m_GuiLV_Chrlist.SelectItem (0);
  6802.                   break;
  6803.                    // TODO: paste object check delete
  6804.                  }
  6805.                }
  6806.             }
  6807.           }
  6808.           break;
  6809.         default:
  6810.           break;
  6811.         }
  6812.       default:
  6813.         break;
  6814.       }
  6815.       UpdateInfos (TRUE);
  6816.       return 0;
  6817.     }
  6818.  
  6819.     BEGIN_MSG_MAP(thisClass)
  6820.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  6821.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  6822.       MESSAGE_HANDLER (WM_PAINT, OnPaint)
  6823.       MESSAGE_HANDLER (WM_VSCROLL, OnVScroll)
  6824.       COMMAND_ID_HANDLER (IDBT_CHR_LOADCHR, OnLoadChr)
  6825.       COMMAND_ID_HANDLER (IDBT_CHR_ADD_NEW, OnAddChr)
  6826.       COMMAND_ID_HANDLER (IDBT_CHR_ADJUST_SEL, OnAdjustChr)
  6827.       COMMAND_ID_HANDLER (IDRD_CHR_ALIGN16, OnAlignT<16>)
  6828.       COMMAND_ID_HANDLER (IDRD_CHR_ALIGN32, OnAlignT<32>)
  6829.       COMMAND_ID_HANDLER (IDRD_CHR_ALIGN64, OnAlignT<64>)
  6830.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWMAIN)
  6831.         MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT <MAP_CONTROL_LV_DRAWMAIN>)
  6832.         MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMoveT <MAP_CONTROL_LV_DRAWMAIN>)
  6833.         MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT <MAP_CONTROL_LV_DRAWMAIN>)
  6834.         MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT <MAP_CONTROL_LV_DRAWMAIN>)
  6835.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWROM)
  6836.         MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT <MAP_CONTROL_LV_DRAWROM>)
  6837.         MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMoveT <MAP_CONTROL_LV_DRAWROM>)
  6838.         MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT <MAP_CONTROL_LV_DRAWROM>)
  6839.         MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT <MAP_CONTROL_LV_DRAWROM>)
  6840.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWRAM)
  6841.         MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT <MAP_CONTROL_LV_DRAWRAM>)
  6842.         MESSAGE_HANDLER (WM_MOUSEMOVE, OnMouseMoveT <MAP_CONTROL_LV_DRAWRAM>)
  6843.         MESSAGE_HANDLER (WM_LBUTTONUP, OnLButtonUpT <MAP_CONTROL_LV_DRAWRAM>)
  6844.         MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT <MAP_CONTROL_LV_DRAWRAM>)
  6845.         MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT <MAP_CONTROL_LV_DRAWRAM>)
  6846.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWCHR0PIX)
  6847.         MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclkT <MAP_CONTROL_LV_DRAWCHR0PIX>)
  6848.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWCHR1PIX)
  6849.         MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclkT <MAP_CONTROL_LV_DRAWCHR1PIX>)
  6850.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWCHR2PIX)
  6851.         MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclkT <MAP_CONTROL_LV_DRAWCHR2PIX>)
  6852.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWCHR3PIX)
  6853.         MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclkT <MAP_CONTROL_LV_DRAWCHR3PIX>)
  6854.       ALT_MSG_MAP (MAP_CONTROL_LV_DRAWCHRLIST)
  6855.         MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT <MAP_CONTROL_LV_DRAWCHRLIST>)
  6856.         MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclkT <MAP_CONTROL_LV_DRAWCHRLIST>)
  6857.         MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT <MAP_CONTROL_LV_DRAWCHRLIST>)
  6858.     END_MSG_MAP()
  6859.  
  6860.     LRESULT OnLoadChr (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  6861.  
  6862.       CFileDialogFilter df (_T("Chr files (*.chr; *.bin; *nes)| *.chr; *.bin; *nes"));
  6863.       CFileDialog fd_dlg  (   TRUE, _T ("Open Chr..."),
  6864.                                   NULL, OFN_ALLOWMULTISELECT | OFN_EXPLORER,
  6865.                                   df,
  6866.                                   this->m_hWnd        );
  6867.  
  6868.       if (fd_dlg.DoModal () == IDOK) {
  6869.         // Do stuff.
  6870.          CAtlFile fd;
  6871.          ULONGLONG fsize;
  6872.  
  6873.          HRESULT sig= fd.Create (fd_dlg.m_szFileName,
  6874.              GENERIC_READ,
  6875.              FILE_SHARE_READ,
  6876.              OPEN_EXISTING);
  6877.  
  6878.           ATLASSERT (SUCCEEDED (sig));
  6879.  
  6880.           sig = fd.GetSize  (fsize);
  6881.           ATLASSERT (SUCCEEDED (sig));
  6882.  
  6883.           sig = fd.Seek (0, FILE_BEGIN);
  6884.           ATLASSERT (SUCCEEDED (sig));
  6885.  
  6886.           // Check is nes. skip 16 byte nes header. XXX: check too simple.
  6887.           if ( ChTraitsCRT<TCHAR>::StringFindString  (fd_dlg.m_szFileName, _T (".nes")) != NULL) {
  6888.             if (fsize <= 16) {
  6889.               AtlMessageBox (*this, _T ("nes file size <= 16!"), _T ("CChrSettings"), MB_ICONERROR);
  6890.               return 0;
  6891.             }
  6892.             fsize -= 16;
  6893.             fd.Seek (16, FILE_BEGIN);
  6894.           }
  6895.           if (fsize <= 0xFFFF) {
  6896.             m_64k_page = 1;
  6897.           } else {
  6898.             m_64k_page = fsize/ 0x10000 + !! (fsize % 0x10000);
  6899.           }
  6900.           if (m_pchrpool != NULL) {
  6901.             CCRTAllocator::Free (m_pchrpool);
  6902.           }
  6903.           m_pchrpool = static_cast<PBYTE> ( CCRTAllocator ::Allocate (m_64k_page * 0x10000));
  6904.           ATLASSERT (m_pchrpool != NULL);
  6905.  
  6906.           sig = fd.Read (m_pchrpool, fsize);
  6907.           ATLASSERT (SUCCEEDED (sig));
  6908.  
  6909.           fd.Close ();
  6910.  
  6911.           // Reset v-scroll bar..
  6912.           // Per unit 4K ...
  6913.           if (m_64k_page <= 1) {
  6914.             m_GuiSCR_VDraw.EnableWindow (FALSE);
  6915.           } else {
  6916.             m_GuiSCR_VDraw.EnableWindow (TRUE);
  6917.  
  6918.             SCROLLINFO scrinfos;
  6919.             scrinfos.cbSize = sizeof (scrinfos);
  6920.             scrinfos.fMask = SIF_ALL;
  6921.             scrinfos.nMin = 0;
  6922.             scrinfos.nMax = 64 * m_64k_page /* - 1 */;
  6923.             scrinfos.nPos = 0;
  6924.             scrinfos.nPage = 64;
  6925.  
  6926.             m_GuiSCR_VDraw.SetScrollInfo (& scrinfos);
  6927.           }
  6928.           Invalidate (TRUE);
  6929.         }
  6930.        return 0;
  6931.     }
  6932.  
  6933.     LRESULT OnPaint (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  6934.       CPaintDC dc (*this);
  6935.       UpdateInfos (TRUE);
  6936.  
  6937.       bHandled= FALSE;
  6938.       return 0;
  6939.     }
  6940.  
  6941.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  6942.      
  6943.       m_GuiLV_Drawchr.UnsubclassWindow (TRUE);
  6944.       m_GuiLV_Drawrom.UnsubclassWindow (TRUE);
  6945.       m_GuiLV_Drawram.UnsubclassWindow (TRUE);
  6946.       m_GuiLV_Drawchr0pix.UnsubclassWindow (TRUE);
  6947.       m_GuiLV_Drawchr1pix.UnsubclassWindow (TRUE);
  6948.       m_GuiLV_Drawchr2pix.UnsubclassWindow (TRUE);
  6949.       m_GuiLV_Drawchr3pix.UnsubclassWindow (TRUE);
  6950.  
  6951.       m_GuiLV_Chrlist.RemoveImageList (LVSIL_SMALL);
  6952.  
  6953.       m_GuiLV_Chrlist.UnsubclassWindow (TRUE);
  6954.  
  6955.       m_GuiSCR_VDraw = NULL;
  6956.       m_GuiET_Comment = NULL;
  6957.      
  6958.       CGlobals::pasteChr = NULL;
  6959.       m_attthis.setStatusText (2, _T ("chr cache:empty"));
  6960.  
  6961.       EndDialog (IDOK);
  6962.       return 0;
  6963.     }
  6964.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  6965.  
  6966.       m_GuiLV_Drawchr.SubclassWindow (GetDlgItem (IDLV_CHR_DRAW));
  6967.       m_GuiLV_Drawrom.SubclassWindow (GetDlgItem (IDLV_CHR_SELFEDIT));
  6968.       m_GuiLV_Drawram.SubclassWindow (GetDlgItem (IDLV_CHR_MIXER));
  6969.       m_GuiLV_Drawchr0pix.SubclassWindow (GetDlgItem (IDLV_CHR_CHR0));
  6970.       m_GuiLV_Drawchr1pix.SubclassWindow (GetDlgItem (IDLV_CHR_CHR1));
  6971.       m_GuiLV_Drawchr2pix.SubclassWindow (GetDlgItem (IDLV_CHR_CHR2));
  6972.       m_GuiLV_Drawchr3pix.SubclassWindow (GetDlgItem (IDLV_CHR_CHR3));
  6973.       m_GuiLV_Chrlist.SubclassWindow (GetDlgItem (IDLV_CHR_CHRLIST));
  6974.  
  6975.       m_MemoryPaintChrpix0.resetMemoryDC (m_GuiLV_Drawchr0pix);
  6976.       m_MemoryPaintChrpix1.resetMemoryDC (m_GuiLV_Drawchr1pix);
  6977.       m_MemoryPaintChrpix2.resetMemoryDC (m_GuiLV_Drawchr2pix);
  6978.       m_MemoryPaintChrpix3.resetMemoryDC (m_GuiLV_Drawchr3pix);
  6979.       m_MemoryPaintDrawpreview.resetMemoryDC (m_GuiLV_Drawchr);
  6980.       m_MemoryPaintRom.resetMemoryDC (m_GuiLV_Drawrom);
  6981.       m_MemoryPaintRam.resetMemoryDC (m_GuiLV_Drawram);
  6982.  
  6983.       // Insert col, desc | value
  6984.       LVCOLUMN vcl;  
  6985.       RtlZeroMemory (& vcl, sizeof (vcl));
  6986.  
  6987.       vcl.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;  
  6988.       vcl.pszText = _T ("$");
  6989.       vcl.cx = 120;
  6990.       m_GuiLV_Chrlist.InsertColumn (0, & vcl);
  6991.  
  6992.       m_GuiSCR_VDraw.Attach (GetDlgItem (IDSR_CHR_VDRAW));
  6993.       m_GuiET_Comment.Attach (GetDlgItem (IDET_CHR_COMMENT));
  6994.  
  6995.       m_GuiLV_Chrlist.SetBkColor (0);
  6996.       m_GuiLV_Chrlist.SetTextBkColor (0);
  6997.       m_GuiLV_Chrlist.SetTextColor (0xff00);
  6998.  
  6999.       // Enum show chr list-infos.
  7000.       m_GuiLV_Chrlist.DeleteAllItems ();
  7001.  
  7002.       auto &r = m_attthis.m_ChrVec;
  7003.  
  7004.       for (int it = 0; it != r.GetCount  (); it++) {
  7005.         m_GuiLV_Chrlist.InsertItem (it, r[it]->comment);
  7006.         m_GuiLV_Chrlist.SetItemData (it, reinterpret_cast <DWORD_PTR> ( r[it]));
  7007.       }
  7008.  
  7009.       if (m_selchr != NULL) {
  7010.          // Fill current pal infos.
  7011.       //  etComment.SetWindowText (m_newmap->comment);
  7012.          CString string;
  7013.  
  7014.          m_GuiET_Comment.SetWindowText (m_selchr->comment);
  7015.  
  7016.          // Draw chr.
  7017.  
  7018.  
  7019.  
  7020.       }
  7021.       Invalidate (TRUE);
  7022.  
  7023.  
  7024.       CheckDlgButton (IDRD_CHR_ALIGN16, BST_CHECKED);
  7025.  
  7026.       m_GuiLV_Chrlist.SetImageList (m_IconChrlist, LVSIL_SMALL);
  7027.  
  7028.       bHandled = FALSE;
  7029.        return 0;
  7030.     }
  7031.     LRESULT OnAdjustChr (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  7032.  
  7033.       auto index = m_GuiLV_Chrlist.GetSelectedIndex ();
  7034.  
  7035.       // m_GuiLV_PalList.Pro
  7036.       if (index >= 0) {
  7037.         CChr *chr = (CChr *) m_GuiLV_Chrlist.GetItemData (index);
  7038.         if (chr != NULL) {
  7039.            *chr = m_tmpchr;
  7040.            CString string;
  7041.  
  7042.            m_GuiET_Comment.GetWindowText (string);
  7043.            chr->comment = string;
  7044.  
  7045.            CGlobals::adjustCommentUnique (m_attthis.m_ChrVec, chr,  FALSE);
  7046.            m_GuiLV_Chrlist.SetItemText (index, 0, chr->comment);
  7047.  
  7048.         }
  7049.       }
  7050.  
  7051.       bHandled = FALSE;
  7052.       return 0;
  7053.     }
  7054.  
  7055.     LRESULT OnAddChr (WORD, WORD, HWND /*lParam*/, BOOL& bHandled) {
  7056.       auto p = new CChr;
  7057.       CString content;
  7058.  
  7059.       *p = m_tmpchr;
  7060.  
  7061.       m_GuiET_Comment.GetWindowText (content);
  7062.       p->comment = content;
  7063.  
  7064.       CGlobals::adjustCommentUnique (m_attthis.m_ChrVec, p, TRUE);
  7065.  
  7066.       auto index = m_GuiLV_Chrlist.InsertItem (
  7067.                 m_GuiLV_Chrlist.GetItemCount (),
  7068.                 p->comment,
  7069.                 0);
  7070.  
  7071.       m_GuiLV_Chrlist.SetItemData (index, reinterpret_cast <DWORD_PTR> ( p));
  7072.  
  7073.       bHandled = FALSE;
  7074.       return 0;
  7075.     }
  7076.  
  7077.     INT_PTR DoModal (CMapUnit *map = NULL)
  7078.     {
  7079.       // m_newmap = map;
  7080.  
  7081.       // Modal it.
  7082.       return baseClass::DoModal ();
  7083.     }
  7084.   };
  7085.   // <CMainFrame::CChrSettings End> =========================================
  7086.   ~CMainFrame(void) {
  7087.     // int intPoint = 0/0;
  7088.     //__asm ud2 bug check
  7089.   }
  7090.   CMainFrame (VOID) :
  7091.     m_bShowAttrShadow (FALSE),
  7092.     m_subFunc (0),
  7093.     m_bShowGridMain (FALSE), /* Q key switch */
  7094.     m_bShowGridAttr (FALSE), /* Z key switch */
  7095.     m_ptRenderStart (0, 0),
  7096.     m_ptRenderEnd (0, 0),
  7097.     m_ptRenderStartY (0, 0),
  7098.     m_szRenderStartY (0, 0),
  7099.     m_ptPastePoint (0, 0),
  7100.     m_ShowMap (NULL),
  7101.     m_ntpWindowPoll (0),
  7102.     m_GuiSWin_Nesmap (*this),
  7103.     m_GuiLV_Map(this, MAP_CONTROL_LV_MAP),
  7104.     m_GuiLV_Chr (this, MAP_CONTROL_LV_CHR),
  7105.     m_GuiLV_Clay (this, MAP_CONTROL_LV_CLAY),
  7106.     m_GuiLV_Page (this, MAP_CONTROL_LV_PAGE){
  7107.  
  7108.     m_IconMaplist.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  7109.     m_IconClaylist.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  7110.     m_IconChrlist.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  7111.     m_IconPagelist.Create (16,16,ILC_COLOR24|ILC_MASK,1,0);
  7112.  
  7113.     // Map-list
  7114.     m_IconMaplist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_MAP)));
  7115.     // Chr-list
  7116.     m_IconChrlist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_CHR)));
  7117.  
  7118.     // Page-list
  7119.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_PAGE)));
  7120.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_CHR)));
  7121.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_PRIVATE_PAL )));
  7122.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_STATIC_PAL)));
  7123.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_GLOBAL_PAL)));
  7124.     m_IconPagelist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_ATTRLIST)));
  7125.  
  7126.     // Clay-list
  7127.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_CLAY)));
  7128.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_CHR)));
  7129.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_PRIVATE_PAL )));
  7130.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_STATIC_PAL)));
  7131.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_GLOBAL_PAL)));
  7132.     m_IconClaylist.AddIcon (LoadIcon (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDI_ATTRLIST)));
  7133.   }
  7134.  
  7135.   virtual BOOL PreTranslateMessage(MSG* pMsg)
  7136.   {
  7137.    if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
  7138.     return TRUE;
  7139.      else
  7140.        return FALSE;
  7141.   }
  7142.  
  7143.   virtual BOOL OnIdle()
  7144.   {
  7145.    return FALSE;
  7146.   }
  7147.  
  7148.   BEGIN_MSG_MAP(CMainFrame)
  7149.     MESSAGE_HANDLER (WM_DESTROY, OnDestroy)
  7150.     MESSAGE_HANDLER(WM_CREATE, OnCreate)
  7151.     COMMAND_ID_HANDLER (ID_FILE_SAVENNEPROJECT, OnSaveNNE)
  7152.     COMMAND_ID_HANDLER (IDTB_BT_SAVENNE, OnSaveNNE)
  7153.     COMMAND_ID_HANDLER (ID_FILE_LOADNNEPROJECT, OnLoadNNE)
  7154.     COMMAND_ID_HANDLER (IDTB_BT_OPENNNE, OnLoadNNE)
  7155.     COMMAND_ID_HANDLER (IDTB_BT_OUTCC65, OnOutputCC65)
  7156.     CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
  7157.     ALT_MSG_MAP (MAP_CONTROL_LV_MAP)
  7158.       MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_MAP>)
  7159.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_MAP>)
  7160.     ALT_MSG_MAP (MAP_CONTROL_LV_PAGE)
  7161.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_PAGE>)
  7162.       MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclk<MAP_CONTROL_LV_PAGE>)
  7163.       MESSAGE_HANDLER (WM_RBUTTONDOWN, OnRButtonDownT<MAP_CONTROL_LV_PAGE>)
  7164.       MESSAGE_HANDLER (WM_RBUTTONUP, OnRButtonUpT<MAP_CONTROL_LV_PAGE>)
  7165.       COMMAND_ID_HANDLER (ID_SETPAGE_GPAL, (OnSetCommonPaletteT <FALSE, 0>) /* 0 := global palette settings */)
  7166.       COMMAND_ID_HANDLER (ID_SETPAGE_SPAL, (OnSetCommonPaletteT <FALSE, 1>) /* 1 := static palette settings */)
  7167.       COMMAND_ID_HANDLER (ID_SETPAGE_CHR, (OnSetCommonPaletteT <FALSE, 2>) /* 1 := chr settings */)
  7168.     ALT_MSG_MAP (MAP_CONTROL_LV_CHR)
  7169.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_CHR>)
  7170.     ALT_MSG_MAP (MAP_CONTROL_LV_CLAY)
  7171.       // MESSAGE_HANDLER (WM_LBUTTONDOWN, OnLButtonDownT<MAP_CONTROL_LV_CLAY>)
  7172.       MESSAGE_HANDLER (WM_RBUTTONDOWN, OnRButtonDownT<MAP_CONTROL_LV_CLAY>)
  7173.       MESSAGE_HANDLER (WM_KEYUP, OnKeyUpT<MAP_CONTROL_LV_CLAY>)
  7174.       MESSAGE_HANDLER (WM_LBUTTONDBLCLK, OnLButtonDblclk<MAP_CONTROL_LV_CLAY>)
  7175.       COMMAND_ID_HANDLER (ID_SETPAGE_GPAL, (OnSetCommonPaletteT <TRUE, 0>) /* 0 := global palette settings */)
  7176.       COMMAND_ID_HANDLER (ID_SETPAGE_CHR, (OnSetCommonPaletteT <TRUE, 2>) /* 1 := chr settings */)
  7177.   END_MSG_MAP()
  7178.  
  7179.   SFINLINE
  7180.   HRESULT atlCreateRwOverwriteFile (CAtlFile &atlfd, CString &path) {
  7181.      return atlfd.Create (path,
  7182.              GENERIC_READ | GENERIC_WRITE,
  7183.               FILE_SHARE_READ,
  7184.               CREATE_ALWAYS);
  7185.   }
  7186.   SFINLINE
  7187.   void atlCreateRwOverwriteFileAssert (CAtlFile &atlfd, CString &path) {
  7188.     HRESULT sig = atlCreateRwOverwriteFile (atlfd, path);
  7189.     ATLASSERT (SUCCEEDED (sig));
  7190.   }
  7191.  
  7192.   HRESULT writeSourcePalFiles (int outputSource, /* 0:Global 1:Static 2: local */
  7193.                             CString outPathBase, /* without \ */
  7194.                             int palIndex,
  7195.                             CPal *pal,
  7196.                             int mapIndex = -1,
  7197.                             CMapUnit *map = NULL,
  7198.                             CPoint *point = NULL,
  7199.                             CNametableCell <FALSE> *ntCell = NULL)
  7200.   {
  7201.     HRESULT sig = 0;
  7202.  
  7203.     CAtlFile outInlFd;    
  7204.     CAtlFile outPalFd;
  7205.     CString outInlPath = outPathBase + _T ("\\");    
  7206.     CString outPalPath = outPathBase + _T ("\\");
  7207.     CStringA comment;
  7208.  
  7209.     :: PathRemoveBackslash (outPathBase.GetBuffer ());
  7210.     outPathBase.ReleaseBuffer ();
  7211.  
  7212.     // Output format.
  7213.     if (outputSource == 0) {
  7214.       outInlPath.AppendFormat (_T ("msgp%d.inl"), palIndex);
  7215.       outPalPath.AppendFormat (_T ("msgp%d.pal"), palIndex);
  7216.  
  7217.       comment.Append ("// --------------------------------------------------\n");
  7218.       comment.Append ("// Section:Global Palette\n");  
  7219.       comment.AppendFormat (
  7220.                       "// Index[Comment]:%d %s\n", palIndex, CStringA (pal->comment));
  7221.       comment.Append ("// --------------------------------------------------\n");                  
  7222.       comment.AppendFormat (
  7223.                       "#define MSGP_%s msgp%d\n", CStringA (pal->comment), palIndex);                  
  7224.       comment.AppendFormat (
  7225.                       "unsigned char msgp%d[16] = { \n",      palIndex);
  7226.     } else if (outputSource == 1) {
  7227.       comment.Append ("// --------------------------------------------------\n");
  7228.       comment.Append ("// Section:Static Palette\n");  
  7229.       comment.AppendFormat (
  7230.                       "// Index[Comment]:%d %s\n", palIndex, CStringA (pal->comment));
  7231.       comment.AppendFormat (
  7232.                       "// SubMapper[Comment]:%d %s\n", mapIndex, CStringA (map->comment));                    
  7233.       comment.Append ("// --------------------------------------------------\n");                  
  7234.       comment.AppendFormat (
  7235.                       "#define MSSP%d_%d_%s mssp%d_%d\n", mapIndex, palIndex, CStringA (pal->comment),
  7236.                                                                mapIndex, palIndex  );                  
  7237.       comment.AppendFormat (
  7238.                       "unsigned char mssp%d_%d[16] = { \n",  mapIndex, palIndex);
  7239.      
  7240.       outInlPath.AppendFormat (_T ("mssp%d_%d.inl"), mapIndex, palIndex);
  7241.       outPalPath.AppendFormat (_T ("mssp%d_%d.pal"), mapIndex, palIndex);
  7242.     } else if (outputSource == 2) {
  7243.       comment.Append ("// --------------------------------------------------\n");
  7244.       comment.Append ("// Section:Local Palette\n");  
  7245.       comment.AppendFormat (
  7246.                       "// Index[Comment]:%d %s\n", palIndex, CStringA (pal->comment));
  7247.       comment.AppendFormat (
  7248.                       "// SubMapper[Comment]:%d %s\n", mapIndex, CStringA (map->comment));  
  7249.       comment.AppendFormat (
  7250.                       "// SubMapper size:%d %d\n", map->width, map->height);                        
  7251.       comment.AppendFormat (
  7252.                       "// SubMapper position:%d %d\n", point->x, point->y);                      
  7253.       comment.Append ("// --------------------------------------------------\n");                  
  7254.       comment.AppendFormat (
  7255.                       "#define MSLP%d_%d_%d_%d_%s mslp%d_%d_%d_%d\n",
  7256.                                                mapIndex, point->x, point->y, palIndex, pal->comment,
  7257.                                                mapIndex, point->x, point->y, palIndex);                  
  7258.       comment.AppendFormat (
  7259.                       "unsigned char mslp%d_%d_%d_%d[16] = { \n", mapIndex, point->x, point->y, palIndex);
  7260.  
  7261.       outInlPath.AppendFormat (_T ("mslp%d_%d_%d_%d.inl"), mapIndex, point->x, point->y, palIndex);
  7262.       outPalPath.AppendFormat (_T ("mslp%d_%d_%d_%d.pal"), mapIndex, point->x, point->y, palIndex);
  7263.     } else {
  7264.       ATLASSERT (FALSE);
  7265.     }
  7266.     if (FAILED (sig = outInlFd.Create (outInlPath,
  7267.              GENERIC_READ | GENERIC_WRITE,
  7268.               FILE_SHARE_READ,
  7269.               CREATE_ALWAYS)) != FALSE) {
  7270.              return sig;
  7271.     }
  7272.     if (FAILED (sig = outPalFd.Create (outPalPath,
  7273.              GENERIC_READ | GENERIC_WRITE,
  7274.               FILE_SHARE_READ,
  7275.               CREATE_ALWAYS)) != FALSE) {
  7276.              return sig;
  7277.     }
  7278.     for (auto count = 0;
  7279.       count != 16;
  7280.       count += 4)
  7281.     {
  7282.       PBYTE source = & pal->pal[count];
  7283.  
  7284.       comment.AppendFormat ("/* bank %d */  0x%02X, 0x%02X, 0x%02X, 0x%02X",
  7285.                              count >> 2,  source[0] & 0x3F,
  7286.                                           source[1] & 0x3F,
  7287.                                           source[2] & 0x3F, source[3] & 0x3F);
  7288.  
  7289.       if (count != 12) {
  7290.         comment += ", \n";
  7291.       }
  7292.     }
  7293.     comment += "\n};";
  7294.     sig = outInlFd.Write (comment.GetString (),
  7295.                                 comment.GetLength ());
  7296.     ATLASSERT (SUCCEEDED (sig));
  7297.     sig = outPalFd.Write (pal->pal, 16);
  7298.     ATLASSERT (SUCCEEDED (sig));
  7299.     return sig;
  7300.   }
  7301.  
  7302.   HRESULT outputCC65 (CString filePath) {
  7303.     HRESULT sig = 0;
  7304.    
  7305.     BYTE transMapper = 0;
  7306.  
  7307.     PathRemoveBackslash (filePath.GetBuffer ());
  7308.    
  7309.     filePath.ReleaseBuffer ();
  7310.     filePath += _T ("\\");
  7311.  
  7312.     // Output globals.h
  7313.     CStringA globalsString(
  7314. #include "nne_globals.string"
  7315.       );
  7316.     CStringA outputString;
  7317.     CAtlFile outGlobalsFd;
  7318.     CAtlFile outOutputFd;
  7319.  
  7320.     //TODO: Check
  7321.     CString nneOutputBase = filePath + _T ("NNametableEditorOutput");
  7322.     CString nneOutputCC65 = nneOutputBase + _T ("\\cc65");
  7323.     CString nneOutputCC65_chr = nneOutputBase + _T ("\\cc65\\chr");
  7324.     CString nneOutputCC65_map = nneOutputBase + _T ("\\cc65\\map");
  7325.     CString nneOutputCC65_gpal = nneOutputBase + _T ("\\cc65\\global_palette");
  7326.     CString nneOutputCA65 = nneOutputBase + _T ("\\ca65");
  7327.     CString nneOutputCA65_chr = nneOutputBase + _T ("\\ca65\\chr");
  7328.     CString nneOutputCA65_map = nneOutputBase + _T ("\\ca65\\map");
  7329.     CString nneOutputCA65_gpal = nneOutputBase + _T ("\\ca65\\global_palette");
  7330.    
  7331.     // Create file path...
  7332.     :: CreateDirectory (nneOutputBase, NULL);
  7333.     :: CreateDirectory (nneOutputCC65, NULL);
  7334.     :: CreateDirectory (nneOutputCC65_chr, NULL);
  7335.     :: CreateDirectory (nneOutputCC65_map, NULL);
  7336.     :: CreateDirectory (nneOutputCC65_gpal, NULL);
  7337.     :: CreateDirectory (nneOutputCA65, NULL);
  7338.     :: CreateDirectory (nneOutputCA65_chr, NULL);
  7339.     :: CreateDirectory (nneOutputCA65_map, NULL);
  7340.     :: CreateDirectory (nneOutputCA65_gpal, NULL);
  7341.    
  7342.     // Prepare nne_globals header.
  7343.     if (FAILED (sig = outGlobalsFd.Create (nneOutputCC65 + _T ("\\nne_globals.h"),
  7344.               GENERIC_READ | GENERIC_WRITE,
  7345.               FILE_SHARE_READ,
  7346.               CREATE_ALWAYS)) != FALSE) {
  7347.               return sig;
  7348.     }
  7349.     sig = outGlobalsFd.Write (globalsString.GetString (),
  7350.                                 globalsString.GetLength ());
  7351.     ATLASSERT (SUCCEEDED (sig));
  7352.  
  7353.     // Prepare nne_bg header.
  7354.     if (FAILED (sig = outOutputFd.Create (nneOutputCC65 + _T ("\\nne_bg.h"),
  7355.               GENERIC_READ | GENERIC_WRITE,
  7356.               FILE_SHARE_READ,
  7357.               CREATE_ALWAYS)) != FALSE) {
  7358.               return sig;
  7359.     }
  7360.     outputString.Append ("#include \"nne_globals.h\"\n\n");
  7361.  
  7362.     // Create sub map path...
  7363.     for (auto it = 0; it != m_GuiLV_Map.GetItemCount (); it ++) {
  7364.       CString subMapPath = nneOutputCC65_map + _T ("\\");
  7365.       subMapPath.AppendFormat (_T ("sub%d"), it);
  7366.      
  7367.       :: CreateDirectory (subMapPath , NULL);
  7368.       :: CreateDirectory (subMapPath , NULL);
  7369.     }
  7370.     // <Output CC65-CHR> ===============================================================================
  7371.     outputString.Append ("//  <section-chr #include>\n");
  7372.     for (auto it = 0; it != m_ChrVec.GetCount (); it ++) {
  7373.       CChr *chr = m_ChrVec[it];
  7374.      
  7375.       CString chrInlPath = nneOutputCC65_chr + _T ("\\");
  7376.       CString chrChrPath = nneOutputCC65_chr + _T ("\\");
  7377.      
  7378.       chrInlPath.AppendFormat (_T ("chr%d.inl"), it);
  7379.       chrChrPath.AppendFormat (_T ("chr%d.chr"), it);
  7380.  
  7381.       outputString.AppendFormat ("#include \"chr/chr%d.inl\" // %s\n", it, CStringA (chr->comment));
  7382.  
  7383.       // Create .inl/.chr files.
  7384.       CAtlFile chrInlFd;
  7385.       CAtlFile chrFileFd;  
  7386.      
  7387.       if (FAILED (sig = chrInlFd.Create (chrInlPath,
  7388.                GENERIC_READ | GENERIC_WRITE,
  7389.                 FILE_SHARE_READ,
  7390.                 CREATE_ALWAYS)) != FALSE) {
  7391.                return sig;
  7392.       }
  7393.       if (FAILED (sig = chrFileFd.Create (chrChrPath,
  7394.                GENERIC_READ | GENERIC_WRITE,
  7395.                 FILE_SHARE_READ,
  7396.                 CREATE_ALWAYS)) != FALSE) {
  7397.                return sig;
  7398.       }
  7399.      
  7400.       // Out chr content -comment
  7401.       CStringA comment;
  7402.       comment.Format ( "// --------------------------------------------------\n"
  7403.                        "// Section:Chr \n"
  7404.                        "// Index[Comment]:%d %s\n"
  7405.                        "// --------------------------------------------------\n"
  7406.                        "#define NNE_CHR_%s nne_chr%d\n"
  7407.                        "unsigned char nne_chr%d[0x1000] = { \n",
  7408.                        it, /* index */
  7409.                        CStringA (chr->comment), /* comment */
  7410.                        CStringA (chr->comment), /* comment */
  7411.                        it, /* index */
  7412.                        it  /* index */);
  7413.  
  7414.       // Out chr content -buffer
  7415.       for (auto count = 0;
  7416.         count != 4096;
  7417.         count += 16)
  7418.       {
  7419.         PBYTE source = & chr->chr[count];
  7420.  
  7421.         comment.AppendFormat ("  0x%02X, 0x%02X, 0x%02X, 0x%02X,"
  7422.                                      " 0x%02X, 0x%02X, 0x%02X, 0x%02X,"
  7423.                                      " 0x%02X, 0x%02X, 0x%02X, 0x%02X,"
  7424.                                      " 0x%02X, 0x%02X, 0x%02X, 0x%02X",
  7425.                                      source[0], source[1], source[2], source[3],
  7426.                                      source[4], source[5], source[6], source[7],
  7427.                                      source[8], source[9], source[10], source[11],
  7428.                                      source[12], source[13], source[14], source[15]);
  7429.  
  7430.         if (count != 4096 - 16) {
  7431.           comment += ", \n";
  7432.         }
  7433.       }
  7434.       comment += "\n};";
  7435.      
  7436.       sig = chrInlFd.Write (comment.GetString (),
  7437.                                   comment.GetLength ());
  7438.       ATLASSERT (SUCCEEDED (sig));
  7439.       sig = chrFileFd.Write (& chr->chr[0], 4096);
  7440.       ATLASSERT (SUCCEEDED (sig));
  7441.     }
  7442.     // Output global palette...
  7443.     outputString.Append ("//  <global palette #include>\n");
  7444.     for (auto it = 0; it != m_globalPal.GetCount (); it ++) {
  7445.       auto pal = m_globalPal[it];
  7446.       outputString.AppendFormat ("#include \"global_palette/msgp%d.inl\" // %s\n", it, CStringA (pal->comment));
  7447.  
  7448.       writeSourcePalFiles (0, nneOutputCC65_gpal, it, pal);
  7449.     }
  7450.     // Output sub map view .
  7451.     outputString.Append ("//  <section-map #include>\n");
  7452.     for (auto it = 0; it != m_MapVec.GetCount (); it ++) {
  7453.       CString subMapPath = nneOutputCC65_map + _T ("\\");
  7454.       CString subMapPathSubInl = subMapPath;
  7455.       CStringA subComment;
  7456.       CAtlFile subHeader;
  7457.       subMapPath.AppendFormat (_T ("sub%d"), it);
  7458.       subMapPathSubInl.AppendFormat (_T ("sub%d.inl"), it);  
  7459.  
  7460.       auto map = m_MapVec[it];
  7461.       ATLASSERT (map != NULL);
  7462.  
  7463.       outputString.AppendFormat ("#include \"map/sub%d.inl\" // %s %d %d spcount:%d\n",
  7464.                               it, CStringA (map->comment), map->width, map->height,
  7465.                                      map->staticPal.GetCount ());
  7466.       atlCreateRwOverwriteFileAssert (subHeader, subMapPathSubInl);
  7467.  
  7468.       // Output sub map static palette
  7469.       subComment.AppendFormat ("// <static-palette>:%d\n", map->staticPal.GetCount ());
  7470.  
  7471.       auto spallist = & map->staticPal;
  7472.       for (auto q = 0; q != spallist->GetCount (); q ++) {
  7473.         auto pal = (*spallist)[q];
  7474.         subComment.AppendFormat ("#include \"sub%d/mssp%d_%d\" // %s\n", it, it, q, CStringA (pal->comment));
  7475.  
  7476.         writeSourcePalFiles (1, subMapPath, q, pal, it, map);
  7477.       }
  7478.        
  7479.       const auto pageTotal = map->width * map->height;
  7480.  
  7481.       for (auto q = 0; q != pageTotal; q++) {
  7482.         auto nt = map->ntList[q];
  7483.         auto x = q % map->width;
  7484.         auto y = q / map->width;
  7485.  
  7486.         subComment.AppendFormat ("//<nametable page>: pos: %d %d pcnt:%d acnt:%d\n",
  7487.                                       x, y, nt->palList.GetCount (), nt->attrList.GetCount ());
  7488.  
  7489.         CString ntPathBase = subMapPath + _T ("\\");
  7490.         CString ntPathInlOut = ntPathBase;
  7491.         CString ntPathNamOut = ntPathBase;
  7492.  
  7493.         CAtlFile ntInlFd;
  7494.         CAtlFile ntNamFd;
  7495.  
  7496.         subComment.AppendFormat ("#include \"sub%d/msnt%d_%d_%d.inl\"\n",  it, it, x, y);
  7497.         ntPathInlOut.AppendFormat (_T ("msnt%d_%d_%d.inl"), it, x, y);
  7498.         ntPathNamOut.AppendFormat (_T ("msnt%d_%d_%d.nam"), it, x, y);
  7499.  
  7500.         if (FAILED (sig = ntInlFd.Create (ntPathInlOut,
  7501.                  GENERIC_READ | GENERIC_WRITE,
  7502.                   FILE_SHARE_READ,
  7503.                   CREATE_ALWAYS)) != FALSE) {
  7504.                  return sig;
  7505.         }
  7506.         if (FAILED (sig = ntNamFd.Create (ntPathNamOut,
  7507.                  GENERIC_READ | GENERIC_WRITE,
  7508.                   FILE_SHARE_READ,
  7509.                   CREATE_ALWAYS)) != FALSE) {
  7510.                  return sig;
  7511.         }
  7512.         // Output nametable .inl | .nam
  7513.         CStringA comment;
  7514.  
  7515.         CStringA indexMixerA;
  7516.         CString indexMixer;
  7517.            
  7518.         indexMixerA.Format ("%d_%d_%d", it, x, y);
  7519.         indexMixer.Format (_T ("%d_%d_%d"), it, x, y);      
  7520.  
  7521.         comment.Append ("// --------------------------------------------------\n");
  7522.         comment.Append ("// Section:Namtable\n");  
  7523.         comment.AppendFormat (
  7524.                         "// PalCount:%d\n", nt->palList.GetCount ());
  7525.         comment.AppendFormat (
  7526.                         "// AttrCount:%d\n", nt->attrList.GetCount ());
  7527.         if (nt->chr != NULL)
  7528.         comment.AppendFormat (
  7529.                         "// Attach chr[Comment]:%d %s\n", forceFindIndexByComment <CChr> (
  7530.                                                                                m_ChrVec, & nt->chr->comment ),  
  7531.                                                                                          CStringA (nt->chr->comment));
  7532.         else
  7533.         comment.AppendFormat ("// Attach chr[Comment]:-1\n");
  7534.  
  7535.         comment.AppendFormat (
  7536.                         "// SubMapper Index[Comment]:%d %s\n", it, CStringA (map->comment));                                                                                      
  7537.         comment.AppendFormat (
  7538.                         "// SubMapper Size:%d %d\n", map->width, map->height);                                                                                        
  7539.                                                                                          
  7540.         comment.AppendFormat (
  7541.                         "// SubMapper Position:%d %d\n", x, y);
  7542.         if (nt->pal != NULL)
  7543.         comment.AppendFormat (
  7544.                         "// Default use palette :%s %d %s\n", nt->getSelectPalSource (),
  7545.                                                               nt->getSelectPalSourceOffset (), nt->pal->comment);
  7546.         else
  7547.         comment.Append ("// Default use palette :null\n");
  7548.         if (nt->attr != NULL)
  7549.         comment.AppendFormat (
  7550.                         "// Default use attr table:%d %s\n",  forceFindIndexByComment <CAttr> (
  7551.                                                                                nt->attrList, & nt->attr->comment ),  
  7552.                                                                                         CStringA (nt->attr->comment) );
  7553.         else
  7554.         comment.Append ("// Default use palette :-1\n");
  7555.                        
  7556.         comment.Append ("// --------------------------------------------------\n");                  
  7557.         comment.AppendFormat (
  7558.                         "#define MSNT%s msnt%s\n", indexMixerA, indexMixerA);            
  7559.         comment.AppendFormat (
  7560.                         "unsigned char msnt%s[0x400] = { \n",  indexMixerA);
  7561.                        
  7562.         comment.Append (" /* -----             00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
  7563.                                               "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F */\n");
  7564.         // Output buffer ...
  7565.         for (auto count = 0;
  7566.           count != 960;
  7567.           count += 32)
  7568.         {
  7569.           PWORD source = & nt->tileSlot[count];
  7570.  
  7571.           comment.AppendFormat (" /* %02X */ NNE_NT_LINE(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,"
  7572.                          "%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,"
  7573.                          "%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,"
  7574.                          "%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X)",
  7575.                                        count >> 5,
  7576. #define TTN(index)\
  7577. source[index] & 0x8000 ? transMapper : source[index] & 0xFF
  7578.                                        TTN (0), TTN (1), TTN (2), TTN (3),
  7579.                                        TTN (4), TTN (5), TTN (6), TTN (7),
  7580.                                        TTN (8), TTN (9), TTN (10), TTN (11),
  7581.                                        TTN (12), TTN (13), TTN (14), TTN (15),
  7582.                                        TTN (16), TTN (17), TTN (18), TTN (19),
  7583.                                        TTN (20), TTN (21), TTN (22), TTN (23),
  7584.                                        TTN (24), TTN (25), TTN (26), TTN (27),
  7585.                                        TTN (28), TTN (29), TTN (30), TTN (31) );
  7586. #undef TTN
  7587.           if (count != 960 - 32) {
  7588.             comment += ", \n";
  7589.           }
  7590.         }
  7591.         comment += "\n};";
  7592.        
  7593.         sig = ntInlFd.Write (comment.GetString (),
  7594.                                     comment.GetLength ());
  7595.         ATLASSERT (SUCCEEDED (sig));
  7596.  
  7597.         for (auto it = 0; it != 960; it += 4)  {
  7598.           BYTE filldw[4];
  7599.           filldw[0] = nt->tileSlot[it+0] & 0x8000 ? transMapper : nt->tileSlot[it+0] & 0xFF;
  7600.           filldw[1] = nt->tileSlot[it+1] & 0x8000 ? transMapper : nt->tileSlot[it+1] & 0xFF;
  7601.           filldw[2] = nt->tileSlot[it+2] & 0x8000 ? transMapper : nt->tileSlot[it+2] & 0xFF;
  7602.           filldw[3] = nt->tileSlot[it+3] & 0x8000 ? transMapper : nt->tileSlot[it+3] & 0xFF;
  7603.           sig = ntNamFd.Write (& filldw[0], 4);
  7604.           ATLASSERT (SUCCEEDED (sig));
  7605.         }
  7606.         // Output attr table
  7607.         for (auto z = 0; z != nt->attrList.GetCount (); z++) {
  7608.           auto attr = nt->attrList[z];
  7609.  
  7610.           subComment.AppendFormat ("#include \"sub%d/msat%d_%d_%d_%d.inl\" // %s\n",  it, it, x, y, z, CStringA (attr->comment));
  7611.  
  7612.           CString ntPathBase = subMapPath + _T ("\\");
  7613.           CString attrPathInlOut = ntPathBase;
  7614.           CString attrPathAttrOut = ntPathBase;
  7615.  
  7616.           CAtlFile attrInlFd;
  7617.           CAtlFile attrAttrFd;
  7618.  
  7619.           CStringA comment;
  7620.           CStringA indexMixerA;
  7621.           CString indexMixer;
  7622.            
  7623.           indexMixerA.Format ("%d_%d_%d_%d", it, x, y, z);
  7624.           indexMixer.Format (_T ("%d_%d_%d_%d"), it, x, y, z);      
  7625.          
  7626.           attrPathInlOut += _T ("msat") + indexMixer + _T (".inl");
  7627.           attrPathAttrOut += _T ("msat") + indexMixer + _T (".attr");
  7628.  
  7629.           if (FAILED (sig = attrInlFd.Create (attrPathInlOut,
  7630.                    GENERIC_READ | GENERIC_WRITE,
  7631.                     FILE_SHARE_READ,
  7632.                     CREATE_ALWAYS)) != FALSE) {
  7633.                    return sig;
  7634.           }
  7635.           if (FAILED (sig = attrAttrFd.Create (attrPathAttrOut,
  7636.                    GENERIC_READ | GENERIC_WRITE,
  7637.                     FILE_SHARE_READ,
  7638.                     CREATE_ALWAYS)) != FALSE) {
  7639.                    return sig;
  7640.           }
  7641.  
  7642.           comment.Append ("// --------------------------------------------------\n");
  7643.           comment.Append ("// Section:Attr table\n\n");  
  7644.           comment.AppendFormat (
  7645.                           "// Index[Comment]:%d %s\n", z, CStringA (attr->comment));
  7646.           comment.AppendFormat (
  7647.                           "// SubMapper Index[Comment]:%d %s\n", it, CStringA (map->comment));
  7648.           comment.AppendFormat (
  7649.                           "// SubMapper Size:%d %d\n\n", map->width, map->height);
  7650.           comment.AppendFormat (
  7651.                           "// SubMapper Position:%d %d\n", x, y);
  7652.           comment.Append ("// --------------------------------------------------\n");                  
  7653.           comment.AppendFormat (
  7654.                           "#define MSAT%s%s msat%s\n", indexMixerA, CStringA (attr->comment),
  7655.                                                                    indexMixerA  );                  
  7656.           comment.AppendFormat (
  7657.                           "NNE_ATTR_TABLE_INIT (msat%s,\n",  indexMixerA);
  7658.                          
  7659.           comment.Append (" /* ----- 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 */\n");
  7660.                    
  7661.           // Output buffer ...
  7662.           for (DWORD count = 0;
  7663.             count != 16;
  7664.             count += 1)
  7665.           {
  7666.             DWORD atrSftLo = count & 1 << 2;
  7667.             DWORD atrSftHi = atrSftLo + 2;
  7668.             PBYTE atrPtr = & attr->attr[count >> 1 << 3];
  7669.            
  7670.             comment.AppendFormat (" /* %02d */ %d,%d,%d,%d"
  7671.                                              ",%d ,%d ,%d ,%d"
  7672.                                              " ,%d ,%d ,%d ,%d"
  7673.                                              " ,%d ,%d ,%d ,%d",
  7674.                                      count << 1,
  7675.                                        atrPtr[0] >> atrSftLo & 3, atrPtr[0] >> atrSftHi & 3,
  7676.                                        atrPtr[1] >> atrSftLo & 3, atrPtr[1] >> atrSftHi & 3,                                      
  7677.                                        atrPtr[2] >> atrSftLo & 3, atrPtr[2] >> atrSftHi & 3,
  7678.                                        atrPtr[3] >> atrSftLo & 3, atrPtr[3] >> atrSftHi & 3,                                          
  7679.                                        atrPtr[4] >> atrSftLo & 3, atrPtr[4] >> atrSftHi & 3,
  7680.                                        atrPtr[5] >> atrSftLo & 3, atrPtr[5] >> atrSftHi & 3,                                      
  7681.                                        atrPtr[6] >> atrSftLo & 3, atrPtr[6] >> atrSftHi & 3,
  7682.                                        atrPtr[7] >> atrSftLo & 3, atrPtr[7] >> atrSftHi & 3);
  7683.             if (count != 16 - 1)
  7684.               comment += ", \n";
  7685.             else
  7686.               comment += ")";
  7687.           }  
  7688.           sig = attrInlFd.Write (comment.GetString (),
  7689.                                       comment.GetLength ());
  7690.           ATLASSERT (SUCCEEDED (sig));
  7691.           sig = attrAttrFd.Write (& attr->attr[0], 64);
  7692.           ATLASSERT (SUCCEEDED (sig));
  7693.         }
  7694.         // Output local palette
  7695.         for (auto z = 0; z != nt->palList.GetCount (); z++) {
  7696.           auto pal = nt->palList[z];
  7697.           subComment.AppendFormat ("#include \"sub%d/mslp%d_%d_%d_%d.inl\"// %s\n",  it, it, x, y, z, CStringA (pal->comment));
  7698.  
  7699.           writeSourcePalFiles (2, subMapPath, z, nt->palList[z], it, map, & CPoint (x, y), nt);
  7700.         }
  7701.       }
  7702.       sig = subHeader.Write (subComment.GetString (),
  7703.                                   subComment.GetLength ());
  7704.       ATLASSERT (SUCCEEDED (sig));
  7705.     }
  7706.     sig = outOutputFd.Write (outputString.GetString (),
  7707.                                 outputString.GetLength ());
  7708.     ATLASSERT (SUCCEEDED (sig));
  7709.     return FALSE;
  7710.   }
  7711.  
  7712.   HRESULT OnOutputCC65 (WORD, WORD, HWND, BOOL &bHandled) {
  7713.     CFolderDialog win32fd_dlg (*this, _T ("Output cc65 files"), BIF_USENEWUI|BIF_RETURNONLYFSDIRS);
  7714.  
  7715.     if (win32fd_dlg.DoModal () == IDOK) {
  7716.       outputCC65 (win32fd_dlg.m_szFolderPath);
  7717.     }
  7718.  
  7719.     return 0;
  7720.   }
  7721.  
  7722.   // <CSetPagePalette> =========================================
  7723.   template <BOOL t_bReadWriteMap, DWORD t_dwSourcePaletteType>
  7724.   struct CSetPagePalette : public CDialogImpl<CSetPagePalette<t_bReadWriteMap, t_dwSourcePaletteType>>
  7725.   {
  7726.     typedef CSetPagePalette thisClass;
  7727.     typedef CDialogImpl<CSetPagePalette<t_bReadWriteMap, t_dwSourcePaletteType>> baseClass;
  7728.  
  7729.     CMainFrame &m_attthis;
  7730.     CComboBox m_GuiCB_Index;
  7731.  
  7732.     CSetPagePalette (CMainFrame &psthis):
  7733.         m_attthis (psthis){}
  7734.  
  7735.     enum { IDD = IDD_SETPAGE_PALETTE };
  7736.  
  7737.     BEGIN_MSG_MAP(thisClass)
  7738.       MESSAGE_HANDLER (WM_INITDIALOG, OnCreate)
  7739.       MESSAGE_HANDLER (WM_CLOSE, OnClose)
  7740.       COMMAND_ID_HANDLER (IDBT_SETPAGE_PALETTE_SETTINGS, OnSettings)
  7741.     END_MSG_MAP()
  7742.  
  7743.     LRESULT OnSettings (WORD, WORD, HWND, BOOL& bHandled) {
  7744.      
  7745.       CMainFrame::CCPObjectHelper<t_bReadWriteMap> helper (m_attthis);
  7746.  
  7747.       auto &lvPage = *helper.getCPListViewObject ();
  7748.       auto itemSel = lvPage.GetNextItem (-1, LVNI_SELECTED);
  7749.       auto itemSetIndex = m_GuiCB_Index.GetCurSel ();
  7750.  
  7751.       while (itemSel >= 0) {
  7752.         auto nt = lvPage.GetItemDataT (itemSel);
  7753.         ATLASSERT (nt != NULL);
  7754.  
  7755.         if (t_dwSourcePaletteType == 0) {
  7756.           nt->pal = nt->globalPalList[itemSetIndex];
  7757.           nt->setIfEmptySelect0 ();
  7758.         } else if (t_dwSourcePaletteType == 1) {
  7759.           nt->pal = nt->staticPalList[itemSetIndex];
  7760.           nt->setIfEmptySelect0 ();
  7761.         } else if (t_dwSourcePaletteType == 2) {
  7762.           nt->chr = m_attthis.m_ChrVec[itemSetIndex];
  7763.         }
  7764.         // Reset text.
  7765.         lvPage.SetItem (itemSel, 1, LVIF_IMAGE | LVIF_TEXT, nt->chr ? nt->chr->comment : _T ("null"), 1, 0, 0, 0);
  7766.         lvPage.SetItem (itemSel, 2, LVIF_IMAGE | LVIF_TEXT, nt->pal ? nt->pal->comment : _T ("null"), 2 + nt->getSelectPalSourceIndex (), 0, 0, 0);
  7767.         lvPage.SetItem (itemSel, 3, LVIF_IMAGE | LVIF_TEXT, nt->attr ? nt->attr->comment : _T ("null"), 5, 0, 0, 0);
  7768.  
  7769.         itemSel = lvPage.GetNextItem (itemSel, LVNI_SELECTED);
  7770.       }
  7771.       helper.allCPCellViewSMutUpdate ();
  7772.  
  7773.       m_attthis.m_GuiSWin_Nesmap.nesPixelGenerator ();
  7774.  
  7775.       EndDialog (IDOK);
  7776.  
  7777.       return 0;
  7778.     }
  7779.  
  7780.     LRESULT OnClose (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  7781.       bHandled = FALSE;
  7782.       EndDialog (IDCANCEL);
  7783.  
  7784.       return 0;
  7785.     }
  7786.  
  7787.     /* t_dwSourcePaletteType 0 := global palette settings */
  7788.     /* t_dwSourcePaletteType 1 := static palette settings */
  7789.     /* t_dwSourcePaletteType 2 := chr settings */
  7790.     LRESULT OnCreate (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
  7791.      
  7792.       m_GuiCB_Index.Attach (GetDlgItem (IDCB_SETPAGE_PALINDEX));
  7793.  
  7794. #define SPP_SETITEM_BASE(capSettingsText, attObj, errorsText, errorsCaption)\
  7795.   SetWindowText (capSettingsText);\
  7796.   \
  7797.   auto &vec = attObj;\
  7798.   \
  7799.   if (vec.GetCount () != 0) {\
  7800.     for (auto it = 0; it != vec.GetCount (); it++) {\
  7801.       CString output;\
  7802.       output.Format (_T ("%d %s"), it, vec[it]->comment);\
  7803.       m_GuiCB_Index.InsertString (it, output);\
  7804.     }\
  7805.     m_GuiCB_Index.SetCurSel (0);\
  7806.     return 0;\
  7807.   } else {\
  7808.     AtlMessageBox (*this, errorsText, errorsCaption, MB_ICONERROR);\
  7809.     EndDialog (IDCANCEL);\
  7810.     return 0;\
  7811.   }
  7812.       if (t_dwSourcePaletteType == 0) {
  7813.         SPP_SETITEM_BASE (_T ("Glabal Palette Page Settings-"), m_attthis.m_globalPal, _T ("no global palette"), _T ("CSetPagePalette"));
  7814.       } else if (t_dwSourcePaletteType == 1) {
  7815.         SPP_SETITEM_BASE (_T ("Static Palette Page Settings-"), m_attthis.m_ShowMap->staticPal, _T ("no static palette"), _T ("CSetPagePalette"));
  7816.       }  else if (t_dwSourcePaletteType == 2) {
  7817.         SPP_SETITEM_BASE (_T ("Chr Page Settings-"), m_attthis.m_ChrVec, _T ("no chr"), _T ("CSetPageChr"));
  7818.       } else {
  7819.         ATLASSERT (FALSE);
  7820.       }  
  7821. #undef   SPP_SETITEM_BASE
  7822.       bHandled = FALSE;
  7823.       return 0;
  7824.     }
  7825.   };
  7826.   /* t_dwSourcePaletteType 0 := global palette settings */
  7827.   /* t_dwSourcePaletteType 1 := static palette settings */
  7828.   /* t_dwSourcePaletteType 2 := chr settings */
  7829.   template <BOOL t_bReadWriteMap, DWORD t_dwSourcePaletteType> // @NEXTTASK
  7830.   HRESULT OnSetCommonPaletteT (WORD, WORD, HWND, BOOL &bHandled) {
  7831.     CSetPagePalette<t_bReadWriteMap, t_dwSourcePaletteType>  (*this).DoModal ();
  7832.     return 0;
  7833.   }
  7834.  
  7835.   HRESULT OnLoadNNE (WORD, WORD, HWND, BOOL &bHandled) {
  7836.     CFileDialogFilter df (_T("NNE files (*.nne)| *.nne"));
  7837.     CFileDialog fd_dlg  (   TRUE, _T ("Open NNE project..."),
  7838.                                 NULL, OFN_EXPLORER,
  7839.                                 df,
  7840.                                 this->m_hWnd        );
  7841.  
  7842.     if (fd_dlg.DoModal () == IDOK) {
  7843.       CString errors;
  7844.       if (readNNEFile (CString (fd_dlg.m_szFileName), errors) == FALSE) {
  7845.         ///
  7846.         AtlMessageBox (NULL, errors.GetString (),
  7847.             _T ("OnLoadNNE"),
  7848.             MB_ICONERROR);
  7849.         return 0;
  7850.       }
  7851.       allViewUpdate ();
  7852.     }
  7853.     return 0;
  7854.   }
  7855.  
  7856.   HRESULT OnSaveNNE (WORD, WORD, HWND, BOOL &bHandled) {
  7857.  
  7858.     CFileDialogFilter df (_T("NNE files (*.nne)| *.nne"));
  7859.     CFileDialog fd_dlg  (   FALSE, _T ("Save NNE project..."),
  7860.                                 NULL, OFN_EXPLORER,
  7861.                                 df,
  7862.                                 this->m_hWnd        );
  7863.  
  7864.     if (fd_dlg.DoModal () == IDOK) {
  7865.       adjustSpecPalette ();
  7866.  
  7867.       if (writeNNEFile (CString (fd_dlg.m_szFileName)) == FALSE) {
  7868.         ///
  7869.         AtlMessageBox (NULL, _T ("errors- writeNNEFile"),
  7870.             _T ("OnSaveNNE"),
  7871.             MB_ICONERROR);
  7872.         return 0;
  7873.       }
  7874.     }
  7875.     return 0;
  7876.   }
  7877.  
  7878.   void destroyAllItem (void) {
  7879.     m_GuiLV_Chr.DeleteAllItems ();
  7880.     m_GuiLV_Clay.DeleteAllItems ();
  7881.     m_GuiLV_Map.DeleteAllItems ();
  7882.     m_GuiLV_Page.DeleteAllItems ();
  7883.  
  7884.     // Clear chr ...
  7885.     for (auto it = 0; it != m_ChrVec.GetCount (); it ++) {
  7886.       auto p = m_ChrVec[it];
  7887.       if (p != NULL) {
  7888.         delete p;
  7889.       }
  7890.     }
  7891.     // Clear clay
  7892.     for (auto it = 0; it != m_VnpVec.GetCount (); it ++) {
  7893.       auto p = m_VnpVec[it];
  7894.       if (p != NULL) {
  7895.         delete p;
  7896.       }
  7897.     }
  7898.     // Clear map
  7899.     for (auto it = 0; it != m_MapVec.GetCount (); it ++) {
  7900.       auto p = m_MapVec[it];
  7901.       if (p != NULL) {
  7902.         delete p;
  7903.       }
  7904.     }
  7905.     // Clear gloal palete
  7906.     for (auto it = 0; it != m_globalPal.GetCount (); it ++) {
  7907.       auto p = m_globalPal[it];
  7908.       delete p;
  7909.     }
  7910.  
  7911.     m_globalPal.RemoveAll ();
  7912.     m_ChrVec.RemoveAll ();
  7913.     m_VnpVec.RemoveAll ();
  7914.     m_MapVec.RemoveAll ();
  7915.  
  7916.     m_ShowMap = NULL;
  7917.  
  7918.     //Clear windows
  7919.     clearClayWindow ();
  7920.     clearNtpWindow ();
  7921.   }
  7922.  
  7923.  VOID removeChr (CChr *chr) {
  7924.    for (auto It = 0; It != m_ChrVec.GetCount (); It++) {
  7925.      if (m_ChrVec[It] == chr) {
  7926.        // delete nametable page's attach link
  7927.        for (auto Iz = 0; Iz != m_MapVec.GetCount (); Iz++) {
  7928.          auto &vec3 = m_MapVec[Iz]->ntList;
  7929.          for (auto Iq = 0; Iq != vec3.GetCount (); Iq++) {
  7930.            if (vec3[Iq]->chr == chr) {
  7931.              // empty it.
  7932.              vec3[Iq]->chr = NULL;
  7933.            }
  7934.          }
  7935.        }
  7936.        m_ChrVec.RemoveAt( It);
  7937.        delete chr;
  7938.        break;
  7939.      }
  7940.    }
  7941.  }
  7942.  
  7943.  template <typename T>
  7944.  INT32 forceFindIndexByComment (CAtlArray<T *> &vec,  CString *comment) {
  7945.    ATLASSERT (comment != NULL);
  7946.  
  7947.    for (auto it = 0; it != vec.GetCount (); it++) {
  7948.      auto p = vec[it];
  7949.      if (p->comment == *comment) {
  7950.        return it;
  7951.      }
  7952.    }
  7953.    // Never reach here..
  7954.    ATLASSERT (FALSE);
  7955.  }
  7956.  
  7957.  BOOL readNNEFile (LPCTSTR filename, CString &error_) {
  7958.    // CAtlFileMapping
  7959.    CAtlFile win32fd;
  7960.    CAtlFileMapping <BYTE> win32map;
  7961. #undef ERRORS_RET
  7962. #undef EZ_ERRORS_RET
  7963. #define ERRORS_RET(/* LPCTSTR */ error__)\
  7964.   do { error_ = error__ + CGlobals::getLastErrorString (); return FALSE; } while (0)
  7965. #define EZ_ERRORS_RET(/* LPCTSTR */ error__)\
  7966.   do { error_ = error__; return FALSE; } while (0)
  7967. #define READ_COMMENT(/* ptr source string**/loc_string, /* CString **/ pointer, mapperRef) \
  7968.   if ((mapperRef).commentLength != 0) {\
  7969.     CString tmpString ( (LPWSTR) (loc_string), \
  7970.                     (mapperRef).commentLength);\
  7971.     (pointer)->comment = tmpString;\
  7972.   }
  7973.  
  7974.    if (FAILED (win32fd.Create (filename,
  7975.             GENERIC_READ,
  7976.              FILE_SHARE_READ,
  7977.              OPEN_EXISTING)) != FALSE) {
  7978.                ERRORS_RET (_T ("CAtlFile::Create Failed\n"));
  7979.    }
  7980.    if (FAILED (win32map.MapFile
  7981.             (win32fd, 0)) != FALSE) {
  7982.               ERRORS_RET (_T ("CAtlCAtlFileMapping <BYTE>::MapFile Failed\n"));
  7983.    }
  7984.    auto fileSize = win32map.GetMappingSize ();
  7985.    auto pBuffer = static_cast<PBYTE> (win32map.GetData ());
  7986.  
  7987.    if (fileSize >= sizeof (CNNEFile::NNEHeader)) {
  7988.      auto header = (CNNEFile::NNEHeader *) pBuffer;
  7989.      char magic[] = "moecmks  nes-nne";
  7990.      if (strncmp ((const char *)& header->magic[0], magic, sizeof (header->magic)) == 0) {
  7991.        // Check crc32
  7992.        auto crc32 = CGlobals::crc32_intel (0,
  7993.                                         & pBuffer[sizeof (CNNEFile::NNEHeader)],
  7994.                                          fileSize - sizeof (CNNEFile::NNEHeader));
  7995.        if (crc32 == header->crc32_intel) {
  7996.          // Reset current ctx
  7997.          destroyAllItem ();
  7998.  
  7999.          PBYTE pRelocChrPool = & pBuffer[header->chrPoolOffset];
  8000.          PBYTE pRelocAttrPool = & pBuffer[header->attrPoolOffset];
  8001.          PBYTE pRelocPalettePool = & pBuffer[header->palettePoolOffset];
  8002.          PBYTE pRelocNametablePool = & pBuffer[header->nclayPoolOffset];
  8003.          PBYTE pRelocStringPool = & pBuffer[header->stringPoolOffset];
  8004.          
  8005.          // Read global palette...
  8006.          auto gpalChunkPtr = (CNNEFile::palChunk *) & pBuffer[header->gPaletteChainOffset];
  8007.          for (auto it = 0; it != header->gPaletteCount; it++) {
  8008.            auto p = new CPal (CPal::global_palette);
  8009.            auto &src_r = gpalChunkPtr[it];
  8010.  
  8011.            // copy pal index.
  8012.            RtlCopyMemory (p->pal, & pRelocPalettePool[src_r.palIndex << 4], 16);
  8013.  
  8014.            READ_COMMENT ( (& pRelocStringPool[src_r.commentOffset]), p, src_r)
  8015.  
  8016.            m_globalPal.InsertAt (m_globalPal.GetCount (), p);
  8017.          }
  8018.          // Read chr-chain...
  8019.          auto chrChunkPtr = (CNNEFile::chrSectionChunk *) & pBuffer[header->chrChainOffset];
  8020.          for (auto it = 0; it != header->chrCount; it++) {
  8021.            auto pMapper  = & chrChunkPtr[it];
  8022.            auto p = new CChr;
  8023.            // Copy chr
  8024.            RtlCopyMemory (p->chr, & pRelocChrPool[pMapper->chrIndex * 0x1000], 0x1000);
  8025.  
  8026.            READ_COMMENT ( (& pRelocStringPool[pMapper->commentOffset]), p, *pMapper)
  8027.  
  8028.            m_ChrVec.InsertAt (m_ChrVec.GetCount (), p);
  8029.          }
  8030.  
  8031.          // Read clay-chain ...
  8032.          auto pClayOffset = (PDWORD) & pBuffer[header->clayChainOffset];
  8033.  
  8034.          for (auto it =0; it != header->clayCount; it++) {
  8035.            auto pMapperClaySecChunk =
  8036.              (CNNEFile::claySectionChunkHeader  *) & pBuffer[pClayOffset[it]];
  8037.            auto pClay = new CNametableCell<TRUE> (m_globalPal, m_globalPal, FALSE);
  8038.  
  8039.            READ_COMMENT ( (& pRelocStringPool[pMapperClaySecChunk->commentOffset]), pClay, *pMapperClaySecChunk)
  8040.  
  8041.            // Copy nametable
  8042.            RtlCopyMemory (pClay->tileSlot, & pRelocNametablePool[pMapperClaySecChunk->clayIndex * 0x800], 0x800);
  8043.            // Attach chr
  8044.            pClay->chr = NULL;
  8045.            pClay->attr = NULL;
  8046.            pClay->pal = NULL;
  8047.  
  8048.            if (pMapperClaySecChunk->chrIndex != MAXDWORD) {
  8049.              ATLASSERT (pMapperClaySecChunk->chrIndex < m_ChrVec.GetCount ());
  8050.  
  8051.              pClay->chr = m_ChrVec[pMapperClaySecChunk->chrIndex ];
  8052.            }
  8053.            // Copy attr table list
  8054.            auto pAttrChunk = (CNNEFile::attrChunk *) & pBuffer[pClayOffset[it]+sizeof (CNNEFile::claySectionChunkHeader)];
  8055.  
  8056.            for (auto it = 0; it != pMapperClaySecChunk->attrCount; it++) {
  8057.              auto pMapperChunk = & pAttrChunk[it];
  8058.              auto pAttr = new CAttr;
  8059.  
  8060.              READ_COMMENT ( (& pRelocStringPool[pMapperChunk->commentOffset]), pAttr, *pMapperChunk)
  8061.  
  8062.              // Copy nametable
  8063.              RtlCopyMemory (pAttr->attr, & pRelocAttrPool[pMapperChunk->attrIndex * 64], 64);
  8064.  
  8065.              // Check select
  8066.              if (pMapperClaySecChunk->attrSel == it) {
  8067.                pClay->attr = pAttr;
  8068.              }
  8069.              pClay->attrList.InsertAt (pClay->attrList.GetCount (), pAttr);
  8070.            }
  8071.            // Copy pal list
  8072.            auto pPalChunk = (CNNEFile::palChunk *) & pAttrChunk[pMapperClaySecChunk->attrCount];
  8073.  
  8074.            for (auto it = 0; it != pMapperClaySecChunk->paletteCount; it++) {
  8075.              auto pMapperChunk = & pPalChunk[it];
  8076.              auto pPal = new CPal (CPal::private_palette);
  8077.  
  8078.              READ_COMMENT ( (& pRelocStringPool[pMapperChunk->commentOffset]), pPal, *pMapperChunk)
  8079.  
  8080.              // Copy nametable
  8081.              RtlCopyMemory (pPal->pal, & pRelocPalettePool[pMapperChunk->palIndex * 16], 16);
  8082.  
  8083.              pClay->palList.InsertAt (pClay->palList.GetCount (), pPal);
  8084.            }
  8085.            if (pMapperClaySecChunk->paletteSel >= 0) {
  8086.              pClay->setSelectPalette (pMapperClaySecChunk->paletteSel);
  8087.            }
  8088.            m_VnpVec.InsertAt (m_VnpVec.GetCount(), pClay);
  8089.          }
  8090.          // Read map-chain
  8091.          auto pMapOffset = (PDWORD) & pBuffer[header->mapChainOffset];
  8092.  
  8093.          for (auto it =0; it != header->mapCount; it++) {
  8094.            auto mapSpec =
  8095.               (CNNEFile::mapSectionChunk *) & pBuffer[pMapOffset[it]];
  8096.            auto map = new CMapUnit (m_globalPal);
  8097.  
  8098.            READ_COMMENT ( (& pRelocStringPool[mapSpec->commentOffset]), map, *mapSpec)
  8099.  
  8100.           map->width = mapSpec->width;
  8101.           map->height = mapSpec->height;
  8102.  
  8103.           // Read static palette
  8104.           auto spalChunkPtr = (CNNEFile::palChunk *) & pBuffer[pMapOffset[it] + sizeof (CNNEFile::mapSectionChunk)];
  8105.           for (auto it = 0; it != mapSpec->sPaletteCount; it++) {
  8106.             auto p = new CPal (CPal::static_palette);
  8107.             auto &src_r = spalChunkPtr[it];
  8108.  
  8109.             // copy pal index.
  8110.             RtlCopyMemory (p->pal, & pRelocPalettePool[src_r.palIndex << 4], 16);
  8111.  
  8112.             READ_COMMENT ( (& pRelocStringPool[src_r.commentOffset]), p, src_r)
  8113.  
  8114.             map->staticPal.InsertAt (map->staticPal.GetCount (), p);
  8115.           }
  8116.  
  8117.           const auto totalAllocpage = mapSpec->height * mapSpec->width;
  8118.  
  8119.           auto pPageOffset = (PDWORD)
  8120.             & spalChunkPtr[mapSpec->sPaletteCount];
  8121.  
  8122.           for (auto it = 0; it != totalAllocpage; it++) {
  8123.             auto map_page =
  8124.             (CNNEFile::mapSectionPageChunk *) & pBuffer[pPageOffset[it]];
  8125.  
  8126.             // Alloc new page..
  8127.             auto na_page = new CNametableCell<FALSE> (map->staticPal, m_globalPal, FALSE);
  8128.  
  8129.              // Copy nametable
  8130.              RtlCopyMemory (na_page->tileSlot, & pRelocNametablePool[map_page->nametableIndex * 0x800], 0x800);
  8131.            
  8132.              na_page->chr = NULL;
  8133.              na_page->attr = NULL;
  8134.              na_page->pal = NULL;
  8135.  
  8136.              // Attach chr
  8137.              if (map_page->chrIndex != MAXDWORD) {
  8138.                ATLASSERT (map_page->chrIndex < m_ChrVec.GetCount ());
  8139.  
  8140.                na_page->chr = m_ChrVec[map_page->chrIndex];
  8141.              }
  8142.              // Copy attr table list
  8143.              auto pAttrChunk = (CNNEFile::attrChunk *) & pBuffer[pPageOffset[it]+sizeof (CNNEFile::mapSectionPageChunk)];
  8144.  
  8145.              for (auto it = 0; it != map_page->attrCount; it++) {
  8146.                auto pMapperChunk = & pAttrChunk[it];
  8147.                auto pAttr = new CAttr;
  8148.  
  8149.                READ_COMMENT ( (& pRelocStringPool[pMapperChunk->commentOffset]), pAttr, *pMapperChunk)
  8150.  
  8151.                // Copy nametable
  8152.                RtlCopyMemory (pAttr->attr, & pRelocAttrPool[pMapperChunk->attrIndex * 64], 64);
  8153.  
  8154.                // Check select
  8155.                if (map_page->attrSel == it) {
  8156.                  na_page->attr = pAttr;
  8157.                }
  8158.                na_page->attrList.InsertAt (na_page->attrList.GetCount (), pAttr);
  8159.              }
  8160.              // Copy pal list
  8161.              auto pPalChunk = (CNNEFile::palChunk *) & pAttrChunk[map_page->attrCount];
  8162.  
  8163.              for (auto it = 0; it != map_page->paletteCount; it++) {
  8164.                auto pMapperChunk = & pPalChunk[it];
  8165.                auto pPal = new CPal (CPal::private_palette);
  8166.  
  8167.                READ_COMMENT ( (& pRelocStringPool[pMapperChunk->commentOffset]), pPal, *pMapperChunk)
  8168.  
  8169.                // Copy nametable
  8170.                RtlCopyMemory (pPal->pal, & pRelocPalettePool[pMapperChunk->palIndex * 16], 16);
  8171.  
  8172.                na_page->palList.InsertAt ( na_page->palList.GetCount (), pPal);
  8173.              }
  8174.              na_page->setSelectPalette (map_page->paletteSel);
  8175.              map->ntList.InsertAt (map->ntList .GetCount (), na_page);
  8176.           }
  8177.           m_MapVec.InsertAt ( m_MapVec.GetCount (), map);
  8178.          }
  8179.          // re-build all item.
  8180.          for (auto it = 0; it != m_ChrVec.GetCount (); it++) {
  8181.            auto p = m_ChrVec[it];
  8182.            m_GuiLV_Chr.InsertItem (it, p->comment.GetLength () > 0 ? p->comment : _T (""), 0);
  8183.            m_GuiLV_Chr.SetItemData (it,     reinterpret_cast <DWORD_PTR> ( p));
  8184.          }
  8185.          for (auto it = 0; it != m_VnpVec.GetCount (); it++) {
  8186.            auto p = m_VnpVec[it];
  8187.  
  8188.            // Set first snapshot cache.
  8189.            p->snapshotToUndoStack ();
  8190.  
  8191.            appendToItemToViewClayList (p);
  8192.          }
  8193.          for (auto it = 0; it != m_MapVec.GetCount (); it++) {
  8194.            auto p = m_MapVec[it];
  8195.            m_GuiLV_Map.InsertItem (it, p->comment.GetLength () > 0 ? p->comment : _T (""), 0);
  8196.            m_GuiLV_Map.SetItemData (it,     reinterpret_cast <DWORD_PTR> ( p));
  8197.          }
  8198.          return TRUE;
  8199.        }
  8200.        EZ_ERRORS_RET ( _T ("crc32 mismatch !\ncorrupted or tampered"));
  8201.      }
  8202.      EZ_ERRORS_RET ( _T ("Magic header mismatch !"));
  8203.    }
  8204.    EZ_ERRORS_RET ( _T ("File too short !"));
  8205.    return FALSE;
  8206.  }
  8207.  
  8208.  BOOL writeNNEFile (CString &filepath) {
  8209.    CAtlFile win32fd;
  8210.  
  8211.    if (FAILED (win32fd.Create (filepath,
  8212.             GENERIC_READ | GENERIC_WRITE,
  8213.              FILE_SHARE_READ,
  8214.              CREATE_ALWAYS)) != FALSE) {
  8215.              return FALSE;
  8216.    }
  8217.    return writeNNEFile (win32fd);
  8218.  }
  8219.  
  8220.  BOOL writeNNEFile (CAtlFile &win32fd) {
  8221.    // NNE File
  8222.    CByteStream NNEFile ( 0x20000, 0x200000);
  8223.  
  8224.    // Buffer pool
  8225.    CByteStream chrPool (0x10000, 0x1000 * 128); // 4K chr block
  8226.    CByteStream nametablePool (0x8000, 0x800 * 128); // 2K 32x32 word tile id block
  8227.    CByteStream attrPool (0x0400, 0x0040 * 128); // 64 byte attr block
  8228.    CByteStream palPool (0x0100, 0x0010 * 128); // 16 byte pal block
  8229.    CByteStream stringPool (0x1000, 0x1000 * 32); // Chr buffer
  8230.  
  8231.    // NNE file header
  8232.    CNNEFile::NNEHeader header;
  8233.  
  8234.    RtlCopyMemory (header.magic, "moecmks  nes-nne", sizeof (header.magic));
  8235.  
  8236.    NNEFile.writeDummyAssert (sizeof (CNNEFile::NNEHeader));
  8237.    
  8238.    header.gPaletteCount = m_globalPal.GetCount ();
  8239.    header.gPaletteChainOffset = NNEFile.getWriteSeek ();
  8240.  
  8241.    // <gloabl-palette-chain section> ===============================================
  8242.    for (auto it = 0; it != m_globalPal.GetCount (); it++)
  8243.    {
  8244. #define APPEND_COMMENT(/*varDummyStringSpecKey*/ Object, /* CString &*/ comment)\
  8245.  do {\
  8246.    CString &commentT = comment;\
  8247.    if (commentT.GetLength () > 0) {\
  8248.      (Object).commentLength  = commentT.GetLength ();\
  8249.      (Object).commentOffset = stringPool.getWriteSeek ();\
  8250.      /* Write chr buffer (UCS-2) */ \
  8251.      CStringW ucs2Buffer (commentT);\
  8252.      stringPool.writeAssert ((const void *) ucs2Buffer.GetString (), commentT.GetLength () << 1);\
  8253.    }\
  8254.  } while (0)
  8255.      auto p = m_globalPal[it];
  8256.      CNNEFile::palChunk chunk = { 0, 0, palPool.getWriteSeek () >> 4 };
  8257.      APPEND_COMMENT (chunk, p->comment);
  8258.  
  8259.      palPool.writeAssert (& p->pal[0], sizeof (p->pal));
  8260.      NNEFile.writeAssert (& chunk, sizeof (chunk));
  8261.    }
  8262.    header.chrChainOffset = NNEFile.getWriteSeek ();
  8263.    header.chrCount = m_ChrVec.GetCount ();
  8264.  
  8265.    // <chr-chain> ===============================================
  8266.    for (auto it = 0; it != m_ChrVec.GetCount (); it++) {
  8267.      CNNEFile::chrSectionChunk chunk = { 0, 0, it };
  8268.      auto chr = m_ChrVec[it];
  8269.      ATLASSERT (chr != NULL);
  8270.      APPEND_COMMENT (chunk, chr->comment);
  8271.  
  8272.      chrPool.writeAssert (chr->chr, 0x1000);
  8273.      NNEFile.writeAssert (& chunk, sizeof (chunk));
  8274.    }
  8275.    header.clayChainOffset = NNEFile.getWriteSeek ();
  8276.    header.clayCount = m_VnpVec.GetCount ();
  8277.    // <clay-chain> ===============================================
  8278.    DWORD ClayOffsetInFile = NNEFile.getWriteSeek ();
  8279.  
  8280.    // Clay chunk offset header
  8281.    NNEFile.writeDummyAssert (m_VnpVec.GetCount () * sizeof (DWORD));
  8282.  
  8283.    for (auto it = 0; it != m_VnpVec.GetCount (); it++) {
  8284.      // Write clay chunk offset
  8285.      DWORD clayChunkOffset = NNEFile.getWriteSeek ();
  8286.  
  8287.      NNEFile.fillExistBufferNoreallocAssert (& clayChunkOffset,
  8288.                            ClayOffsetInFile + (it << 2), sizeof (DWORD));
  8289.      
  8290.      // Write clay chunk header
  8291.      DWORD chunkHeaderInFile = NNEFile.getWriteSeek ();
  8292.      NNEFile.writeDummyAssert (sizeof (CNNEFile::claySectionChunkHeader));
  8293.  
  8294.      auto p = m_VnpVec[it];
  8295.      CNNEFile::claySectionChunkHeader chunkHeader = {
  8296.        0, /* commentLength */
  8297.        0, /* commentOffset */
  8298.        MAXDWORD, /* chrIndex */
  8299.        nametablePool.getWriteSeek () >> 11, /* clayIndex */
  8300.        p->attrList.GetCount (), /* attrCount */
  8301.        p->palList.GetCount (),  /* paletteCount */
  8302.        MAXDWORD,  /* attr select */
  8303.        p->select
  8304.      };
  8305.  
  8306.      if (p->chr != NULL) {
  8307.        chunkHeader.chrIndex = forceFindIndexByComment<CChr> (m_ChrVec, & p->chr->comment);
  8308.        ATLASSERT (chunkHeader.chrIndex >= 0);
  8309.      }
  8310.      // Write attr-list
  8311.      for (auto it = 0; it != p->attrList.GetCount (); it++) {
  8312.        auto p2 = p->attrList[it];
  8313.        if (  p->attr != NULL
  8314.          && p2->comment == p->attr->comment)
  8315.          chunkHeader.attrSel = it;
  8316.  
  8317.        CNNEFile::attrChunk chunk = { 0, 0, attrPool.getWriteSeek () >> 6 };
  8318.  
  8319.        // Make attr comment
  8320.        APPEND_COMMENT (chunk, p2->comment);
  8321.        
  8322.        attrPool.writeAssert (p2->attr, 64);
  8323.        NNEFile.writeAssert (& chunk, sizeof (chunk));
  8324.      }
  8325.      // Write pal-list
  8326.      CByteStream palChunkSet (32, 64);
  8327.      for (auto it = 0; it != p->palList.GetCount (); it++) {
  8328.        auto p2 = p->palList[it];
  8329.  
  8330.        CNNEFile::palChunk chunk = { 0, 0, palPool.getWriteSeek () >> 4 };
  8331.  
  8332.        // Make pal comment
  8333.        APPEND_COMMENT (chunk, p2->comment);
  8334.        
  8335.        palPool.writeAssert (p2->pal, 16);
  8336.        NNEFile.writeAssert (& chunk, sizeof (chunk));
  8337.      }
  8338.      // Write Comment
  8339.      APPEND_COMMENT (chunkHeader, p->comment);
  8340.  
  8341.      // Fill header
  8342.      NNEFile.fillExistBufferNoreallocAssert (& chunkHeader,
  8343.                  chunkHeaderInFile, sizeof (chunkHeader));
  8344.  
  8345.      // Write nametable tile id
  8346.      nametablePool.writeAssert (p->tileSlot, 0x800);
  8347.    }
  8348.    // <map-chain> ===============================================
  8349.    header.mapChainOffset = NNEFile.getWriteSeek ();
  8350.    header.mapCount = m_MapVec.GetCount ();
  8351.    
  8352.    DWORD MapOffsetInFile = NNEFile.getWriteSeek ();
  8353.    NNEFile.writeDummyAssert (m_MapVec.GetCount () * sizeof (DWORD));
  8354.  
  8355.    for (auto it = 0; it != m_MapVec.GetCount (); it++) {
  8356.      auto p = m_MapVec[it];
  8357.      ATLASSERT (p != NULL);
  8358.  
  8359.      // Write map-chunk offset
  8360.      DWORD mapChunkOffset = NNEFile.getWriteSeek ();
  8361.  
  8362.      NNEFile.fillExistBufferNoreallocAssert (& mapChunkOffset,
  8363.                            MapOffsetInFile + (it << 2), sizeof (DWORD));
  8364.  
  8365.      // Prepare map section chunk
  8366.      CNNEFile::mapSectionChunk mapSecChunk = {
  8367.        0, /* commentLength */
  8368.        0, /* commentOffset */
  8369.        p->width, /* width */
  8370.        p->height, /* height */
  8371.        p->staticPal.GetCount () /* sPaletteCount */
  8372.      };
  8373.      // Make map comment
  8374.      APPEND_COMMENT (mapSecChunk, p->comment);
  8375.  
  8376.      // Write section chunk
  8377.      NNEFile.writeAssert (& mapSecChunk, sizeof (CNNEFile::mapSectionChunk));
  8378.  
  8379.      // Write static palette
  8380.      for (auto it = 0; it != p->staticPal.GetCount (); it++)
  8381.      {
  8382.        auto p2 = p->staticPal[it];
  8383.        CNNEFile::palChunk chunk = { 0, 0, palPool.getWriteSeek () >> 4 };
  8384.        APPEND_COMMENT (chunk, p2->comment);
  8385.  
  8386.        palPool.writeAssert (& p2->pal[0], sizeof (p2->pal));
  8387.        NNEFile.writeAssert (& chunk, sizeof (chunk));
  8388.      }
  8389.      DWORD PageOffsetInFile = NNEFile.getWriteSeek ();
  8390.      NNEFile.writeDummyAssert (p->ntList.GetCount () * sizeof (DWORD));
  8391.  
  8392.      for (auto it = 0; it != p->ntList.GetCount (); it++) {
  8393.        auto p2 = p->ntList[it];
  8394.  
  8395.        // Write page-chunk offset
  8396.        DWORD pageChunkOffset = NNEFile.getWriteSeek ();
  8397.  
  8398.        NNEFile.fillExistBufferNoreallocAssert (& pageChunkOffset,
  8399.                              PageOffsetInFile + (it << 2), sizeof (DWORD));
  8400.  
  8401.        CNNEFile::mapSectionPageChunk pageChunk = {
  8402.          MAXDWORD, /* chrIndex */
  8403.          nametablePool.getWriteSeek () >> 11, /* nametableIndex */
  8404.          p2->attrList.GetCount (), /* attrCount */
  8405.          p2->palList.GetCount (), /* paletteCount */
  8406.          MAXDWORD, /* attrSel */
  8407.          p2->select /* paletteSel */
  8408.        };
  8409.        
  8410.        DWORD sectionPageChunkOffset = NNEFile.getWriteSeek ();
  8411.        NNEFile.writeDummyAssert (sizeof (CNNEFile::mapSectionPageChunk));
  8412.  
  8413.        if (p2->chr != NULL) {
  8414.          pageChunk.chrIndex = forceFindIndexByComment<CChr> (m_ChrVec, & p2->chr->comment);
  8415.          ATLASSERT (pageChunk.chrIndex >= 0);
  8416.        }
  8417.        nametablePool.writeAssert (p2->tileSlot, sizeof (p2->tileSlot));
  8418.  
  8419.        // Collect attr-list
  8420.        for (auto it = 0; it != p2->attrList.GetCount (); it++) {
  8421.          auto p3 = p2->attrList[it];
  8422.          if (  p2->attr != NULL
  8423.            && p3->comment == p2->attr->comment)
  8424.            pageChunk.attrSel = it;
  8425.  
  8426.          CNNEFile::attrChunk chunk = { 0, 0, attrPool.getWriteSeek () >> 6 };
  8427.  
  8428.          // Make attr comment
  8429.          APPEND_COMMENT (chunk, p3->comment);
  8430.          
  8431.          attrPool.writeAssert (p3->attr, 64);
  8432.          NNEFile.writeAssert (& chunk, sizeof (chunk));        
  8433.        }
  8434.        // Write pal-list
  8435.        for (auto it = 0; it != p2->palList.GetCount (); it++) {
  8436.          auto p3 = p2->palList[it];
  8437.  
  8438.          CNNEFile::palChunk chunk = { 0, 0, palPool.getWriteSeek () >> 4 };
  8439.  
  8440.          // Make pal comment
  8441.          APPEND_COMMENT (chunk, p3->comment);
  8442.  
  8443.          palPool.writeAssert (p3->pal, 16);
  8444.          NNEFile.writeAssert (& chunk, sizeof (chunk));
  8445.        }
  8446.        // Write clay-chunk header
  8447.        NNEFile.fillExistBufferNoreallocAssert
  8448.                 (& pageChunk, sectionPageChunkOffset,
  8449.                        sizeof (CNNEFile::mapSectionPageChunk));
  8450.      }
  8451.    }
  8452.    // Link body and item-pool
  8453.    header.chrPoolOffset = NNEFile.getWriteSeek ();
  8454.    header.attrPoolOffset = header.chrPoolOffset + chrPool.getWriteSeek ();
  8455.    header.palettePoolOffset = header.attrPoolOffset + attrPool.getWriteSeek ();
  8456.    header.nclayPoolOffset = header.palettePoolOffset  + palPool.getWriteSeek ();
  8457.    header.stringPoolOffset = header.nclayPoolOffset  + nametablePool.getWriteSeek ();
  8458.  
  8459.    NNEFile.writeAssert (* chrPool.getBuffer (), chrPool.getWriteSeek ());
  8460.    NNEFile.writeAssert (* attrPool.getBuffer (), attrPool.getWriteSeek ());
  8461.    NNEFile.writeAssert (* palPool.getBuffer (), palPool.getWriteSeek ());
  8462.    NNEFile.writeAssert (* nametablePool.getBuffer (), nametablePool.getWriteSeek ());
  8463.    NNEFile.writeAssert (* stringPool.getBuffer (), stringPool.getWriteSeek ());
  8464.  
  8465.    // Calc crc32
  8466.    header.crc32_intel = CGlobals::crc32_intel (0,
  8467.                 &( ( static_cast<PBYTE> ((*NNEFile.getBuffer())))[sizeof (CNNEFile::NNEHeader)])
  8468.                         , NNEFile.getWriteSeek () - sizeof (CNNEFile::NNEHeader));
  8469.  
  8470.    NNEFile.fillExistBufferNoreallocAssert
  8471.              (& header, 0,
  8472.                    sizeof (CNNEFile::NNEHeader));
  8473.    // Write file
  8474.    return  SUCCEEDED ( win32fd.Write (* NNEFile.getBuffer (), NNEFile.getWriteSeek ()));
  8475.  }
  8476.  
  8477.  LRESULT OnCheck (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  8478.    bHandled = FALSE;
  8479.    return 0;
  8480.  }
  8481.     LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  8482.     {
  8483.    const DWORD splitterStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  8484.    const DWORD splitterStyleEx = 0;
  8485.    const DWORD listListStyle = WS_VISIBLE | WS_CHILD  | LVS_SINGLESEL | LVS_SHOWSELALWAYS
  8486.                                        | LVS_NOCOLUMNHEADER | LVS_LIST | LVS_ALIGNLEFT  | WS_BORDER;
  8487.    const DWORD listReportStyle = WS_VISIBLE | WS_CHILD  | LVS_SINGLESEL | LVS_SHOWSELALWAYS
  8488.                                        | LVS_NOCOLUMNHEADER | LVS_REPORT | LVS_ALIGNLEFT  | WS_BORDER;
  8489.  
  8490.    m_hWndClient = m_SWinSplitterMain.Create (*this, rcDefault, _T (""), splitterStyle, splitterStyleEx);
  8491.    
  8492.    m_SWinSplitterLeft.Create (m_SWinSplitterMain, rcDefault, _T (""), splitterStyle, splitterStyleEx);
  8493.    m_SWinSplitterRight.Create (m_SWinSplitterMain, rcDefault, _T (""), splitterStyle, splitterStyleEx);
  8494.    m_SWinSplitterList.Create (m_SWinSplitterRight, rcDefault, _T (""), splitterStyle, splitterStyleEx);
  8495.    m_GuiSWin_Nesmap.Create (m_SWinSplitterRight, rcDefault);
  8496.  
  8497.    m_GuiLV_Map.Create (this, MAP_CONTROL_LV_MAP, m_SWinSplitterLeft, rcDefault, _T (""), listListStyle | LVS_SINGLESEL);
  8498.    m_GuiLV_Page.Create (this, MAP_CONTROL_LV_PAGE, m_SWinSplitterLeft, rcDefault, _T (""), listReportStyle & ~LVS_SINGLESEL, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);
  8499.    m_GuiLV_Page.SetExtendedListViewStyle (LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES /* | LVS_EX_GRIDLINES */ | m_GuiLV_Page.GetExtendedListViewStyle ());
  8500.  
  8501.    m_GuiLV_Chr.Create (this, MAP_CONTROL_LV_CHR, m_SWinSplitterList, rcDefault, _T (""), listListStyle | LVS_SINGLESEL);
  8502.    m_GuiLV_Clay.Create (this, MAP_CONTROL_LV_CLAY, m_SWinSplitterList, rcDefault, _T (""), listReportStyle & ~LVS_SINGLESEL);
  8503.    m_GuiLV_Clay.SetExtendedListViewStyle (LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES /* | LVS_EX_GRIDLINES */ | m_GuiLV_Page.GetExtendedListViewStyle ());
  8504.  
  8505.    LVCOLUMN vcl;  
  8506.    RtlZeroMemory (& vcl, sizeof (vcl));
  8507.  
  8508.    vcl.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_IMAGE;  
  8509.    vcl.cx = 72;
  8510.    m_GuiLV_Page.InsertColumn (0, & vcl);
  8511.    m_GuiLV_Clay.InsertColumn (0, & vcl);
  8512.    vcl.cx = 92;
  8513.    m_GuiLV_Page.InsertColumn (1, & vcl);
  8514.    m_GuiLV_Clay.InsertColumn (1, & vcl);
  8515.    vcl.cx = 92;
  8516.    m_GuiLV_Page.InsertColumn (2, & vcl);
  8517.    m_GuiLV_Clay.InsertColumn (2, & vcl);
  8518.    vcl.cx = 68;
  8519.    m_GuiLV_Page.InsertColumn (3, & vcl);
  8520.    m_GuiLV_Clay.InsertColumn (3, & vcl);
  8521.  
  8522.    m_SWinSplitterMain.SetSplitterPanes (m_SWinSplitterLeft, m_SWinSplitterRight);
  8523.    m_SWinSplitterLeft.SetSplitterPanes (m_GuiLV_Map, m_GuiLV_Page);
  8524.    m_SWinSplitterRight.SetSplitterPanes (m_SWinSplitterList, m_GuiSWin_Nesmap);
  8525.    m_SWinSplitterList.SetSplitterPanes (m_GuiLV_Chr, m_GuiLV_Clay);
  8526.  
  8527.    MoveWindow (0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN));
  8528.    ShowWindow (SW_MAXIMIZE);
  8529.  
  8530.    m_GuiSWin_Nesmap.SetScrollSize (800, 400, FALSE, true);
  8531.  
  8532.    m_SWinSplitterMain.SetSplitterPos (160);
  8533.    m_SWinSplitterLeft.SetSplitterPos (200);
  8534.    m_SWinSplitterRight.SetSplitterPos (200);
  8535.    m_SWinSplitterList.SetSplitterPos ((GetSystemMetrics (SM_CXSCREEN) - 160) / 2 + 20);
  8536.  
  8537.    CGlobals::setDefaultListViewColor (m_GuiLV_Map);
  8538.    CGlobals::setDefaultListViewColor (m_GuiLV_Page);
  8539.    CGlobals::setDefaultListViewColor (m_GuiLV_Chr);
  8540.    CGlobals::setDefaultListViewColor (m_GuiLV_Clay);
  8541.    
  8542.    m_GuiLV_Chr.SetImageList (m_IconChrlist, LVSIL_SMALL);
  8543.    m_GuiLV_Clay.SetImageList (m_IconClaylist, LVSIL_SMALL);
  8544.    m_GuiLV_Map.SetImageList (m_IconMaplist, LVSIL_SMALL);
  8545.    m_GuiLV_Page.SetImageList (m_IconPagelist, LVSIL_SMALL);
  8546.  
  8547.    allocNtpWindow ();
  8548.    allocClayWindow ();
  8549.  
  8550.    CreateSimpleToolBar();
  8551.    CreateSimpleStatusBar();
  8552.  
  8553.    
  8554.    // TBSTYLE_TOOLTIPS
  8555.  
  8556.    // CBRS_TOOLTIPS
  8557.    // CReBarCtrlT
  8558.     // CDoc
  8559.    // nes-map mode | pos infos | chr cache | palette cache | attrtable cache
  8560.    int skipBar[] = { 120, 360, 720, 960, -1 };
  8561.    :: SendMessage (m_hWndStatusBar, SB_SETPARTS, sizeof (skipBar) / sizeof (skipBar[0]), (LPARAM)& skipBar[0]);
  8562.    :: SendMessage (m_hWndStatusBar, SB_SETTEXT, 0, (LPARAM) _T ("map:paste mode"));
  8563.    :: SendMessage (m_hWndStatusBar, SB_SETTEXT, 2, (LPARAM) _T ("chr cache:"));
  8564.    :: SendMessage (m_hWndStatusBar, SB_SETTEXT, 3, (LPARAM) _T ("pal cache:"));
  8565.    :: SendMessage (m_hWndStatusBar, SB_SETTEXT, 4, (LPARAM) _T ("attr cache:"));
  8566.    //SetBarStyle
  8567.    //CToolBarCtrlT
  8568.    // Create directx device
  8569.    m_Direct3D9 = Direct3DCreate9 (D3D_SDK_VERSION);
  8570.    ATLASSERT (m_Direct3D9 != NULL);
  8571.  
  8572.    D3DPRESENT_PARAMETERS d3dpp;
  8573.    RtlZeroMemory (& d3dpp, sizeof (d3dpp));
  8574.  
  8575.    d3dpp.BackBufferFormat =  D3DFMT_X1R5G5B5;
  8576.    d3dpp.SwapEffect            = D3DSWAPEFFECT_DISCARD;
  8577.    d3dpp.hDeviceWindow         = m_GuiSWin_Nesmap;
  8578.    d3dpp.Windowed              = TRUE;
  8579.    d3dpp.BackBufferWidth       = GetSystemMetrics (SM_CXSCREEN) + 320;
  8580.    d3dpp.BackBufferHeight      = GetSystemMetrics (SM_CYSCREEN) + 320;
  8581.    d3dpp.PresentationInterval  = D3DPRESENT_INTERVAL_IMMEDIATE; /* Disable VSync */
  8582.  
  8583.    CRect rc;
  8584.    GetClientRect (rc);
  8585.  
  8586.    auto width = rc.Width ();
  8587.    auto height = rc.Height ();
  8588.    
  8589.    // Create direct3d device
  8590.    HRESULT sig = m_Direct3D9->CreateDevice (0,
  8591.                          D3DDEVTYPE_HAL,
  8592.                             d3dpp.hDeviceWindow,
  8593.                                D3DCREATE_SOFTWARE_VERTEXPROCESSING, & d3dpp, & m_Direct3D9Deivce);
  8594.    ATLASSERT (SUCCEEDED (sig));
  8595.  
  8596.    // Create direct3d surface (system-memory)
  8597.    sig = m_Direct3D9Deivce->CreateOffscreenPlainSurface (d3dpp.BackBufferWidth,
  8598.          d3dpp.BackBufferHeight, d3dpp.BackBufferFormat, D3DPOOL_SYSTEMMEM,
  8599.        & m_Direct3D9Surface, NULL);
  8600.  
  8601.    ATLASSERT (SUCCEEDED (sig));
  8602.    // CContainedWindowT
  8603.  
  8604.    CGlobals::globalInit ();
  8605.    CGlobals::loadFontPixel (m_Direct3D9Deivce);
  8606.  
  8607.    // register object for message filtering and idle updates
  8608.    CMessageLoop* pLoop = _Module.GetMessageLoop();
  8609.    ATLASSERT(pLoop != NULL);
  8610.    pLoop->AddMessageFilter(this);
  8611.    pLoop->AddIdleHandler(this);
  8612.  
  8613.    // Create tracker menu
  8614.    auto menuHandle = ::LoadMenu (ModuleHelper::GetResourceInstance (), MAKEINTRESOURCE (IDM_PAGETRACKER));
  8615.    m_GuiMenu_MapAttach.Attach (:: GetSubMenu (menuHandle, 0));
  8616.  
  8617.    return 0;
  8618.     }
  8619.  
  8620.   void appendToItemToViewPageList (CNametableCell<FALSE> *p) {
  8621.     int index = m_GuiLV_Page.GetItemCount ();
  8622.     if (index < 0) {
  8623.       index = 0;
  8624.     }
  8625.     // Insert, set item-0
  8626.     ATLASSERT (p != NULL);
  8627.     m_GuiLV_Page.InsertItem (index, p->comment, 0);
  8628.  
  8629.     resetItemToViewPageList (index, p);
  8630.   }
  8631.  
  8632.   void resetItemToViewPageList (int index, CNametableCell<FALSE> *p) {
  8633.     // Insert, set item-0
  8634.     ATLASSERT (p != NULL);
  8635.  
  8636.     // Item-0 comment.
  8637.     m_GuiLV_Page.SetItem (index, 0, LVIF_IMAGE | LVIF_TEXT, p->comment, 0, 0, 0, 0);
  8638.  
  8639.     // Item-1 chr.
  8640.     if (p->chr != NULL) {
  8641.       m_GuiLV_Page.SetItem (index, 1, LVIF_IMAGE | LVIF_TEXT, p->chr->comment, 1, 0, 0, 0);
  8642.     } else {
  8643.       m_GuiLV_Page.SetItem (index, 1, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 1, 0, 0, 0);
  8644.     }
  8645.     // Item-2 palette.
  8646.     if (p->pal != NULL) {
  8647.       m_GuiLV_Page.SetItem (index, 2, LVIF_IMAGE | LVIF_TEXT, p->pal->comment, 2 + p->pal->source, 0, 0, 0);
  8648.     } else {
  8649.       m_GuiLV_Page.SetItem (index, 2, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 2, 0, 0, 0);
  8650.     }
  8651.     // Item-3 attr
  8652.     if (p->attr != NULL) {
  8653.       m_GuiLV_Page.SetItem (index, 3, LVIF_IMAGE | LVIF_TEXT, p->attr->comment, 5, 0, 0, 0);
  8654.     } else {
  8655.       m_GuiLV_Page.SetItem (index, 3, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 5, 0, 0, 0);
  8656.     }
  8657.     m_GuiLV_Page.SetItemDataT (index, p);
  8658.   }
  8659.  
  8660.   void appendToItemToViewClayList (CNametableCell<TRUE> *p) {
  8661.     int index = m_GuiLV_Clay.GetItemCount ();
  8662.     if (index < 0) {
  8663.       index = 0;
  8664.     }
  8665.     // Insert, set item-0
  8666.     ATLASSERT (p != NULL);
  8667.     m_GuiLV_Clay.InsertItem (index, p->comment, 0);
  8668.  
  8669.     resetItemToViewClayList (index, p);
  8670.   }
  8671.  
  8672.   void resetItemToViewClayList (int index, CNametableCell<TRUE> *p) {
  8673.     // Insert, set item-0
  8674.     ATLASSERT (p != NULL);
  8675.  
  8676.     // Item-0 comment.
  8677.     m_GuiLV_Clay.SetItem (index, 0, LVIF_IMAGE | LVIF_TEXT, p->comment, 0, 0, 0, 0);
  8678.  
  8679.     // Item-1 chr.
  8680.     if (p->chr != NULL) {
  8681.       m_GuiLV_Clay.SetItem (index, 1, LVIF_IMAGE | LVIF_TEXT, p->chr->comment, 1, 0, 0, 0);
  8682.     } else {
  8683.       m_GuiLV_Clay.SetItem (index, 1, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 1, 0, 0, 0);
  8684.     }
  8685.     // Item-2 palette.
  8686.     if (p->pal != NULL) {
  8687.       m_GuiLV_Clay.SetItem (index, 2, LVIF_IMAGE | LVIF_TEXT, p->pal->comment, 2 + p->pal->source, 0, 0, 0);
  8688.     } else {
  8689.       m_GuiLV_Clay.SetItem (index, 2, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 2, 0, 0, 0);
  8690.     }
  8691.     // Item-3 attr
  8692.     if (p->attr != NULL) {
  8693.       m_GuiLV_Clay.SetItem (index, 3, LVIF_IMAGE | LVIF_TEXT, p->attr->comment, 5, 0, 0, 0);
  8694.     } else {
  8695.       m_GuiLV_Clay.SetItem (index, 3, LVIF_IMAGE | LVIF_TEXT, _T ("null"), 5, 0, 0, 0);
  8696.     }
  8697.     m_GuiLV_Clay.SetItemDataT (index, p);
  8698.   }
  8699.  
  8700.   void __cdecl setStatusText (int bar_bank, LPCTSTR format, ...) {
  8701.     CString output;
  8702.  
  8703.     va_list va;
  8704.     va_start (va, format);
  8705.  
  8706.     output.FormatV (format, va);
  8707.  
  8708.     ::SendMessage (m_hWndStatusBar, SB_SETTEXT, bar_bank, (LPARAM) output.GetString ());
  8709.  
  8710.     va_end (va);
  8711.   }
  8712.  
  8713.   LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  8714.   {
  8715.     m_GuiLV_Chr.RemoveImageList (LVSIL_SMALL);
  8716.     m_GuiLV_Clay.RemoveImageList (LVSIL_SMALL);
  8717.     m_GuiLV_Map.RemoveImageList (LVSIL_SMALL);
  8718.     m_GuiLV_Page.RemoveImageList (LVSIL_SMALL);
  8719.  
  8720.     // unregister message filtering and idle updates
  8721.     CMessageLoop* pLoop = _Module.GetMessageLoop();
  8722.     ATLASSERT(pLoop != NULL);
  8723.     pLoop->RemoveMessageFilter(this);
  8724.     pLoop->RemoveIdleHandler(this);
  8725.  
  8726.     bHandled = FALSE;
  8727.     return 1;
  8728.   }
  8729.  
  8730.   LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  8731.   {
  8732.    //CAboutDlg dlg;
  8733.    //dlg.DoModal();
  8734.    return 0;
  8735.   }
  8736. };
  8737.  
  8738. int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
  8739. {
  8740.   CMessageLoop theLoop;
  8741.   _Module.AddMessageLoop(&theLoop);
  8742.  
  8743.   CMainFrame wndMain;
  8744.  
  8745.   if(wndMain.CreateEx() == NULL)
  8746.   {
  8747.    ATLTRACE(_T("Main window creation failed!\n"));
  8748.    return 0;
  8749.   }
  8750.  
  8751.   wndMain.SetWindowText (_T ("NNametableEditor"));
  8752.   wndMain.ShowWindow(nCmdShow);
  8753.  
  8754.   int nRet = theLoop.Run();
  8755.  
  8756.   _Module.RemoveMessageLoop();
  8757.   return nRet;
  8758. }
  8759.  
  8760. int WINAPI _tWinMain (HINSTANCE hInstance,
  8761.                       HINSTANCE hPrevInstance,
  8762.                       LPTSTR lpstrCmdLine,
  8763.                       int nCmdShow)
  8764. {
  8765.   HRESULT hRes = ::CoInitialize(NULL);
  8766.  // If you are running on NT 4.0 or higher you can use the following call instead to
  8767.  // make the EXE CCRTAllocator::Free threaded. This means that calls come in on a random RPC thread.
  8768.  // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
  8769.   ATLASSERT(SUCCEEDED(hRes));
  8770.  
  8771.   // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
  8772.   ::DefWindowProc(NULL, 0, 0, 0L);
  8773.  
  8774.   AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);    // add flags to support other controls
  8775.  
  8776.   hRes = _Module.Init(NULL, hInstance);
  8777.   ATLASSERT(SUCCEEDED(hRes));
  8778.  
  8779.   int nRet = Run(lpstrCmdLine, nCmdShow);
  8780.  
  8781.   _Module.Term();
  8782.   ::CoUninitialize();
  8783.  
  8784.   return nRet;
  8785. }
  8786.  
  8787. int main (VOID) {
  8788.   HINSTANCE  hInstance = GetModuleHandle (NULL);
  8789.   HINSTANCE hPrevInstance = NULL;
  8790.   LPTSTR lpCmdLine = GetCommandLine ();
  8791.   int nShowCmd = SW_SHOWNORMAL;
  8792.  
  8793.   return _tWinMain (hInstance,
  8794.                     hPrevInstance,
  8795.                     lpCmdLine,
  8796.                     nShowCmd);
  8797. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement