From 8203414e204704f081be2ed5d61cc571da1a29fe Mon Sep 17 00:00:00 2001 From: Abe Pralle Date: Sat, 4 Jul 2020 18:46:08 -0700 Subject: [PATCH] [Tools] GBConv2 --- Tools/GBConv2/GBConv2.exe | Bin 0 -> 327680 bytes Tools/GBConv2/Source/BGSaveDialog.cpp | 54 + Tools/GBConv2/Source/BGSaveDialog.h | 36 + Tools/GBConv2/Source/ChildFrm.cpp | 121 ++ Tools/GBConv2/Source/ChildFrm.h | 61 + Tools/GBConv2/Source/ChildView.cpp | 184 +++ Tools/GBConv2/Source/ChildView.h | 70 + Tools/GBConv2/Source/Controls.cpp | 437 +++++ Tools/GBConv2/Source/Controls.h | 108 ++ Tools/GBConv2/Source/EditArea.cpp | 223 +++ Tools/GBConv2/Source/EditArea.h | 61 + Tools/GBConv2/Source/EditPaletteDialog.cpp | 109 ++ Tools/GBConv2/Source/EditPaletteDialog.h | 63 + Tools/GBConv2/Source/GBConv2.cpp | 157 ++ Tools/GBConv2/Source/GBConv2.dsp | 253 +++ Tools/GBConv2/Source/GBConv2.dsw | 29 + Tools/GBConv2/Source/GBConv2.h | 54 + Tools/GBConv2/Source/GBConv2.plg | 87 + Tools/GBConv2/Source/GBConv2.rc | 411 +++++ Tools/GBConv2/Source/MainFrm.cpp | 108 ++ Tools/GBConv2/Source/MainFrm.h | 57 + Tools/GBConv2/Source/PaletteButton.cpp | 33 + Tools/GBConv2/Source/PaletteButton.h | 48 + Tools/GBConv2/Source/PaletteListBox.cpp | 126 ++ Tools/GBConv2/Source/PaletteListBox.h | 62 + Tools/GBConv2/Source/StdAfx.cpp | 8 + Tools/GBConv2/Source/StdAfx.h | 27 + Tools/GBConv2/Source/gb_pic.cpp | 1727 ++++++++++++++++++++ Tools/GBConv2/Source/gb_pic.h | 196 +++ Tools/GBConv2/Source/res/GBConv2.ico | Bin 0 -> 1078 bytes Tools/GBConv2/Source/res/GBConv2.rc2 | 13 + Tools/GBConv2/Source/res/Toolbar.bmp | Bin 0 -> 358 bytes Tools/GBConv2/Source/resource.h | 49 + Tools/GBConv2/Source/wingk.cbk | 1434 ++++++++++++++++ Tools/GBConv2/Source/wingk.cpp | 1546 ++++++++++++++++++ Tools/GBConv2/Source/wingk.h | 187 +++ Tools/GBConv2/Source/wingk.hbk | 184 +++ Tools/GBConv2/converter_gfx.bmp | Bin 0 -> 15416 bytes 38 files changed, 8323 insertions(+) create mode 100644 Tools/GBConv2/GBConv2.exe create mode 100644 Tools/GBConv2/Source/BGSaveDialog.cpp create mode 100644 Tools/GBConv2/Source/BGSaveDialog.h create mode 100644 Tools/GBConv2/Source/ChildFrm.cpp create mode 100644 Tools/GBConv2/Source/ChildFrm.h create mode 100644 Tools/GBConv2/Source/ChildView.cpp create mode 100644 Tools/GBConv2/Source/ChildView.h create mode 100644 Tools/GBConv2/Source/Controls.cpp create mode 100644 Tools/GBConv2/Source/Controls.h create mode 100644 Tools/GBConv2/Source/EditArea.cpp create mode 100644 Tools/GBConv2/Source/EditArea.h create mode 100644 Tools/GBConv2/Source/EditPaletteDialog.cpp create mode 100644 Tools/GBConv2/Source/EditPaletteDialog.h create mode 100644 Tools/GBConv2/Source/GBConv2.cpp create mode 100644 Tools/GBConv2/Source/GBConv2.dsp create mode 100644 Tools/GBConv2/Source/GBConv2.dsw create mode 100644 Tools/GBConv2/Source/GBConv2.h create mode 100644 Tools/GBConv2/Source/GBConv2.plg create mode 100644 Tools/GBConv2/Source/GBConv2.rc create mode 100644 Tools/GBConv2/Source/MainFrm.cpp create mode 100644 Tools/GBConv2/Source/MainFrm.h create mode 100644 Tools/GBConv2/Source/PaletteButton.cpp create mode 100644 Tools/GBConv2/Source/PaletteButton.h create mode 100644 Tools/GBConv2/Source/PaletteListBox.cpp create mode 100644 Tools/GBConv2/Source/PaletteListBox.h create mode 100644 Tools/GBConv2/Source/StdAfx.cpp create mode 100644 Tools/GBConv2/Source/StdAfx.h create mode 100644 Tools/GBConv2/Source/gb_pic.cpp create mode 100644 Tools/GBConv2/Source/gb_pic.h create mode 100644 Tools/GBConv2/Source/res/GBConv2.ico create mode 100644 Tools/GBConv2/Source/res/GBConv2.rc2 create mode 100644 Tools/GBConv2/Source/res/Toolbar.bmp create mode 100644 Tools/GBConv2/Source/resource.h create mode 100644 Tools/GBConv2/Source/wingk.cbk create mode 100644 Tools/GBConv2/Source/wingk.cpp create mode 100644 Tools/GBConv2/Source/wingk.h create mode 100644 Tools/GBConv2/Source/wingk.hbk create mode 100644 Tools/GBConv2/converter_gfx.bmp diff --git a/Tools/GBConv2/GBConv2.exe b/Tools/GBConv2/GBConv2.exe new file mode 100644 index 0000000000000000000000000000000000000000..0b12b36494ecd4d14001a02ec3163b62be0bc258 GIT binary patch literal 327680 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

