diff --git a/Tools/GBConv2/GBConv2.exe b/Tools/GBConv2/GBConv2.exe new file mode 100644 index 0000000..0b12b36 Binary files /dev/null and b/Tools/GBConv2/GBConv2.exe differ 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; i + +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 0000000..2cbd3ca Binary files /dev/null and b/Tools/GBConv2/converter_gfx.bmp differ