g%E9$*`orPsqWlQI&m3bet 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%0D@I#WXf+frR%)(sc+C!ey1wG+aj;a)xOrD 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 MOQ2f<$0vdR0R{Tne*gdg literal 0 HcmV?d00001 diff --git a/Tools/GBConv2/Source/BGSaveDialog.cpp b/Tools/GBConv2/Source/BGSaveDialog.cpp new file mode 100644 index 0000000..fc9a2b2 --- /dev/null +++ b/Tools/GBConv2/Source/BGSaveDialog.cpp @@ -0,0 +1,54 @@ +// BGSaveDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "BGSaveDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBGSaveDialog + +IMPLEMENT_DYNAMIC(CBGSaveDialog, CFileDialog) + +CBGSaveDialog::CBGSaveDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, + DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : + CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) +{ +} + + +BEGIN_MESSAGE_MAP(CBGSaveDialog, CFileDialog) + //{{AFX_MSG_MAP(CBGSaveDialog) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +void CBGSaveDialog::OnTypeChange() +{ + int index = this->m_ofn.nFilterIndex; + char *filter = (char*) this->m_ofn.lpstrFilter; + int i; + for(i=1; i 1000 +#pragma once +#endif // _MSC_VER > 1000 +// BGSaveDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBGSaveDialog dialog + +class CBGSaveDialog : public CFileDialog +{ + DECLARE_DYNAMIC(CBGSaveDialog) + +public: + virtual void OnTypeChange(); + CBGSaveDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + CWnd* pParentWnd = NULL); + +protected: + //{{AFX_MSG(CBGSaveDialog) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BGSAVEDIALOG_H__F9E2F187_1EE9_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/ChildFrm.cpp b/Tools/GBConv2/Source/ChildFrm.cpp new file mode 100644 index 0000000..8e81650 --- /dev/null +++ b/Tools/GBConv2/Source/ChildFrm.cpp @@ -0,0 +1,121 @@ +// ChildFrm.cpp : implementation of the CChildFrame class +// + +#include "stdafx.h" +#include "GBConv2.h" + +#include "ChildFrm.h" +#include "gb_pic.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#include "Controls.h" + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame + +IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) + +BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) + //{{AFX_MSG_MAP(CChildFrame) + ON_COMMAND(ID_FILE_CLOSE, OnFileClose) + ON_WM_SETFOCUS() + ON_WM_CREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame construction/destruction + +CChildFrame::CChildFrame() +{ + +} + +CChildFrame::~CChildFrame() +{ + +} + +BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CMDIChildWnd::PreCreateWindow(cs) ) + return FALSE; + + cs.dwExStyle &= ~WS_EX_CLIENTEDGE; + cs.style &= ~WS_THICKFRAME; + cs.lpszClass = AfxRegisterWndClass(0); + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame diagnostics + +#ifdef _DEBUG +void CChildFrame::AssertValid() const +{ + CMDIChildWnd::AssertValid(); +} + +void CChildFrame::Dump(CDumpContext& dc) const +{ + CMDIChildWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame message handlers +void CChildFrame::OnFileClose() +{ + + SendMessage(WM_CLOSE); +} + +int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + // create a view to occupy the client area of the frame + if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, + CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) + { + TRACE0("Failed to create view window\n"); + return -1; + } + + //if(!OnLoadBMP()) OnFileClose(); + + return 0; +} + +void CChildFrame::OnSetFocus(CWnd* pOldWnd) +{ + CMDIChildWnd::OnSetFocus(pOldWnd); + + m_wndView.SetFocus(); +} + +BOOL CChildFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) +{ + // let the view have first crack at the command + if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) + return TRUE; + + // otherwise, do default handling + return CMDIChildWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + + +int CChildFrame::OnLoadBMP() +{ + return 1; +} diff --git a/Tools/GBConv2/Source/ChildFrm.h b/Tools/GBConv2/Source/ChildFrm.h new file mode 100644 index 0000000..d56cec3 --- /dev/null +++ b/Tools/GBConv2/Source/ChildFrm.h @@ -0,0 +1,61 @@ +// ChildFrm.h : interface of the CChildFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDFRM_H__2F0A9B4A_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_CHILDFRM_H__2F0A9B4A_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ChildView.h" +#include "gb_pic.h" // Added by ClassView + +class CChildFrame : public CMDIChildWnd +{ + DECLARE_DYNCREATE(CChildFrame) +public: + CChildFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildFrame) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + int OnLoadBMP(); + // view for the client area of the frame. + CChildView m_wndView; + virtual ~CChildFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CChildFrame) + afx_msg void OnFileClose(); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDFRM_H__2F0A9B4A_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/ChildView.cpp b/Tools/GBConv2/Source/ChildView.cpp new file mode 100644 index 0000000..efbf7a5 --- /dev/null +++ b/Tools/GBConv2/Source/ChildView.cpp @@ -0,0 +1,184 @@ +// ChildView.cpp : implementation of the CChildView class +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "ChildView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#include "Controls.h" +#include "EditArea.h" + +///////////////////////////////////////////////////////////////////////////// +// CChildView + +CString CChildView::preferredSourcePath = "d:\\aprogs\\fgbpix\\*.bmp"; + +CChildView::CChildView() +{ + sourceFile = destFile = 0; + sourceFileName = destFileName = ""; +} + +CChildView::~CChildView() +{ + if(sourceFile){ + delete sourceFile; + sourceFile = 0; + } + + if(destFile){ + delete destFile; + destFile = 0; + } +} + + +BEGIN_MESSAGE_MAP(CChildView,CWnd ) + //{{AFX_MSG_MAP(CChildView) + ON_WM_PAINT() + ON_WM_CREATE() + ON_WM_ERASEBKGND() + ON_WM_MOUSEMOVE() + ON_WM_KEYDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CChildView message handlers + +BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) +{ + if (!CWnd::PreCreateWindow(cs)) + return FALSE; + + cs.dwExStyle |= WS_EX_CLIENTEDGE; + cs.style &= ~WS_BORDER; + cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, + ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); + + return TRUE; +} + +void CChildView::OnPaint() +{ + CPaintDC dc(this); // device context for painting + +} + + +int CChildView::OnLoadBMP() +{ + if(!sourceFile){ + sourceFile = new CFileDialog(TRUE,"*.bmp", preferredSourcePath, + 0, "Bitmap Files (.bmp)|*.bmp|Backgrounds (*.bg)|*.bg|Sprites (*.sp)|*.sp|Bitmap, BG, & Sprite Files (.bmp;.bg;.sp)|*.bmp;*.bg;*.sp||"); + } + + + if(sourceFile->DoModal()==IDOK){ + sourceFileName = sourceFile->GetPathName(); + + //set dest + destFileName = sourceFileName.Left(sourceFileName.GetLength() + - (sourceFile->GetFileName()).GetLength()); + + preferredSourcePath = destFileName; + preferredSourcePath += "*.bmp"; + + destFileName += sourceFile->GetFileTitle(); + + if(sourceFileName.Right(3).CompareNoCase("bmp")==0){ + // BMP + pic.LoadBMP((char*) (LPCTSTR) sourceFileName); + }else if(sourceFileName.Right(2).CompareNoCase("bg")==0){ + // gameboy BG file + pic.LoadGBPic(sourceFileName); + }else{ + //hopefully a .sp file + pic.LoadGBSprite(sourceFileName); + } + + CFrameWnd *frame = this->GetParentFrame(); + int innerHeight = pic.GetDisplayHeight(); + if(innerHeight < CTRLHEIGHT) innerHeight = CTRLHEIGHT; + CRect frameRect(0,0,pic.GetDisplayWidth()+CTRLWIDTH,innerHeight); + AdjustWindowRectEx(&frameRect, frame->GetStyle() | GetStyle(), 0, + frame->GetExStyle()|GetExStyle()); + + int width = frameRect.Width(); + int height = frameRect.Height(); + //if(height < CTRLHEIGHT) height = CTRLHEIGHT; + + frame->SetWindowPos(&wndTop, 0, 0, width, height, SWP_NOMOVE); + + width = pic.GetDisplayWidth(); + height = pic.GetDisplayHeight(); + if(height < CTRLHEIGHT) height = CTRLHEIGHT; + + controls.SetWindowPos(&wndTop, 0, 0, CTRLWIDTH, height, SWP_SHOWWINDOW); + editArea.SetWindowPos(&wndTop, CTRLWIDTH, 0, width, height, SWP_SHOWWINDOW); + + return 1; + /* + switch(m_listType.GetCurSel()){ + case 0: + destFileName += ".bg"; + break; + case 1: + destFileName += ".tx"; + break; + case 2: + destFileName += ".sp"; + break; + } + */ + } + return 0; +} + +int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + + if (CWnd ::OnCreate(lpCreateStruct) == -1) + return -1; + + controls.Create(0,0,WS_CHILD,CRect(0,0,0,0),this,0,0); + editArea.Create(0,0,WS_CHILD,CRect(0,0,0,0),this,0,0); + + if(!OnLoadBMP()) this->GetParent()->PostMessage(WM_CLOSE); + + return 0; +} + +BOOL CChildView::OnEraseBkgnd(CDC* pDC) +{ + //return true; + return CWnd ::OnEraseBkgnd(pDC); +} + +void CChildView::DebugMesg(char *title, int num) +{ + char st[80]; + ostrstream stout(st,80); + stout << num << ends; + this->MessageBox(st,title); +} + + + +void CChildView::OnMouseMove(UINT nFlags, CPoint point) +{ + + CWnd ::OnMouseMove(nFlags, point); +} + +void CChildView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CWnd ::OnKeyDown(nChar, nRepCnt, nFlags); +} diff --git a/Tools/GBConv2/Source/ChildView.h b/Tools/GBConv2/Source/ChildView.h new file mode 100644 index 0000000..bd5ee34 --- /dev/null +++ b/Tools/GBConv2/Source/ChildView.h @@ -0,0 +1,70 @@ +// ChildView.h : interface of the CChildView class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDVIEW_H__2F0A9B4C_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_CHILDVIEW_H__2F0A9B4C_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_ + +#include "EditArea.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "gb_pic.h" +#include "EditArea.h" +#include "Controls.h" + + +///////////////////////////////////////////////////////////////////////////// +// CChildView window + +class CChildView : public CWnd +{ +// Construction +public: + CChildView(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildView) + protected: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + CEditArea editArea; + CControls controls; + void DebugMesg(char *title, int num); + int OnLoadBMP(); + virtual ~CChildView(); + + static CString preferredSourcePath; + gbPic pic; + CString sourceFileName, destFileName; + CFileDialog* sourceFile, *destFile; + + // Generated message map functions +protected: + //{{AFX_MSG(CChildView) + afx_msg void OnPaint(); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDVIEW_H__2F0A9B4C_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/Controls.cpp b/Tools/GBConv2/Source/Controls.cpp new file mode 100644 index 0000000..2479366 --- /dev/null +++ b/Tools/GBConv2/Source/Controls.cpp @@ -0,0 +1,437 @@ +// Controls.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "Controls.h" +#include "ChildView.h" +#include "wingk.h" +#include "EditPaletteDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CControls + +//statics +CString CControls::preferredDestPath = "d:\\aprogs\\fgbpix\\*.sp"; + +CControls::CControls() +{ + showSprites = 1; + showMapping = 1; + destFileDialog = 0; + bgFileDialog = 0; +} + +CControls::~CControls() +{ + if(destFileDialog){ + delete destFileDialog; + destFileDialog = 0; + } + if(bgFileDialog){ + delete bgFileDialog; + bgFileDialog = 0; + } +} + + +BEGIN_MESSAGE_MAP(CControls, CWnd) + //{{AFX_MSG_MAP(CControls) + ON_WM_CREATE() + ON_WM_PAINT() + ON_WM_MOUSEMOVE() + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDB_PALETTEFROMSEL,OnPaletteFromSel) + ON_BN_CLICKED(IDB_SETTOBGCOLOR,OnB_SetToBGColor) + ON_BN_CLICKED(IDB_SWAPWITHBGCOLOR,OnB_SwapWithBGColor) + ON_BN_CLICKED(IDB_AUTOMAPTOPALETTE,OnB_AutoMapToPalette) + ON_BN_CLICKED(IDB_MAPTOPALETTE,OnB_MapToPalette) + ON_BN_CLICKED(IDB_UNMAP,OnB_Unmap) + ON_BN_CLICKED(IDB_SELECTNONEMPTY,OnB_SelectNonEmpty) + ON_BN_CLICKED(IDB_MAKESPRITES,OnB_MakeSprites) + ON_BN_CLICKED(IDB_SHOWSPRITES,OnB_CheckShowSprites) + ON_BN_CLICKED(IDB_SHOWMAPPING,OnB_ShowMapping) + ON_BN_CLICKED(IDB_SELECTUNMAPPED,OnB_SelectUnmapped) + ON_BN_CLICKED(IDB_SAVEGBSPRITE,OnB_SaveGBSprite) + ON_BN_CLICKED(IDB_EDITPALETTE,OnB_EditPalette) + + ON_BN_CLICKED(IDB_AUTOMAPALL,OnB_AutoMapAll) + ON_BN_CLICKED(IDB_SAVEGBPIC,OnB_SaveGBPic) + + ON_LBN_SELCHANGE(IDLIST_PALETTES,OnSelChangePalettes) +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CControls message handlers + +int CControls::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + view = (CChildView*) this->GetParent(); + + palettes.Create( + WS_CHILD|WS_VISIBLE|LBS_MULTIPLESEL|LBS_EXTENDEDSEL|LBS_OWNERDRAWFIXED, + CRect(CTRLWIDTH-64,0,CTRLWIDTH,272),this,IDLIST_PALETTES); + + CChildView *view = (CChildView*) this->GetParent(); + + palettes.pic = &(view->pic); + + int i; + for(i=0; i<8; i++){ + int index = palettes.AddString(""); + palettes.SetItemData(index, i); + } + /* + palettes.AddString((char*) -1); + for(i=0; i<8; i++){ + int index = palettes.AddString(""); + palettes.SetItemData(index, i+8); + } + */ + + CRect rect(0,0,144,24); + createPaletteFromSel.Create("Colors->Palette",WS_CHILD|WS_VISIBLE, + rect,this,IDB_PALETTEFROMSEL); + + rect.OffsetRect(0,24); + b_setToBGColor.Create("Colors To BG Color",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SETTOBGCOLOR); + + rect.OffsetRect(0,24); + b_swapWithBGColor.Create("Swap Colors w/BG",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SWAPWITHBGCOLOR); + + rect.OffsetRect(0,32); + b_autoMapToPalette.Create("AutoMap To Palette",WS_CHILD|WS_VISIBLE, + rect,this,IDB_AUTOMAPTOPALETTE); + + rect.OffsetRect(0,24); + b_mapToPalette.Create("Map To Palette",WS_CHILD|WS_VISIBLE,rect,this, + IDB_MAPTOPALETTE); + + rect.OffsetRect(0,24); + b_unmap.Create("Unmap",WS_CHILD|WS_VISIBLE, + rect,this,IDB_UNMAP); + + rect.OffsetRect(0,24); + b_selectUnmapped.Create("Select Unmapped",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SELECTUNMAPPED); + + rect.OffsetRect(0,24); + b_autoMapAll.Create("AutoMap All",WS_CHILD|WS_VISIBLE, + rect,this,IDB_AUTOMAPALL); + + rect.OffsetRect(0,24); + b_saveGBPic.Create("Save GB Pic",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SAVEGBPIC); + + rect.OffsetRect(0,32); + b_selectNonEmpty.Create("Select Non-Empty",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SELECTNONEMPTY); + + rect.OffsetRect(0,24); + b_makeSprites.Create("Make 8x16 Sprites",WS_CHILD|WS_VISIBLE, + rect,this,IDB_MAKESPRITES); + + rect.OffsetRect(0,24); + b_saveGBSprite.Create("Save GB Sprite",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SAVEGBSPRITE); + + rect.OffsetRect(0,32); + b_editPalette.Create("Edit Palette",WS_CHILD|WS_VISIBLE, + rect,this,IDB_EDITPALETTE); + + rect.OffsetRect(0,24); + b_showSprites.Create("Show Sprites",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SHOWSPRITES); + + rect.OffsetRect(0,24); + b_showMapping.Create("Show Mapping",WS_CHILD|WS_VISIBLE, + rect,this,IDB_SHOWMAPPING); + + + + return 0; +} + +void CControls::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + CChildView *view = (CChildView*) this->GetParent(); + + //------------------------draw magnified area------------------------------- + CPoint point; + GetCursorPos(&point); + view->editArea.ScreenToClient(&point); + + //view->pic.GetMagnifiedArea(point.x,point.y)->BlitToDC(&dc, CTRLWIDTH-80,288); + view->pic.GetMagnifiedArea(point.x,point.y)->BlitToHDC(dc, CTRLWIDTH-80,288); + + //-----------------------draw bg color & selected colors-------------------- + //clear the color area + dc.FillSolidRect(0,CTRLHEIGHT-16,CTRLWIDTH,CTRLHEIGHT,0x303030); + CBrush blackBrush; + blackBrush.CreateSolidBrush(0); + + //draw the bg color + CRect rect(0,CTRLHEIGHT-16,16,CTRLHEIGHT); + dc.FillSolidRect(&rect, view->pic.GetBGColor()); + dc.FrameRect(&rect,&blackBrush); + + int count = view->pic.GetNumSelectedColors(); + if(count > 0){ + int pixelsPer = (CTRLWIDTH-32) / count; + int totalWidth = count * pixelsPer; + CRect curRect(32,CTRLHEIGHT-16,32+pixelsPer,CTRLHEIGHT); + gkRGB *colors = view->pic.GetSelectedColors(); + + int i; + for(i=0; ipic.SetNeedsRedraw(); + view->editArea.InvalidateRect(0); +} + +void CControls::OnPaletteFromSel() +{ + int curPal = palettes.GetCurSel(); + if(curPal==-1) return; + if(curPal>=8) curPal--; //blank divider item + + int n = view->pic.GetNumSelectedColors(); + if(n>4) n = 4; + + gkRGB *colors = view->pic.GetSelectedColors(); + + int i; + for(i=0; ipic.SetColor(curPal, i, colors[i]); + } + + palettes.InvalidateRect(0); + InvalidateEditArea(); +} + +void CControls::OnB_SetToBGColor() +{ + //set selected colors to be the background color + view->pic.RemapSelectedToBGColor(); + InvalidateMagnifiedArea(); + InvalidateEditArea(); +} + +void CControls::OnB_SwapWithBGColor() +{ + view->pic.SwapSelectedWithBGColor(); + InvalidateMagnifiedArea(); + InvalidateEditArea(); +} + +void CControls::OnB_AutoMapToPalette() +{ + int pal = 0; + int numSel = palettes.GetSelItems(17,palettesSelected); + int i; + for(i=0; ipic.AutoMapToPalette(pal); + InvalidateEditArea(); +} + +void CControls::OnB_SelectNonEmpty() +{ + view->pic.SelectNonEmpty(); + InvalidateEditArea(); + InvalidateMagnifiedArea(); +} + +void CControls::OnB_Unmap() +{ + view->pic.Unmap(); + InvalidateEditArea(); +} + +void CControls::OnB_MakeSprites() +{ + view->pic.SetCurPalette(palettes.GetCurSel()); + view->pic.MakeSprites(); + InvalidateEditArea(); +} + +void CControls::OnSelChangePalettes() +{ + //See same in CPaletteListBox + this->MessageBox("Super!"); +} + +void CControls::OnB_CheckShowSprites() +{ + showSprites ^= 1; + view->pic.SetNeedsRedraw(); + InvalidateEditArea(); +} + +void CControls::OnB_SelectUnmapped() +{ + view->pic.SelectUnmapped(); + InvalidateEditArea(); +} + +void CControls::OnB_SaveGBSprite() +{ + if(!destFileDialog){ + CString initialDestFilename = view->destFileName; + if(initialDestFilename.Right(3).CompareNoCase(".sp")!=0) initialDestFilename += ".sp"; + destFileDialog = new CFileDialog(FALSE,".sp", initialDestFilename, + 0, "Sprite Files (.sp)|*.sp||"); + } + + + if(destFileDialog->DoModal()==IDOK){ + destFilename = destFileDialog->GetPathName(); + view->pic.SaveGBSprite((char*) (const char*) destFilename); + + char st[80]; + ostrstream stout(st,80); + stout << view->pic.GetFileSize() << " Bytes" << ends; + this->MessageBox(st); + } +} + + +void CControls::OnB_EditPalette() +{ + gbPic &pic = view->pic; + + int pal = pic.GetCurPalette(); + if(pal<0 || pal>7) return; + + CEditPaletteDialog dialog; + + int i; + for(i=0; i<4; i++){ + dialog.initColors[i] = pic.GetColor(pal,i); + } + + if(dialog.DoModal()==IDOK){ + for(i=0; i<4; i++){ + pic.SetColor(pal,i,dialog.initColors[i]); + } + view->controls.InvalidateEditArea(); + } +} + +void CControls::OnB_AutoMapAll() +{ + view->pic.AutoMap(255); + InvalidateEditArea(); + palettes.Invalidate(0); +} + +void CControls::OnB_SaveGBPic() +{ + if(!bgFileDialog){ + CString initialDestFilename = view->destFileName; + if(initialDestFilename.Right(3).CompareNoCase(".bg")!=0) initialDestFilename += ".bg"; + bgFileDialog = new CBGSaveDialog(FALSE,".bg", initialDestFilename, + 0, "Background (.bg)|*.bg||"); + } + + //CString path = bgFileDialog->GetPathName(); + //CString ext = bgFileDialog->GetFileExt(); + //if(ext.GetLength()>0) path = path.Left(path.GetLength() - ext.GetLength() - 1); + //strcpy(bgFileDialog->m_ofn.lpstrFile,path); + if(bgFileDialog->DoModal()==IDOK){ + bgFilename = bgFileDialog->GetPathName(); + //if(bgFileDialog->GetFileExt().CompareNoCase("bg")){ + view->pic.SaveGBPic(bgFilename); + //}else{ + //view->pic.SaveGBText(bgFilename); + //} + + char st[80]; + ostrstream stout(st,80); + stout << view->pic.GetNumUniqueTiles() << " Unique Tiles" << endl; + stout << view->pic.GetFileSize() << " Bytes" << ends; + this->MessageBox(st); + } + + InvalidateEditArea(); + palettes.Invalidate(0); +} + +BOOL CControls::OnEraseBkgnd(CDC* pDC) +{ + CRect rect; + GetClientRect(&rect); + + pDC->FillSolidRect(&rect,0x303030); + return 1; + + //return CWnd::OnEraseBkgnd(pDC); +} + +void CControls::OnB_ShowMapping() +{ + showMapping ^= 1; + view->pic.SetNeedsRedraw(); + InvalidateEditArea(); +} + +void CControls::OnB_MapToPalette() +{ + int pal = 0; + int numSel = palettes.GetSelItems(17,palettesSelected); + int i; + for(i=0; ipic.MapToPalette(pal); + InvalidateEditArea(); +} diff --git a/Tools/GBConv2/Source/Controls.h b/Tools/GBConv2/Source/Controls.h new file mode 100644 index 0000000..768bf64 --- /dev/null +++ b/Tools/GBConv2/Source/Controls.h @@ -0,0 +1,108 @@ +#if !defined(AFX_CONTROLS_H__74CE4C48_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_CONTROLS_H__74CE4C48_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_ + +#include "PaletteListBox.h" // Added by ClassView +#include "BGSaveDialog.h" + +class CChildView; +class CPaletteListBox; + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Controls.h : header file +// + + +#define CTRLWIDTH 224 +#define CTRLHEIGHT 416 + + +///////////////////////////////////////////////////////////////////////////// +// CControls window + +class CControls : public CWnd +{ +// Construction +public: + CControls(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CControls) + //}}AFX_VIRTUAL + +// Implementation +public: + void OnB_MapToPalette(); + void OnB_ShowMapping(); + void OnB_SaveGBPic(); + void OnB_AutoMapAll(); + void OnB_EditPalette(); + void OnB_SaveGBSprite(); + void OnB_SelectUnmapped(); + void OnB_CheckShowSprites(); + void OnSelChangePalettes(); + void OnB_MakeSprites(); + void OnB_Unmap(); + void OnB_SelectNonEmpty(); + void OnB_AutoMapToPalette(); + void OnB_SwapWithBGColor(); + void OnB_SetToBGColor(); + void OnPaletteFromSel(); + void InvalidateEditArea(); + void InvalidateColors(); + void InvalidateMagnifiedArea(); + CPaletteListBox palettes; + virtual ~CControls(); + + int showSprites, showMapping; + + // Generated message map functions +protected: + int palettesSelected[17]; + CChildView *view; + CButton createPaletteFromSel; + CButton b_setToBGColor; + CButton b_swapWithBGColor; + CButton b_selectNonEmpty; + CButton b_unmap; + CButton b_makeSprites; + CButton b_autoMapToPalette; + CButton b_mapToPalette; + CButton b_showSprites; + CButton b_showMapping; + CButton b_selectUnmapped; + CButton b_saveGBSprite; + CButton b_editPalette; + + CButton b_autoMapAll; + CButton b_saveGBPic; + + static CString preferredDestPath; + CString destFilename; + CFileDialog *destFileDialog; + CString bgFilename; + CBGSaveDialog *bgFileDialog; + + //{{AFX_MSG(CControls) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnPaint(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTROLS_H__74CE4C48_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/EditArea.cpp b/Tools/GBConv2/Source/EditArea.cpp new file mode 100644 index 0000000..a375303 --- /dev/null +++ b/Tools/GBConv2/Source/EditArea.cpp @@ -0,0 +1,223 @@ +// EditArea.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "EditArea.h" +#include "ChildView.h" +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CEditArea + +CEditArea::CEditArea() +{ + view = 0; + downLMB = downRMB = 0; + pickingColors = 0; +} + +CEditArea::~CEditArea() +{ +} + + +BEGIN_MESSAGE_MAP(CEditArea, CWnd) + //{{AFX_MSG_MAP(CEditArea) + ON_WM_ERASEBKGND() + ON_WM_PAINT() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_CREATE() + ON_WM_KEYDOWN() + ON_WM_RBUTTONDOWN() + ON_WM_RBUTTONUP() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CEditArea message handlers + +BOOL CEditArea::OnEraseBkgnd(CDC* pDC) +{ + CRect rect; + GetClientRect(&rect); + + //fill to the right of the picture + int width = rect.Width() - view->pic.GetDisplayWidth(); + if(width > 0){ + pDC->FillSolidRect(view->pic.GetDisplayWidth(), 0, width, rect.Height(), 0x303030); + } + + int height = rect.Height() - view->pic.GetDisplayHeight(); + if(height > 0){ + pDC->FillSolidRect(0,view->pic.GetDisplayHeight(), + view->pic.GetDisplayWidth(), height, 0x303030); + } + + return 1; + + //return CWnd::OnEraseBkgnd(pDC); +} + +void CEditArea::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + //view->pic.GetDisplayBuffer()->BlitToDC(&dc, 0, 0); + int flags = (view->controls.showMapping << 1) | view->controls.showSprites; + view->pic.GetDisplayBuffer(flags)->BlitToHDC(dc, 0, 0); + + } + +void CEditArea::OnMouseMove(UINT nFlags, CPoint point) +{ + this->SetFocus(); + + view->controls.InvalidateMagnifiedArea(); + + if(downLMB){ + if(!pickingColors){ + view->pic.OnMouseLDrag(point.x, point.y); + view->controls.InvalidateColors(); + if(view->pic.GetNeedsRedraw()) this->InvalidateRect(0); + }else{ + if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ + if(GetAsyncKeyState(VK_SHIFT) & 0x8000){ + view->pic.AddNextColor(view->pic.GetColorAtPoint(point.x,point.y)); + }else{ + view->pic.SetFirstColor(view->pic.GetColorAtPoint(point.x,point.y)); + } + view->controls.InvalidateColors(); + }else{ + pickingColors = 0; + } + } + } + + if(downRMB){ + if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ + if(GetAsyncKeyState(VK_SHIFT) & 0x8000){ + //remove a color + view->pic.RemoveColor(view->pic.GetColorAtPoint(point.x,point.y)); + }else{ + //set the bg color + view->pic.SetBGColor(view->pic.GetColorAtPoint(point.x,point.y)); + } + view->controls.InvalidateColors(); + } + } + + CMainFrame *frame = (CMainFrame*) view->GetTopLevelFrame(); + char st[80]; + ostrstream stout(st,80); + stout << "Selected: " << view->pic.GetNumSelTiles() + << " Sprites: " << view->pic.GetNumSprites() << " "; + stout << "Mapping: "; + int mapping = view->pic.GetMappingAtPoint(point.x,point.y); + if(mapping==-1) stout << "(None) "; + else stout << mapping << " "; + stout << ends; + CString str(st); + frame->ShowStatus(&str); + + CWnd::OnMouseMove(nFlags, point); +} + +void CEditArea::OnLButtonDown(UINT nFlags, CPoint point) +{ + if(view->controls.showSprites){ + if(view->pic.UnmakeSprite(point.x, point.y)){ + this->InvalidateRect(0); + return; + } + } + + downLMB = 1; + if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ + if(GetAsyncKeyState(VK_SHIFT) & 0x8000){ + view->pic.AddNextColor(view->pic.GetColorAtPoint(point.x,point.y)); + }else{ + //pick a color + view->pic.SetFirstColor(view->pic.GetColorAtPoint(point.x,point.y)); + } + view->controls.InvalidateColors(); + pickingColors = 1; + }else{ + //select tiles + view->pic.OnMouseLMB(point.x, point.y); + view->controls.InvalidateColors(); + pickingColors = 0; + } + if(view->pic.GetNeedsRedraw()) this->InvalidateRect(0); + this->SetCapture(); + CWnd::OnLButtonDown(nFlags, point); +} + +void CEditArea::OnLButtonUp(UINT nFlags, CPoint point) +{ + if(downLMB){ + downLMB = 0; + if(!pickingColors){ + view->pic.OnMouseLRelease(point.x, point.y); + view->controls.InvalidateColors(); + CWnd::OnLButtonUp(nFlags, point); + if(view->pic.GetNeedsRedraw()) this->InvalidateRect(0); + } + ReleaseCapture(); + pickingColors = 0; + } +} + +int CEditArea::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + view = (CChildView*) this->GetParent(); + return 0; +} + +void CEditArea::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if(nChar==VK_CONTROL){ + //this->MessageBox("CTRL pressed!"); + } + CWnd::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CEditArea::OnRButtonDown(UINT nFlags, CPoint point) +{ + if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ + if(GetAsyncKeyState(VK_SHIFT) & 0x8000){ + //remove a color + view->pic.RemoveColor(view->pic.GetColorAtPoint(point.x,point.y)); + }else{ + //set the bg color + view->pic.SetBGColor(view->pic.GetColorAtPoint(point.x,point.y)); + } + view->controls.InvalidateColors(); + }else{ + //not picking colors; clear all selected pixels + view->pic.ClearSelection(); + this->InvalidateRect(0); + view->controls.InvalidateMagnifiedArea(); + view->controls.InvalidateColors(); + } + downRMB = 1; + CWnd::OnRButtonDown(nFlags, point); +} + +void CEditArea::OnRButtonUp(UINT nFlags, CPoint point) +{ + downRMB = 0; + CWnd::OnRButtonUp(nFlags, point); +} diff --git a/Tools/GBConv2/Source/EditArea.h b/Tools/GBConv2/Source/EditArea.h new file mode 100644 index 0000000..c75345a --- /dev/null +++ b/Tools/GBConv2/Source/EditArea.h @@ -0,0 +1,61 @@ +#if !defined(AFX_EDITAREA_H__74CE4C4A_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_EDITAREA_H__74CE4C4A_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditArea.h : header file +// + +class CChildView; + +///////////////////////////////////////////////////////////////////////////// +// CEditArea window + +class CEditArea : public CWnd +{ +// Construction +public: + CEditArea(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditArea) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CEditArea(); + + // Generated message map functions +protected: + int downRMB; + short int pickingColors; + CChildView *view; + int downLMB; + //{{AFX_MSG(CEditArea) + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPaint(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITAREA_H__74CE4C4A_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/EditPaletteDialog.cpp b/Tools/GBConv2/Source/EditPaletteDialog.cpp new file mode 100644 index 0000000..01a569d --- /dev/null +++ b/Tools/GBConv2/Source/EditPaletteDialog.cpp @@ -0,0 +1,109 @@ +// EditPaletteDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "EditPaletteDialog.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CEditPaletteDialog dialog + + +CEditPaletteDialog::CEditPaletteDialog(CWnd* pParent /*=NULL*/) + : CDialog(CEditPaletteDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CEditPaletteDialog) + //}}AFX_DATA_INIT +} + + +void CEditPaletteDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CEditPaletteDialog) + DDX_Control(pDX, IDC_EDIT_PAL_RED3, m_editRed3); + DDX_Control(pDX, IDC_EDIT_PAL_RED2, m_editRed2); + DDX_Control(pDX, IDC_EDIT_PAL_RED1, m_editRed1); + DDX_Control(pDX, IDC_EDIT_PAL_RED0, m_editRed0); + DDX_Control(pDX, IDC_EDIT_PAL_GREEN3, m_editGreen3); + DDX_Control(pDX, IDC_EDIT_PAL_GREEN2, m_editGreen2); + DDX_Control(pDX, IDC_EDIT_PAL_GREEN1, m_editGreen1); + DDX_Control(pDX, IDC_EDIT_PAL_GREEN0, m_editGreen0); + DDX_Control(pDX, IDC_EDIT_PAL_BLUE3, m_editBlue3); + DDX_Control(pDX, IDC_EDIT_PAL_BLUE2, m_editBlue2); + DDX_Control(pDX, IDC_EDIT_PAL_BLUE1, m_editBlue1); + DDX_Control(pDX, IDC_EDIT_PAL_BLUE0, m_editBlue0); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CEditPaletteDialog, CDialog) + //{{AFX_MSG_MAP(CEditPaletteDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CEditPaletteDialog message handlers + +void CEditPaletteDialog::OnOK() +{ + //copy working colors to initColors + initColors[0] = gkRGB(GetNum(m_editRed0),GetNum(m_editGreen0),GetNum(m_editBlue0)); + initColors[1] = gkRGB(GetNum(m_editRed1),GetNum(m_editGreen1),GetNum(m_editBlue1)); + initColors[2] = gkRGB(GetNum(m_editRed2),GetNum(m_editGreen2),GetNum(m_editBlue2)); + initColors[3] = gkRGB(GetNum(m_editRed3),GetNum(m_editGreen3),GetNum(m_editBlue3)); + + CDialog::OnOK(); +} + +int CEditPaletteDialog::GetNum(CEdit &edit) +{ + char st[80]; + edit.GetWindowText(st,80); + istrstream stin(st,80); + + int num; + stin >> num; + + if(num<0) num = 0; + if(num>255) num = 255; + num &= 0xf8; + return num; +} + +BOOL CEditPaletteDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetNum(m_editRed0,initColors[0].GetR()); + SetNum(m_editRed1,initColors[1].GetR()); + SetNum(m_editRed2,initColors[2].GetR()); + SetNum(m_editRed3,initColors[3].GetR()); + SetNum(m_editGreen0,initColors[0].GetG()); + SetNum(m_editGreen1,initColors[1].GetG()); + SetNum(m_editGreen2,initColors[2].GetG()); + SetNum(m_editGreen3,initColors[3].GetG()); + SetNum(m_editBlue0,initColors[0].GetB()); + SetNum(m_editBlue1,initColors[1].GetB()); + SetNum(m_editBlue2,initColors[2].GetB()); + SetNum(m_editBlue3,initColors[3].GetB()); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CEditPaletteDialog::SetNum(CEdit &edit, int n) +{ + char st[80]; + ostrstream stout(st,80); + n &= 0xff; + stout << n << ends; + edit.SetWindowText(st); +} diff --git a/Tools/GBConv2/Source/EditPaletteDialog.h b/Tools/GBConv2/Source/EditPaletteDialog.h new file mode 100644 index 0000000..12357f8 --- /dev/null +++ b/Tools/GBConv2/Source/EditPaletteDialog.h @@ -0,0 +1,63 @@ +#if !defined(AFX_EDITPALETTEDIALOG_H__E83CE848_1BC5_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_EDITPALETTEDIALOG_H__E83CE848_1BC5_11D4_B6CE_525400E2D57B__INCLUDED_ + +#include "wingk.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditPaletteDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CEditPaletteDialog dialog + +class CEditPaletteDialog : public CDialog +{ +// Construction +public: + void SetNum(CEdit &edit, int n); + int GetNum(CEdit &edit); + gkRGB colors[4]; + gkRGB initColors[4]; + CEditPaletteDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CEditPaletteDialog) + enum { IDD = IDD_EDIT_PALETTE }; + CEdit m_editRed3; + CEdit m_editRed2; + CEdit m_editRed1; + CEdit m_editRed0; + CEdit m_editGreen3; + CEdit m_editGreen2; + CEdit m_editGreen1; + CEdit m_editGreen0; + CEdit m_editBlue3; + CEdit m_editBlue2; + CEdit m_editBlue1; + CEdit m_editBlue0; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditPaletteDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CEditPaletteDialog) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITPALETTEDIALOG_H__E83CE848_1BC5_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/GBConv2.cpp b/Tools/GBConv2/Source/GBConv2.cpp new file mode 100644 index 0000000..c5d474e --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.cpp @@ -0,0 +1,157 @@ +// GBConv2.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "GBConv2.h" + +#include "MainFrm.h" +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App + +BEGIN_MESSAGE_MAP(CGBConv2App, CWinApp) + //{{AFX_MSG_MAP(CGBConv2App) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + ON_COMMAND(ID_FILE_NEW, OnFileNew) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App construction + +CGBConv2App::CGBConv2App() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CGBConv2App object + +CGBConv2App theApp; + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App initialization + +BOOL CGBConv2App::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + + + CMDIFrameWnd* pFrame = new CMainFrame; + m_pMainWnd = pFrame; + + // create main MDI frame window + if (!pFrame->LoadFrame(IDR_MAINFRAME)) + return FALSE; + + // try to load shared MDI menus and accelerator table + + HINSTANCE hInst = AfxGetResourceHandle(); + m_hMDIMenu = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_GBCONVTYPE)); + m_hMDIAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_GBCONVTYPE)); + + + pFrame->ShowWindow(SW_SHOWMAXIMIZED); + pFrame->UpdateWindow(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App message handlers + +int CGBConv2App::ExitInstance() +{ + if (m_hMDIMenu != NULL) + FreeResource(m_hMDIMenu); + if (m_hMDIAccel != NULL) + FreeResource(m_hMDIAccel); + + return CWinApp::ExitInstance(); +} + +void CGBConv2App::OnFileNew() +{ + CMainFrame* pFrame = STATIC_DOWNCAST(CMainFrame, m_pMainWnd); + + // create a new MDI child window + pFrame->CreateNewChild( + RUNTIME_CLASS(CChildFrame), IDR_GBCONVTYPE, m_hMDIMenu, m_hMDIAccel); +} + + + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CGBConv2App::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App message handlers + diff --git a/Tools/GBConv2/Source/GBConv2.dsp b/Tools/GBConv2/Source/GBConv2.dsp new file mode 100644 index 0000000..c47ae36 --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.dsp @@ -0,0 +1,253 @@ +# Microsoft Developer Studio Project File - Name="GBConv2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=GBConv2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "GBConv2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "GBConv2.mak" CFG="GBConv2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "GBConv2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "GBConv2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "GBConv2 - Win32 Release" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=copy exe from Release directory +PostBuild_Cmds=copy /y Release\*.exe . +# End Special Build Tool + +!ELSEIF "$(CFG)" == "GBConv2 - Win32 Debug" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "GBConv2 - Win32 Release" +# Name "GBConv2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\BGSaveDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChildFrm.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChildView.cpp +# End Source File +# Begin Source File + +SOURCE=.\Controls.cpp +# End Source File +# Begin Source File + +SOURCE=.\EditArea.cpp +# End Source File +# Begin Source File + +SOURCE=.\EditPaletteDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\gb_pic.cpp + +!IF "$(CFG)" == "GBConv2 - Win32 Release" + +# ADD CPP /Yu + +!ELSEIF "$(CFG)" == "GBConv2 - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\GBConv2.cpp +# End Source File +# Begin Source File + +SOURCE=.\GBConv2.rc +# End Source File +# Begin Source File + +SOURCE=.\MainFrm.cpp +# End Source File +# Begin Source File + +SOURCE=.\PaletteButton.cpp +# End Source File +# Begin Source File + +SOURCE=.\PaletteListBox.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\wingk.cpp + +!IF "$(CFG)" == "GBConv2 - Win32 Release" + +# ADD CPP /Yu + +!ELSEIF "$(CFG)" == "GBConv2 - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\BGSaveDialog.h +# End Source File +# Begin Source File + +SOURCE=.\ChildFrm.h +# End Source File +# Begin Source File + +SOURCE=.\ChildView.h +# End Source File +# Begin Source File + +SOURCE=.\Controls.h +# End Source File +# Begin Source File + +SOURCE=.\EditArea.h +# End Source File +# Begin Source File + +SOURCE=.\EditPaletteDialog.h +# End Source File +# Begin Source File + +SOURCE=.\gb_pic.h +# End Source File +# Begin Source File + +SOURCE=.\GBConv2.h +# End Source File +# Begin Source File + +SOURCE=.\MainFrm.h +# End Source File +# Begin Source File + +SOURCE=.\PaletteButton.h +# End Source File +# Begin Source File + +SOURCE=.\PaletteListBox.h +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\wingk.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\res\GBConv2.ico +# End Source File +# Begin Source File + +SOURCE=.\res\GBConv2.rc2 +# End Source File +# Begin Source File + +SOURCE=.\res\Toolbar.bmp +# End Source File +# End Group +# End Target +# End Project diff --git a/Tools/GBConv2/Source/GBConv2.dsw b/Tools/GBConv2/Source/GBConv2.dsw new file mode 100644 index 0000000..7ab3cd4 --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "GBConv2"=.\GBConv2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Tools/GBConv2/Source/GBConv2.h b/Tools/GBConv2/Source/GBConv2.h new file mode 100644 index 0000000..d59462a --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.h @@ -0,0 +1,54 @@ +// GBConv2.h : main header file for the GBCONV2 application +// + +#if !defined(AFX_GBCONV2_H__2F0A9B44_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_GBCONV2_H__2F0A9B44_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CGBConv2App: +// See GBConv2.cpp for the implementation of this class +// + +class CGBConv2App : public CWinApp +{ +public: + CGBConv2App(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGBConv2App) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + //}}AFX_VIRTUAL + +// Implementation +protected: + HMENU m_hMDIMenu; + HACCEL m_hMDIAccel; + +public: + //{{AFX_MSG(CGBConv2App) + afx_msg void OnAppAbout(); + afx_msg void OnFileNew(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GBCONV2_H__2F0A9B44_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/GBConv2.plg b/Tools/GBConv2/Source/GBConv2.plg new file mode 100644 index 0000000..d92ee57 --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.plg @@ -0,0 +1,87 @@ + + +

+

Build Log

+

+--------------------Configuration: GBConv2 - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release/GBConv2.res" /d "NDEBUG" "D:\Aprogs\GBConv2\GBConv2.rc"" +Creating temporary file "C:\WINDOWS\TEMP\RSP1245.TMP" with contents +[ +/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"Release/GBConv2.pch" /Yu"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"D:\Aprogs\GBConv2\BGSaveDialog.cpp" +"D:\Aprogs\GBConv2\ChildFrm.cpp" +"D:\Aprogs\GBConv2\ChildView.cpp" +"D:\Aprogs\GBConv2\Controls.cpp" +"D:\Aprogs\GBConv2\EditArea.cpp" +"D:\Aprogs\GBConv2\EditPaletteDialog.cpp" +"D:\Aprogs\GBConv2\gb_pic.cpp" +"D:\Aprogs\GBConv2\GBConv2.cpp" +"D:\Aprogs\GBConv2\MainFrm.cpp" +"D:\Aprogs\GBConv2\PaletteButton.cpp" +"D:\Aprogs\GBConv2\PaletteListBox.cpp" +"D:\Aprogs\GBConv2\wingk.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP1245.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP1246.TMP" with contents +[ +/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"Release/GBConv2.pch" /Yc"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"D:\Aprogs\GBConv2\StdAfx.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP1246.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP1247.TMP" with contents +[ +/nologo /subsystem:windows /incremental:no /pdb:"Release/GBConv2.pdb" /machine:I386 /out:"Release/GBConv2.exe" +.\Release\BGSaveDialog.obj +.\Release\ChildFrm.obj +.\Release\ChildView.obj +.\Release\Controls.obj +.\Release\EditArea.obj +.\Release\EditPaletteDialog.obj +.\Release\gb_pic.obj +.\Release\GBConv2.obj +.\Release\MainFrm.obj +.\Release\PaletteButton.obj +.\Release\PaletteListBox.obj +.\Release\StdAfx.obj +.\Release\wingk.obj +.\Release\GBConv2.res +] +Creating command line "link.exe @C:\WINDOWS\TEMP\RSP1247.TMP" +

Output Window

+Compiling resources... +Compiling... +StdAfx.cpp +Compiling... +BGSaveDialog.cpp +ChildFrm.cpp +ChildView.cpp +Controls.cpp +EditArea.cpp +EditPaletteDialog.cpp +gb_pic.cpp +GBConv2.cpp +MainFrm.cpp +PaletteButton.cpp +PaletteListBox.cpp +wingk.cpp +Generating Code... +Linking... +Creating temporary file "C:\WINDOWS\TEMP\RSP1370.BAT" with contents +[ +@echo off +copy /y Release\*.exe . +] +Creating command line "C:\WINDOWS\TEMP\RSP1370.BAT" +copy exe from Release directory +Release\GBConv2.exe + 1 file(s) copied + + + +

Results

+GBConv2.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/Tools/GBConv2/Source/GBConv2.rc b/Tools/GBConv2/Source/GBConv2.rc new file mode 100644 index 0000000..b205b05 --- /dev/null +++ b/Tools/GBConv2/Source/GBConv2.rc @@ -0,0 +1,411 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\GBConv2.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "res\\GBConv2.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15 +BEGIN + BUTTON ID_FILE_NEW + SEPARATOR + BUTTON ID_APP_ABOUT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About GBConv2...", ID_APP_ABOUT + MENUITEM "Instructions", ID_APP_INSTRUCTIONS + END +END + +IDR_GBCONVTYPE MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Close", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Window" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "&Tile", ID_WINDOW_TILE_HORZ + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + END + POPUP "&Help" + BEGIN + MENUITEM "&About GBConv2...", ID_APP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT + VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT + "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 236, 55 +STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | + WS_CAPTION | WS_SYSMENU +CAPTION "About GBConv2" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "GBConv2 Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2000 by Abe Pralle",IDC_STATIC,40,25,119, + 8 + DEFPUSHBUTTON "OK",IDOK,179,7,50,14,WS_GROUP +END + +IDD_EDIT_PALETTE DIALOG DISCARDABLE 0, 0, 231, 103 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Palette" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_PAL_RED0,37,23,38,15,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_PAL_GREEN0,81,23,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_BLUE0,125,23,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_RED1,37,41,38,15,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_PAL_GREEN1,81,41,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_BLUE1,125,41,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_RED2,37,58,38,15,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_PAL_GREEN2,81,58,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_BLUE2,125,58,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_RED3,37,76,38,15,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_PAL_GREEN3,81,76,38,15,ES_AUTOHSCROLL | + ES_NUMBER + EDITTEXT IDC_EDIT_PAL_BLUE3,125,76,38,15,ES_AUTOHSCROLL | + ES_NUMBER + DEFPUSHBUTTON "OK",IDOK,174,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,174,24,50,14 + LTEXT "Color 0",IDC_STATIC,7,26,29,13 + CTEXT "Red",IDC_STATIC,41,7,28,12 + CTEXT "Green",IDC_STATIC,83,7,32,11 + CTEXT "Blue",IDC_STATIC,126,7,34,10 + LTEXT "Color 1",IDC_STATIC,7,44,29,13 + LTEXT "Color 2",IDC_STATIC,7,61,29,13 + LTEXT "Color 3",IDC_STATIC,7,79,29,13 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "GBConv2 MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "GBConv2\0" + VALUE "LegalCopyright", "Copyright (C) 2000\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "GBConv2.EXE\0" + VALUE "ProductName", "GBConv2 Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 229 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_EDIT_PALETTE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 224 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "GBConv2" + IDR_GBCONVTYPE "\nGBConv\nGBConv" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "GBConv2" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Create a new document\nNew" + ID_FILE_CLOSE "Close the active document\nClose" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons" + ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows" + ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" + AFX_IDS_MDICHILD "Activate this window" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\GBConv2.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Tools/GBConv2/Source/MainFrm.cpp b/Tools/GBConv2/Source/MainFrm.cpp new file mode 100644 index 0000000..2986113 --- /dev/null +++ b/Tools/GBConv2/Source/MainFrm.cpp @@ -0,0 +1,108 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "GBConv2.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CMDIFrameWnd::PreCreateWindow(cs) ) + return FALSE; + cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE + | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CMDIFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CMDIFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + + +void CMainFrame::ShowStatus(CString *st) +{ + if(IsWindow(m_wndStatusBar.m_hWnd)){ + m_wndStatusBar.SetWindowText(*st); + } +} diff --git a/Tools/GBConv2/Source/MainFrm.h b/Tools/GBConv2/Source/MainFrm.h new file mode 100644 index 0000000..0e200b3 --- /dev/null +++ b/Tools/GBConv2/Source/MainFrm.h @@ -0,0 +1,57 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__2F0A9B48_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_MAINFRM_H__2F0A9B48_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMainFrame : public CMDIFrameWnd +{ + DECLARE_DYNAMIC(CMainFrame) +public: + CMainFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + void ShowStatus(CString *st); + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__2F0A9B48_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/PaletteButton.cpp b/Tools/GBConv2/Source/PaletteButton.cpp new file mode 100644 index 0000000..82e6f46 --- /dev/null +++ b/Tools/GBConv2/Source/PaletteButton.cpp @@ -0,0 +1,33 @@ +// PaletteButton.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "PaletteButton.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPaletteButton + +CPaletteButton::CPaletteButton() +{ +} + +CPaletteButton::~CPaletteButton() +{ +} + + +BEGIN_MESSAGE_MAP(CPaletteButton, CButton) + //{{AFX_MSG_MAP(CPaletteButton) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPaletteButton message handlers diff --git a/Tools/GBConv2/Source/PaletteButton.h b/Tools/GBConv2/Source/PaletteButton.h new file mode 100644 index 0000000..22db0db --- /dev/null +++ b/Tools/GBConv2/Source/PaletteButton.h @@ -0,0 +1,48 @@ +#if !defined(AFX_PALETTEBUTTON_H__74CE4C52_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_PALETTEBUTTON_H__74CE4C52_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PaletteButton.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPaletteButton window + +class CPaletteButton : public CButton +{ +// Construction +public: + CPaletteButton(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPaletteButton) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CPaletteButton(); + + // Generated message map functions +protected: + //{{AFX_MSG(CPaletteButton) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PALETTEBUTTON_H__74CE4C52_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/PaletteListBox.cpp b/Tools/GBConv2/Source/PaletteListBox.cpp new file mode 100644 index 0000000..6a89df6 --- /dev/null +++ b/Tools/GBConv2/Source/PaletteListBox.cpp @@ -0,0 +1,126 @@ +// PaletteListBox.cpp : implementation file +// + +#include "stdafx.h" +#include "GBConv2.h" +#include "PaletteListBox.h" +#include "gb_pic.h" +#include "ChildView.h" +#include "Controls.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPaletteListBox + +CPaletteListBox::CPaletteListBox() +{ + int i; + for(i=0; i<17; i++) itemSelected[i] = 0; + pic = 0; +} + +CPaletteListBox::~CPaletteListBox() +{ +} + + +BEGIN_MESSAGE_MAP(CPaletteListBox, CListBox) + //{{AFX_MSG_MAP(CPaletteListBox) + ON_WM_CREATE() + ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange) + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP + ON_LBN_SELCHANGE(IDLIST_PALETTES, OnSelchange) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPaletteListBox message handlers + +void CPaletteListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + lpMeasureItemStruct->itemWidth = 64; + lpMeasureItemStruct->itemHeight = 16; +} + +void CPaletteListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); + + int index = this->GetItemData(lpDrawItemStruct->itemID); + if(index < 0 || index>15) return; + + if(lpDrawItemStruct->itemState & ODS_SELECTED){ + pic->SetCurPalette(index); + } + + CRect rect = lpDrawItemStruct->rcItem; + int x = rect.left; + int y = rect.top; + + CBrush black((int) 0); + CBrush white(0xffffff); + //CBrush bgColor(pDC->GetBkColor()); + CBrush bgColor(0x303030); + + gkRGB *pal = view->pic.GetPalette(index); + + int i; + for(i=0; i<4; i++){ + gkRGB color = pal[i]; + if(color.GetA()==0){ + //blit the "no color" image + //pic->nonColorBG.BlitToDC(pDC, x+3, y+3); + pic->nonColorBG.BlitToHDC(*pDC, x+3, y+3); + }else{ + pDC->FillSolidRect(x+3,y+3,10,10,color); + } + pDC->FrameRect(CRect(x+2,y+2,x+14,y+14), &black); + x += 16; + } + + //clear the frame to the bg color + //pDC->FrameRect(rect, &bgColor); + + if(lpDrawItemStruct->itemState & ODS_SELECTED){ + itemSelected[index] = 1; + pDC->FrameRect(rect, &white); + }else{ + itemSelected[index] = 0; + pDC->FrameRect(rect, &bgColor); + } +} + +int CPaletteListBox::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CListBox::OnCreate(lpCreateStruct) == -1) + return -1; + + controls = (CControls*) this->GetParent(); + view = (CChildView*) controls->GetParent(); + + return 0; +} + + + +void CPaletteListBox::OnSelchange() +{ + this->MessageBox("Super Duper!"); +} + + +BOOL CPaletteListBox::OnEraseBkgnd(CDC* pDC) +{ + CRect rect; + GetClientRect(&rect); + + pDC->FillSolidRect(&rect, 0x303030); + return 1; + + //return CListBox::OnEraseBkgnd(pDC); +} diff --git a/Tools/GBConv2/Source/PaletteListBox.h b/Tools/GBConv2/Source/PaletteListBox.h new file mode 100644 index 0000000..5fe5403 --- /dev/null +++ b/Tools/GBConv2/Source/PaletteListBox.h @@ -0,0 +1,62 @@ +#if !defined(AFX_PALETTELISTBOX_H__74CE4C4B_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_PALETTELISTBOX_H__74CE4C4B_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PaletteListBox.h : header file +// + +#include "gb_pic.h" + +class CChildView; +class CControls; + +///////////////////////////////////////////////////////////////////////////// +// CPaletteListBox window + +class CPaletteListBox : public CListBox +{ +// Construction +public: + CPaletteListBox(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPaletteListBox) + public: + virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + //}}AFX_VIRTUAL + +// Implementation +public: + CChildView *view; + CControls *controls; + gbPic * pic; + virtual ~CPaletteListBox(); + + // Generated message map functions +protected: + int itemSelected[17]; + //{{AFX_MSG(CPaletteListBox) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSelchange(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PALETTELISTBOX_H__74CE4C4B_0DAC_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/StdAfx.cpp b/Tools/GBConv2/Source/StdAfx.cpp new file mode 100644 index 0000000..f43b5a0 --- /dev/null +++ b/Tools/GBConv2/Source/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// GBConv2.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/Tools/GBConv2/Source/StdAfx.h b/Tools/GBConv2/Source/StdAfx.h new file mode 100644 index 0000000..5d66901 --- /dev/null +++ b/Tools/GBConv2/Source/StdAfx.h @@ -0,0 +1,27 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__2F0A9B46_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_STDAFX_H__2F0A9B46_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__2F0A9B46_0CC2_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/GBConv2/Source/gb_pic.cpp b/Tools/GBConv2/Source/gb_pic.cpp new file mode 100644 index 0000000..27a7505 --- /dev/null +++ b/Tools/GBConv2/Source/gb_pic.cpp @@ -0,0 +1,1727 @@ +#include "stdafx.h" +#include "gb_pic.h" +#include +#include + +//statics +gkWinShape gbPic::nonPictureBG; +gkWinShape gbPic::nonColorBG; +gkWinShape gbPic::gfxTiles[20]; + +////////////////////////////////////////////////////////////////////// +// Open8BitHashTable +////////////////////////////////////////////////////////////////////// +Open8BitHashTable::Open8BitHashTable(){ + table = 0; + Reset(); +} + +Open8BitHashTable::~Open8BitHashTable(){ + Reset(); +} + +void Open8BitHashTable::Reset(){ + if(table) delete table; + table = 0; + size = 0; +} + +void Open8BitHashTable::Create(int maxElements){ + Reset(); + + size = maxElements + 1; + int powerTwo = 1; + while(powerTwo < size) powerTwo<<=1; + size = powerTwo; + + table = new HashEntry[size]; + + int i; + for(i=0; i<256; i++){ + entryPoint[i] = (size * i) / 256; + } +} + +int Open8BitHashTable::SetFirstIndex(int code){ + return entryPoint[code & 0xff]; +} + +int Open8BitHashTable::GetNextIndex(int &position){ + int retVal; + if(table[position].hash==-1){ + retVal = -1; + position++; + }else{ + retVal = table[position++].index; + } + position &= (size-1); //size is always power of two + return retVal; +} + +void Open8BitHashTable::Add(int code, int index){ + int pos = SetFirstIndex(code); + + //advance 'pos' to the proper position + while(GetNextIndex(pos)!=-1); + + pos--; + pos &= (size-1); + + table[pos].hash = code; + table[pos].index = index; +} + + + +////////////////////////////////////////////////////////////////////// +// gbTile +////////////////////////////////////////////////////////////////////// + +gbTile::gbTile(){ + gkWinShape::gkWinShape(); + colors = 0; + Reset(); +} + +gbTile::~gbTile(){ + Reset(); +} + +void gbTile::Reset(){ + gkWinShape::FreeData(); + if(colors) delete colors; + colors = 0; +} + +void gbTile::OnColorChange(){ + paletteUsed = -1; + + gkPaletteGenerator gen; + int numPixels; + numPixels = width * height; + gkRGB *curData = (gkRGB*) data; + while(numPixels--){ + gen.AddColor(*(curData++)); + } + colorsUsed = gen.GetNumColors(); + if(colors) delete colors; + colors = new gkRGB[colorsUsed]; + gen.CreatePalette(colors,colorsUsed); +} + +int gbTile::OnPaletteChange(int palettes){ + int result = 0; + + if(paletteUsed==-1) return 0; + if(palettes & (1 << paletteUsed)){ + paletteUsed = -1; + OnColorChange(); + result = 1; + } + + return result; +} + +int gbTile::TestMatch(gkRGB *palette){ + int i, diff = 0; + gkPaletteGenerator gen; + + for(i=0; i<4; i++){ + if(palette[i].GetA()==0){ + if(i==0) return 0xffff; + break; + } + gen.AddColor(palette[i]); + } + + for(i=0; idata; + int i, bit, dest; + dest = 0; + dataHash = 0; + for(i=0; i<8; i++){ //8 lines + int byte1 = 0; + int byte2 = 0; + for(bit=0; bit<8; bit++){ // 8 bits per line + //find the color index of next pixel + gkRGB color = *(src++); + int index; + for(index=0; index<4; index++){ + if(palettePtr[index]==color) break; + } + + //save the two bits of the color index in separate bytes + byte1 = (byte1<<1) | (index & 1); + byte2 = (byte2<<1) | ((index>>1)&1); + } + + dataHash += byte1 + byte2; + rawData[dest++] = byte1; + rawData[dest++] = byte2; + } +} + +void gbTile::SetRawData(gkBYTE *data){ + dataHash = 0; + int i; + for(i=0; i<16; i++){ + rawData[i] = data[i]; + dataHash += data[i]; + } +} + +void gbTile::CreateFromRawData(gbPic *pic){ + Create(8,8); + + gkRGB *dest = (gkRGB*) data; + int pos = 0; + + int i; + for(i=0; i<8; i++){ + int byte1 = rawData[pos++]; + int byte2 = rawData[pos++]; + + for(int bit=0; bit<8; bit++){ + int index = 0; + if(byte1 & 128) index += 1; + if(byte2 & 128) index += 2; + byte1<<=1; + byte2<<=1; + *(dest++) = palettePtr[index]; + } + } + + int pal = paletteUsed; + OnColorChange(); + SetPaletteUsed(pic,pal); +} + +int gbTile::CompareRawData(gkBYTE *data2){ + int i; + for(i=0; i<16; i++){ + if(rawData[i] != data2[i]) return 0; + } + return 1; +} + +void gbTile::SetPaletteUsed(gbPic *pic, int n){ + paletteUsed = n; + palettePtr = pic->GetPalette(n); +} + +void gbTile::CopyRawDataTo(gkBYTE *dest){ + int i; + for(i=0; i<16; i++) dest[i] = rawData[i]; +} + +void gbTile::WriteRawData(ostream &out){ + int i; + for(i=0; i<16; i++) out.put(rawData[i]); +} + + +////////////////////////////////////////////////////////////////////// +// gbSprite +////////////////////////////////////////////////////////////////////// +gbSprite::gbSprite(){ + gkWinShape::gkWinShape(); + Reset(); +} + +gbSprite::~gbSprite(){ + Reset(); + gkWinShape::~gkWinShape(); +} + +void gbSprite::Reset(){ + gkWinShape::Reset(); +} + +void gbSprite::Create8x16FromSelection(int x1, int y1, + gbTile *tile1, gbTile *tile2, gkWinShape *selection, gbPic *pic){ + + xp = x1; + yp = y1; + + Create(8,16); + int pal = tile1->GetPaletteUsed(); + if(pal==-1) pal = pic->GetCurPalette(); + + palette = pic->GetPalette(pal); + paletteNum = pal; + + gkRGB bgColor = pic->GetColor(pal,0); + Cls(bgColor); + + int x,y; + for(y=0; y<8; y++){ + for(x=0; x<8; x++){ + gkRGB color = selection->Point(x+x1,y+y1); + if(color.GetA() != 255){ + Plot(x,y,tile1->Point(x,y)); + selection->Plot(x+x1,y+y1,gkRGB(0,0,0,255)); + tile1->Plot(x,y,bgColor); + } + } + } + tile1->OnColorChange(); + + if(tile2){ + for(y=8; y<16; y++){ + for(x=0; x<8; x++){ + gkRGB color = selection->Point(x+x1,y+y1); + if(color.GetA() != 255){ + Plot(x,y,tile2->Point(x,y-8)); + selection->Plot(x+x1,y+y1,gkRGB(0,0,0,255)); + tile2->Plot(x,y-8,bgColor); + } + } + } + tile2->OnColorChange(); + } + + SetColorAlpha(bgColor,0); + MakeRawData(); +} + +void gbSprite::Blit(gkWinShape *dest){ + gkWinShape::Blit(dest,xp,yp); +} + +void gbSprite::DrawFrame(gkWinShape *dest, int magnification){ + int shrink = 1; + if(((yp>>3)&1) == 1) shrink = 3; + + int x = ((xp*magnification) >> 8); + int y = ((yp*magnification) >> 8); + + int width = (8 * magnification) >> 8; + int height = (16 * magnification) >> 8; + + dest->RectFrame(x+shrink,y+shrink,width-shrink*2,height-shrink*2, + gkRGB(128,255,128)); +} + +int gbSprite::ExistsAtIndex(int i, int j){ + int my_i = xp>>3; + int my_j = yp>>3; + if(my_i==i && (my_j==j || my_j+1==j)) return 1; + return 0; +} + +int gbSprite::Unmake(gbPic *pic){ + int i,j; + i = xp>>3; + j = yp>>3; + int index1 = j * pic->tileWidth + i; + int index2 = index1 + pic->tileWidth; + + this->gkWinShape::Blit(&pic->tiles[index1], 0, 0); + pic->tiles[index1].OnColorChange(); + if(j+1 < pic->tileHeight){ + this->gkWinShape::Blit(&pic->tiles[index2],0,-8); + pic->tiles[index2].OnColorChange(); + } + + return 1; +} + +void gbSprite::WriteTileDefinitions(ostream &out){ + int i; + for(i=0; i<32; i++) out.put((char) rawData[i]); +} + + +void gbSprite::ReadTileDefinitions(istream &in){ + //no palette yet, have to store raw data for later + int i; + for(i=0; i<32; i++) rawData[i] = in.get(); +} + + +void gbSprite::WriteAttributes(ostream &out, int index){ + // BYTE: Y-position + // BYTE: X-position + // BYTE: Image index of sprite used (0-127) + // BYTE: ATTRIBUTES: + // Bit 7: 0 = Sprite displayed over BG & window + // 1 = Sprite hidden behind colors 1,2,&3 of + // BG & win (stored as 0) + // Bit 6: Y flip status (stored as 0) + // Bit 5: X flip status (stored as 0) + // Bit 4: Not used in GBC (stored as 0) + // Bit 3: Character bank used (1/0) + // Bits[2:0]: Palette number (0-7) (Stored as 0) + out.put((char) (yp + 16)); + out.put((char) (xp + 8)); + out.put((char) (index * 2)); + + int attributes = paletteNum; + out.put((char) attributes); +} + + +void gbSprite::ReadAttributes(istream &in, gbPic *pic){ + // BYTE: Y-position + // BYTE: X-position + // BYTE: Image index of sprite used (0-127) + // BYTE: ATTRIBUTES: + // Bit 7: 0 = Sprite displayed over BG & window + // 1 = Sprite hidden behind colors 1,2,&3 of + // BG & win (stored as 0) + // Bit 6: Y flip status (stored as 0) + // Bit 5: X flip status (stored as 0) + // Bit 4: Not used in GBC (stored as 0) + // Bit 3: Character bank used (1/0) + // Bits[2:0]: Palette number (0-7) (Stored as 0) + yp = (in.get() & 0xff) - 16; + xp = (in.get() & 0xff) - 8; + in.get(); //discard index + paletteNum = in.get() & 7; + palette = pic->GetPalette(paletteNum); +} + + +void gbSprite::CreateFromRawData(){ + Create(8,16); + + gkRGB *dest = (gkRGB*) data; + int pos = 0; + + int i; + for(i=0; i<16; i++){ + int byte1 = rawData[pos++]; + int byte2 = rawData[pos++]; + + for(int bit=0; bit<8; bit++){ + int index = 0; + if(byte1 & 128) index += 1; + if(byte2 & 128) index += 2; + byte1<<=1; + byte2<<=1; + *(dest++) = palette[index]; + } + } + + SetColorAlpha(palette[0],0); +} + +void gbSprite::MakeRawData(){ + gkRGB *src = (gkRGB*) this->data; + int i, bit, dest; + dest = 0; + for(i=0; i<16; i++){ //16 lines + int byte1 = 0; + int byte2 = 0; + for(bit=0; bit<8; bit++){ // 8 bits per line + //find the color index of next pixel + gkRGB color = *(src++); + int index; + for(index=0; index<4; index++){ + if(palette[index]==color) break; + } + + //save the two bits of the color index in separate bytes + byte1 = (byte1<<1) | (index & 1); + byte2 = (byte2<<1) | ((index>>1)&1); + } + + rawData[dest++] = byte1; + rawData[dest++] = byte2; + } +} + + +////////////////////////////////////////////////////////////////////// +// gbPic +////////////////////////////////////////////////////////////////////// + +gbPic::gbPic(){ + tiles = 0; + selected = 0; + magnifiedArea.Create(80,80); + numSprites = 0; + Reset(); + + //set up static stuff + if(!nonPictureBG.GetData()){ + nonPictureBG.Create(80,80); + nonPictureBG.Cls(gkRGB(0x60,0x60,0x60)); + int i,j; + for(j=0; j<5; j++){ + for(i=0; i<5; i++){ + if(((j&1) && !(i&1)) || (!(j&1) && (i&1))){ + nonPictureBG.RectFill(i<<4, j<<4, 16, 16, gkRGB(0xa0,0xa0,0xa0)); + } + } + } + + nonColorBG.Create(10,10); + nonPictureBG.BlitScale(&nonColorBG,0,0,0x48,0); + + gkWinShape buffer; + buffer.LoadBMP("converter_gfx.bmp"); + for(i=0; i<20; i++){ + gfxTiles[i].GetShape(&buffer,i*16,0,16,16); + if(i<16) gfxTiles[i].SetAlpha(0xc0); + gfxTiles[i].SetColorAlpha(gkRGB(0,0,255), 0); + } + } +} + +gbPic::~gbPic(){ + Reset(); +} + +void gbPic::Reset(){ + if(tiles) delete [] tiles; + tiles = 0; + if(selected) delete selected; + selected = 0; + tileWidth = tileHeight = displayWidth = displayHeight = 0; + totalTiles = 0; + displayBuffer.FreeData(); + magnification = 0x400; + needsRedraw = 1; + showGrid = 1; + dragSetOrClear = 0; + + int i; + for(i=0; i<64; i++) palettes[i] = gkRGB(0,0,0,0); + + for(i=0; i> 3; + tileHeight = ((original.GetHeight() + 7) & (~7)) >> 3; + //displayWidth = tileWidth * 8 * 4; + //displayHeight = tileHeight * 8 * 4; + //magnification = 0x10000 << 2; + + original.ReduceColors(56); + + //merge vagrant colors (colors that will appear the same in the GBC + //15-bit palette) + int *data = (int*) original.GetData(); + int i = original.GetWidth() * original.GetHeight(); + while(i--){ + *(data++) &= 0xfff8f8f8; //clear bits 2:0 of each color + } + + //create some buffers + int pixelWidth = tileWidth << 3; + int pixelHeight = tileHeight << 3; + totalTiles = tileWidth * tileHeight; + SetMagnification(0x400); //default 4x magnification + + backbuffer.Create(pixelWidth, pixelHeight); + pixelBuffer.Create(pixelWidth, pixelHeight); + selectionBuffer.Create(pixelWidth, pixelHeight); + displayBuffer.Create(displayWidth, displayHeight); + + displayBuffer.Cls(gkRGB(255,255,0)); + original.Blit(&displayBuffer,0,0,0); + + selectionBuffer.SetAlpha(255); + + int j,index; + selected = new int[totalTiles]; + for(i=0; i=0; i--) sprites[i]->Blit(&backbuffer); + } + + //highlight selected tiles + //index = 0; + //for(j=0; j> 8; + for(i=0; i> 8; + int pal = tiles[index].GetPaletteUsed(); + if(pal>=0){ + gfxTiles[TILE_PAL0+pal].Blit(&displayBuffer,x,y); + } + index++; + } + } + } + + //draw the grid + if(showGrid){ + for(j=0; j> 8) - 1; + displayBuffer.Line(0,y,displayWidth-1,y,gkRGB(128,128,128)); + } + for(i=0; i> 8) - 1; + displayBuffer.Line(x,0,x,displayHeight-1,gkRGB(128,128,128)); + } + } + + //draw the sprite bounding boxes + if(flags & 1){ + for(i=numSprites-1; i>=0; i--){ + sprites[i]->DrawFrame(&displayBuffer,magnification); + } + } +} + +gkWinShape *gbPic::GetDisplayBuffer(int showSprites){ + if(needsRedraw){ + needsRedraw = 0; + Redraw(showSprites); + } + + return &displayBuffer; +} + +gkWinShape *gbPic::GetMagnifiedArea(int x, int y){ + //magnifiedArea.Cls(); + nonPictureBG.Blit(&magnifiedArea, 0, 0, 0); + + if(x<0 || y<0 || x>=displayWidth || y>=displayHeight + || !backbuffer.GetData()){ + //draw black frame + magnifiedArea.RectFrame(0,0,80,80,gkRGB(0,0,0)); + return &magnifiedArea; + } + + x = (x<<8) / magnification; + y = (y<<8) / magnification; + + x = (x * 0x1000) >> 8; + y = (y * 0x1000) >> 8; + backbuffer.BlitScale(&magnifiedArea,-x + 32, -y + 32, 0x1000, 0); + + //draw green highlight box around pixel under cursor + //magnifiedArea.RectFrame(32,32,16,16,gkRGB(128,255,128)); + gfxTiles[TILE_BORDER].Blit(&magnifiedArea,32,32); + + //draw black border around whole thing + magnifiedArea.RectFrame(0,0,80,80,gkRGB(0,0,0)); + + return &magnifiedArea; +} + + +void gbPic::SetMagnification(int n){ + int width = tileWidth * 8; + int height = tileHeight * 8; + + int sx = GetSystemMetrics(SM_CXSCREEN) - (224 + 32); + int sy = GetSystemMetrics(SM_CYSCREEN) - 128; + + //reduce magnification until image is <= width & height of screen + while(width * n > (sx << 8)){ + if(n > 0x200) n -= 0x100; + else n -= 0x10; + } + + while(height * n > (sy << 8)){ + if(n > 0x200) n -= 0x100; + else n -= 0x10; + } + + width = (width * n) >> 8; + height = (height * n) >> 8; + + if(width > displayWidth || height > displayHeight){ + displayBuffer.Create(width, height); + } + + displayWidth = width; + displayHeight = height; + magnification = n; +} + +gkRGB gbPic::GetColor(int pal, int n){ + return palettes[pal*4+n]; +} + +void gbPic::SetColor(int pal, int n, gkRGB c){ + palettes[pal*4+n] = c; + + int palChanged = (1<CreateFromRawData(); + sprites[i]->MakeRawData(); + } +} + +// Returns: 1 if tile index is selected, 0 if not or out of bounds +int gbPic::GetSelected(int i, int j){ + if(i<0 || j<0 || i>=tileWidth || j>=tileHeight) return 0; + return selected[j*tileWidth + i]; +} + +void gbPic::GetIndicesAtPoint(int x, int y, int &i, int &j){ + //get unmagnified pixel coords + x = (x<<8) / magnification; + y = (y<<8) / magnification; + + //divide by 8 to get tile indices + i = x >> 3; + j = y >> 3; + + if(i<0 || j<0 || i>=tileWidth || j>=tileHeight){ + i = j = -1; + } +} + + +gkRGB gbPic::GetColorAtPoint(int x, int y){ + //get unmagnified pixel coords + x = (x<<8) / magnification; + y = (y<<8) / magnification; + + if(x<0 || x<0 || x>=pixelBuffer.GetWidth() || y>=pixelBuffer.GetHeight()){ + return gkRGB(0,0,0); + } + + return pixelBuffer.Point(x,y); +} + + +int gbPic::GetMappingAtPoint(int x, int y){ + //get unmagnified pixel coords + x = (x<<8) / magnification; + y = (y<<8) / magnification; + + //divide by 8 to get tile indices + int i = x >> 3; + int j = y >> 3; + + if(i<0 || j<0 || i>=tileWidth || j>=tileHeight){ + return -1; + } + + return tiles[j*tileWidth+i].GetPaletteUsed(); +} + + + +void gbPic::OnMouseLMB(int x, int y){ + int i,j; + + GetIndicesAtPoint(x,y,i,j); + if(i==-1) return; + + //set selection to "set" if *all* pixels in selectionBuffer + //have alpha 255, "clear" otherwise. +//static int times=1; +//if(times++ == 2){ +//ASSERT(0); +//} + + x = i<<3; + y = j<<3; + int sel = 0, ii, jj; + for(jj=y+7; jj>=y; jj--){ + gkRGB *data = (gkRGB*) selectionBuffer.GetData(); + data += jj*selectionBuffer.GetWidth() + x + 7; + for(ii=x+7; ii>=x; ii--){ + if(data->GetA()!=255){ + sel = 1; + break; + } + data--; + } + if(sel==1) break; + } + dragSetOrClear = 1 - sel; + + //if(GetSelected(i,j)){ + //already highlighted, so clear it + //dragSetOrClear = 0; + //}else{ + //dragSetOrClear = 1; + //} + + int index = j*tileWidth + i; + //if(selected[index] != dragSetOrClear){ + selected[index] = dragSetOrClear; + needsRedraw = 1; + //} + + dragStart_i = i; + dragStart_j = j; +} + +void gbPic::OnMouseLDrag(int x, int y){ + int i1,j1,i2,j2; + GetIndicesAtPoint(x,y,i2,j2); + if(i2==-1) return; + + if(i2 > dragStart_i) i1 = dragStart_i; + else{ + i1 = i2; + i2 = dragStart_i; + } + + if(j2 > dragStart_j) j1 = dragStart_j; + else{ + j1 = j2; + j2 = dragStart_j; + } + + //clear temporary "visual feedback" selected grids + int i,j,index = 0; + for(j=0; j dragStart_i) i1 = dragStart_i; + else{ + i1 = i2; + i2 = dragStart_i; + } + + if(j2 > dragStart_j) j1 = dragStart_j; + else{ + j1 = j2; + j2 = dragStart_j; + } + + //select permanent + //ASSERT(0); + numSelColors = 0; + for(j=j1; j<=j2; j++){ + for(i=i1; i<=i2; i++){ + index = j*tileWidth + i; + selected[index] = dragSetOrClear; + if(dragSetOrClear){ + //set + selectionBuffer.RectFill(i<<3,j<<3,8,8,gkRGB(255,255,255,0x80)); + int numPixels = 64; + gkRGB *colors = (gkRGB*) tiles[index].GetData(); + while(numPixels--){ + gkRGB c = *(colors++); + int sel, found=0; + for(sel=0; sel=0; i--){ + gkRGB color = selectedColors[i]; + for(j=0; j1 || + tiles[index].GetColors()[0]!=bgColor){ + if(!selected[index]) numSelTiles++; + selected[index] = 1; + selectionBuffer.RectFill(i<<3,j<<3,8,8,gkRGB(255,255,255,0x80)); + needsRedraw = 1; + } + index++; + } + } +} + + +void gbPic::SelectUnmapped(){ + int i,j,index; + index = 0; + for(j=0; j=40) return; + int myIndex = j*tileWidth + i; + int nextIndex = (j+1)*tileWidth + i; + gbTile *tile1 = &tiles[myIndex]; + if(selected[myIndex]){ + selected[myIndex] = 0; + + //extract the tile + gbTile *tile2; + if(j == tileHeight-1 || !selected[nextIndex]){ + //no tile below or not selected + tile2 = 0; + }else{ + tile2 = &tiles[nextIndex]; + if(tile2->GetPaletteUsed() != tile1->GetPaletteUsed()){ + tile2 = 0; + }else{ + selected[nextIndex] = 0; + } + } + sprites[numSprites] = new gbSprite(); + sprites[numSprites]->Create8x16FromSelection(i<<3,j<<3, + tile1, tile2, &selectionBuffer, this); + numSprites++; + } + } + } + + needsRedraw = 1; +} + +int gbPic::FindBestSpritePalette(gkRGB *pal, int numColors){ + return 0; +} + +int gbPic::UnmakeSprite(int x, int y){ + int i2,j2; + GetIndicesAtPoint(x,y,i2,j2); + if(i2==-1) return 0; + + int i; + for(i=numSprites-1; i>=0; i--){ + if(sprites[i]->ExistsAtIndex(i2,j2)){ + sprites[i]->Unmake(this); + delete sprites[i]; + numSprites--; + for(; i> 3) & 31; + int g = (color.GetG() >> 3) & 31; + int b = (color.GetB() >> 3) & 31; + int gbColor = (b<<10) | (g<<5) | r; + out.put((char) (gbColor & 0xff)); + out.put((char) ((gbColor>>8) & 0xff)); + index++; + } + } + +} + +void gbPic::SaveGBSprite(const char *filename){ + + ofstream out(filename,ios::out|ios::binary); + if(!out) return; + + int numTiles = numSprites * 2; //will be 80 max + int i; + + // BYTE Bank 0 Sprite definition data exists (!0 = true) + // BYTE Number of sprite patterns (0 = 256) + // REPT[number of defined sprites] + // BYTE[16] sprite data + out.put((char) (numTiles!=0)); + if(numTiles>0){ + out.put((char) (numTiles)); + for(i=0; iWriteTileDefinitions(out); + } + } + + + // BYTE Bank 1 Sprite definition data exists (!0 = true) + out.put((char) 0); //no bank 1 sprites + + //width & height + out.put((char) tileWidth); + out.put((char) 0); //store zero for pitch + out.put((char) tileHeight); + + //sprite instances (composing metasprite) + // BYTE numSprites + // REPT[numSprites]: SPRITE ATTRIBUTE DATA (Copy to spriteOAMBuffer) + out.put((char) numSprites); + for(i=0; iWriteAttributes(out,i); + } + + SavePaletteInfo(out); + + fileSize = (int) out.tellp(); + + out.close(); +} + + +int gbPic::LoadGBSprite(const char *filename){ + ifstream in(filename, ios::in | ios::binary | ios::nocreate); + if(!in) return 0; + + Reset(); + + int hasBank0 = in.get(); + if(!hasBank0) return 1; + + int numTileDefs = in.get(); + numSprites = numTileDefs / 2; + + int i; + for(i=0; iReadTileDefinitions(in); + } + + in.get(); //discard bank 1 definitions exist + + tileWidth = in.get() & 0xff; + in.get(); + tileHeight = in.get() & 0xff; + + //Set up buffers + int pixelWidth = tileWidth << 3; + int pixelHeight = tileHeight << 3; + totalTiles = tileWidth * tileHeight; + SetMagnification(0x400); //default 4x magnification + + backbuffer.Create(pixelWidth, pixelHeight); + pixelBuffer.Create(pixelWidth, pixelHeight); + selectionBuffer.Create(pixelWidth, pixelHeight); + displayBuffer.Create(displayWidth, displayHeight); + + displayBuffer.Cls(gkRGB(0,0,0xf8)); + selectionBuffer.SetAlpha(255); + + int j,index; + selected = new int[totalTiles]; + for(i=0; iReadAttributes(in,this); + } + + //read palette + int numColors = in.get() & 0xff; + for(i=0; i> 3) & 7; + int entry = (spec >> 1) & 3; + int gbColor = in.get() & 0xff; + gbColor = ((in.get() & 0xff) << 8) | gbColor; + int r = (gbColor & 31) << 3; + int g = ((gbColor>>5) & 31) << 3; + int b = ((gbColor>>10) & 31) << 3; + palettes[pal*4 + entry] = gkRGB(r,g,b); + } + + for(i=0; iCreateFromRawData(); + } + + needsRedraw = 1; + + in.close(); + return 1; +} + +void gbPic::SaveGBPic(const char *filename){ + ofstream out(filename,ios::out|ios::binary); + if(!out) return; + + ClearSelection(); + AutoMap(255); + + out.put((char) 1); //bank 0 exists + out.put((char) 0); //allocate space for numBank0Tiles + + gkBYTE rawData[512*16]; + int dataHash[512]; + int numUnique = 0; + + //Write out blank tile definition as tile zero + int i; + for(i=0; i<16; i++){ + out.put((char) 0); + rawData[i] = 0; + } + dataHash[numUnique++] = 0; + + //write out tile definitions, avoiding duplicates + int bank1Pos = 0; + int index; + for(i=0; i0){ + out.seekp(bank1Pos); + out.put((char) (numUnique - 256)); + out.seekp(curFilePos); + }else{ + out.seekp(curFilePos); + out.put((char) 0); //no bank 1 tiles + } + + int tilePitch = 1; + while(tilePitch < tileWidth) tilePitch<<=1; + + out.put((char) tileWidth); + //out.put((char) tilePitch); + out.put((char) tileHeight); + + //write out tile index data + for(i=0; i=256) attr1 |= 8; + i++; + + index = tiles[i].GetTileIndex(); + int attr2 = tiles[i].GetPaletteUsed(); + if(index>=256) attr2 |= 8; + + out.put((char) ((attr1<<4) | attr2)); + } + + SavePaletteInfo(out); + + fileSize = (int) out.tellp(); + + out.close(); +} + +int gbPic::LoadGBPic(const char *filename){ + ifstream in(filename, ios::in | ios::binary | ios::nocreate); + if(!in) return 0; + + Reset(); + + int i; + gkBYTE rawData[1024*16]; //twice as much as max + + int hasBank0 = in.get(); + if(!hasBank0) return 1; + + int numBank0 = in.get(); + if(!numBank0) numBank0 = 256; + in.read(rawData,numBank0*16); + + int numBank1 = 0; + int hasBank1 = in.get(); + if(hasBank1){ + numBank1 = in.get(); + if(!numBank1) numBank1 = 256; + in.read(rawData + numBank0*16, numBank1*16); + } + + tileWidth = in.get(); + tileHeight = in.get(); + totalTiles = tileWidth * tileHeight; + + //Set up buffers + int pixelWidth = tileWidth << 3; + int pixelHeight = tileHeight << 3; + SetMagnification(0x400); //default 4x magnification + + backbuffer.Create(pixelWidth, pixelHeight); + pixelBuffer.Create(pixelWidth, pixelHeight); + selectionBuffer.Create(pixelWidth, pixelHeight); + displayBuffer.Create(displayWidth, displayHeight); + + displayBuffer.Cls(gkRGB(0,0,0xf8)); + selectionBuffer.SetAlpha(255); + + selected = new int[totalTiles]; + for(i=0; i>4) & 15; + int attr2 = combo & 15; + if(attr1 & 8) tiles[i].SetRawData( + rawData+numBank0*16+tiles[i].GetTileIndex()*16); + else tiles[i].SetRawData(rawData + tiles[i].GetTileIndex()*16); + tiles[i].SetPaletteUsed(this, attr1 & 7); + i++; + + if(attr2 & 8) tiles[i].SetRawData( + rawData+numBank0*16+tiles[i].GetTileIndex()*16); + else tiles[i].SetRawData(rawData + tiles[i].GetTileIndex()*16); + tiles[i].SetPaletteUsed(this, attr2 & 7); + } + + //read palette + int numColors = in.get() & 0xff; + for(i=0; i> 3) & 7; + int entry = (spec >> 1) & 3; + int gbColor = in.get() & 0xff; + gbColor = ((in.get() & 0xff) << 8) | gbColor; + int r = (gbColor & 31) << 3; + int g = ((gbColor>>5) & 31) << 3; + int b = ((gbColor>>10) & 31) << 3; + palettes[pal*4 + entry] = gkRGB(r,g,b); + } + + for(i=0; i bestRating){ + bestIndex = i; + bestRating = rating; + } + } + + if(bestRating>0){ + //add new colors to that palette + for(i=0; ib>!3`M`)038ezK7ywr$LNu=dG(RBd#I1owQ~mbecDzU*GY>kWkh~`QjAEM zQl(m5*UIuyORr$t&iq(OFHh1DUx&V-l@3^hv->hgEDgg9Shkv`33MRGQqJC?{Oq!k znsFQxI>PPnHu(E3o|F>DN_@+I%iqSexexyR|EXz*Czbmn{|>*t&pj8R#nNxWYi>jW z;R~e*oV&d5PpnJ)zj>5@v)-$I87>dlL&{s^M|0Oa&v}b>QNjVs7>C_6L>y$M1F&rW zHs_6JjCy|{vlV_YE%6oYUnHNM&-Xv$XpGON{w}WP<~*KwtQaX2jOQ-gx6E;E;^v9i GXZ;21`B8_W@yT5AYBUA@N%u;L2x3sXU)4;ERr#Aa0W^(^)+YuD#; q%)g6|{jJm}_`g?`14NwjR5_md7!TE1(I9m~#$B?W=|gtUZ~Oq?yP2;5 literal 0 HcmV?d00001 diff --git a/Tools/GBConv2/Source/resource.h b/Tools/GBConv2/Source/resource.h new file mode 100644 index 0000000..b1bb1d0 --- /dev/null +++ b/Tools/GBConv2/Source/resource.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by GBConv2.rc +// +#define IDD_ABOUTBOX 100 +#define IDB_PALETTEFROMSEL 101 +#define IDB_SETTOBGCOLOR 102 +#define IDB_SWAPWITHBGCOLOR 103 +#define IDB_AUTOMAPTOPALETTE 104 +#define IDB_SELECTNONEMPTY 105 +#define IDB_UNMAP 106 +#define IDB_MAKESPRITES 107 +#define IDLIST_PALETTES 108 +#define IDB_SHOWSPRITES 109 +#define IDB_SELECTUNMAPPED 110 +#define IDB_SAVEGBSPRITE 111 +#define IDB_EDITPALETTE 112 +#define IDB_AUTOMAPALL 113 +#define IDB_SAVEGBPIC 114 +#define IDB_SHOWMAPPING 115 +#define IDB_MAPTOPALETTE 116 +#define IDR_MAINFRAME 128 +#define IDR_GBCONVTYPE 129 +#define IDD_EDIT_PALETTE 130 +#define IDC_EDIT_PAL_RED0 1001 +#define IDC_EDIT_PAL_GREEN0 1002 +#define IDC_EDIT_PAL_BLUE0 1003 +#define IDC_EDIT_PAL_RED1 1004 +#define IDC_EDIT_PAL_GREEN1 1005 +#define IDC_EDIT_PAL_BLUE1 1006 +#define IDC_EDIT_PAL_RED2 1007 +#define IDC_EDIT_PAL_GREEN2 1008 +#define IDC_EDIT_PAL_BLUE2 1009 +#define IDC_EDIT_PAL_RED3 1010 +#define IDC_EDIT_PAL_GREEN3 1011 +#define IDC_EDIT_PAL_BLUE3 1012 +#define ID_APP_INSTRUCTIONS 32771 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32772 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 117 +#endif +#endif diff --git a/Tools/GBConv2/Source/wingk.cbk b/Tools/GBConv2/Source/wingk.cbk new file mode 100644 index 0000000..c60584d --- /dev/null +++ b/Tools/GBConv2/Source/wingk.cbk @@ -0,0 +1,1434 @@ +#include "wingk.h" +#include + +gkTransparencyTable gkWinShape::tranTable; + +struct BMP_header{ + gkLONG fSize; //54 byte header + 4*numColors (1-8bit) + (w*h*bpp)/8 + gkWORD zero1, zero2; //0,0 + gkLONG offsetBytes; //should be header (54) plus Palette Size + + gkLONG headerSize; //size of remaining header (40) + gkLONG width, height; //w,h in pixels + gkWORD planes, bpp; //plane=1, bpp=1,2,4, or most commonly 8 + gkLONG compression, imageSize; //compression to zero, size is w*h(8bit) + gkLONG xpels, ypels, zero3, zero4; //set to 0,0,0,0 +}; + +int gkIO::ReadWord(istream &in){ + int retval = in.get() << 8; + return retval | (in.get() & 0xff); +} + +int gkIO::ReadLong(istream &in){ + int retval = ReadWord(in) << 16; + return retval | (ReadWord(in) & 0xffff); +} + +char *gkIO::ReadString(istream &in){ + static char st[80]; + int len = ReadWord(in); + if(!len) return 0; + in.read(st,len); + st[len] = 0; + return st; +} + +char *gkIO::ReadNewString(istream &in){ + int len = ReadWord(in); + if(!len) return 0; + + char *st = new char[len+1]; + in.read(st,len); + st[len] = 0; + return st; +} + +void gkIO::WriteLong(ostream &out, int n){ + WriteWord(out, n>>16); + WriteWord(out, n); +} + +void gkIO::WriteWord(ostream &out, int n){ + out << (char) ((n>>8)&0xff); + out << (char) (n&0xff); +} + +void gkIO::WriteString(ostream &out, char *st){ + WriteWord(out,strlen(st)); + out.write(st,strlen(st)); +} + + +int gkRGB::operator==(gkRGB &c2){ + return ((color.argb & 0xffffff) == (c2.color.argb & 0xffffff)); +} + +int gkRGB::Equals(int _r, int _g, int _b){ + return _r==color.bytes.r && _g==color.bytes.g && _b==color.bytes.b; +} + +void gkRGB::Combine(gkRGB c2, int alpha){ + //mix alpha + color.bytes.r += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetR()-GetR(), alpha); + color.bytes.g += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetG()-GetG(), alpha); + color.bytes.b += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetB()-GetB(), alpha); +} + +gkRGB::operator COLORREF(){ + return (color.bytes.b<<16) | (color.bytes.g<<8) | (color.bytes.r); +} + +gkPalGenItem::gkPalGenItem(gkRGB _color){ + color = _color; + occurrences = 1; + nextItem = 0; +} + +gkPalGenItem::~gkPalGenItem(){ +} + +gkRGB gkPalGenItem::GetColor(){ + return color; +} + +void gkPalGenItem::AddOccurrence(){ + occurrences++; +} + +int gkPalGenItem::GetOccurrences(){ + return occurrences; +} + +void gkPalGenItem::SetOccurrences(int n){ + occurrences = n; +} + +void gkPalGenItem::SetNextItem(gkPalGenItem *item){ + nextItem = item; +} + +gkPalGenItem *gkPalGenItem::GetNextItem(){ + return nextItem; +} + +int gkPalGenItem::GetCount(){ + gkPalGenItem *cur; + int count = 0; + for(cur=this; cur; cur=cur->nextItem){ + if(cur->occurrences) count++; + } + return count; +} + +int gkPalGenItem::SortCallback(const void *e1, const void *e2){ + gkPalGenItem *i1 = *((gkPalGenItem**) e1); + gkPalGenItem *i2 = *((gkPalGenItem**) e2); + if(i1->occurrences > i2->occurrences) return -1; + if(i1->occurrences == i2->occurrences) return 0; + return 1; +} + +gkPaletteGenerator::gkPaletteGenerator(){ + int i; + for(i=0; i<52; i++){ + colorCube[i] = 0; + } +} + +gkPaletteGenerator::~gkPaletteGenerator(){ + Reset(); +} + +void gkPaletteGenerator::Reset(){ + int i; + for(i=0; i<52; i++){ + if(colorCube[i]){ + gkPalGenItem *cur, *next; + for(cur=colorCube[i]; cur; cur=next){ + next = cur->GetNextItem(); + delete cur; + } + colorCube[i] = 0; + } + } +} + +void gkPaletteGenerator::AddColor(gkRGB color){ + int i = GetHash(color); + + if(!colorCube[i]){ + colorCube[i] = new gkPalGenItem(color); + }else{ + gkPalGenItem *cur, *prev; + for(cur=colorCube[i]; cur; cur=cur->GetNextItem()){ + if((cur->GetColor()) == color){ + cur->AddOccurrence(); //Color already in list + break; + } + prev = cur; + } + if(!cur){ //color not in list + prev->SetNextItem(new gkPalGenItem(color)); + } + } +} + +void gkPaletteGenerator::CreatePalette(gkRGB *palette, int numEntries){ + if(numEntries<=0) return; + + //Set all entries to black + int i; + for(i=0; iGetCount(); + } + while(!count){ //if no colors yet expand area of inclusion + if(first==0 && last==51) return; //no colors anywhere! + if(first>0){ + first--; + if(colorCube[first]) count += colorCube[first]->GetCount(); + } + if(last<51){ + last++; + if(colorCube[last]) count += colorCube[last]->GetCount(); + } + } + + //Create an array to hold all the colors for sorting purposes + gkPalGenItem **colors = new gkPalGenItem*[count]; + gkPalGenItem *cur; + i = 0; + int j; + for(j=first; j<=last; j++){ + if(colorCube[j]){ + for(cur=colorCube[j]; cur; cur=cur->GetNextItem()){ + if(cur->GetOccurrences()) colors[i++] = cur; + } + } + } + + //figure out how many colors will come from this section of the cube + int numToGrab = 1; + int tempCurEntry = curEntry; + while(nextEntry==first && tempCurEntry<52){ + tempCurEntry++; + nextEntry = (int) (scaleFactor * (tempCurEntry+1)); + numToGrab++; + } + + if(numToGrab > count) numToGrab = count; + + //sort colors into descending order and pick "num" most frequent + qsort(colors, count, sizeof(gkPalGenItem*), gkPalGenItem::SortCallback); + + for(i=0; iGetColor(); + colors[i]->SetOccurrences(0); + } + + //delete sorting table + delete colors; + } +} + + +int gkPaletteGenerator::GetNumColors(){ + int num = 0, i; + for(i=0; i<52; i++) + if(colorCube[i]) num += colorCube[i]->GetCount(); + return num; +} + + +int gkPaletteGenerator::GetHash(gkRGB color){ + int r = color.GetR() >> 6; //rough categories 0-3 + int g = color.GetG() >> 6; + int b = color.GetB() >> 6; + int highest = r; + if(g > highest) highest = g; + if(b > highest) highest = b; + + int hash; + + // r > (g < b) + // r > (g = b) + // r > (g > b) + // g > (r < b) + // g > (r = b) + // g > (r > b) + // b > (r < g) + // b > (r = g) + // b > (r > g) + // (r = b) > g + // (r = g) > b + // (g = b) > r + // (r = g) = b + if(r > g && r > b){ //red high + if(g < b) hash = 0; // r > (g < b) + else if(g==b) hash = 1; // r > (g = b) + else hash = 2; // r > (g > b) + }else if(g > r && g > b){ //green high + if(r < b) hash = 3; // g > (r < b) + else if(r==b) hash = 4; // g > (r = b) + else hash = 5; // g > (r > b) + }else if(b > r && b > g){ //blue high + if(r < g) hash = 6; // b > (r < g) + else if(r==g) hash = 7; // b > (r = g) + else hash = 8; // b > (r > g) + }else if(r==b && b==g){ //r = g = b + hash = 9; + }else if(r==b){ //(r = b) > g + hash = 10; + }else if(r==g){ //(r = g) > b + hash = 11; + }else{ //(g = b) > r + hash = 12; + } + + //make room in each category for four levels of intensity (0-3) + hash = hash*4 + highest; + + return hash; +} + +int gkPaletteGenerator::ColorExists(gkRGB color){ + int hash = GetHash(color); + if(!colorCube[hash]) return 0; + + gkPalGenItem *cur; + for(cur=colorCube[hash]; cur; cur=cur->GetNextItem()){ + if(cur->GetColor()==color) return 1; //found exact color + } + return 0; +} + +gkRGB gkPaletteGenerator::MatchColor(gkRGB color){ + int hash = GetHash(color); + int r = color.GetR(); + int g = color.GetG(); + int b = color.GetB(); + if(colorCube[hash]){ //near colors; search just this section + gkPalGenItem *cur, *bestMatch; + int bestDiff; + bestMatch = colorCube[hash]; + int r2, g2, b2; + r2 = abs(r - bestMatch->GetColor().GetR()); + g2 = abs(g - bestMatch->GetColor().GetG()); + b2 = abs(b - bestMatch->GetColor().GetB()); + bestDiff = r2 + g2 + b2; + for(cur=bestMatch->GetNextItem(); cur; cur=cur->GetNextItem()){ + r2 = abs(r - cur->GetColor().GetR()); + g2 = abs(g - cur->GetColor().GetG()); + b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2 + g2 + b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + return bestMatch->GetColor(); + }else{ + //no colors nearby; expand search + //Get it from ~greyscale if possible + int first, last; + first = last = 36 + (hash % 4); + if(!colorCube[first]){ + first = 0; //nothing there either; search everything + last = 51; + /* + first = 36; + last = 39; + //first = hash - (hash%4); //different intensities, same color + //last = first + 3; + if(!colorCube[first] && !colorCube[first+1] && !colorCube[first+2] + && !colorCube[last]){ + first = 0; //nothing there either; search everything + last = 51; + } + */ + } + gkPalGenItem *cur, *bestMatch; + int bestDiff = 0x7fffffff; + bestMatch = 0; + int i; + for(i=first; i<=last; i++){ + for(cur=colorCube[i]; cur; cur=cur->GetNextItem()){ + int r2 = abs(r - cur->GetColor().GetR()); + int g2 = abs(g - cur->GetColor().GetG()); + int b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2 + g2 + b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + } + if(!bestMatch) return gkRGB(0,0,0); + return bestMatch->GetColor(); + } +} + +gkTransparencyTable::gkTransparencyTable(){ + lookup = new gkBYTE[256*256]; + + int baseOffset, alpha, i; + i = 0; + for(baseOffset=0; baseOffset<256; baseOffset++){ + for(alpha=0; alpha<256; alpha++){ + lookup[i++] = (baseOffset * alpha) / 255; + } + } +} + +gkTransparencyTable::~gkTransparencyTable(){ + if(lookup) delete lookup; + lookup = 0; +} + +int gkTransparencyTable::LookupTransparencyOffset(int baseOffset, int alpha){ + return (baseOffset>=0) ? lookup[(baseOffset<<8)+alpha] + : (-lookup[((-baseOffset)<<8)+alpha]); +} + + +gkWinShape::gkWinShape(){ + data = 0; + width = height = bpp = 0; +} + +gkWinShape::~gkWinShape(){ + FreeData(); +} + +void gkWinShape::FreeData(){ + if(data){ + delete data; + data = 0; + } +} + +void gkWinShape::Create(int _width, int _height){ + if(_width <= 0 || _height <= 0) return; + + FreeData(); + width = _width; + height = _height; + + //round up width to ensure multiple of 4 pixels + //width = (width + 3) & (~3); + + data = new gkBYTE[(width*height)<<2]; + bpp = 32; +} + +void gkWinShape::Cls(){ + if(!this->data) return; + memset(this->data, 0, (this->width * this->height)<<2); +} + +void gkWinShape::Cls(gkRGB color){ + if(!this->data) return; + + gkLONG *dest = (gkLONG*) this->data; + int i = this->width * this->height; + while(i--){ + *(dest++) = color.GetARGB(); + } +} + +void gkWinShape::Plot(int x, int y, gkRGB color, int testBoundaries){ + if(!data) return; + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return; + } + + gkRGB *dest = (gkRGB*) (data + ((y*width + x) << 2)); + *dest = color; +} + +gkRGB gkWinShape::Point(int x, int y, int testBoundaries){ + if(!data) return gkRGB(0,0,0); + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return gkRGB(0,0,0); + } + + gkRGB *color = (gkRGB*) (data + ((y*width + x) << 2)); + return *color; +} + +void gkWinShape::Line(int x1, int y1, int x2, int y2, gkRGB color){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + (((y1 * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + *(dest++) = color; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest += pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + *dest = color; + dest += pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + +void gkWinShape::LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, + int alpha){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + (((y1 * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + dest->Combine(color,alpha); + dest++; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest += pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + dest->Combine(color,alpha); + dest += pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + +void gkWinShape::RectFrame(int x, int y, int w, int h, gkRGB color){ + int x2 = x + w - 1; + int y2 = y + h - 1; + RectFill(x,y,w,1,color); + RectFill(x,y2,w,1,color); + RectFill(x,y,1,h,color); + RectFill(x2,y,1,h,color); +} + +void gkWinShape::RectFill(int x, int y, int w, int h, gkRGB color){ + int x2 = (x + w) - 1; + int y2 = (y + h) - 1; + + //Clip rectangle + if(x < 0) x = 0; + if(y < 0) y = 0; + + if(x2 >= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + (((y * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; i= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + (((y * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; iCombine(color,alpha); + dest++; + } + destStart += width; + } +} + +void gkWinShape::RectFillChannel(int x, int y, int w, int h, + gkRGB color, int mask){ + int x2 = (x + w) - 1; + int y2 = (y + h) - 1; + + //Clip rectangle + if(x < 0) x = 0; + if(y < 0) y = 0; + + if(x2 >= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkLONG *destStart = (gkLONG*) (data + (((y * width) + x) <<2)); + gkLONG *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + gkLONG srcColor = color.GetARGB() & mask; + gkLONG destMask = ~mask; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; iSetA(alpha); + } +} + +void gkWinShape::SetColorAlpha(gkRGB color, int alpha){ + if(!data) return; + + gkRGB *src = (gkRGB*) data; + int i, j; + for(j=0; jSetA(alpha); + } + src++; + } + } +} + +int gkWinShape::GetShape(gkWinShape *srcShape, int x, int y, int w, int h){ + if(!srcShape || !srcShape->data) return 0; + + //adjust src rectangle until it fits within source data + if(x<0){ + w += x; + x = 0; + } + if(y<0){ + h += y; + y = 0; + } + if(x + w > srcShape->width){ + w = srcShape->width - x; + } + if(y + h > srcShape->height){ + h = srcShape->height - y; + } + + if(w<=0 || h<=0) return 0; + + FreeData(); + Create(w, h); + + gkBYTE *src = srcShape->data + ((y*srcShape->width + x)<<2); + gkBYTE *dest = this->data; + int srcSkip = srcShape->width << 2; //4 bytes per pixel + w <<= 2; //4 bytes per pixel + + while(h--){ + memcpy(dest, src, w); + dest += w; + src += srcSkip; + } + + return 1; +} + +int gkWinShape::GetShape(gkWinShape *srcShape){ + if(this->width != srcShape->width || this->height != srcShape->height + || (!this->data) || (!srcShape->data)){ + //mem needs to be reallocated + FreeData(); + memcpy(this, srcShape, sizeof(gkWinShape)); + data = 0; + if(srcShape->data){ + data = new gkBYTE[(width * height) << 2]; + memcpy(data, srcShape->data, (width * height) << 2 ); + } + }else{ + //already got right size mem, just copy data over + memcpy(data, srcShape->data, (width * height) << 2); + fontSpacing = srcShape->fontSpacing; + fontKerning = srcShape->fontKerning; + x_handle = srcShape->x_handle; + y_handle = srcShape->y_handle; + } + return data!=0; +} + +int gkWinShape::SaveShape(char *filename){ + ofstream outfile(filename, ios::out | ios::binary); + if(!outfile) return 0; + + int result = SaveShape(outfile); + outfile.close(); + + return result; +} + +int gkWinShape::SaveShape(ostream &out){ + int totalSize = ((width * height) << 2); + + out << "SHPE"; + int skipSize = totalSize + 20; + gkIO::WriteLong(out, skipSize); + + //Write shape header + gkIO::WriteWord(out, 3); //type 3 + gkIO::WriteWord(out, width); + gkIO::WriteWord(out, height); + gkIO::WriteWord(out, (bpp==8)?8:32); + out << (char) fontSpacing << (char) fontKerning; + gkIO::WriteWord(out, x_handle); + gkIO::WriteWord(out, y_handle); + gkIO::WriteWord(out, 0); //6 bytes of reserved space + gkIO::WriteLong(out, 0); + + + //Write data + if(data){ + int pitch = width << 2; + gkLONG *src; + gkBYTE *srcStart = data; + + int i,j; + for(j=0; jLoadShape(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadShape(istream &infile){ + FreeData(); + if(infile.get() != 'S') return 0; + if(infile.get() != 'H') return 0; + if(infile.get() != 'P') return 0; + if(infile.get() != 'E') return 0; + + gkIO::ReadLong(infile); //discard skipsize + + //Read shape header + if(gkIO::ReadWord(infile) != 2) return 0; + width = gkIO::ReadWord(infile); + height = gkIO::ReadWord(infile); + int filebpp = gkIO::ReadWord(infile); + if(!bpp) bpp = filebpp; + + if(width && height){ + Create(width,height); + } + + fontSpacing = infile.get(); + fontKerning = infile.get(); + x_handle = gkIO::ReadWord(infile); + y_handle = gkIO::ReadWord(infile); + + gkIO::ReadWord(infile); + gkIO::ReadLong(infile); //discard reserved space + + if(!width || !height) return 1; //nothing to load, null shape + + int pitch = width << 2; + gkBYTE *destStart = data; + gkLONG *dest; + int x,y; + for(y=0; yLoadBMP(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadBMP(istream &infile){ + BMP_header header; + if(gkIO::ReadWord(infile)!=0x424d){ //check for "BM" + return 0; + } + infile.read((char*)&header, sizeof(BMP_header)); + if(header.bpp != 24){ + cout << "LoadBMP can only handle 24-bit files" << endl; + return 0; + } + + FreeData(); + width = header.width; + height = header.height; + bpp = (char) header.bpp; + Create(width,height); + + // load graphics, coverting every three (B,R,G) bytes to one ARGB value. + // lines padded to even multiple of 4 bytes + int srcPitch = ((header.width * 3) + 3) & (~3); + gkBYTE *buffer = new gkBYTE[srcPitch * height]; + gkBYTE *nextBuffPtr = buffer + ((height-1) * srcPitch); + gkBYTE *buffPtr; + + infile.read(buffer, srcPitch * height); + + gkBYTE *nextDest = data; + gkRGB *dest; + int destPitch = (width << 2); + + int i, j; + j = height; + while(j--){ + buffPtr = nextBuffPtr; + nextBuffPtr -= srcPitch; + dest = (gkRGB*) nextDest; + nextDest += destPitch; + i = header.width; + while(i--){ + dest->SetB(*(buffPtr++)); + dest->SetG(*(buffPtr++)); + dest->SetR(*(buffPtr++)); + dest->SetA(0xff); + dest++; + } + for(i=header.width; iSetARGB(0); + dest++; + } + } + + delete buffer; + + return 1; +} + + +void gkWinShape::Blit(gkWinShape *destShape, int x, int y, int flags){ + if(!data || !destShape || !destShape->data) return; + + gkBYTE *src = 0; + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += (-y * this->width); + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcWidth <<= 2; + srcSkip <<= 2; + destSkip <<= 2; + + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTrans(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + memcpy(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + } +} + +////////////////////////////////////////////////////////////////////// +// Function: BlitScale +// Arguments: destShape +// x +// y +// flags +// scale - number of source pixels for every one +// dest pixel, stored in 24:8 fixed point. +// $100=100%, $200=200% (mag x2), $80=50% +////////////////////////////////////////////////////////////////////// +void gkWinShape::BlitScale(gkWinShape *destShape, int x, int y, + int scale, int flags){ + if(!data || !destShape || !destShape->data || !scale) return; + + gkBYTE *src = 0; + int srcSkip = this->width; + int srcWidth = (this->width * scale) >> 8; + int lines = (this->height * scale) >> 8; + + //clip left side + if(x < 0){ + src += (-x << 8) / scale; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += ((-y * this->width) << 8) / scale; + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcSkip <<= 2; + destSkip <<= 2; + + int ratio = (int) ((1.0f / (((float) scale) / 256.0f)) * 256.0f); + + int lineError = 0; + while(lines--){ + BlitLineScale(dest, src, srcWidth, ratio); + lineError += ratio; + src += srcSkip * (lineError >> 8); + lineError &= 0xff; + dest += destSkip; + } + + /* + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTrans(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + memcpy(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + } + */ +} + +void gkWinShape::BlitScale(gkWinShape *destShape, int x, int y, + float scale, int flags){ + BlitScale(destShape,x,y,flags,(int) (256.0f * scale)); +} + +void gkWinShape::BlitChannel(gkWinShape *destShape, int x, int y, int mask){ + if(!data || !destShape || !destShape->data) return; + + gkBYTE *src = 0; + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += (-y * this->width); + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcSkip <<= 2; + destSkip <<= 2; + + int inverseMask = ~mask; + + while(lines--){ + gkLONG *curSrc = (gkLONG*) src; + gkLONG *curDest = (gkLONG*) dest; + int pixels = srcWidth; + while(pixels--){ + *curDest = (*curSrc & mask) | (*curDest & inverseMask); + curSrc++; + curDest++; + } + src += srcSkip; + dest += destSkip; + } +} + +HBITMAP gkWinShape::GetDIB(CDC *pDC){ + //note you must DeleteObject() on the dib that's returned once done + static BITMAPINFO bmInfo={{40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}}; + static int setup=0; + + if(!setup){ + setup = 1; + *((int*)(&bmInfo.bmiColors[0])) = 0xff0000; //red mask + *((int*)(&bmInfo.bmiColors[4])) = 0x00ff00; //green mask + *((int*)(&bmInfo.bmiColors[8])) = 0x0000ff; //blue mask + } + + bmInfo.bmiHeader.biWidth = width; + bmInfo.bmiHeader.biHeight = -height; + + HBITMAP dib = CreateDIBitmap((HDC) (*pDC), + &bmInfo.bmiHeader, + CBM_INIT, + data, + &bmInfo, + DIB_RGB_COLORS); + + return dib; +} + +void gkWinShape::BlitToDC(CDC *pDC, int x, int y){ + static CDC srcDC; + static int setup=0; + + if(!setup){ + setup = 1; + srcDC.CreateCompatibleDC(0); + } + + HBITMAP dib = GetDIB(pDC); + + CBitmap bitmap; + bitmap.Attach(dib); + + CBitmap *oldBitmap = srcDC.SelectObject(&bitmap); + pDC->BitBlt(x, y, width, height, &srcDC, 0, 0, SRCCOPY); + srcDC.SelectObject(oldBitmap); + + bitmap.Detach(); + DeleteObject(dib); +} + +void gkWinShape::MemCpyTrans(gkBYTE *dest, gkBYTE *src, + int numBytes){ + //copies colors using the Alpha for transparency + gkRGB *destColor = (gkRGB*) dest; + gkRGB *srcColor = (gkRGB*) src; + int numColors = numBytes >> 2; + int c1; + while(numColors--){ + int alpha; + switch(alpha = (srcColor->GetA())){ + case 0: break; + case 255: //Straight copy + *destColor = *srcColor; + break; + default: //mix alpha + c1 = destColor->GetR(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetR()-c1, alpha); + destColor->SetR(c1); + c1 = destColor->GetG(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetG()-c1, alpha); + destColor->SetG(c1); + c1 = destColor->GetB(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetB()-c1, alpha); + destColor->SetB(c1); + break; + } + srcColor++; + destColor++; + } +} + +void gkWinShape::BlitLineScale(gkBYTE *dest,gkBYTE *src,int pixels,int ratio){ + gkRGB *srcRGB = (gkRGB*) src; + gkRGB *destRGB = (gkRGB*) dest; + + int error = 0; + + while(pixels--){ + *(destRGB++) = *srcRGB; + error += ratio; + srcRGB += error >> 8; + error &= 0xff; + } +} + diff --git a/Tools/GBConv2/Source/wingk.cpp b/Tools/GBConv2/Source/wingk.cpp new file mode 100644 index 0000000..93c4237 --- /dev/null +++ b/Tools/GBConv2/Source/wingk.cpp @@ -0,0 +1,1546 @@ +#include "stdafx.h" +#include "wingk.h" +#include + +gkTransparencyTable gkWinShape::tranTable; + +struct BMP_header{ + gkLONG fSize; //54 byte header + 4*numColors (1-8bit) + (w*h*bpp)/8 + gkWORD zero1, zero2; //0,0 + gkLONG offsetBytes; //should be header (54) plus Palette Size + + gkLONG headerSize; //size of remaining header (40) + gkLONG width, height; //w,h in pixels + gkWORD planes, bpp; //plane=1, bpp=1,2,4, or most commonly 8 + gkLONG compression, imageSize; //compression to zero, size is w*h(8bit) + gkLONG xpels, ypels, zero3, zero4; //set to 0,0,0,0 +}; + +int gkIO::ReadWord(istream &in){ + int retval = in.get() << 8; + return retval | (in.get() & 0xff); +} + +int gkIO::ReadLong(istream &in){ + int retval = ReadWord(in) << 16; + return retval | (ReadWord(in) & 0xffff); +} + +char *gkIO::ReadString(istream &in){ + static char st[80]; + int len = ReadWord(in); + if(!len) return 0; + in.read(st,len); + st[len] = 0; + return st; +} + +char *gkIO::ReadNewString(istream &in){ + int len = ReadWord(in); + if(!len) return 0; + + char *st = new char[len+1]; + in.read(st,len); + st[len] = 0; + return st; +} + +void gkIO::WriteLong(ostream &out, int n){ + WriteWord(out, n>>16); + WriteWord(out, n); +} + +void gkIO::WriteWord(ostream &out, int n){ + out << (char) ((n>>8)&0xff); + out << (char) (n&0xff); +} + +void gkIO::WriteString(ostream &out, char *st){ + WriteWord(out,strlen(st)); + out.write(st,strlen(st)); +} + +int gkRGB::Equals(int _r, int _g, int _b){ + return _r==color.bytes.r && _g==color.bytes.g && _b==color.bytes.b; +} + +void gkRGB::Combine(gkRGB c2, int alpha){ + //mix alpha + color.bytes.r += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetR()-GetR(), alpha); + color.bytes.g += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetG()-GetG(), alpha); + color.bytes.b += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetB()-GetB(), alpha); +} + +gkRGB::operator COLORREF(){ + return (color.bytes.b<<16) | (color.bytes.g<<8) | (color.bytes.r); +} + +gkPalGenItem::gkPalGenItem(gkRGB _color){ + color = _color; + occurrences = 1; + nextItem = 0; +} + +gkPalGenItem::~gkPalGenItem(){ +} + +gkRGB gkPalGenItem::GetColor(){ + return color; +} + +void gkPalGenItem::AddOccurrence(){ + occurrences++; +} + +int gkPalGenItem::GetOccurrences(){ + return occurrences; +} + +void gkPalGenItem::SetOccurrences(int n){ + occurrences = n; +} + +void gkPalGenItem::SetNextItem(gkPalGenItem *item){ + nextItem = item; +} + +gkPalGenItem *gkPalGenItem::GetNextItem(){ + return nextItem; +} + +int gkPalGenItem::GetCount(){ + gkPalGenItem *cur; + int count = 0; + for(cur=this; cur; cur=cur->nextItem){ + if(cur->occurrences) count++; + } + return count; +} + +int gkPalGenItem::SortCallback(const void *e1, const void *e2){ + gkPalGenItem *i1 = *((gkPalGenItem**) e1); + gkPalGenItem *i2 = *((gkPalGenItem**) e2); + if(i1->occurrences > i2->occurrences) return -1; + if(i1->occurrences == i2->occurrences) return 0; + return 1; +} + +gkPaletteGenerator::gkPaletteGenerator(){ + int i; + for(i=0; i<52; i++){ + colorCube[i] = 0; + } +} + +gkPaletteGenerator::~gkPaletteGenerator(){ + Reset(); +} + +void gkPaletteGenerator::Reset(){ + int i; + for(i=0; i<52; i++){ + if(colorCube[i]){ + gkPalGenItem *cur, *next; + for(cur=colorCube[i]; cur; cur=next){ + next = cur->GetNextItem(); + delete cur; + } + colorCube[i] = 0; + } + } +} + +void gkPaletteGenerator::AddColor(gkRGB color){ + int i = GetHash(color); + + if(!colorCube[i]){ + colorCube[i] = new gkPalGenItem(color); + }else{ + gkPalGenItem *cur, *prev; + for(cur=colorCube[i]; cur; cur=cur->GetNextItem()){ + if((cur->GetColor()) == color){ + cur->AddOccurrence(); //Color already in list + break; + } + prev = cur; + } + if(!cur){ //color not in list + prev->SetNextItem(new gkPalGenItem(color)); + } + } +} + +void gkPaletteGenerator::CreatePalette(gkRGB *palette, int numEntries){ + if(numEntries<=0) return; + + //Set all entries to black + int i; + for(i=0; iGetCount(); + } + while(!count){ //if no colors yet expand area of inclusion + if(first==0 && last==51) return; //no colors anywhere! + if(first>0){ + first--; + if(colorCube[first]) count += colorCube[first]->GetCount(); + } + if(last<51){ + last++; + if(colorCube[last]) count += colorCube[last]->GetCount(); + } + } + + //Create an array to hold all the colors for sorting purposes + gkPalGenItem **colors = new gkPalGenItem*[count]; + gkPalGenItem *cur; + i = 0; + int j; + for(j=first; j<=last; j++){ + if(colorCube[j]){ + for(cur=colorCube[j]; cur; cur=cur->GetNextItem()){ + if(cur->GetOccurrences()) colors[i++] = cur; + } + } + } + + //figure out how many colors will come from this section of the cube + int numToGrab = 1; + int tempCurEntry = curEntry; + while(nextEntry==first && tempCurEntry<(52-1)){ + tempCurEntry++; + nextEntry = (int) (scaleFactor * (tempCurEntry+1)); + numToGrab++; + } + + if(numToGrab > count) numToGrab = count; + + //sort colors into descending order and pick "num" most frequent + qsort(colors, count, sizeof(gkPalGenItem*), gkPalGenItem::SortCallback); + + for(i=0; iGetColor(); + colors[i]->SetOccurrences(0); + } + + //delete sorting table + delete colors; + } +} + + +int gkPaletteGenerator::GetNumColors(){ + int num = 0, i; + for(i=0; i<52; i++) + if(colorCube[i]) num += colorCube[i]->GetCount(); + return num; +} + + +int gkPaletteGenerator::GetHash(gkRGB color){ + int r = color.GetR() >> 6; //rough categories 0-3 + int g = color.GetG() >> 6; + int b = color.GetB() >> 6; + int highest = r; + if(g > highest) highest = g; + if(b > highest) highest = b; + + int hash; + + // r > (g < b) + // r > (g = b) + // r > (g > b) + // g > (r < b) + // g > (r = b) + // g > (r > b) + // b > (r < g) + // b > (r = g) + // b > (r > g) + // (r = b) > g + // (r = g) > b + // (g = b) > r + // (r = g) = b + if(r > g && r > b){ //red high + if(g < b) hash = 0; // r > (g < b) + else if(g==b) hash = 1; // r > (g = b) + else hash = 2; // r > (g > b) + }else if(g > r && g > b){ //green high + if(r < b) hash = 3; // g > (r < b) + else if(r==b) hash = 4; // g > (r = b) + else hash = 5; // g > (r > b) + }else if(b > r && b > g){ //blue high + if(r < g) hash = 6; // b > (r < g) + else if(r==g) hash = 7; // b > (r = g) + else hash = 8; // b > (r > g) + }else if(r==b && b==g){ //r = g = b + hash = 9; + }else if(r==b){ //(r = b) > g + hash = 10; + }else if(r==g){ //(r = g) > b + hash = 11; + }else{ //(g = b) > r + hash = 12; + } + + //make room in each category for four levels of intensity (0-3) + hash = hash*4 + highest; + + return hash; +} + +int gkPaletteGenerator::ColorExists(gkRGB color){ + int hash = GetHash(color); + if(!colorCube[hash]) return 0; + + gkPalGenItem *cur; + for(cur=colorCube[hash]; cur; cur=cur->GetNextItem()){ + if(cur->GetColor()==color) return 1; //found exact color + } + return 0; +} + +gkRGB gkPaletteGenerator::MatchColor(gkRGB color){ + int hash = GetHash(color); + int r = color.GetR(); + int g = color.GetG(); + int b = color.GetB(); + if(colorCube[hash]){ //near colors; search just this section + gkPalGenItem *cur, *bestMatch; + int bestDiff; + bestMatch = colorCube[hash]; + int r2, g2, b2; + r2 = abs(r - bestMatch->GetColor().GetR()); + g2 = abs(g - bestMatch->GetColor().GetG()); + b2 = abs(b - bestMatch->GetColor().GetB()); + bestDiff = r2 + g2 + b2; + for(cur=bestMatch->GetNextItem(); cur; cur=cur->GetNextItem()){ + r2 = abs(r - cur->GetColor().GetR()); + g2 = abs(g - cur->GetColor().GetG()); + b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2 + g2 + b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + return bestMatch->GetColor(); + }else{ + //no colors nearby; expand search + //Get it from ~greyscale if possible + int first, last; + first = last = 36 + (hash % 4); + if(!colorCube[first]){ + first = 0; //nothing there either; search everything + last = 51; + /* + first = 36; + last = 39; + //first = hash - (hash%4); //different intensities, same color + //last = first + 3; + if(!colorCube[first] && !colorCube[first+1] && !colorCube[first+2] + && !colorCube[last]){ + first = 0; //nothing there either; search everything + last = 51; + } + */ + } + gkPalGenItem *cur, *bestMatch; + int bestDiff = 0x7fffffff; + bestMatch = 0; + int i; + for(i=first; i<=last; i++){ + for(cur=colorCube[i]; cur; cur=cur->GetNextItem()){ + int r2 = abs(r - cur->GetColor().GetR()); + int g2 = abs(g - cur->GetColor().GetG()); + int b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2 + g2 + b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + } + if(!bestMatch) return gkRGB(0,0,0); + return bestMatch->GetColor(); + } +} + +gkTransparencyTable::gkTransparencyTable(){ + lookup = new gkBYTE[256*256]; + + int baseOffset, alpha, i; + i = 0; + for(baseOffset=0; baseOffset<256; baseOffset++){ + for(alpha=0; alpha<256; alpha++){ + lookup[i++] = (baseOffset * alpha) / 255; + } + } +} + +gkTransparencyTable::~gkTransparencyTable(){ + if(lookup) delete lookup; + lookup = 0; +} + +int gkTransparencyTable::LookupTransparencyOffset(int baseOffset, int alpha){ + return (baseOffset>=0) ? lookup[(baseOffset<<8)+alpha] + : (-lookup[((-baseOffset)<<8)+alpha]); +} + + +gkWinShape::gkWinShape(){ + data = 0; + width = height = bpp = 0; +} + +gkWinShape::~gkWinShape(){ + FreeData(); +} + +void gkWinShape::FreeData(){ + if(data){ + delete data; + data = 0; + } + width = height = 0; +} + +void gkWinShape::Create(int _width, int _height){ + if(_width <= 0 || _height <= 0) return; + + FreeData(); + width = _width; + height = _height; + + //round up width to ensure multiple of 4 pixels + width = (width + 3) & (~3); + + data = new gkBYTE[(width*height)<<2]; + bpp = 32; +} + +void gkWinShape::Cls(){ + if(!this->data) return; + + gkLONG *dest = (gkLONG*) this->data; + int i = this->width * this->height; + while(i--){ + *(dest++) = 0xff000000; + } +} + +void gkWinShape::Cls(gkRGB color){ + if(!this->data) return; + + gkLONG *dest = (gkLONG*) this->data; + int i = this->width * this->height; + while(i--){ + *(dest++) = color.GetARGB(); + } +} + +void gkWinShape::Plot(int x, int y, gkRGB color, int testBoundaries){ + if(!data) return; + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return; + } + + gkRGB *dest = (gkRGB*) (data + ((y*width + x) << 2)); + *dest = color; +} + +gkRGB gkWinShape::Point(int x, int y, int testBoundaries){ + if(!data) return gkRGB(0,0,0); + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return gkRGB(0,0,0); + } + + gkRGB *color = (gkRGB*) (data + ((y*width + x) << 2)); + return *color; +} + +void gkWinShape::Line(int x1, int y1, int x2, int y2, gkRGB color){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + (((y1 * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + *(dest++) = color; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest += pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + *dest = color; + dest += pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + +void gkWinShape::LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, + int alpha){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + (((y1 * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + dest->Combine(color,alpha); + dest++; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest += pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + dest->Combine(color,alpha); + dest += pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + +void gkWinShape::RectFrame(int x, int y, int w, int h, gkRGB color){ + int x2 = x + w - 1; + int y2 = y + h - 1; + RectFill(x,y,w,1,color); + RectFill(x,y2,w,1,color); + RectFill(x,y,1,h,color); + RectFill(x2,y,1,h,color); +} + +void gkWinShape::RectFill(int x, int y, int w, int h, gkRGB color){ + int x2 = (x + w) - 1; + int y2 = (y + h) - 1; + + //Clip rectangle + if(x < 0) x = 0; + if(y < 0) y = 0; + + if(x2 >= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + (((y * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; i= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + (((y * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; iCombine(color,alpha); + dest++; + } + destStart += width; + } +} + +void gkWinShape::RectFillChannel(int x, int y, int w, int h, + gkRGB color, int mask){ + int x2 = (x + w) - 1; + int y2 = (y + h) - 1; + + //Clip rectangle + if(x < 0) x = 0; + if(y < 0) y = 0; + + if(x2 >= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkLONG *destStart = (gkLONG*) (data + (((y * width) + x) <<2)); + gkLONG *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + gkLONG srcColor = color.GetARGB() & mask; + gkLONG destMask = ~mask; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; i=width || cur.y>=height) continue; + + //filling correct color check + if(!(*(cur.pos)==fillColor)) continue; + + //fill color & add adjacent + *(cur.pos) = color; + + queue[qTail++] = gkFillItem(cur.x+1,cur.y,cur.pos+1); + qTail &= 16383; + queue[qTail++] = gkFillItem(cur.x-1,cur.y,cur.pos-1); + qTail &= 16383; + queue[qTail++] = gkFillItem(cur.x,cur.y+1,cur.pos+width); + qTail &= 16383; + queue[qTail++] = gkFillItem(cur.x,cur.y-1,cur.pos-width); + qTail &= 16383; + } +} + +int gkWinShape::GetNumColors(){ + gkPaletteGenerator palGen; + int i = width * height; + gkRGB *src = (gkRGB*) data; + while(i--){ + palGen.AddColor(*(src++)); + } + + return palGen.GetNumColors(); +} + +void gkWinShape::RemapColor(gkRGB oldColor, gkRGB newColor){ + if(!data) return; + + gkRGB *src = (gkRGB*) data; + int i, j; + for(j=0; jSetA(alpha); + } +} + +void gkWinShape::SetColorAlpha(gkRGB color, int alpha){ + if(!data) return; + + gkRGB *src = (gkRGB*) data; + int i, j; + for(j=0; jSetA(alpha); + } + src++; + } + } +} + +int gkWinShape::GetShape(gkWinShape *srcShape, int x, int y, int w, int h){ + if(!srcShape || !srcShape->data) return 0; + + //adjust src rectangle until it fits within source data + if(x<0){ + w += x; + x = 0; + } + if(y<0){ + h += y; + y = 0; + } + if(x + w > srcShape->width){ + w = srcShape->width - x; + } + if(y + h > srcShape->height){ + h = srcShape->height - y; + } + + if(w<=0 || h<=0) return 0; + + FreeData(); + Create(w, h); + + gkBYTE *src = srcShape->data + ((y*srcShape->width + x)<<2); + gkBYTE *dest = this->data; + int srcSkip = srcShape->width << 2; //4 bytes per pixel + w <<= 2; //4 bytes per pixel + + while(h--){ + memcpy(dest, src, w); + dest += w; + src += srcSkip; + } + + return 1; +} + +int gkWinShape::GetShape(gkWinShape *srcShape){ + if(this->width != srcShape->width || this->height != srcShape->height + || (!this->data) || (!srcShape->data)){ + //mem needs to be reallocated + FreeData(); + memcpy(this, srcShape, sizeof(gkWinShape)); + data = 0; + if(srcShape->data){ + data = new gkBYTE[(width * height) << 2]; + memcpy(data, srcShape->data, (width * height) << 2 ); + } + }else{ + //already got right size mem, just copy data over + memcpy(data, srcShape->data, (width * height) << 2); + fontSpacing = srcShape->fontSpacing; + fontKerning = srcShape->fontKerning; + x_handle = srcShape->x_handle; + y_handle = srcShape->y_handle; + } + return data!=0; +} + + +int gkWinShape::GetShape(HDC hdc){ + //get a handle to the bitmap currently in the HDC + HBITMAP bitmap = (HBITMAP) GetCurrentObject(hdc,OBJ_BITMAP); + + //get info about that bitmap + BITMAP bm; + GetObject(bitmap,sizeof(BITMAP),&bm); + + int width = bm.bmWidth; + int height = bm.bmHeight; + + static BITMAPINFO bmInfo={{40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}}; + static int setup=0; + + if(!setup){ + setup = 1; + *((int*)(&bmInfo.bmiColors[0])) = 0xff0000; //red mask + *((int*)(&bmInfo.bmiColors[4])) = 0x00ff00; //green mask + *((int*)(&bmInfo.bmiColors[8])) = 0x0000ff; //blue mask + } + + //specify height as negative to get a top-to-bottom bitmap + bmInfo.bmiHeader.biWidth = width; + bmInfo.bmiHeader.biHeight = -height; + + Create(width,height); + GetDIBits(hdc,bitmap,0,height,data,&bmInfo,DIB_RGB_COLORS); + return 1; +} + +int gkWinShape::GetShape(HBITMAP bitmap){ + //Create a DC compatible with the screen + HDC hdc = CreateDC("DISPLAY",0,0,0); + + //get info about that bitmap + BITMAP bm; + GetObject(bitmap,sizeof(BITMAP),&bm); + + int width = bm.bmWidth; + int height = bm.bmHeight; + + static BITMAPINFO bmInfo={{40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}}; + static int setup=0; + + if(!setup){ + setup = 1; + *((int*)(&bmInfo.bmiColors[0])) = 0xff0000; //red mask + *((int*)(&bmInfo.bmiColors[4])) = 0x00ff00; //green mask + *((int*)(&bmInfo.bmiColors[8])) = 0x0000ff; //blue mask + } + + //specify height as negative to get a top-to-bottom bitmap + bmInfo.bmiHeader.biWidth = width; + bmInfo.bmiHeader.biHeight = -height; + + Create(width,height); + GetDIBits(hdc,bitmap,0,height,data,&bmInfo,DIB_RGB_COLORS); + DeleteDC(hdc); + return 1; +} + + +int gkWinShape::SaveShape(char *filename){ + ofstream outfile(filename, ios::out | ios::binary); + if(!outfile) return 0; + + int result = SaveShape(outfile); + outfile.close(); + + return result; +} + +int gkWinShape::SaveShape(ostream &out){ + int totalSize = ((width * height) << 2); + + out << "SHPE"; + int skipSize = totalSize + 20; + gkIO::WriteLong(out, skipSize); + + //Write shape header + gkIO::WriteWord(out, 3); //type 3 + gkIO::WriteWord(out, width); + gkIO::WriteWord(out, height); + gkIO::WriteWord(out, (bpp==8)?8:32); + out << (char) fontSpacing << (char) fontKerning; + gkIO::WriteWord(out, x_handle); + gkIO::WriteWord(out, y_handle); + gkIO::WriteWord(out, 0); //6 bytes of reserved space + gkIO::WriteLong(out, 0); + + + //Write data + if(data){ + int pitch = width << 2; + gkLONG *src; + gkBYTE *srcStart = data; + + int i,j; + for(j=0; jLoadShape(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadShape(istream &infile){ + FreeData(); + if(infile.get() != 'S') return 0; + if(infile.get() != 'H') return 0; + if(infile.get() != 'P') return 0; + if(infile.get() != 'E') return 0; + + gkIO::ReadLong(infile); //discard skipsize + + //Read shape header + if(gkIO::ReadWord(infile) != 2) return 0; + width = gkIO::ReadWord(infile); + height = gkIO::ReadWord(infile); + int filebpp = gkIO::ReadWord(infile); + if(!bpp) bpp = filebpp; + + if(width && height){ + Create(width,height); + } + + fontSpacing = infile.get(); + fontKerning = infile.get(); + x_handle = gkIO::ReadWord(infile); + y_handle = gkIO::ReadWord(infile); + + gkIO::ReadWord(infile); + gkIO::ReadLong(infile); //discard reserved space + + if(!width || !height) return 1; //nothing to load, null shape + + int pitch = width << 2; + gkBYTE *destStart = data; + gkLONG *dest; + int x,y; + for(y=0; yLoadBMP(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadBMP(istream &infile){ + BMP_header header; + if(gkIO::ReadWord(infile)!=0x424d){ //check for "BM" + return 0; + } + infile.read((char*)&header, sizeof(BMP_header)); + if(header.bpp != 24){ + cout << "LoadBMP can only handle 24-bit files" << endl; + return 0; + } + + FreeData(); + width = header.width; + height = header.height; + bpp = (char) header.bpp; + Create(width,height); + + // load graphics, coverting every three (B,R,G) bytes to one ARGB value. + // lines padded to even multiple of 4 bytes + int srcPitch = ((header.width * 3) + 3) & (~3); + gkBYTE *buffer = new gkBYTE[srcPitch * height]; + gkBYTE *nextBuffPtr = buffer + ((height-1) * srcPitch); + gkBYTE *buffPtr; + + infile.read(buffer, srcPitch * height); + + gkBYTE *nextDest = data; + gkRGB *dest; + int destPitch = (width << 2); + + int i, j; + j = height; + while(j--){ + buffPtr = nextBuffPtr; + nextBuffPtr -= srcPitch; + dest = (gkRGB*) nextDest; + nextDest += destPitch; + i = header.width; + while(i--){ + dest->SetB(*(buffPtr++)); + dest->SetG(*(buffPtr++)); + dest->SetR(*(buffPtr++)); + dest->SetA(0xff); + dest++; + } + for(i=header.width; iSetARGB(0); + dest++; + } + } + + delete buffer; + + return 1; +} + + +void gkWinShape::Blit(gkWinShape *destShape, int x, int y, int flags){ + if(!data || !destShape || !destShape->data) return; + + gkBYTE *src = 0; + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; //times 4 later + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += (-y * this->width); //times 4 later + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcWidth <<= 2; + srcSkip <<= 2; + destSkip <<= 2; + + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTrans(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + memcpy(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + } +} + +////////////////////////////////////////////////////////////////////// +// Function: BlitScale +// Arguments: destShape +// x +// y +// flags +// scale - number of source pixels for every one +// dest pixel, stored in 24:8 fixed point. +// $100=100%, $200=200% (mag x2), $80=50% +////////////////////////////////////////////////////////////////////// +void gkWinShape::BlitScale(gkWinShape *destShape, int x, int y, + int scale, int flags){ + if(!data || !destShape || !destShape->data || !scale) return; + + gkBYTE *src = 0; + int srcSkip = this->width; + int srcWidth = (this->width * scale) >> 8; + int lines = (this->height * scale) >> 8; + + //clip left side + if(x < 0){ + src += (-x << 8) / scale; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += ((-y * this->width) << 8) / scale; + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcSkip <<= 2; + destSkip <<= 2; + + int ratio = (int) ((1.0f / (((float) scale) / 256.0f)) * 256.0f); + + int lineError = 0; + while(lines--){ + BlitLineScale(dest, src, srcWidth, ratio); + lineError += ratio; + src += srcSkip * (lineError >> 8); + lineError &= 0xff; + dest += destSkip; + } + + /* + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTrans(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + memcpy(dest, src, srcWidth); + src += srcSkip; + dest += destSkip; + } + } + */ +} + +void gkWinShape::BlitScale(gkWinShape *destShape, int x, int y, + float scale, int flags){ + BlitScale(destShape,x,y,flags,(int) (256.0f * scale)); +} + +void gkWinShape::BlitChannel(gkWinShape *destShape, int x, int y, int mask){ + if(!data || !destShape || !destShape->data) return; + + gkBYTE *src = 0; + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src += (-y * this->width); + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = destShape->data + (((y * destShape->width) + x) << 2); + src = this->data + ((int)src << 2); + srcSkip <<= 2; + destSkip <<= 2; + + int inverseMask = ~mask; + + while(lines--){ + gkLONG *curSrc = (gkLONG*) src; + gkLONG *curDest = (gkLONG*) dest; + int pixels = srcWidth; + while(pixels--){ + *curDest = (*curSrc & mask) | (*curDest & inverseMask); + curSrc++; + curDest++; + } + src += srcSkip; + dest += destSkip; + } +} + +HBITMAP gkWinShape::GetDIB(HDC hdc){ + //note you must DeleteObject() on the dib that's returned once done + static BITMAPINFO bmInfo={{40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}}; + static int setup=0; + + if(!setup){ + setup = 1; + *((int*)(&bmInfo.bmiColors[0])) = 0xff0000; //red mask + *((int*)(&bmInfo.bmiColors[4])) = 0x00ff00; //green mask + *((int*)(&bmInfo.bmiColors[8])) = 0x0000ff; //blue mask + } + + bmInfo.bmiHeader.biWidth = width; + bmInfo.bmiHeader.biHeight = -height; + + HBITMAP dib = CreateDIBitmap(hdc, + &bmInfo.bmiHeader, + CBM_INIT, + data, + &bmInfo, + DIB_RGB_COLORS); + + return dib; +} + + +void gkWinShape::BlitToHDC(HDC hDC, int x, int y){ + static HDC srcHDC; + static int setup=0; + + if(!setup){ + setup = 1; + srcHDC = CreateCompatibleDC(0); + } + + HBITMAP dib = GetDIB(hDC); + + HBITMAP oldBitmap = (HBITMAP) SelectObject(srcHDC,dib); + BitBlt(hDC, x, y, width, height, srcHDC, 0, 0, SRCCOPY); + SelectObject(srcHDC,oldBitmap); + + DeleteObject(dib); +} + +void gkWinShape::MemCpyTrans(gkBYTE *dest, gkBYTE *src, + int numBytes){ + //copies colors using the Alpha for transparency + gkRGB *destColor = (gkRGB*) dest; + gkRGB *srcColor = (gkRGB*) src; + int numColors = numBytes >> 2; + int c1; + while(numColors--){ + int alpha; + switch(alpha = (srcColor->GetA())){ + case 0: break; + case 255: //Straight copy + *destColor = *srcColor; + break; + default: //mix alpha + c1 = destColor->GetR(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetR()-c1, alpha); + destColor->SetR(c1); + c1 = destColor->GetG(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetG()-c1, alpha); + destColor->SetG(c1); + c1 = destColor->GetB(); + c1 += tranTable.LookupTransparencyOffset( + srcColor->GetB()-c1, alpha); + destColor->SetB(c1); + break; + } + srcColor++; + destColor++; + } +} + +void gkWinShape::BlitLineScale(gkBYTE *dest,gkBYTE *src,int pixels,int ratio){ + gkRGB *srcRGB = (gkRGB*) src; + gkRGB *destRGB = (gkRGB*) dest; + + int error = 0; + + while(pixels--){ + *(destRGB++) = *srcRGB; + error += ratio; + srcRGB += error >> 8; + error &= 0xff; + } +} + diff --git a/Tools/GBConv2/Source/wingk.h b/Tools/GBConv2/Source/wingk.h new file mode 100644 index 0000000..e2735c0 --- /dev/null +++ b/Tools/GBConv2/Source/wingk.h @@ -0,0 +1,187 @@ +#ifndef WINGK_H +#define WINGK_H + +#include "stdafx.h" + +#include +#include +#include +#include +#include + +typedef unsigned char gkBYTE; +typedef short int gkWORD; +typedef int gkLONG; + +#define GKHANDLE_TL 0 +#define GKHANDLE_TC 1 +#define GKHANDLE_TR 2 +#define GKHANDLE_CR 3 +#define GKHANDLE_BR 4 +#define GKHANDLE_BC 5 +#define GKHANDLE_BL 6 +#define GKHANDLE_CL 7 +#define GKHANDLE_CENTER 8 + +#define GKBLT_TRANSPARENT 1 + +class gkIO{ + public: + inline static int ReadByte(istream &in){ return in.get(); } + static int ReadWord(istream &in); + static int ReadLong(istream &in); + static char *ReadString(istream &in); + static char *ReadNewString(istream &in); + inline static void WriteByte(ostream &out, int n){ out << (char) n; } + static void WriteLong(ostream &out, int n); + static void WriteWord(ostream &out, int n); + static void WriteString(ostream &out, char *st); +}; + +struct gkRGB_4bytes{ + unsigned char b, g, r, a; +}; + +union gkRGB_ColorUnion{ + gkRGB_4bytes bytes; + gkLONG argb; +}; + +class gkRGB{ + public: + gkRGB_ColorUnion color; + + inline gkRGB(){ color.argb = 0xff000000; } + inline gkRGB(int _r, int _g, int _b, int _a=255){ + color.bytes.r=_r; color.bytes.g=_g; color.bytes.b=_b; color.bytes.a=_a;} + inline void SetR(gkBYTE n){ color.bytes.r = n; } + inline void SetG(gkBYTE n){ color.bytes.g = n; } + inline void SetB(gkBYTE n){ color.bytes.b = n; } + inline void SetA(gkBYTE n){ color.bytes.a = n; } + inline void SetARGB(gkLONG n){ color.argb = n; } + inline gkBYTE GetR(){ return color.bytes.r; } + inline gkBYTE GetG(){ return color.bytes.g; } + inline gkBYTE GetB(){ return color.bytes.b; } + inline gkBYTE GetA(){ return color.bytes.a; } + inline gkLONG GetARGB(){ return color.argb; } + inline int operator==(gkRGB &c2){ + return ((color.argb & 0xffffff) == (c2.color.argb & 0xffffff)); } + inline int Equals(int _r, int _g, int _b); + void Combine(gkRGB c2, int alpha); + operator COLORREF(); +}; + +class gkPalGenItem{ + protected: + gkRGB color; + int occurrences; + gkPalGenItem *nextItem; + + public: + gkPalGenItem(gkRGB _color); + ~gkPalGenItem(); + inline gkRGB GetColor(); + inline void AddOccurrence(); + inline int GetOccurrences(); + inline void SetOccurrences(int n); + inline void SetNextItem(gkPalGenItem *item); + inline gkPalGenItem *GetNextItem(); + int GetCount(); + static int SortCallback(const void *e1, const void *e2); +}; + +class gkPaletteGenerator{ + protected: + gkPalGenItem *colorCube[13*4]; + + public: + gkPaletteGenerator(); + ~gkPaletteGenerator(); + void Reset(); + void AddColor(gkRGB color); + int GetNumColors(); + void CreatePalette(gkRGB *palette, int numEntries); + int GetHash(gkRGB color); + int ColorExists(gkRGB color); + gkRGB MatchColor(gkRGB color); +}; + +class gkTransparencyTable{ + protected: + gkBYTE *lookup; + + public: + gkTransparencyTable(); + ~gkTransparencyTable(); + inline int LookupTransparencyOffset(int baseOffset, int alpha); +}; + +class gkWinShape{ + friend class gkRGB; + + protected: + gkBYTE *data; + int width, height; + char bpp, fontSpacing, fontKerning; + short int x_handle, y_handle; + static gkTransparencyTable tranTable; + + public: + gkWinShape(); + ~gkWinShape(); + + inline gkBYTE* GetData(){ return data; } + + void FreeData(); + inline void Reset(){ FreeData(); } + void Create(int _width, int _height); + HBITMAP GetDIB(HDC hdc); + void Cls(); + void Cls(gkRGB color); + void Plot(int x, int y, gkRGB color, int testBoundaries=1); + gkRGB Point(int x, int y, int testBoundaries=1); + void Line(int x1, int y1, int x2, int y2, gkRGB color); + void LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, int alpha); + void RectFrame(int x, int y, int w, int h, gkRGB color); + void RectFill(int x, int y, int w, int h, gkRGB color); + void RectFillAlpha(int x, int y, int w, int h, gkRGB color, int alpha); + void RectFillChannel(int x, int y, int w, int h, gkRGB color, int mask); + void FloodFill(int x, int y, gkRGB color); + void RemapColor(gkRGB oldColor, gkRGB newColor); + int GetNumColors(); + int GetPalette(gkRGB *palette, int maxColors); + void RemapToPalette(gkRGB *palette, int numColors); + void ReduceColors(int numColors); + void ExchangeColors(gkRGB c1, gkRGB c2); + void SetAlpha(int alpha); + void SetColorAlpha(gkRGB color, int alpha); + + int GetShape(gkWinShape *srcShape, int x, int y, int w, int h); + int GetShape(gkWinShape *srcShape); + int GetShape(HDC hdc); + int GetShape(HBITMAP bitmap); + int SaveShape(char *filename); + int SaveShape(ostream &outfile); + int LoadShape(char *filename); + int LoadShape(istream &infile); + int LoadBMP(char *filename); + int LoadBMP(istream &infile); + void Blit(gkWinShape *destShape, int x, int y, + int flags=GKBLT_TRANSPARENT); + void BlitScale(gkWinShape *destShape, int x, int y, int scale, + int flags=GKBLT_TRANSPARENT); + void BlitScale(gkWinShape *destShape, int x, int y, float scale, + int flags=GKBLT_TRANSPARENT); + void BlitChannel(gkWinShape *destShape, int x, int y, int mask); + void BlitToHDC(HDC hDC, int x, int y); + + int GetWidth(){ return width; } + int GetHeight(){ return height; } + + //internal support routines + static void MemCpyTrans(gkBYTE *dest, gkBYTE *src, int nBytes); + static void BlitLineScale(gkBYTE *dest, gkBYTE *src, int pixels,int ratio); +}; + +#endif + diff --git a/Tools/GBConv2/Source/wingk.hbk b/Tools/GBConv2/Source/wingk.hbk new file mode 100644 index 0000000..205bc5f --- /dev/null +++ b/Tools/GBConv2/Source/wingk.hbk @@ -0,0 +1,184 @@ +#ifndef WINGK_H +#define WINGK_H + +#include "stdafx.h" + +#include +#include +#include +#include +#include + +typedef unsigned char gkBYTE; +typedef short int gkWORD; +typedef int gkLONG; + +#define GKHANDLE_TL 0 +#define GKHANDLE_TC 1 +#define GKHANDLE_TR 2 +#define GKHANDLE_CR 3 +#define GKHANDLE_BR 4 +#define GKHANDLE_BC 5 +#define GKHANDLE_BL 6 +#define GKHANDLE_CL 7 +#define GKHANDLE_CENTER 8 + +#define GKBLT_TRANSPARENT 1 + +class gkIO{ + public: + inline static int ReadByte(istream &in){ return in.get(); } + static int ReadWord(istream &in); + static int ReadLong(istream &in); + static char *ReadString(istream &in); + static char *ReadNewString(istream &in); + inline static void WriteByte(ostream &out, int n){ out << (char) n; } + static void WriteLong(ostream &out, int n); + static void WriteWord(ostream &out, int n); + static void WriteString(ostream &out, char *st); +}; + +struct gkRGB_4bytes{ + unsigned char b, g, r, a; +}; + +union gkRGB_ColorUnion{ + gkRGB_4bytes bytes; + gkLONG argb; +}; + +class gkRGB{ + public: + gkRGB_ColorUnion color; + + inline gkRGB(){ color.argb = 0xff000000; } + inline gkRGB(int _r, int _g, int _b, int _a=255){ + color.bytes.r=_r; color.bytes.g=_g; color.bytes.b=_b; color.bytes.a=_a;} + inline void SetR(gkBYTE n){ color.bytes.r = n; } + inline void SetG(gkBYTE n){ color.bytes.g = n; } + inline void SetB(gkBYTE n){ color.bytes.b = n; } + inline void SetA(gkBYTE n){ color.bytes.a = n; } + inline void SetARGB(gkLONG n){ color.argb = n; } + inline gkBYTE GetR(){ return color.bytes.r; } + inline gkBYTE GetG(){ return color.bytes.g; } + inline gkBYTE GetB(){ return color.bytes.b; } + inline gkBYTE GetA(){ return color.bytes.a; } + inline gkLONG GetARGB(){ return color.argb; } + inline int operator==(gkRGB &c2); + inline int Equals(int _r, int _g, int _b); + void Combine(gkRGB c2, int alpha); + operator COLORREF(); +}; + +class gkPalGenItem{ + protected: + gkRGB color; + int occurrences; + gkPalGenItem *nextItem; + + public: + gkPalGenItem(gkRGB _color); + ~gkPalGenItem(); + inline gkRGB GetColor(); + inline void AddOccurrence(); + inline int GetOccurrences(); + inline void SetOccurrences(int n); + inline void SetNextItem(gkPalGenItem *item); + inline gkPalGenItem *GetNextItem(); + int GetCount(); + static int SortCallback(const void *e1, const void *e2); +}; + +class gkPaletteGenerator{ + protected: + gkPalGenItem *colorCube[13*4]; + + public: + gkPaletteGenerator(); + ~gkPaletteGenerator(); + void Reset(); + void AddColor(gkRGB color); + int GetNumColors(); + void CreatePalette(gkRGB *palette, int numEntries); + int GetHash(gkRGB color); + int ColorExists(gkRGB color); + gkRGB MatchColor(gkRGB color); +}; + +class gkTransparencyTable{ + protected: + gkBYTE *lookup; + + public: + gkTransparencyTable(); + ~gkTransparencyTable(); + inline int LookupTransparencyOffset(int baseOffset, int alpha); +}; + +class gkWinShape{ + friend class gkRGB; + + protected: + gkBYTE *data; + int width, height; + char bpp, fontSpacing, fontKerning; + short int x_handle, y_handle; + static gkTransparencyTable tranTable; + + HBITMAP GetDIB(CDC *pDC); + + public: + gkWinShape(); + ~gkWinShape(); + + inline gkBYTE* GetData(){ return data; } + + void FreeData(); + inline void Reset(){ FreeData(); } + void Create(int _width, int _height); + void Cls(); + void Cls(gkRGB color); + void Plot(int x, int y, gkRGB color, int testBoundaries=1); + gkRGB Point(int x, int y, int testBoundaries=1); + void Line(int x1, int y1, int x2, int y2, gkRGB color); + void LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, int alpha); + void RectFrame(int x, int y, int w, int h, gkRGB color); + void RectFill(int x, int y, int w, int h, gkRGB color); + void RectFillAlpha(int x, int y, int w, int h, gkRGB color, int alpha); + void RectFillChannel(int x, int y, int w, int h, gkRGB color, int mask); + void RemapColor(gkRGB oldColor, gkRGB newColor); + int GetNumColors(); + int GetPalette(gkRGB *palette, int maxColors); + void RemapToPalette(gkRGB *palette, int numColors); + void ReduceColors(int numColors); + void ExchangeColors(gkRGB c1, gkRGB c2); + void SetAlpha(int alpha); + void SetColorAlpha(gkRGB color, int alpha); + + int GetShape(gkWinShape *srcShape, int x, int y, int w, int h); + int GetShape(gkWinShape *srcShape); + int SaveShape(char *filename); + int SaveShape(ostream &outfile); + int LoadShape(char *filename); + int LoadShape(istream &infile); + int LoadBMP(char *filename); + int LoadBMP(istream &infile); + void Blit(gkWinShape *destShape, int x, int y, + int flags=GKBLT_TRANSPARENT); + void BlitScale(gkWinShape *destShape, int x, int y, int scale, + int flags=GKBLT_TRANSPARENT); + void BlitScale(gkWinShape *destShape, int x, int y, float scale, + int flags=GKBLT_TRANSPARENT); + void BlitChannel(gkWinShape *destShape, int x, int y, int mask); + void BlitToDC(CDC *pDC, int x, int y); + + int GetWidth(){ return width; } + int GetHeight(){ return height; } + + //internal support routines + static void MemCpyTrans(gkBYTE *dest, gkBYTE *src, int nBytes); + static void BlitLineScale(gkBYTE *dest, gkBYTE *src, int pixels,int ratio); +}; + +#endif + diff --git a/Tools/GBConv2/converter_gfx.bmp b/Tools/GBConv2/converter_gfx.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2cbd3ca1bd04051e2f59ab52eec9e10657dbf8ed GIT binary patch literal 15416 zcmeI1!EO{m3`8d?(vQU zKYxAyaXkNgTc2Oo@59}3d|H3r9bcZ~e?LBd)bGE*({b!;cVKrQ?7;D`=IVHSdR$kc zL)(q*4(txRLI>8&=Bun3&*5{V-oy9zA6{IQ8~KW1oV=FcUDq$lSbuegs(OEW@;sUD5wXxOKfi1+#GcS=54k$mqgH+DPW zSp#z!rzVs5JD+6vURVS5t^HXEHP>Z5WL!JxOz(U-&l;+;U_7aZp1po+^ZVO=xOd-+ z@Sb57?KR81>zaJNihPpVrvBs;f9@#ZU&mjaOx9w})Z7;}8Tyl{V#RDZq;dRCfiB}~GrLXy(-uOiHHzTdm^9-+T9tEG1Gea>&vL-k7JIX=m{ zwLedMTF>oxf99*T7^mjGsL4n(LQS)-j75lhX-hcm) z@11p*J?xz?=abqlsVDJgPZFN>+>YP#%X4wf&PzL^$a|Y#{hJm0Q*}mhf6{uM&eT;F znf&`CAz6RE3)VxO)PD(IrJ*5=nM+>zaZ-GQnDqgU!^ e*sB$He0N}X;94D6^SiD!nCnXPwbreCj^ht(sn^l~ literal 0 HcmV?d00001