diff -Nru corsix-th-0.61/AnimView/CMakeLists.txt corsix-th-0.62/AnimView/CMakeLists.txt --- corsix-th-0.61/AnimView/CMakeLists.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/CMakeLists.txt 2018-07-21 11:13:17.000000000 +0000 @@ -1,31 +1,25 @@ # Project Declaration -PROJECT(AnimView) +project(AnimView) # Generate source files list # Note: do not use generic includes (*.cpp and such) this will break things with cmake -SET(animview_source_files +set(animview_source_files app.cpp frmMain.cpp frmSprites.cpp - rnc.cpp + ${CMAKE_SOURCE_DIR}/common/rnc.h + ${CMAKE_SOURCE_DIR}/common/rnc.cpp th.cpp - tinystr.cpp - tinyxml.cpp - tinyxmlerror.cpp - tinyxmlparser.cpp app.h backdrop.h frmMain.h frmSprites.h th.h - tinystr.h - tinyxml.h AnimView.rc ) # Declaration of the executable -IF(APPLE) - +if(APPLE) set(corsixth_icon_file ${CMAKE_SOURCE_DIR}/AnimView/Icon.icns) set_source_files_properties( ${corsixth_icon_file} @@ -43,57 +37,36 @@ set_target_properties(AnimView PROPERTIES LINK_FLAGS_MINSIZEREL "-dead_strip") set_target_properties(AnimView PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks") - -ELSE() +else() add_executable( AnimView WIN32 # This prevents the dos console showing up ${animview_source_files} ) -ENDIF() +endif() -# Finding libraries +## Finding libraries # Find WxWidgets -SET(wxWidgets_USE_LIBS core base) # optionally: more than wx std libs -FIND_PACKAGE(wxWidgets REQUIRED) -IF(wxWidgets_FOUND) - LINK_LIBRARIES(${wxWidgets_LIBRARIES}) - INCLUDE_DIRECTORIES(${wxWidgets_INCLUDE_DIRS}) - INCLUDE(${wxWidgets_USE_FILE}) - TARGET_LINK_LIBRARIES(AnimView ${wxWidgets_LIBRARIES}) +set(wxWidgets_USE_LIBS core base) # optionally: more than wx std libs +find_package(wxWidgets REQUIRED) +if(wxWidgets_FOUND) + link_libraries(${wxWidgets_LIBRARIES}) + include_directories(${wxWidgets_INCLUDE_DIRS}) + include(${wxWidgets_USE_FILE}) + target_link_libraries(AnimView ${wxWidgets_LIBRARIES}) message(" wxWidgets found") -ELSE(wxWidgets_FOUND) +else() message(FATAL_ERROR "error: wxWdigets library not found, it is required to build") message("Make sure the path is correctly defined or set the environment variable WXWIN to the correct location") -ENDIF(wxWidgets_FOUND) +endif() -# Basic platform dependant stuff -IF(UNIX) - IF(APPLE) - # fruit goes here - ELSE(APPLE) - # regular unix/linux - ENDIF(APPLE) -ELSE(UNIX) - IF(WIN32) - # Win32 specific - IF(MSVC) - # We want to bind against the very latest versions of the MSVC runtimes - add_definitions(/D "_BIND_TO_CURRENT_VCLIBS_VERSION=1") - ELSE(MSVC) - IF(MSYS) - # MSYS stuff - ELSE(MSYS) - # What's left? MINGW? CYGWIN? BORLAND? - ENDIF(MSYS) - ENDIF(MSVC) - ELSE(WIN32) - # other OS (not UNIX, not 32/64 bit Windows) - ENDIF(WIN32) -ENDIF(UNIX) +if(MSVC) + # We want to bind against the very latest versions of the MSVC runtimes + add_definitions(/D "_BIND_TO_CURRENT_VCLIBS_VERSION=1") +endif() -IF(APPLE) +if(APPLE) install(TARGETS AnimView BUNDLE DESTINATION .) # Fix the OS X bundle to include required libraries (create a redistributable app) @@ -102,7 +75,7 @@ SET(BU_CHMOD_BUNDLE_ITEMS ON) FIXUP_BUNDLE(${CMAKE_INSTALL_PREFIX}/AnimView.app \"\" \"\") ") -ELSE() +else() install(TARGETS AnimView RUNTIME DESTINATION AnimView) install(FILES LICENSE.txt DESTINATION AnimView ) -ENDIF() +endif() diff -Nru corsix-th-0.61/AnimView/frmMain.cpp corsix-th-0.62/AnimView/frmMain.cpp --- corsix-th-0.61/AnimView/frmMain.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/frmMain.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -36,12 +36,10 @@ #include #include #include "backdrop.h" -#include "tinyxml.h" BEGIN_EVENT_TABLE(frmMain, wxFrame) EVT_BUTTON(ID_LOAD , frmMain::_onLoad) EVT_BUTTON(ID_BROWSE , frmMain::_onBrowse) - EVT_BUTTON(ID_EXPORT , frmMain::_onExport) EVT_BUTTON(ID_FIRST_ANIM, frmMain::_onFirstAnim) EVT_BUTTON(ID_PREV_ANIM , frmMain::_onPrevAnim) EVT_BUTTON(ID_NEXT_ANIM , frmMain::_onNextAnim) @@ -77,7 +75,6 @@ pThemeHospital->Add(m_txtTHPath = new wxTextCtrl(this, wxID_ANY, L"", def, wxTE_CENTRE), 1, wxALIGN_CENTER_VERTICAL | wxALL, 1); pThemeHospital->Add(new wxButton(this, ID_BROWSE, L"Browse..."), 0, wxALIGN_CENTER_VERTICAL | wxALL, 1); pThemeHospital->Add(new wxButton(this, ID_LOAD, L"Load"), 0, wxALIGN_CENTER_VERTICAL | wxALL, 1); - pThemeHospital->Add(m_btnExport = new wxButton(this, ID_EXPORT, L"Export"), 0, wxALIGN_CENTER_VERTICAL | wxALL, 1); pSidebarSizer->Add(pThemeHospital, 0, wxEXPAND | wxALL, 0); wxStaticBoxSizer *pPalette = new wxStaticBoxSizer(wxVERTICAL, this, L"Palette"); @@ -285,13 +282,6 @@ load(); } -void frmMain::_onExport(wxCommandEvent& WXUNUSED(evt)) -{ - m_tmrAnimate.Stop(); - ::wxInitAllImageHandlers(); - export_png(); -} - void frmMain::load() { wxBusyCursor oBusy; @@ -313,20 +303,7 @@ aPath += wxFileName::GetPathSeparator(); m_oAnims.setSpritePath(aPath); - bool bXmlLoaded = false; - wxString xmlFile = _getCaseSensitivePath(L"VSPR-0.xml", sPath); - TiXmlDocument xmlDocument((const char*)xmlFile.mb_str()); - if(wxFileName::FileExists(xmlFile) && xmlDocument.LoadFile()) - { - m_oAnims.loadXMLFile(&xmlDocument); - m_oAnims.loadPaletteFile(_getCaseSensitivePath(L"MPALETTE.DAT", sPath)); - m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST1.DAT", sPath), 1); - m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST2.DAT", sPath), 2); - m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST66.DAT", sPath), 3); - bXmlLoaded = true; - m_btnExport->Disable(); - } - else if(!m_oAnims.loadAnimationFile(_getCaseSensitivePath(L"VSTART-1.ANI", sPath)) + if(!m_oAnims.loadAnimationFile(_getCaseSensitivePath(L"VSTART-1.ANI", sPath)) ||!m_oAnims.loadFrameFile(_getCaseSensitivePath(L"VFRA-1.ANI", sPath)) ||!m_oAnims.loadListFile(_getCaseSensitivePath(L"VLIST-1.ANI", sPath)) ||!m_oAnims.loadElementFile(_getCaseSensitivePath(L"VELE-1.ANI", sPath)) @@ -339,7 +316,7 @@ { ::wxMessageBox(L"Cannot load one or more data files", L"Load Animations", wxOK | wxICON_ERROR, this); } - if(!bXmlLoaded) { m_oAnims.markDuplicates(); } + m_oAnims.markDuplicates(); m_txtAnimCount->SetValue(wxString::Format(L"%u", (int)m_oAnims.getAnimationCount())); @@ -377,284 +354,6 @@ _onAnimChange(0); } -void frmMain::export_png() -{ - wxBusyCursor oBusy; - wxString sPath = m_txtTHPath->GetValue(); - if(sPath.IsEmpty()) - return; - if(sPath.Mid(sPath.Len() - 1) != wxFileName::GetPathSeparator()) - { - sPath += wxFileName::GetPathSeparator(); - } - if(!wxFileName::DirExists(sPath)) - { - ::wxMessageBox(L"Theme Hospital path non-existant", L"Load Animations", wxOK | wxICON_ERROR, this); - return; - } - wxString sdPath = _getCaseSensitivePath(L"DATA", sPath); - sdPath += wxFileName::GetPathSeparator(); - - //wxDialog warnDialog(this, wxID_ANY, L"Export Warning"); - //warnDialog::CreateButtonSizer(wxOK|wxCANCEL); - bool bWriteFrames = false; - int response = ::wxMessageBox(L"If you click Yes, the export process will write animation frames \n \ -in separate folders and will run for about 20 minutes, and will create about 18,000 files on \n \ -your hard disk (~250MB). \n If you click No, it will write the XML and element files only. This will create \n \ -2,950 files (~80MB) and is everything you need to modify graphics. As long as the XML file is present in \n \ -the DATA folder, the Animation Viewer will use PNG sprites instead of Theme Hospital data files.", - L"Export Warning", wxYES_NO | wxCANCEL); - if( response == wxYES) { bWriteFrames = true; } - if( response != wxCANCEL) - { - //Start with animations, then move on to sprite sheets (map tiles) - if(!m_oAnims.loadAnimationFile(_getCaseSensitivePath(L"VSTART-1.ANI", sdPath)) - ||!m_oAnims.loadFrameFile(_getCaseSensitivePath(L"VFRA-1.ANI", sdPath)) - ||!m_oAnims.loadListFile(_getCaseSensitivePath(L"VLIST-1.ANI", sdPath)) - ||!m_oAnims.loadElementFile(_getCaseSensitivePath(L"VELE-1.ANI", sdPath)) - ||!m_oAnims.loadTableFile(_getCaseSensitivePath(L"VSPR-0.TAB", sdPath)) - ||!m_oAnims.loadSpriteFile(_getCaseSensitivePath(L"VSPR-0.DAT",sdPath)) - ||!m_oAnims.loadPaletteFile(_getCaseSensitivePath(L"MPALETTE.DAT", sdPath)) - ||!m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST1.DAT", sdPath), 1) - ||!m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST2.DAT", sdPath), 2) - ||!m_oAnims.loadGhostFile(_getCaseSensitivePath(L"../QDATA/GHOST66.DAT", sdPath), 3)) - { - ::wxMessageBox(L"Cannot load one or more data files", L"Load Animations", wxOK | wxICON_ERROR, this); - } - m_oAnims.markDuplicates(); - wxString aPath = _getCaseSensitivePath(L"VSPR-0", sdPath); - aPath += wxFileName::GetPathSeparator(); - if(!wxFileName::DirExists(aPath)) - { - wxFileName::Mkdir(aPath); - } - size_t iExportCount = m_oAnims.getAnimationCount(); - wxFile f(_getCaseSensitivePath(L"VSPR-0export.log", sdPath), wxFile::write_append); - wxFileOutputStream fos(f); - wxTextOutputStream outputLog(fos); - outputLog.WriteString(wxString::Format(L"File\tIndex\tFrame\tLayer\tID\tWidth\tHeight\tUnknown\n")); - m_oAnims.writeTableDataHeader(&outputLog); - wxFile fxml(_getCaseSensitivePath(L"VSPR-0.xml", sdPath), wxFile::write); - wxFileOutputStream fosxml(fxml); - wxTextOutputStream outputXml(fosxml); - outputXml.WriteString(wxString::Format(L"\n")); - outputXml.WriteString(wxString::Format(L"\n")); - - int iAnimationCount = 0; - int iFrameCountTotal = 1; - int iElementCount = 0; - int iSpriteCount = 0; - int iListIndex = 0; - for(size_t iAnimation = 0; iAnimation < iExportCount; ++iAnimation) - { - if(!m_oAnims.isAnimationDuplicate(iAnimation) && m_oAnims.getFrameField(iAnimation) >= iFrameCountTotal) - { - wxString aiPath = aPath + wxString::Format(L"a%04u", iAnimation); - if(!wxFileName::DirExists(aiPath)) - { - wxFileName::Mkdir(aiPath); - } - outputXml.WriteString(wxString::Format(L"\n", - iAnimation, m_oAnims.getFrameField(iAnimation), m_oAnims.getUnknownField(iAnimation))); - aiPath += wxFileName::GetPathSeparator(); - size_t iFrameCount = m_oAnims.getFrameCount(iAnimation); - for(size_t iFrame = 0; iFrame < iFrameCount; ++iFrame) - { - wxImage imgCanvas; - th_frame_t* pFrame = m_oAnims.getFrameStruct(iAnimation,iFrame); - outputXml.WriteString(wxString::Format(L"\t\n", - iFrameCountTotal, iListIndex, pFrame->width, pFrame->height, pFrame->flags, pFrame->next)); - - wxSize oSize; - m_oAnims.writeElementData(aPath, &outputLog, &outputXml, iAnimation, iFrame, &m_mskLayers, oSize, &iListIndex); - - if( bWriteFrames && oSize.x > 0 && oSize.y > 0 ) - { - if(!imgCanvas.IsOk()) - { - imgCanvas.Create(oSize.x, oSize.y, true); - if(!imgCanvas.HasAlpha()) - { - imgCanvas.SetAlpha(); - } - for(int iX = 0; iX < oSize.x; ++iX) - { - for(int iY = 0; iY < oSize.y; ++iY) - { - //set completely transparent - imgCanvas.SetAlpha(iX,iY,(unsigned char)0); - } - } - } - - m_oAnims.drawFrame(imgCanvas, iAnimation, iFrame, &m_mskLayers, oSize, 0, 0); - outputLog.WriteString(wxString::Format(L"%s\t%u\t%u\t%u\t%u\t%u\n", L"VSPR-0", iAnimation, iFrame, - oSize.x, oSize.y, m_oAnims.getUnknownField(iAnimation))); - } - - outputXml.WriteString(wxString::Format(L"\t\n")); - iFrameCountTotal++; - - if( bWriteFrames && imgCanvas.IsOk() ) - { - if(!imgCanvas.SaveFile(aiPath + wxString::Format(L"a%u_f%u.png", iAnimation, iFrame),wxBITMAP_TYPE_PNG)) - return; - imgCanvas.Destroy(); - } - } - outputXml.WriteString(wxString::Format(L"\n")); - iAnimationCount++; - } - } - //outputXml.WriteString(wxString::Format(L"\t\n", - // iAnimationCount, iFrameCount, iElementCount, iSpriteCount)); - outputXml.WriteString(wxString::Format(L"\n")); - - //Sprite sheet code for Data directory - exportSpritesPage(false, sdPath, L"MONEY01V"); - exportSpritesPage(false, sdPath, L"MPOINTER"); - exportSpritesPage(true, sdPath, L"PANEL02V"); - exportSpritesPage(true, sdPath, L"PANEL04V"); - exportSpritesPage(true, sdPath, L"PULLDV"); - exportSpritesPage(false, sdPath, L"VBLK-0"); - exportSpritesPage(true, sdPath, L"WATCH01V"); - //Skip DataM directory because it appears to be low-res versions of same - - //Sprite sheet code for QData directory - wxString sqPath = _getCaseSensitivePath(L"QDATA", sPath); - sqPath += wxFileName::GetPathSeparator(); - exportSpritesPage(true, sqPath, L"AWARD03V", L"", L"AWARD02V.PAL"); - exportSpritesPage(true, sqPath, L"BANK02V", L"", L"BANK01V.PAL"); - exportSpritesPage(true, sqPath, L"DRUGN02V", L"", L"DRUGN01V.PAL"); - exportSpritesPage(true, sqPath, L"FAME02V", L"", L"FAME01V.PAL"); - exportSpritesPage(true, sqPath, L"FAX02V", L"", L"FAX01V.PAL"); - exportSpritesPage(false, sqPath, L"FONT00V", sdPath); - exportSpritesPage(false, sqPath, L"FONT01V", sdPath); - exportSpritesPage(false, sqPath, L"FONT02V", sdPath); - exportSpritesPage(false, sqPath, L"FONT04V", sdPath); - exportSpritesPage(false, sqPath, L"FONT05V", sdPath); - exportSpritesPage(false, sqPath, L"FONT09V", sdPath); - exportSpritesPage(false, sqPath, L"FONT16V", sdPath); - exportSpritesPage(false, sqPath, L"FONT18V", sdPath); - exportSpritesPage(false, sqPath, L"FONT19V", sdPath); - exportSpritesPage(false, sqPath, L"FONT24V", sdPath); - exportSpritesPage(false, sqPath, L"FONT25V", sdPath); - exportSpritesPage(false, sqPath, L"FONT26V", sdPath); - exportSpritesPage(false, sqPath, L"FONT31V", sdPath); - exportSpritesPage(false, sqPath, L"FONT34V", sdPath); - exportSpritesPage(false, sqPath, L"FONT35V", sdPath); - exportSpritesPage(false, sqPath, L"FONT36V", sdPath); - exportSpritesPage(false, sqPath, L"FONT37V", sdPath); - exportSpritesPage(false, sqPath, L"FONT38V", sdPath); - exportSpritesPage(false, sqPath, L"FONT39V", sdPath); - exportSpritesPage(false, sqPath, L"FONT40V", sdPath); - exportSpritesPage(false, sqPath, L"FONT43V", sdPath); - exportSpritesPage(false, sqPath, L"FONT44V", sdPath); - exportSpritesPage(false, sqPath, L"FONT45V", sdPath); - exportSpritesPage(false, sqPath, L"FONT46V", sdPath); - exportSpritesPage(false, sqPath, L"FONT47V", sdPath); - exportSpritesPage(false, sqPath, L"FONT50V", sdPath); - exportSpritesPage(false, sqPath, L"FONT51V", sdPath); - exportSpritesPage(false, sqPath, L"FONT60V", sdPath); - exportSpritesPage(false, sqPath, L"FONT74V", sdPath); - exportSpritesPage(false, sqPath, L"FONT100V", sdPath); - exportSpritesPage(false, sqPath, L"FONT101V", sdPath); - exportSpritesPage(false, sqPath, L"FONT102V", sdPath); - exportSpritesPage(false, sqPath, L"FONT105V", sdPath); - exportSpritesPage(false, sqPath, L"FONT106V", sdPath); - exportSpritesPage(false, sqPath, L"FONT110V", sdPath); - exportSpritesPage(false, sqPath, L"FONT111V", sdPath); - exportSpritesPage(false, sqPath, L"FONT112V", sdPath); - exportSpritesPage(false, sqPath, L"FONT113V", sdPath); - exportSpritesPage(false, sqPath, L"FONT115V", sdPath); - exportSpritesPage(false, sqPath, L"FONT120V", sdPath); - exportSpritesPage(false, sqPath, L"FONT121V", sdPath); - exportSpritesPage(false, sqPath, L"FONT122V", sdPath); - exportSpritesPage(false, sqPath, L"FONT124V", sdPath); - exportSpritesPage(false, sqPath, L"FONT250V", sdPath); - exportSpritesPage(false, sqPath, L"FONT502V", sdPath); - exportSpritesPage(true, sqPath, L"GRAPH02V", L"", L"GRAPH01V.PAL"); - exportSpritesPage(true, sqPath, L"LETTR02V", L"", L"REP01V.PAL"); - exportSpritesPage(true, sqPath, L"LOAD02V", L"", L"LOAD01V.PAL"); - exportSpritesPage(true, sqPath, L"MAIN02M", L"", L"MAIN01M.PAL"); - exportSpritesPage(true, sqPath, L"POL02V", L"", L"POL01V.PAL"); - exportSpritesPage(true, sqPath, L"PREF02V", L"", L"PREF01V.PAL"); - exportSpritesPage(true, sqPath, L"REP02V", L"", L"REP01V.PAL"); - //exportSpritesPage(true, sqPath, L"REQ00V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ01V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ02V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ03V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ04V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ05V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ06V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ09V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ10V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ11V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ12V", sdPath); - //exportSpritesPage(true, sqPath, L"REQ13V", sdPath); - exportSpritesPage(true, sqPath, L"RES02V", L"", L"RES01V.PAL"); - exportSpritesPage(true, sqPath, L"REP02V", L"", L"REP01V.PAL"); - exportSpritesPage(true, sqPath, L"SPOINTER", sdPath); - exportSpritesPage(true, sqPath, L"STAFF02V", L"", L"STAFF01V.PAL"); - exportSpritesPage(true, sqPath, L"STAT02V", L"", L"STAT01V.PAL"); - exportSpritesPage(true, sqPath, L"TOWN02V", L"", L"TOWN01V.PAL"); - exportSpritesPage(true, sqPath, L"VER00V", L"", L"REP01V.PAL"); - } -} - -void frmMain::exportSpritesPage(bool bComplex, wxString sPath, wxString sFilename, wxString spPath, wxString sPalette) -{ - if(spPath.length() == 0) - { - spPath = sPath; - } - if(!m_oAnims.loadTableFile(_getCaseSensitivePath(wxString::Format(L"%s.TAB",sFilename.wx_str()), sPath)) - ||!m_oAnims.loadSpriteFile(_getCaseSensitivePath(wxString::Format(L"%s.DAT",sFilename.wx_str()), sPath)) - ||!m_oAnims.loadPaletteFile(_getCaseSensitivePath(sPalette, spPath))) - { - return; - } - - wxFile f(_getCaseSensitivePath(sFilename + L"export.log", sPath), wxFile::write); - wxFileOutputStream fos(f); - wxTextOutputStream outputLog(fos); - outputLog.WriteString(wxString::Format(L"File\tIndex\tPalette\tComplex\tWidth\tHeight\n")); - - wxString aPath = _getCaseSensitivePath(sFilename, sPath); - aPath += wxFileName::GetPathSeparator(); - if(!wxFileName::DirExists(aPath)) - { - wxFileName::Mkdir(aPath); - for(size_t i = 0; i < m_oAnims.getSpriteCount(); ++i) - { - Bitmap* pSpriteBitmap = m_oAnims.getSpriteBitmap(i, bComplex); - if(pSpriteBitmap->getWidth() * pSpriteBitmap->getHeight() > 0) - { - wxImage imgSprite(pSpriteBitmap->getWidth(), pSpriteBitmap->getHeight(), false); - pSpriteBitmap->blit(imgSprite, 0, 0, NULL, m_oAnims.getPalette(), 0x8000); - if(!imgSprite.HasAlpha()) - { - imgSprite.SetAlpha(); - } - for(int iX = 0; iX < pSpriteBitmap->getWidth(); ++iX) - { - for(int iY = 0; iY < pSpriteBitmap->getHeight(); ++iY) - { - if(imgSprite.GetRed(iX,iY) == 255 && imgSprite.GetBlue(iX,iY) == 255) { - imgSprite.SetAlpha(iX,iY,(unsigned char)0); - } else { - imgSprite.SetAlpha(iX,iY,(unsigned char)255); - } - } - } - if(!imgSprite.SaveFile(_getCaseSensitivePath(wxString::Format(L"s%u.png", i), aPath),wxBITMAP_TYPE_PNG)) - return; - outputLog.WriteString(wxString::Format(L"%s\t%u\t%s\t%u\t%u\n", sFilename.wx_str(), i, sPalette.wx_str(), pSpriteBitmap->getWidth(),pSpriteBitmap->getHeight())); - } - } - } -} - void frmMain::_onToggleMask(wxCommandEvent& evt) { int iID = evt.GetId() - ID_LAYER_CHECKS; diff -Nru corsix-th-0.61/AnimView/frmSprites.cpp corsix-th-0.62/AnimView/frmSprites.cpp --- corsix-th-0.61/AnimView/frmSprites.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/frmSprites.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -194,16 +194,16 @@ void frmSprites::_onBrowseTable(wxCommandEvent& WXUNUSED(evt)) { m_txtTable->SetValue(::wxFileSelector(L"Select location of Font00V.tab (DATA)", - m_txtTable->GetValue(),L"Font00V.tab",L"tab",L"Tab files (*.tab)|*.tab" + m_txtTable->GetValue(),L"Font00V.tab",L"tab",L"Tab files (*.tab)|*.[tT][aA][bB]" ,0, this)); } void frmSprites::_onBrowseData(wxCommandEvent& WXUNUSED(evt)) { m_txtData->SetValue(::wxFileSelector(L"Choose Theme Hospital data file", - m_txtData->GetValue(),L"",L"dat",L"Dat files (*.dat)|*.dat", 0, this)); + m_txtData->GetValue(),L"",L"dat",L"Dat files (*.dat)|*.[dD][aA][tT]", 0, this)); } void frmSprites::_onBrowsePalette(wxCommandEvent& WXUNUSED(evt)) { m_txtPalette->SetValue(::wxFileSelector(L"Select location of MPalette.dat (QDATA)", - m_txtPalette->GetValue(),L"MPalette.dat",L"dat",L"Dat or Pal files (*.dat, *.pal)|*.dat;*.pal", 0, this)); + m_txtPalette->GetValue(),L"MPalette.dat",L"dat",L"Dat or Pal files (*.dat, *.pal)|*.[dD][aA][tT];*.[pP][aA][lL]", 0, this)); } diff -Nru corsix-th-0.61/AnimView/rnc.cpp corsix-th-0.62/AnimView/rnc.cpp --- corsix-th-0.61/AnimView/rnc.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/rnc.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,433 +0,0 @@ -/* - RNC decompression library. - - Original code was from http://www.yoda.arachsys.com/dk/utils.html, - which links to http://www.yoda.arachsys.com/dk/utilsrc.zip - which itself includes this LICENSE.TXT: - -The MIT License (MIT) - -Copyright (c) 2009 Jon Skeet, Simon Tatham - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the"Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - Modifications made to the original code include: - * Const correctness - * Prebuilt CRC table - * Indentation and code style -*/ - -#include "th.h" - -#define RNC_OK 0 -#define RNC_FILE_IS_NOT_RNC -1 -#define RNC_HUF_DECODE_ERROR -2 -#define RNC_FILE_SIZE_MISMATCH -3 -#define RNC_PACKED_CRC_ERROR -4 -#define RNC_UNPACKED_CRC_ERROR -5 -#define RNC_SIGNATURE 0x524E4301 /* "RNC\001" */ - -static const unsigned short rnc_crc_table[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, -}; - -struct bit_stream -{ - unsigned long bitbuf; /* holds between 16 and 32 bits */ - int bitcount; /* how many bits does bitbuf hold? */ -}; - -struct huf_table -{ - int num; /* number of nodes in the tree */ - struct - { - unsigned long code; - int codelen; - int value; - } table[32]; -}; - -/* - * Calculate a CRC, the RNC way. - */ -static long rnc_crc(const unsigned char* data, long len) -{ - unsigned short val = 0; - - while(len--) - { - val ^= *data++; - val = (val >> 8) ^ rnc_crc_table[val & 0xFF]; - } - - return val; -} - - -/* - * Return the big-endian longword at p. - */ -static unsigned long blong (const unsigned char *p) -{ - unsigned long n; - n = p[0]; - n = (n << 8) + p[1]; - n = (n << 8) + p[2]; - n = (n << 8) + p[3]; - return n; -} - -/* - * Return the little-endian longword at p. - */ -static unsigned long llong (const unsigned char *p) -{ - unsigned long n; - n = p[3]; - n = (n << 8) + p[2]; - n = (n << 8) + p[1]; - n = (n << 8) + p[0]; - return n; -} - -/* - * Return the big-endian word at p. - */ -static unsigned long bword (const unsigned char *p) -{ - unsigned long n; - n = p[0]; - n = (n << 8) + p[1]; - return n; -} - -/* - * Return the little-endian word at p. - */ -static unsigned long lword (const unsigned char *p) -{ - unsigned long n; - n = p[1]; - n = (n << 8) + p[0]; - return n; -} - -/* - * Mirror the bottom n bits of x. - */ -static unsigned long mirror (unsigned long x, int n) -{ - unsigned long top = 1 << (n-1), bottom = 1; - while (top > bottom) - { - unsigned long mask = top | bottom; - unsigned long masked = x & mask; - if (masked != 0 && masked != mask) - { - x ^= mask; - } - top >>= 1; - bottom <<= 1; - } - return x; -} - - -/* - * Initialises a bit stream with the first two bytes of the packed - * data. - */ -static void bitread_init (bit_stream *bs, const unsigned char **p) -{ - bs->bitbuf = lword (*p); - bs->bitcount = 16; -} - -/* - * Fixes up a bit stream after literals have been read out of the - * data stream. - */ -static void bitread_fix (bit_stream *bs, const unsigned char **p) -{ - bs->bitcount -= 16; - bs->bitbuf &= (1<bitcount)-1; /* remove the top 16 bits */ - bs->bitbuf |= (lword(*p)<bitcount);/* replace with what's at *p */ - bs->bitcount += 16; -} - -/* - * Returns some bits. - */ -static unsigned long bit_peek (bit_stream *bs, const unsigned long mask) -{ - return bs->bitbuf & mask; -} - -/* - * Advances the bit stream. - */ -static void bit_advance (bit_stream *bs, int n, const unsigned char **p) -{ - bs->bitbuf >>= n; - bs->bitcount -= n; - if (bs->bitcount < 16) - { - (*p) += 2; - bs->bitbuf |= (lword(*p)<bitcount); - bs->bitcount += 16; - } -} - -/* - * Reads some bits in one go (ie the above two routines combined). - */ -static unsigned long bit_read (bit_stream *bs, unsigned long mask, int n, const unsigned char **p) -{ - unsigned long result = bit_peek(bs, mask); - bit_advance(bs, n, p); - return result; -} - -/* - * Read a Huffman table out of the bit stream and data stream given. - */ -static void read_huftable(huf_table *h, bit_stream *bs, const unsigned char **p) -{ - int i, j, k, num; - int leaflen[32]; - int leafmax; - unsigned long codeb; /* big-endian form of code */ - - num = bit_read(bs, 0x1F, 5, p); - - if(num == 0) - { - return; - } - - leafmax = 1; - for(i = 0; i < num; i++) - { - leaflen[i] = bit_read(bs, 0x0F, 4, p); - if (leafmax < leaflen[i]) - { - leafmax = leaflen[i]; - } - } - - codeb = 0L; - k = 0; - for(i = 1; i <= leafmax; i++) - { - for(j = 0; j < num; j++) - { - if(leaflen[j] == i) - { - h->table[k].code = mirror(codeb, i); - h->table[k].codelen = i; - h->table[k].value = j; - codeb++; - k++; - } - } - codeb <<= 1; - } - h->num = k; -} - -/* - * Read a value out of the bit stream using the given Huffman table. - */ -static unsigned long huf_read(huf_table *h, bit_stream *bs, const unsigned char **p) -{ - int i; - unsigned long val; - - for (i = 0; i < h->num; i++) - { - unsigned long mask = (1 << h->table[i].codelen) - 1; - if(bit_peek(bs, mask) == h->table[i].code) - { - break; - } - } - if(i == h->num) - { - return -1; - } - bit_advance(bs, h->table[i].codelen, p); - - val = h->table[i].value; - - if (val >= 2) - { - val = 1 << (val-1); - val |= bit_read(bs, val-1, h->table[i].value - 1, p); - } - return val; -} - -static int rnc_unpack(const unsigned char* input, unsigned char* output) -{ - const unsigned char *inputend; - unsigned char *outputend; - bit_stream bs; - huf_table raw, dist, len; - unsigned long ch_count; - unsigned long ret_len; - unsigned out_crc; - if(blong(input) != RNC_SIGNATURE) - { - return RNC_FILE_IS_NOT_RNC; - } - ret_len = blong(input + 4); - outputend = output + ret_len; - inputend = input + 18 + blong(input + 8); - - input += 18; /* skip header */ - - /* - * Check the packed-data CRC. Also save the unpacked-data CRC - * for later. - */ - if(rnc_crc(input, inputend-input) != bword(input - 4)) - { - return RNC_PACKED_CRC_ERROR; - } - out_crc = bword(input - 6); - - bitread_init(&bs, &input); - bit_advance(&bs, 2, &input); /* discard first two bits */ - - /* - * Process chunks. - */ - while (output < outputend) - { - read_huftable(&raw, &bs, &input); - read_huftable(&dist, &bs, &input); - read_huftable(&len, &bs, &input); - ch_count = bit_read(&bs, 0xFFFF, 16, &input); - - while(true) - { - long length, posn; - - length = huf_read(&raw, &bs, &input); - if(length == -1) - { - return RNC_HUF_DECODE_ERROR; - } - if(length) - { - while(length--) - *output++ = *input++; - bitread_fix(&bs, &input); - } - if(--ch_count <= 0) - { - break; - } - - posn = huf_read(&dist, &bs, &input); - if(posn == -1) - { - return RNC_HUF_DECODE_ERROR; - } - length = huf_read(&len, &bs, &input); - if(length == -1) - { - return RNC_HUF_DECODE_ERROR; - } - posn += 1; - length += 2; - while(length--) - { - *output = output[-posn]; - output++; - } - } - } - - if(outputend != output) - { - return RNC_FILE_SIZE_MISMATCH; - } - - /* - * Check the unpacked-data CRC. - */ - if(rnc_crc(outputend - ret_len, ret_len) != out_crc) - { - return RNC_UNPACKED_CRC_ERROR; - } - - return RNC_OK; -} - -unsigned char* THAnimations::Decompress(unsigned char* pData, size_t& iLength) -{ - unsigned long outlen = blong(pData + 4); - unsigned char* outbuf = new unsigned char[outlen]; - if(rnc_unpack(pData, outbuf) == RNC_OK) - { - delete[] pData; - iLength = outlen; - return outbuf; - } - else - { - delete[] pData; - delete[] outbuf; - iLength = 0; - return NULL; - } -} diff -Nru corsix-th-0.61/AnimView/th.cpp corsix-th-0.62/AnimView/th.cpp --- corsix-th-0.61/AnimView/th.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/th.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -21,10 +21,14 @@ */ #include "th.h" +#include "../common/rnc.h" #include #include #include -#include +#include +#include +#include +#include #include static const unsigned char palette_upscale_map[0x40] = { @@ -228,50 +232,33 @@ THAnimations::THAnimations() { - m_pAnims = NULL; - m_pFrames = NULL; - m_pElementList = NULL; - m_pElements = NULL; - m_pSprites = NULL; - m_pSpriteBitmaps = NULL; - m_pChunks = NULL; - m_pColours = NULL; - m_pGhostMaps = new unsigned char[256 * 256 * 4]; + anims = std::vector(); + frames = std::vector(); + elementList = std::vector(); + elements = std::vector(); + sprites = std::vector(); + spriteBitmaps = std::vector(); + chunks = std::vector(); + colours = std::vector(); + ghostMaps = std::array(); for(int iMap = 0; iMap < 256 * 4; ++iMap) { for(int iCol = 0; iCol < 256; ++iCol) { - m_pGhostMaps[iMap * 256 + iCol] = iCol; + ghostMaps[iMap * 256 + iCol] = iCol; } } m_iGhostMapOffset = 0; - m_iAnimCount = 0; - m_iFrameCount = 0; - m_iElementListCount = 0; - m_iElementCount = 0; - m_iSpriteCount = 0; - m_iChunkCount = 0; - m_iColourCount = 0; - m_bXmlLoaded = false; } THAnimations::~THAnimations() { - delete[] m_pAnims; - delete[] m_pFrames; - delete[] m_pElementList; - delete[] m_pElements; - delete[] m_pSprites; - delete[] m_pSpriteBitmaps; - delete[] m_pChunks; - delete[] m_pColours; - delete[] m_pGhostMaps; } bool THAnimations::isAnimationDuplicate(size_t iAnimation) { - if(iAnimation < m_iAnimCount) - return m_pAnims[iAnimation].unknown == 1; + if(iAnimation < anims.size()) + return anims.at(iAnimation).unknown == 1; else return true; } @@ -280,20 +267,22 @@ { size_t iNonDuplicateCount = 0; - std::map mapSeen; - for(size_t i = 0; i < m_iAnimCount; ++i) + std::set seen; + for(th_anim_t& anim : anims) { - uint16_t iFrame = m_pAnims[i].frame; + uint16_t iFrame = anim.frame; uint16_t iFirstFrame = iFrame; do { - if(mapSeen[iFrame]) - m_pAnims[i].unknown = 1; - else - mapSeen[iFrame] = true; - iFrame = m_pFrames[iFrame].next; + if(seen.find(iFrame) != seen.end()) { + anim.unknown = 1; + } else { + seen.insert(iFrame); + } + iFrame = frames.at(iFrame).next; } while(iFrame != iFirstFrame); - if(m_pAnims[i].unknown == 0) + + if(anim.unknown == 0) { ++iNonDuplicateCount; } @@ -304,7 +293,7 @@ bool THAnimations::loadFrameFile(wxString sFilename) { - if(!_loadArray(m_pFrames, m_iFrameCount, sFilename)) + if(!loadVector(frames, sFilename)) return false; /* @@ -312,262 +301,28 @@ The lower byte can also take non-zero values - could be ghost palette indices. */ - /* - FILE *f = fopen("E:\\list.txt", "wt"); - for(size_t i = 0; i < m_iFrameCount; ++i) - { - if(m_pFrames[i].flags != 0) - { - fprintf(f, "%i, %i,\n", (int)i, (int)m_pFrames[i].flags); - } - } - fclose(f); - */ return true; } bool THAnimations::loadTableFile(wxString sFilename) { - delete[] m_pSpriteBitmaps; - m_pSpriteBitmaps = 0; - if(!_loadArray(m_pSprites, m_iSpriteCount, sFilename)) + spriteBitmaps.clear(); + if(!loadVector(sprites, sFilename)) return false; - m_pSpriteBitmaps = new Bitmap[m_iSpriteCount]; + spriteBitmaps.resize(sprites.size()); return true; } -bool THAnimations::loadXMLFile(TiXmlDocument* xmlDocument) -{ - TiXmlHandle hDoc(xmlDocument); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - //navigate to - pElem=hDoc.FirstChildElement().Element(); - hRoot=TiXmlHandle(pElem); - - //count elements - int iAnimation = 0; - pElem=pElem->LastChild()->ToElement(); - pElem->QueryIntAttribute("id",&iAnimation); - m_pAnims = new th_anim_t[iAnimation]; - - for( int i=0; i <= iAnimation; i++ ) - { - m_pAnims[i].unknown = 1; - m_pAnims[i].frame = 1; - } - //temporary hacks to avoid complicated allocation, the only drawback is that reducing - //element count won't automatically reduce memory consumption, and increasing element - //count might require a recompile. - m_iAnimCount = iAnimation+1; - m_iFrameCount = 11642; - m_iElementListCount = 185864; - m_iElementCount = 26557; - m_iSpriteCount = 4399; - m_pFrames = new th_frame_t[m_iFrameCount]; - m_pElementList = new uint16_t[m_iElementListCount]; - m_pElements = new th_element_t[m_iElementCount]; - std::vector tmp_elementMap(m_iElementListCount, 0); - m_pSprites = new th_sprite_t[m_iSpriteCount]; - m_pSpriteImages = new wxImage[m_iSpriteCount]; - m_pSpriteScaleFactors = new uint8_t[m_iSpriteCount]; - //navigate to first element - pElem=hRoot.FirstChild( "an" ).Element(); - //pElem->QueryIntAttribute("id",&iAnimation); - iAnimation = 0; - int iFrame = 0; - int tmpInteger = 0; - int iNewListIndex = 0; - int iOldElementCount = 0; - int iNewElementCount = 0; - int iOldElement = 0; - m_pFrames[0].list_index = 0; - m_pFrames[0].width = 0; - m_pFrames[0].height = 0; - m_pFrames[0].flags = 0; - m_pFrames[0].next = 0; - for( pElem; pElem; pElem=pElem->NextSiblingElement()) - { - pElem->QueryIntAttribute("id",&iAnimation); - pElem->QueryIntAttribute("fr",&iFrame); - m_pAnims[iAnimation].frame = iFrame; - m_pAnims[iAnimation].unknown = 0; - TiXmlElement* pFrameElement = pElem->FirstChildElement("fr"); - for( pFrameElement; pFrameElement; pFrameElement=pFrameElement->NextSiblingElement()) - { - pFrameElement->QueryIntAttribute("id",&iFrame); - //ignore original frame indexes, they are only for looking up "first elements" - //pFrameElement->QueryIntAttribute("li",&iListIndex); - //m_pElementList[iListIndex] = iFrame; - if(iFrame < m_iFrameCount) { - m_pFrames[iFrame].list_index = iNewListIndex; - pFrameElement->QueryIntAttribute("w",&tmpInteger); - m_pFrames[iFrame].width=tmpInteger; - pFrameElement->QueryIntAttribute("h",&tmpInteger); - m_pFrames[iFrame].height=tmpInteger; - pFrameElement->QueryIntAttribute("fl",&tmpInteger); - m_pFrames[iFrame].flags=tmpInteger; - pFrameElement->QueryIntAttribute("nx",&tmpInteger); - m_pFrames[iFrame].next=tmpInteger; - TiXmlElement* pElementElement = pFrameElement->FirstChildElement("el"); - for( pElementElement; pElementElement; pElementElement=pElementElement->NextSiblingElement()) - { - int iNewElement = 0; - pElementElement->QueryIntAttribute("id",&iOldElement); - //complex mapping of original element ids to new sequential id system - if(iOldElement < iOldElementCount) { - //this is a re-used element id from the old numbering system, so look up the new element id - //in the new numbering system. - iNewElement = tmp_elementMap.at(iOldElement); - } else { - if( iNewElementCount < m_iElementCount ) - { - tmp_elementMap[iOldElement] = iNewElementCount; - iOldElementCount = iOldElement + 1; - iNewElement = iNewElementCount; - iNewElementCount++; - //new fill fields in the new element - pElementElement->QueryIntAttribute("fl",&tmpInteger); - m_pElements[iNewElement].flags = tmpInteger; - pElementElement->QueryIntAttribute("ox",&tmpInteger); - m_pElements[iNewElement].offx = tmpInteger; - pElementElement->QueryIntAttribute("oy",&tmpInteger); - m_pElements[iNewElement].offy = tmpInteger; - //pElementElement->QueryIntAttribute("tb",&tmpInteger); - //m_pElements[iNewElement].table_position = tmpInteger; - pElementElement->QueryIntAttribute("ly",&tmpInteger); - m_pElements[iNewElement].layerid = tmpInteger; - int iSprite = 0; - pElementElement->QueryIntAttribute("sp",&iSprite); - if(iSprite < m_iSpriteCount) - { - //set table position to Sprite ID * 6 (sizeof th_sprite_t) - m_pElements[iNewElement].table_position = iSprite*6; - //zero means "attribute found", 1 means "no such attribute" - if(pElementElement->QueryIntAttribute("sf",&tmpInteger) == 0) - { - m_pSpriteScaleFactors[iSprite] = tmpInteger; - pElementElement->QueryIntAttribute("w",&tmpInteger); - m_pSprites[iSprite].width = tmpInteger/m_pSpriteScaleFactors[iSprite]; - pElementElement->QueryIntAttribute("h",&tmpInteger); - m_pSprites[iSprite].height = tmpInteger/m_pSpriteScaleFactors[iSprite]; - } else { - m_pSpriteScaleFactors[iSprite] = 1; - pElementElement->QueryIntAttribute("w",&tmpInteger); - m_pSprites[iSprite].width = tmpInteger; - pElementElement->QueryIntAttribute("h",&tmpInteger); - m_pSprites[iSprite].height = tmpInteger; - } - pElementElement->QueryIntAttribute("of",&tmpInteger); - m_pSprites[iSprite].offset = tmpInteger; - } - } - } - m_pElementList[iNewListIndex] = iNewElement; - iNewListIndex++; - if(iNewListIndex >= m_iElementListCount) - break; - } - m_pElementList[iNewListIndex] = 65535; - iNewListIndex++; - if(iNewListIndex >= m_iElementListCount) - break; - } - } - } - - m_bXmlLoaded = true; - return m_bXmlLoaded; -} - -void THAnimations::writeElementData(wxString aPath, wxTextOutputStream *outputLog, wxTextOutputStream *outputXml, - size_t iAnimation, size_t iFrame, const THLayerMask* pMask, wxSize& size, int *iListIndex) -{ - if(iAnimation >= m_iAnimCount) - return; - uint16_t iFrameIndex = m_pAnims[iAnimation].frame; - while(iFrame--) - { - iFrameIndex = m_pFrames[iFrameIndex].next; - } - - th_frame_t* pFrame = m_pFrames + iFrameIndex; - th_element_t* pElement; - uint32_t iOldListIndex = pFrame->list_index; - int iFarX = 0; - int iFarY = 0; - int iNewListIndex = *iListIndex; - - while((pElement = _getElement(iOldListIndex))) - { - if(pElement->flags >> 4 != 1) - { - uint16_t iElementIndex = m_pElementList[iOldListIndex]; - outputXml->WriteString(wxString::Format(L"\t\ttable_position, pElement->flags, pElement->offx, pElement->offy, pElement->layerid )); - uint16_t iSpriteIndex = pElement->table_position / sizeof(th_sprite_t); - wxString spriteFile = aPath + wxString::Format(L"a%04ue.png", iSpriteIndex); - - th_sprite_t* pSprite = m_pSprites + iSpriteIndex; - int iRight = pElement->offx + pSprite->width; - int iBottom = pElement->offy + pSprite->height; - if(iRight > iFarX) - iFarX = iRight; - if(iBottom > iFarY) - iFarY = iBottom; - //if(pMask != NULL && !pMask->isSet(pElement->flags >> 4, pElement->layerid)) - // continue; - outputXml->WriteString(wxString::Format(L"sp='%u' of='%u' w='%u' h='%u'/>\n", - iSpriteIndex, pSprite->offset, pSprite->width, pSprite->height )); - if(!wxFileName::FileExists(spriteFile) && pSprite->width > 0 && pSprite->height > 0) - { - wxImage imgSprite(pSprite->width, pSprite->height, true); - if(!imgSprite.HasAlpha()) - { - imgSprite.SetAlpha(); - } - for(int iX = 0; iX < pSprite->width; ++iX) - { - for(int iY = 0; iY < pSprite->height; ++iY) - { - imgSprite.SetAlpha(iX,iY,(unsigned char)0); - } - } - //ignore element "mirroring" flags, they will cause the sprite to be written mirrored and then that sprite - //will mirrored again when loaded later. - getSpriteBitmap(iSpriteIndex)->blit(imgSprite, 0, 0, m_pGhostMaps + m_iGhostMapOffset, m_pColours, 0 & 0xF); - if(!imgSprite.SaveFile(spriteFile,wxBITMAP_TYPE_PNG)) - return; - outputLog->WriteString(wxString::Format(L"E%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\n", iSpriteIndex, - pElement->table_position, pElement->flags, pElement->layerid, pElement->offx, pElement->offy, - iNewListIndex, sizeof(th_sprite_t), pSprite->width, pSprite->height, pSprite->offset)); - } - iNewListIndex++; - } - iOldListIndex++; - } - size.x = iFarX; - size.y = iFarY; - *iListIndex = iNewListIndex; - -} - -void THAnimations::writeTableDataHeader(wxTextOutputStream *outputLog) -{ - outputLog->WriteString(wxString::Format(L"Element\tTablePos\tFlags\tLayerID\tXoff\tYoff\tListIndex\tSpriteSize\tWidth\tHeight\tOffset\n")); -} - bool THAnimations::loadPaletteFile(wxString sFilename) { - if(!_loadArray(m_pColours, m_iColourCount, sFilename)) + if (!loadVector(colours, sFilename)) return false; - for(size_t i = 0; i < m_iColourCount; ++i) + for (th_colour_t& colour : colours) { - m_pColours[i].r = palette_upscale_map[m_pColours[i].r & 0x3F]; - m_pColours[i].g = palette_upscale_map[m_pColours[i].g & 0x3F]; - m_pColours[i].b = palette_upscale_map[m_pColours[i].b & 0x3F]; + colour.r = palette_upscale_map[colour.r & 0x3F]; + colour.g = palette_upscale_map[colour.g & 0x3F]; + colour.b = palette_upscale_map[colour.b & 0x3F]; } return true; } @@ -577,20 +332,16 @@ if(iIndex < 0 || iIndex >= 4) return false; - unsigned char *pData = NULL; - size_t iDataLen; + std::vector data; - if(!_loadArray(pData, iDataLen, sFilename)) + if (!loadVector(data, sFilename)) return false; - if(iDataLen != 256 * 256) - { - delete[] pData; + if (data.size() != 256 * 256) { return false; } - memcpy(m_pGhostMaps + iIndex * 256 * 256, pData, 256 * 256); - delete[] pData; + std::copy(data.begin(), data.end(), ghostMaps.begin() + iIndex * 256 * 256); return true; } @@ -601,12 +352,12 @@ size_t THAnimations::getAnimationCount() { - return m_iAnimCount; + return anims.size(); } size_t THAnimations::getSpriteCount() { - return m_iSpriteCount; + return sprites.size(); } void THAnimations::setSpritePath(wxString aPath) @@ -617,41 +368,41 @@ void THAnimations::getAnimationMask(size_t iAnimation, THLayerMask& mskLayers) { mskLayers.clear(); - if(iAnimation >= m_iAnimCount) + if(iAnimation >= anims.size()) return; - uint16_t iFrameIndex = m_pAnims[iAnimation].frame; - if(iFrameIndex >= m_iFrameCount) + uint16_t iFrameIndex = anims.at(iAnimation).frame; + if(iFrameIndex >= frames.size()) return; uint16_t iFirstFrameIndex = iFrameIndex; do { - th_frame_t* pFrame = m_pFrames + iFrameIndex; + th_frame_t* pFrame = &(frames.at(iFrameIndex)); uint32_t iListIndex = pFrame->list_index; th_element_t* pElement; while((pElement = _getElement(iListIndex++))) { mskLayers.set(pElement->flags >> 4, pElement->layerid); } - iFrameIndex = m_pFrames[iFrameIndex].next; - } while(iFrameIndex != iFirstFrameIndex); + iFrameIndex = frames.at(iFrameIndex).next; + } while(iFrameIndex < frames.size() && iFrameIndex != iFirstFrameIndex); } size_t THAnimations::getFrameCount(size_t iAnimation) { - if(iAnimation >= m_iAnimCount) + if(iAnimation >= anims.size()) return 0; size_t iCount = 0; - uint16_t iFirstFrame = m_pAnims[iAnimation].frame; - if(iFirstFrame < m_iFrameCount) + uint16_t iFirstFrame = anims.at(iAnimation).frame; + if(iFirstFrame < frames.size()) { ++iCount; - uint16_t iFrame = m_pFrames[iFirstFrame].next; - while(iFrame != iFirstFrame && iFrame < m_iFrameCount && iCount < 1024) + uint16_t iFrame = frames.at(iFirstFrame).next; + while(iFrame != iFirstFrame && iFrame < frames.size() && iCount < 1024) { ++iCount; - iFrame = m_pFrames[iFrame].next; + iFrame = frames.at(iFrame).next; } } return iCount; @@ -659,69 +410,62 @@ bool THAnimations::doesAnimationIncludeFrame(size_t iAnimation, size_t iFrame) { - if(iAnimation >= m_iAnimCount || iFrame >= m_iFrameCount) + if(iAnimation >= anims.size() || iFrame >= frames.size()) return 0; - uint16_t iFirstFrame = m_pAnims[iAnimation].frame; + uint16_t iFirstFrame = anims.at(iAnimation).frame; uint16_t iFrameNow = iFirstFrame; do { - if(iFrameNow >= m_iFrameCount) + if(iFrameNow >= frames.size()) break; if(iFrame == iFrameNow) return true; - iFrameNow = m_pFrames[iFrameNow].next; + iFrameNow = frames.at(iFrameNow).next; } while(iFrameNow != iFirstFrame); return false; } Bitmap* THAnimations::getSpriteBitmap(size_t iSprite, bool bComplex) { - if(iSprite >= m_iSpriteCount) - return NULL; + if(iSprite >= sprites.size()) + return nullptr; - if(!m_pSpriteBitmaps[iSprite].IsOk()) + if (!spriteBitmaps.at(iSprite).IsOk()) { wxString spriteFile = m_sSpritePath + wxString::Format(L"a%04ue.png", (int)iSprite); - th_sprite_t* pSprite = m_pSprites + iSprite; + th_sprite_t* pSprite = &(sprites.at(iSprite)); - if(m_bXmlLoaded && wxFileName::FileExists(spriteFile)) - { - wxImage imgSprite(pSprite->width, pSprite->height, true); - imgSprite.LoadFile(spriteFile,wxBITMAP_TYPE_PNG); - m_pSpriteBitmaps[iSprite].create(pSprite->width, pSprite->height, imgSprite.GetData()); - } else { - ChunkRenderer oRenderer(pSprite->width, pSprite->height); - (bComplex ? decode_chunks_complex : decode_chunks)(oRenderer, (const unsigned char*)m_pChunks + pSprite->offset, m_iChunkCount - pSprite->offset, 0xFF); - m_pSpriteBitmaps[iSprite].create(pSprite->width, pSprite->height, oRenderer.getData()); - } + ChunkRenderer oRenderer(pSprite->width, pSprite->height); + (bComplex ? decode_chunks_complex : decode_chunks)(oRenderer, (const unsigned char*)chunks.data() + pSprite->offset, chunks.size() - pSprite->offset, 0xFF); + spriteBitmaps[iSprite].create(pSprite->width, pSprite->height, oRenderer.getData()); } - return m_pSpriteBitmaps + iSprite; + return &(spriteBitmaps.at(iSprite)); } th_frame_t* THAnimations::getFrameStruct(size_t iAnimation, size_t iFrame) { - if(iAnimation >= m_iAnimCount) + if(iAnimation >= anims.size()) return 0; - uint16_t iFrameIndex = m_pAnims[iAnimation].frame; + uint16_t iFrameIndex = anims.at(iAnimation).frame; while(iFrame--) { - iFrameIndex = m_pFrames[iFrameIndex].next; + iFrameIndex = frames.at(iFrameIndex).next; } - return &m_pFrames[iFrameIndex]; + return &(frames.at(iFrameIndex)); } void THAnimations::drawFrame(wxImage& imgCanvas, size_t iAnimation, size_t iFrame, const THLayerMask* pMask, wxSize& size, int iXOffset, int iYOffset) { - if(iAnimation >= m_iAnimCount) + if(iAnimation >= anims.size()) return; - uint16_t iFrameIndex = m_pAnims[iAnimation].frame; + uint16_t iFrameIndex = anims.at(iAnimation).frame; while(iFrame--) { - iFrameIndex = m_pFrames[iFrameIndex].next; + iFrameIndex = frames.at(iFrameIndex).next; } - th_frame_t* pFrame = m_pFrames + iFrameIndex; + th_frame_t* pFrame = &(frames.at(iFrameIndex)); th_element_t* pElement; uint32_t iListIndex = pFrame->list_index; int iFarX = 0; @@ -731,89 +475,58 @@ if(pMask != NULL && !pMask->isSet(pElement->flags >> 4, pElement->layerid)) continue; uint16_t iSpriteIndex = pElement->table_position / sizeof(th_sprite_t); - th_sprite_t* pSprite = m_pSprites + iSpriteIndex; + th_sprite_t* pSprite = &(sprites.at(iSpriteIndex)); int iRight = pElement->offx + pSprite->width; int iBottom = pElement->offy + pSprite->height; if(iRight > iFarX) iFarX = iRight; if(iBottom > iFarY) iFarY = iBottom; - wxString spriteFile = m_sSpritePath + wxString::Format(L"a%04ue.png", iSpriteIndex); - if(m_bXmlLoaded && wxFileName::FileExists(spriteFile)) - { - copySpriteToCanvas(spriteFile, iSpriteIndex, imgCanvas, pElement->offx + iXOffset, pElement->offy + iYOffset, pElement->flags & 0xF); - } else { - getSpriteBitmap(iSpriteIndex)->blit(imgCanvas, pElement->offx + iXOffset, pElement->offy + iYOffset, m_pGhostMaps + m_iGhostMapOffset, m_pColours, pElement->flags & 0xF); - } + + getSpriteBitmap(iSpriteIndex)->blit(imgCanvas, pElement->offx + iXOffset, pElement->offy + iYOffset, ghostMaps.data() + m_iGhostMapOffset, colours.data(), pElement->flags & 0xF); } size.x = iFarX; size.y = iFarY; } -void THAnimations::copySpriteToCanvas(wxString spriteFile, int iSpriteIndex, wxImage& imgCanvas, int iX, int iY, int iFlags) { - if(!m_pSpriteImages[iSpriteIndex].IsOk()) - { - th_sprite_t* pSprite = m_pSprites + iSpriteIndex; - if(m_pSpriteScaleFactors[iSpriteIndex] > 1) - { - int scale = m_pSpriteScaleFactors[iSpriteIndex]; - m_pSpriteImages[iSpriteIndex].Create(pSprite->width*scale, pSprite->height*scale, true); - m_pSpriteImages[iSpriteIndex].LoadFile(spriteFile,wxBITMAP_TYPE_PNG); - m_pSpriteImages[iSpriteIndex].Rescale(pSprite->width, pSprite->height); - } else { - m_pSpriteImages[iSpriteIndex].Create(pSprite->width, pSprite->height, true); - m_pSpriteImages[iSpriteIndex].LoadFile(spriteFile,wxBITMAP_TYPE_PNG); - } - //m_pSpriteImages[iSpriteIndex].SetMaskColour(0,0,0); - if(!m_pSpriteImages[iSpriteIndex].HasAlpha()) - { - m_pSpriteImages[iSpriteIndex].InitAlpha(); - } +th_element_t* THAnimations::_getElement(uint32_t iListIndex) +{ + if(iListIndex >= elementList.size()) + return nullptr; + uint16_t iElementIndex = elementList.at(iListIndex); + if(iElementIndex >= elements.size()) + return nullptr; + return &(elements.at(iElementIndex)); +} + +unsigned char* THAnimations::Decompress(unsigned char* pData, size_t& iLength) +{ + unsigned long outlen = rnc_output_size(pData); + unsigned char* outbuf = new unsigned char[outlen]; + if (rnc_input_size(pData) != iLength) { + throw std::length_error("rnc data does not match the expected length"); } - for(int y = 0; y < m_pSpriteImages[iSpriteIndex].GetHeight(); ++y) + if(rnc_unpack(pData, outbuf) == rnc_status::ok) { - for(int x = 0; x < m_pSpriteImages[iSpriteIndex].GetWidth(); ++x) - { - int iDstX = iX + x; - int iDstY = iY + y; - if(iFlags & 0x2) - iDstY = iY + m_pSpriteImages[iSpriteIndex].GetHeight() - 1 - y; - if(iFlags & 0x1) - iDstX = iX + m_pSpriteImages[iSpriteIndex].GetWidth() - 1 - x; - - if(m_pSpriteImages[iSpriteIndex].HasAlpha()) - { - if(!m_pSpriteImages[iSpriteIndex].IsTransparent(x,y,128)) - { - imgCanvas.SetRGB(iDstX,iDstY,m_pSpriteImages[iSpriteIndex].GetRed(x,y),m_pSpriteImages[iSpriteIndex].GetGreen(x,y), - m_pSpriteImages[iSpriteIndex].GetBlue(x,y)); - imgCanvas.SetAlpha(iDstX,iDstY,m_pSpriteImages[iSpriteIndex].GetAlpha(x,y)); - } - } else { - imgCanvas.SetRGB(iDstX,iDstY,m_pSpriteImages[iSpriteIndex].GetRed(x,y),m_pSpriteImages[iSpriteIndex].GetGreen(x,y), - m_pSpriteImages[iSpriteIndex].GetBlue(x,y)); - //imgCanvas.SetAlpha(iDstX,iDstY,m_pSpriteImages[iSpriteIndex].GetAlpha(x,y)); - } - } + delete[] pData; + iLength = outlen; + return outbuf; + } + else + { + delete[] pData; + delete[] outbuf; + iLength = 0; + return nullptr; } } -th_element_t* THAnimations::_getElement(uint32_t iListIndex) +Bitmap::Bitmap() : + m_iWidth(0), + m_iHeight(0), + m_pData(nullptr) { - if(iListIndex >= m_iElementListCount) - return NULL; - uint16_t iElementIndex = m_pElementList[iListIndex]; - if(iElementIndex > m_iElementCount) - return NULL; - return m_pElements + iElementIndex; -} - -Bitmap::Bitmap() -{ - m_iWidth = 0; - m_iHeight = 0; - m_pData = NULL; } Bitmap::~Bitmap() diff -Nru corsix-th-0.61/AnimView/th.h corsix-th-0.62/AnimView/th.h --- corsix-th-0.61/AnimView/th.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/th.h 2018-07-21 11:13:17.000000000 +0000 @@ -39,17 +39,9 @@ #include #include #include -#include "tinyxml.h" -#ifdef _MSC_VER -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -#else +#include #include -#endif // _MSC_VER +#include #pragma pack(push) #pragma pack(1) @@ -153,7 +145,7 @@ void blit(Bitmap& bmpCanvas, int iX, int iY, int iFlags = 0) const; void blit(wxImage& imgCanvas, int iX, int iY, const unsigned char* pColourTranslate, const th_colour_t* pPalette, int iFlags = 0) const; - bool IsOk() {return m_pData != NULL;} + bool IsOk() {return m_pData != nullptr;} protected: int m_iWidth; @@ -167,30 +159,37 @@ THAnimations(); ~THAnimations(); - bool loadAnimationFile(wxString sFilename) {return _loadArray(m_pAnims, m_iAnimCount, sFilename);} + bool loadAnimationFile(wxString sFilename) { + return loadVector(anims, sFilename); + } + bool loadFrameFile(wxString sFilename); - bool loadListFile(wxString sFilename) {return _loadArray(m_pElementList, m_iElementListCount, sFilename);} - bool loadElementFile(wxString sFilename) {return _loadArray(m_pElements, m_iElementCount, sFilename);} + + bool loadListFile(wxString sFilename) { + return loadVector(elementList, sFilename); + } + + bool loadElementFile(wxString sFilename) { + return loadVector(elements, sFilename); + } + bool loadTableFile(wxString sFilename); - bool loadSpriteFile(wxString sFilename) {return _loadArray(m_pChunks, m_iChunkCount, sFilename);} + + bool loadSpriteFile(wxString sFilename) { + return loadVector(chunks, sFilename); + } + bool loadPaletteFile(wxString sFilename); - bool loadGhostFile(wxString sFilename, int iIndex); - bool loadXMLFile(TiXmlDocument* xmlDocument); - void writeElementData(wxString aPath, wxTextOutputStream *outputLog, wxTextOutputStream *outputXml, - size_t iAnimation, size_t iFrame, const THLayerMask* pMask, wxSize& size, int* iListIndex); - void writeTableDataHeader(wxTextOutputStream *outputLog); + bool loadGhostFile(wxString sFilename, int iIndex); size_t markDuplicates(); size_t getAnimationCount(); size_t getSpriteCount(); size_t getFrameCount(size_t iAnimation); - uint16_t getUnknownField(size_t iAnimation) {return m_pAnims[iAnimation].unknown; } - uint16_t getFrameField(size_t iAnimation) {return m_pAnims[iAnimation].frame; } - //uint32_t getListIndexField(size_t iFrame) {return m_pFrames[iFrame].list_index; } - //uint8_t getFrameWidthField(size_t iFrame) {return m_pFrames[iFrame].width; } - //uint8_t getFrameHeightField(size_t iFrame) {return m_pFrames[iFrame].height; } + uint16_t getUnknownField(size_t iAnimation) {return anims.at(iAnimation).unknown; } + uint16_t getFrameField(size_t iAnimation) {return anims.at(iAnimation).frame; } th_frame_t* getFrameStruct(size_t iAnimation, size_t iFrame); bool isAnimationDuplicate(size_t iAnimation); bool doesAnimationIncludeFrame(size_t iAnimation, size_t iFrame); @@ -198,7 +197,7 @@ void setSpritePath(wxString aPath); Bitmap* getSpriteBitmap(size_t iSprite, bool bComplex = false); - th_colour_t* getPalette() {return m_pColours;} + th_colour_t* getPalette() { return colours.data(); } void setGhost(int iFile, int iIndex); void drawFrame(wxImage& imgCanvas, size_t iAnimation, size_t iFrame, const THLayerMask* pMask, wxSize& size, int iXOffset = 0, int iYOffset = 0); @@ -207,18 +206,13 @@ static unsigned char* Decompress(unsigned char* pData, size_t& iLength); protected: template - bool _loadArray(T*& pArray, size_t& iCount, wxString sFilename) - { - if(pArray != NULL) - { - delete[] pArray; - pArray = NULL; - } - iCount = 0; + bool loadVector(std::vector& vector, wxString sFilename) { + vector.clear(); wxFile oFile(sFilename); - if(!oFile.IsOpened()) + if (!oFile.IsOpened()) return false; + size_t iLen = oFile.Length(); unsigned char* pBuffer = new unsigned char[iLen]; oFile.Read(pBuffer, iLen); @@ -230,31 +224,25 @@ return false; } } - pArray = (T*)pBuffer; - iCount = iLen / sizeof(T); + + for (int offset = 0; offset < iLen; offset += sizeof(T)) { + vector.push_back(*(reinterpret_cast(pBuffer + offset))); + } + return true; } + th_element_t* _getElement(uint32_t iListIndex); - th_anim_t* m_pAnims; - th_frame_t* m_pFrames; - uint16_t* m_pElementList; - th_element_t* m_pElements; - th_sprite_t* m_pSprites; - Bitmap* m_pSpriteBitmaps; - wxImage* m_pSpriteImages; - uint8_t* m_pSpriteScaleFactors; - uint8_t* m_pChunks; - th_colour_t* m_pColours; - unsigned char* m_pGhostMaps; + std::vector anims; + std::vector frames; + std::vector elementList; + std::vector elements; + std::vector sprites; + std::vector spriteBitmaps; + std::vector chunks; + std::vector colours; + std::array ghostMaps; size_t m_iGhostMapOffset; - size_t m_iAnimCount; - size_t m_iFrameCount; - size_t m_iElementListCount; - size_t m_iElementCount; - size_t m_iSpriteCount; - size_t m_iChunkCount; - size_t m_iColourCount; - bool m_bXmlLoaded; wxString m_sSpritePath; }; diff -Nru corsix-th-0.61/AnimView/tinystr.cpp corsix-th-0.62/AnimView/tinystr.cpp --- corsix-th-0.61/AnimView/tinystr.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/tinystr.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff -Nru corsix-th-0.61/AnimView/tinystr.h corsix-th-0.62/AnimView/tinystr.h --- corsix-th-0.61/AnimView/tinystr.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/tinystr.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,305 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developed. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff -Nru corsix-th-0.61/AnimView/tinyxml.cpp corsix-th-0.62/AnimView/tinyxml.cpp --- corsix-th-0.61/AnimView/tinyxml.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/tinyxml.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1886 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - -FILE* TiXmlFOpen( const char* filename, const char* mode ); - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; - target->location = location; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( !replaceThis ) - return 0; - - if ( replaceThis->parent != this ) - return 0; - - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( !removeThis ) { - return false; - } - - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); - return *this; -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} - - -int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; -} - - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; -} - - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} -#endif - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; - } - } - else { - *q++ = *p++; - } - } - assert( q <= (buf+length) ); - *q = 0; - - Parse( buf, 0, encoding ); - - delete [] buf; - return !Error(); -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); - #else - sprintf (buf, "%g", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); - return *this; -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - copy.CopyTo( this ); -} - - -TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} -#endif - - -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} - - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff -Nru corsix-th-0.61/AnimView/tinyxmlerror.cpp corsix-th-0.62/AnimView/tinyxmlerror.cpp --- corsix-th-0.61/AnimView/tinyxmlerror.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/tinyxmlerror.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml.h" - -// The goal of the separate error file is to make the first -// step towards localization. tinyxml (currently) only supports -// english error messages, but the could now be translated. -// -// It also cleans up the code a bit. -// - -const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = -{ - "No error", - "Error", - "Failed to open file", - "Error parsing Element.", - "Failed to read Element name", - "Error reading Element value.", - "Error reading Attributes.", - "Error: empty tag.", - "Error reading end tag.", - "Error parsing Unknown.", - "Error parsing Comment.", - "Error parsing Declaration.", - "Error document empty.", - "Error null (0) or unexpected EOF found in input stream.", - "Error parsing CDATA.", - "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", -}; diff -Nru corsix-th-0.61/AnimView/tinyxml.h corsix-th-0.62/AnimView/tinyxml.h --- corsix-th-0.61/AnimView/tinyxml.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/AnimView/tinyxml.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,1805 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 6; -const int TIXML_PATCH_VERSION = 2; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contain the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occurred. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occurred. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occurred. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occurred. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); - -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif - - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - TiXmlElement& operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occurred. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -#include - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() const { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p && *p ) - p += strlen( endTag ); - return ( p && *p ) ? p : 0; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p && *p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i SDL 2 and added support for Lua 5.2 and Lua 5.3. +* New ready-to-use Eclipse Workspace. +* Debugging Lua code using DBGp has been added. See + the Wiki for more information. +* The Windows Installer now uses NSIS 3.0 and only produces one executable + since SDL 2 handles renderer itself. +* Framework for Busted Unit Tests in Lua. +* Support for custom graphics has been improved. + + +------------------------------------------------------------------------------- +Version 0.40 - released December 2014 +------------------------------------------------------------------------------- + +It has been a while since our last release, but good things come to those who wait! +Or... in this case it's contagious diseases. Watch out for epidemics on the +later levels in the campaign! Your patients are not as good as they used to be +either, so those who are not lucky enough to get vaccinated and cured might +get a visit from the Grim Reaper. +Also, don't forget to try out the new map St. Peter's near Cawley! + +Happy gaming! + + +--- Gameplay --- + +* Added: Epidemics. You can either choose to pay a fine to the authorities or + try to cover up the epidemic by vaccinating and curing the contagious patients. + Patients going between buildings will NOT trigger the alarm to the authorities. +* Added: The Grim Reaper. Previously patients have always gone to heaven when + they die. No more! Sometimes they will instead fall down to the middle of the + earth in a Lava Hole. +* Added: People with visual diseases will no longer arrive at the beginning of + the level if that has been specified in the level file. Instead they arrive + once a certain amount of months have passed. +* Added: If you refuse VIP visits a few times he can sometimes show up anyway. + +* Change: Machine usage and explosions are now based on absolute number of uses. + A machine that goes down to 0 will explode. Previously they were percentage based. + +* Fix: The game would crash if you sacked a doctor in a room while a patient + was using some equipment in that room. +* Fix: Sometimes the emergency bonus was not correctly calculated. +* Fix: Patients could die inside a room. They will now die outside the room + unless they are just being cured. +* Fix: If winning the level at end of year the annual report would hide the + winning fax. +* Fix: If there was no queue to a room a leaving staff member would not trigger + a call for staff for the patient who had to abort their procedure in that room. +* Fix: If a handyman had pending tasks when he died in an exploding room the game + could crash. +* Fix: A surgeon that is removed in mid-operation will now get properly replaced + by a new one. +* Fix: If the GP room was built too early in the tutorial the game would crash + when building a GP room later on if debug mode was turned off. +* Fix: Patients would try to enter an exploding room. As you can imagine, + this was bad. +* Fix: Psychiatrists would become shut-ins and just wander about their office + forever. +* Fix: Patients leaving the queue to get a drink could be left to sit on a + bench forever. + + +--- User Interface --- + +* Added: Tooltips for the increase and decrease buttons in the research screen. +* Added: A sound that indicates if a screenshot was taken successfully. +* Added: Any dialog that pops up, such as the award screen, pauses the game. +* Added: 'Continue Game' in the main menu. + +* Fix: Sometimes the game would not pause on year end. +* Fix: Staff raise description was hard to read in some languages +* Fix: The current language setting is translated and consistent with the + options in the list. + + +--- Graphics --- + +* Fix: Instead of turning into a Bloaty Head, Baldness patients will die + with gracious hair. +* Fix: Patients will no longer fall through walls when dying. +* Fix: Dying Hairyitis patients should not lose their head when on the floor. + + +--- Hotkeys --- + +* Added: 'Z' temporarily moves the game at maximum speed. Release to go back + to the previous speed. +* Added: 'X' makes walls transparent until released. +* Added: Use the Numpad to change game speed. +* Added: Arrow key hotkeys in the staff management screen. +* Added: Press and hold on '+' and '-' when buying furniture to + repeat the action. + +* Change: Quick Save is now Shift+Alt+S, Quick Load is Shift+Alt+L. + + +--- Languages --- + +* Change: "Plot" is used instead of "Parcel" to indicate where a handyman has + been zoned to work in the Handyman staff dialog. + +Most languages have been updated since our last release, but if you find that +your language has not, please help us to finish it! + + +--- CorsixTH Development --- + +* Added: New flag for CMAKE: 'WITH_LUAJIT'. This way you can choose to use + either LuaJIT or Lua5.1. +* Added: CMake toolchain for building with MinGW. +* Added: New debug menu option 'Run debug Script' that executes + /Lua/debug_script.lua + + +------------------------------------------------------------------------------- +Version 0.30 - released November 2013 +------------------------------------------------------------------------------- + +This release contains a whole new Level Editor, which means that in combination +with the already existing Map Editor whole levels can now be created a lot +easier. Give it a try! We have also added many new options previously only +available by manually editing the config file to the options dialog. +Players will also notice that we have added an automatic update +check on game launch once we release the version after this one. +As usual there are of course also numerous minor tweaks here and there. + + + +--- Gameplay --- + +* Change: You can now build more than one desk in the ward. More nurses means + a slightly faster throughput. +* Change: Patients would previously queue outside toilets even though there were + free loos since it was dependent on number of people in the room. Now, as soon + as a loo becomes free another patient enters the room to use it, + even if there is a long queue for the sink). + If there is a queue for the sinks there is a chance the patient will leave + without washing their hands - but will not be happy about doing this. + +* Added: The ability to control alien behaviour - sitting, knocking doors, + only to be available through emergency or arrive like all other patients. +* Added: Winning fax opens automatically and pauses the game. +* Added: Option to automatically accept wage increase requests when they "time out". +* Added: A new option allows for your average build content for each type of room + to be remembered, so will be added for each new room built later. + +* Fix: Doctors should get stuck less often, and handymen should not crash the + game as frequently. +* Fix: It was not possible to replace a surgeon when a patient was in the room. +* Fix: Patients would sometimes get stuck inside a room when they should + have died. + + + +--- User Interface --- + +* Added: A new customization menu in the Options dialog. Most options from the + configuration file are now available for change in-game. +* Added: A new directory menu in the Options dialog. +* Added: The game does now check for a more recent version of itself when + launching. +* Added: A helpful message when the player puts more Researchers in the + research department than there are desks. +* Added: The game now does a small integrity check on the Theme Hospital + files to make sure that the most common corruptions are not present. +* Added: Confirm dialog to the quit/exit button on the main menu. + +* Fix: The tooltip for the tutorial button was incorrect since the dialog + has been visually changed. +* Fix: The announcer has had a few corrections made to his manuscripts. + He is very happy about this! + +* Removed: The settings menu is no longer available from within the game. + + + +--- Hotkeys --- + +Some hotkeys have been changed and/or added: + +* Alt + A = Toggle Announcements +* Alt + M = Toggle Music +* Alt + S = Toggle Sound Effects +* Shift and + to zoom in five steps and Shift and - to zoom out five steps at a time. + + + +--- Campaign levels --- + +* Fix: An error in level 8 made it possible to win without meeting the + reputation criterion. + + + +--- Custom levels --- + +* Change: For random emergencies each illness now has its own average number of + patients to spawn. Previously they were all the same. + +* Fix: Researching improvements was not really possible on some custom levels, + i.e. if the map creator had made it so there were no machines at the start. + + + +--- Demo files --- + +* Fix: When winning the demo level CorsixTH looked for another level to load, + showing the wrong fax options and eventually crashing. + + + +--- Languages --- + +* Added: Korean language. + +* Fix: It was not possible to dump strings for a language with unicode + characters in the name. + + + +--- Compiling --- + +* Fix: You could not compile the game with WITH_AUDIO=0 if SDL_mixer was + not present at all. +* Fix: WITH_AUDIO=OFF is now illegal in combination with WITH_MOVIES=ON. + + + +------------------------------------------------------------------------------- +Version 0.21 - released 2013-05-04 +------------------------------------------------------------------------------- + +This is mainly a bugfix release, but a few minor features are still also +introduced, see the changelog below. + + + +--- Gameplay --- + +* Fix: Staff would sometimes not go for a break. +* Fix: A few crashes related to Handymen. +* Fix: An error could occur if a fax message was removed just as it was animating + into view. +* Fix: Patients could sometimes be told to go home multiple times, + resulting in a crash. +* Fix: If a queueing patient was heading for a drinks machine just as the player + moved that machine the game would crash. + + + +--- User Interface --- + +* Added: Scrolling momentum when using the middle button. +* Added: There is now a clock in the right corner of the menu bar that + shows the real world time. It can be toggled between AM/PM and 24h + in the configuration file. + + + +--- Hotkeys --- + +* Added: Hotkeys for the Jukebox (J), Save game menu (Shift + S), + Load game menu (Shift + L), to restart the level (Shift + R) and finally + quit the current game and take you back to the opening screen (Shift + Q). + +* Change: Restart is now Shift + F10 instead of only F10. +* Change: Toggle adviser is now Shift + A instead of only A. +* Change: Key combinations will only trigger if that exact combination + is pressed. E.g. Ctrl + R will not trigger R too. +* Change: Alt + F4 is now the hotkey to quit CorsixTH. + +* Fix: Added a configuration option to have the possibility to use Shift + C + as hotkey to open the Drug casebook instead of C. This is to workaround + a bug that when you press on the volume down key on your keyboard + the Drug casebook would open. + + + +--- Map Editor --- + +* Added: Undo/Redo functionality. +* Added: Street lamps and the dead looking tree. + + + +------------------------------------------------------------------------------- +Version 0.20 - released 2013-03-24 +------------------------------------------------------------------------------- + +In this version major new features include in-game movies, objects that +occupy only the edge of a tile and the graph window. + + + +--- Main features not yet implemented --- + +* Epidemics. +* Rats (and the rat level). +* Insurance company graphs, illness graphs. +* Visual effects on patients with serious radiation and jellyitis. +* Some fullscreen animations such as the winning letter. +* Multiplayer support. + +For a (nearly) complete list, visit our Programming Ideas wiki page: +http://code.google.com/p/corsix-th/wiki/ProgrammingIdeas + + + +--- Known Issues --- + +* Emotion icons don't appear just above a humanoid's head at all times. +* Main menu/in-game may glitch when using the OpenGL version. + +For a complete list, visit the issue tracker: +http://code.google.com/p/corsix-th/issues/list + + + +--- Gameplay --- + +* Added: Radiators and other "edge tile" objects now occupy just one edge of + the tile, inline with the original game. As a result one tile corridors can + now be heated properly. An addition is that you can place many such objects + on a single tile as long as they face different directions. + +* Added: Possibility to play movies in-game. At the moment the intro movie, + advancement between levels and the win/lose movies has been added. + +* Added: The atom analyzer can now be built in the research department if it + is available on the map. + +* Added: User actions are no longer allowed by default (for new games) when + the game is paused. When trying this it might seem like it doesn't work + correctly, but we try to mimic the original as much as possible. This for + example means that a staff member being placed as you pause will disappear + from the cursor. We might change this behaviour in the future though. + +* Added: Some background sounds, coughs, phones ringing etc. + +* Change: Placing a member of staff inside a room that is already occupied + will now replace that person. + +* Fix: Earthquakes could be four times as severe as intended. Still todo: + A tremor before a coming big earthquake. + +* Fix: Crashes in certain situations involving receptionists and reception + desks. +* Fix: Patients being handled at a reception desk even if no receptionist + is present. +* Fix: Allow patients to be sent to the research room only if the corresponding + room is not yet researched (so not if it is researched but not built). +* Fix: Don't cancel a place staff action just because the player happens to + click on a door. +* Fix: The VIP would try to sit down if there was a queue for the reception desk. + The VIP will no longer ever try to sit down, and he will have priority in + the queue anyway. +* Fix: If a member of staff was done resting at the same time as he/she was + also finished using the pool table or the video game another object in the + room could get reserved indefinitely. + + + +--- User Interface --- + +* Added: You can now see in the bank statement which drug company a certain + drug was bought from. It has no effect on gameplay though. + +* Added: The adviser now tells you why the research screen can't be opened + before you have built a research department. + +* Added: The Town Map functionality has been extended inline with Theme + Hospital. For example, if you right-click somewhere in your hospital the + view will be moved there. + +* Added: Available options on open faxes now gets updated if for example a room + explodes or the player builds a research department. +* Added: Keyboard shortcuts F1 - F9 for the fullscreen windows. They are NOT the + same as in original TH but instead correspond to the order on the bottom panel. +* Added: Possibility to choose font file in the options dialog. +* Added: Player name is now customizable in the new game dialog. + +* Removed: Keyboard shortcuts F8 and F9 for debug fax and debug patients. +* Change: Don't require debug mode to be able to dump the gamelog. +* Change: The shortcut for dumping strings is now Ctrl+T instead of Ctrl+Shift+D. + +* Change: Restructured options window to make it more consistent, less clutter-y + and smaller. +* Change: It is now possible to concentrate research on operating theatre + diseases and redistribution of research is automatically done when + a category has been completely researched. +* Change: Add disease name to patients' treatment history when they are + diagnosed. +* Change: Buttons on the bottom panel for fullscreen windows are now + toggle buttons. +* Change: Reordered entries of graphs menu to correspond with order in + bottom panel. + +* Fix: Colour selection algorithm for freetype fonts resulted in unreadable text + on faxes for some languages. +* Fix: When an unanswered fax became meaningless (e.g. if you built the + required room), it was only removed if its message button was visible at the + bottom panel (not if it was queued because of 5 buttons being there already). +* Fix: Update the drug casebook if the last room of one kind explodes. +* Fix: The directory browser was not always shown if the chosen Theme Hospital + install directory was illegal. +* Fix: Settings changed in the game will be saved immediately so that they + persist to the next session regardless of how the game is shut down. +* Fix: The bottom panel is no longer always on top, making fullscreen + dialogs truly fullscreen on 640x480. +* Fix: Don't play any announcements if there is no receptionist to do it. +* Fix: The adviser would not idle again if a new message arrived as he was + idling from a previous message. +* Fix: While a player viewed the confirm dialog to delete a room he/she could + continue to edit the room and complete it again resulting in an inconsistent + game state. + + + +--- Graphics --- + +* Added: The graph dialog now actually displays graphs and statistics information. + +* Added: It is now possible to choose among three colour scales for warmth + level. Look in the top menu for this choice. + +* Added: Print some info in the command prompt when the user wants to take + a screenshot, so he can see if and why it failed. +* Added: Screenshot functionality for OpenGL version. +* Change: Screenshots get saved to a dedicated screenshot folder now, + which can be changed in the config. +* Fix: Loading a game on startup where a fullscreen window was open would + open with the font messed up. +* Fix: Taking a screenshot (Ctrl+S) is now possible under windows without + fiddling in a lua file. + + + +--- Translations --- + +* Added: The beginning of Brazilian Portuguese and Hungarian. +* Change: The "utf8" prefix has been obsolete for some time and has been + removed from all language files. + + + +--- When using Demo files --- + +* Fix: The game would crash if the player tried to open the staff management + dialog by clicking on a staff portrait in the staff dialog. + + + +------------------------------------------------------------------------------- +Version 0.11 - released 2012-11-17 +------------------------------------------------------------------------------- + +This is a bugfix release. For known issues etcetera, check out the +changelog for version 0.10 below. + + +-- Gameplay -- + +* Fix: Patients were not fully diagnosed according to settings + in the policy screen. +* Fix: The game now handles a player trying to cheat into an earthquake + on levels 1-4. +* Fix: It was not possible to sell equipment in rooms if you had a negative + balance. +* Fix: Handymen could not be placed inside rooms. +* Fix: Handymen would get called to clean soot in blown up rooms. +* Fix: Machines that need to be repaired will now cancel that request if + they are blown up. +* Fix: If a cured patient was leaving a room just as it crashed because + of an earthquake the game would throw an error. +* Fix: Alien DNA could under some circumstances not have the + "concentrate research" button clicked without triggering a crash. +* Fix: A crash occurring under some circumstances if the player picked + up a staff member. + + +-- User Interface -- + +* Enhancement: Since consultants are unable to learn new skills icons for + not yet fully learned skills are now removed when a doctor is promoted. +* Fix: Disabling background music no longer disables sound effects on Windows. +* Fix: Checking if a sound exists crashed the game if there was no sound + archive at all. +* Fix: If the player paused the game from the top menu bar while an earthquake + was active it would be impossible to scroll. + + +-- Graphics -- + +* Fix: On a few levels some sliding doors would not animate correctly. +* Fix: Vomiting standard males had the wrong animation. + + + +------------------------------------------------------------------------------- +Version 0.10 - released 2012-09-24 +------------------------------------------------------------------------------- + +-- How versions work -- + +If you have been wondering how the new version system works: +When major new features are added the second digit is increased. +When there are only fixes or smaller new features the third digit +is increased. + +In this version, for example, earthquakes have been added. + +-- Not Yet Implemented -- + +* Epidemics +* Rats +* Graphs +* Visual effects on patients with serious radiation and jellyitis. +* Fullscreen animations such as the level screen and winning letter. + +-- Known Issues -- + +* If the X-Ray Viewer is inaccessible in the Operating Theatre no image will + be shown on it. +* If the user exits the game via "the cross" when in windowed mode settings + are not saved. +* Radiators and other "edge tile" objects occupy a whole tile instead of + just one edge of the tile. + +-- Gameplay -- + +* Added: Earthquakes have recently been reported! +* Added: Handyman priorities have been added. They can also be told to stay + and respond to calls in one building (parcel) only. +* Added: Staff's happiness will change due to more environmental factors. + +* Change: The files containing dumped strings are now created alongside the + config file instead of in the installation directory. + +* Fix: Handymen will now meander inside a room until the machine which needs + repair is free for use. +* Fix: The URL in the config file pointing to better quality music was outdated. + Note that this only affects new installations. +* Fix: Two identical entries were shown in the drug casebook if a new disease + was discovered when it was open. +* Fix: Don't crash when a saved game with the town map open is loaded. +* Fix: Too large rooms could make them unusable. +* Some graphical glitches have been fixed. + +-- User Interface -- + +* Added: The Map Editor and Animation Viewer have new icons. +* Change: In debug mode all gamelog output is now also displayed in the + command prompt. +* Fix: Don't initiate a window move if it happens to be below a top menu + selection. +* Fix: Don't show the main menu under any circumstances when closing the + options menu in-game. + +-- Map Editor -- + +* Fix: The "Save" and "Save As" buttons now do what they should do. +* Fix: There were some strange log messages on opening the editor. +* Added: The arrow keys can now be used to scroll the map. +* Change: Removed a lot of tiles from the palette, since maps may not + work as intended if they would be used. + +------------------------------------------------------------------------------- +Version 0.01 - released 2012-03-24 +------------------------------------------------------------------------------- + +-- Not Yet Implemented -- + +* Earthquakes +* Epidemics +* Handyman priorities +* Rats +* Graphs +* Visual effects on patients with serious radiation and jellyitis. +* Fullscreen animations such as the level screen and winning letter. + +-- Known Issues -- + +* If the X-Ray Viewer is inaccessible in the Operating Theatre no image will + be shown on it. +* If the user exits the game via "the cross" when in windowed mode settings + are not saved. +* Radiators and other "edge tile" objects occupy a whole tile instead of + just one edge of the tile. + +-- Gameplay -- + +* Added: A host of awards given at year end. +* Added: A new mode: Free Build Mode. In this mode you don't have to worry + about money. All custom maps can be played in this mode. +* Added: Patient animations such as yawning and checking watch when waiting. + +* Change: The queue size for a room can be set to 0 to prevent patients + from going there. +* Change: Patients now spend some more time in the ward. + +* Fix: Crash when removing a room that has humanoids on their way to it. +* Fix: Patients sitting down, but about to get a soda got ordered to sit down again. +* Fix: A crash could occur if a new room was accepted when there were multiple types + of objects left to place. +* Fix: Emergencies with diseases not available on a level no longer happen. +* Fix: The VIP no longer makes staff be called to the rooms he visits. +* Fix: With multiple reception desks new patients now find their way to the + reception with the least queue size. +* Fix: The wrong amount of money was returned when selling a room. +* Fix: Aliens could not be cured on the last two levels. +* Fix: The transparent walls setting made new rooms remove outer walls. +* Fix: Sometimes patients who had left the hospital could still wait for a new room, + making said room impossible to build. +* Fix: A crash when the staff member left a room before the patient. +* Fix: Build cost of objects were not always correct. + +-- User Interface -- + +* Added: The save and load dialogs can now sort both ascending and descending + and are a little more spacy. +* Added: More messages in the progress report dialog. +* Added: More advice in different situations from the adviser. +* Added: Adviser messages now has priorities, making more important messages + appear faster. + +* Change: When the mouse cursor leaves the game window it will stop scrolling + the in-game world. +* Change: The message when a crash occurs is now a little more informative, and + humanoids no longer get stuck as easily. + +* Fix: The staff management window is now updated when staff is hired or + fired from outside the window itself. +* Fix: If the desired language cannot be loaded on startup the game now + reverts to English instead of crashing. +* Fix: The game could not autosave if the save or load dialog was open. + +* The auto-scroll setting is now saved between sessions. +* The adviser can now be turned off from the top menu. +* The game uses a new icon. + +-- Map Editor -- + +* Fix: The game no longer crash just because the map builder has not added any + access roads from the edge of the map. + +------------------------------------------------------------------------------- +Version Beta 8 - released 2011-09-24 +------------------------------------------------------------------------------- + +-- Gameplay -- + +* Fix: Patients should manage to use benches more often now. +* Fix: Staff will never have the "waiting for patient" mood when in a training + room or a staff room anymore. +* Change: Which diagnosis rooms different patients go to have been changed + to be more like the original game. +* Change: No patients will arrive until you have both a receptionist and a reception + desk. There will be no emergencies or VIP visits either until this criterion is met. +* Added: People may now puke or pee on the floor. +* Added: Various things such as litter and plants affect patient happiness. +* Added: A doctor may now get crazy if he is waaay too tired. +* Added: VIP visits. Watch out for those picky black suit visitors! +* Added: The "guess cure" fax message will now properly pop up. + +-- User Interface -- + +* Change: The save and load dialogs now look a little different. Autosaves are stored + in a separate folder and there can be up to 12 autosaves at the same time. One for + each month. The dialogs now show when a save was made, and the list can also be + sorted by this criterion. +* Added: It is now possible to cycle through owned machines by right-clicking + the machine name in the machine dialog. +* Added: Sound, announcement and music volumes and on/off settings are now + saved between sessions.s + +-- Graphics -- + +* Added: Waiting patients may sometimes check their watch or start to tap their foot. +* Added: Soda machines now sell more than soda cans. This can be seen through the + litter people throw on the floor after using said machines. +* Added: (Animation Viewer) A new export function has been added. Note that there + is currently no import equivalent, so it is mostly for people to try out and + see what graphics there are in the game. In the future we hope to make it possible + to import these graphics after changing them in your favourite graphics program. + +-- Translations -- + +New language: Polish + +------------------------------------------------------------------------------- +Version Beta 7 - released 2011-06-24 +------------------------------------------------------------------------------- + +-- Known Issues -- + +* If the X-Ray Viewer is inaccessible in the Operating Theatre the whole + room will be unusable. +* There are still many features which are not yet implemented including trash, + earthquakes, epidemics and awards. +* The graph window doesn't show any graphs. +* Handyman priorities are not yet fully implemented. + +-- Gameplay -- + +* Added: Staff severance pay. +* Added: Patients may die if they don't get treated in time. +* Added: Doctors slowly gain skill when working. +* Added: Extra objects and the number of trainees influence speed of training + in the training room. +* Added: Even with no research new machines will eventually become available. +* Added: Some patients have started littering your hospital with soda cans! + Make sure you have enough handymen to keep your hospital clean. +* Added: Modern heating systems aren't as reliable as they used to be. Prepare + for breakdowns now and then. + +* New disease: Alien DNA! Note that there are still a few glitches to fix + concerning this new disease. + +* Change: Vending maintenance costs have increased throughout the world and + as a result Sodas now cost $20, up from $15. +* Change: Heating costs are calculated on a per day basis, rather than per month. +* Change: Machine and drug improvements are now made evenly across all eligible + objects rather than maxing one at a time. +* Change: Humanoids never meander outside anymore. + +* Fix: Handymen no longer crash the game when trying to water an unreachable + plant. +* Fix: Staff resting in the staff room should keep their sofa until fully + rested if there's nothing else to do. +* Fix: The player can't hire new staff or pay bonuses without a positive balance. + +-- User Interface -- + +* Added: The graph window, no graphs yet though. +* Added: Right click menu in the queue dialog. +* Added: Confirmation dialog when about to fire a member of staff. + +* Fix: If there is only one person who is in an emergency, use the singular + form in the sentence. +* Fix: The pickup item button in the edit room dialog is now fully functional. +* Fix: The pointer should no longer jump around in Linux when using SDL. + +-- Graphics -- + +* Added: The scanner uses more than one animation. + +* Fix: Some objects were cut in half after a relocation. + +-- Translations -- + +* Change: If the specified language is not found, try to revert to English. +* Fix: Competitor names are now translatable. + +------------------------------------------------------------------------------- +Version Beta 6 - released 2011-03-24 +------------------------------------------------------------------------------- + +-- Gameplay -- + +* Feature: Staff speed! +* Added: All parts of research have been implemented, including + machine strength improvements, drug improvements and the + "concentrate research" button in the drug casebook. +* Added: Overdraft charges for having a negative balance. +* Fix: The length of a day was about half as long as it should be. +* Fix: A few occurrences of bone-idle patients have been resolved. +* Fix: Juniors were not correctly labeled as Doctors after promotion. +* Fix: Some crashes regarding receptionists. +* Fix: Never charge less than initial cost when reputation is below 500. +* Fix: Some repair animations were too short. +* Fix: Don't check winning and losing conditions so often. +* Fix: Taking loans can now make the player avoid losing. +* Fix: Level 7 had an emergency with an unavailable disease. +* Fix: Doctors on their way back to the research room or training room + will no longer answer to any calls. +* Fix: Don't crash if a patient in a machine is sent home. +* Fix: Various tweaks to the operating theatre logic. +* Fix: Don't crash if the staff window of a leaving staff member + is open when he/she leaves the world. +* Fix: Persistent data (salary, built rooms etc) are no longer lost + after restarting a level. + +-- User Interface -- + +* Feature: The drug casebook now shows if you can treat a disease or not, + and in the latter case the tooltip tells you what is missing. Actual + price is shown after some time, instead of charge %. +* Feature: Press and hold on value buttons will now make the value continue + to increase until the button is released again. +* Feature: The Theme Hospital installation path can be changed from the + options menu. +* Added: The adviser will help out in a few more situations. +* Fix: Mouse position events such as moving staff around didn't work + when scrolling using the arrow keys. +* Fix: Tooltips are now updated more frequently, + most evidently in the research pane. + +-- Translations -- + +* Feature: CorsixTH now supports TrueType fonts via FreeType2! +* Feature: To assist translators a new diff file is now created when you + choose the debug option "dump strings" (with languages other than English). + It contains those strings which are either found in English but not in + the given language, or found in the given language but not in English. + +* New languages: Traditional Chinese, Simplified Chinese, Russian. + +------------------------------------------------------------------------------- +Version Beta 5 - released 2010-12-24 +------------------------------------------------------------------------------- + +-- Gameplay -- + +* Feature: (Some) Cheats added. Type 24328 into the fax machine to get access to them. +* Feature: Custom map "Avatar" added. +* Feature: Player's "salary" (read: score) now increases over your level progress. +* Feature: Level based interest rate. +* Feature: Level based "starting staff" (e.g. original level 5). +* Feature: "No deaths" trophy added. +* Fix: Error could occur when losing a game. +* Fix: Multiple handymen watering the same plant at the same time. +* Fix: Some placements of opposite doors/objects were wrongly forbidden. +* Fix: Error could occur when building a surgery. +* Fix: Autopsy now has an appropriate impact on research. +* Fix: Salaries for doctors were too high. +* Fix: In some cases lose conditions were not triggered. +* Fix: Research room door could disappear after autopsy. + ... and various other bugs fixed. + +-- User Interface -- + +* Feature: The player is now told the reason why he lost, when he loses, instead of being left in the dark. +* Fix: Wrong winning faxes shown for levels 5-11. +* Fix: Weird scrolling behavior could occur after loading a game. +* Fix: No tutorial when playing with demo files. +* Fix: Adviser disappeared too quickly during tutorial. +* Some improvements to textboxes. +* Some improvements to windows. + ... and various other small improvements and fixes. + +-- Translations -- + +* Fix: Error caused by some winning faxes in Norwegian. + +------------------------------------------------------------------------------- +Version Beta 4 - released 2010-11-12 +------------------------------------------------------------------------------- + +-- Gameplay -- + +* Feature: The Research Department and research policy dialog. +* Feature: The Operating Theatre. +* Feature: Not all parcels are owned by the player from the beginning, but + can now be bought from the Town Map dialog. +* Feature: Calculate staff wages and properties for those for hire based + on the level files. + +* Added 7 new diseases related to the operating theatre. +* Added treatment room: Operating Theatre. + +* Fix: The adviser no longer complains about watering of plants all the time. +* Fix: Some crashes related to crashed rooms has been fixed. + + +-- User Interface -- + +* Feature: Possibility to choose difficulty level when starting a new game. +* Feature: Zooming (only when using DirectX or OpenGL). +* Feature: The Annual Report Dialog. + +* Graphics: Improved the main menu background. +* Fix: Solved issues with non-English keyboard layouts. + + +-- Translations -- + +* New languages: Finnish and Danish +* Fix: When playing the game in French it no longer crashes upon completion of a level. + + +------------------------------------------------------------------------------- +Version Beta 3 - released 2010-06-24 +------------------------------------------------------------------------------- + +-- Gameplay -- + +* Feature: Swing doors (used by new diagnosis room ward). +* Feature: Plants will now droop unless they are watered by a handyman. +* Feature: Adjustable handyman priorities. +* Feature: Existing rooms can now be edited and deleted. +* Feature: Watch for initial opening of hospital at start of each level. +* Feature: Each level has its own goals, shown at the beginning of the level and + in the new status dialog. When the goals have been achieved the player may go on + to the next one. +* Feature: Not all implemented rooms and diseases appear anymore in each level, but + only those defined by the level script. +* Feature: Support for custom levels with their own maps and level scripts. +* Feature: A heating system that depends on outside temperature, adjacent tiles + and radiators among other things. + +* Added 6 new diseases +* Added treatment rooms: Jelly Vat, Decontamination +* Added diagnosis rooms: Blood Machine, Ward, Scanner + +* Fix: Staff needed in rooms is handled much better. +* Fix: Objects retain their statistics when moved. +* Fix: A horde of other bugs have also been fixed. + + +-- User Interface -- + +* Feature: Savegames are no longer limited to 8 slots + autosave. +* Feature: Fullscreen mode, screen resolution and interface language can be changed + ingame. The changes are saved in the config file and preserved. +* Feature: Hovering the mouse over a room will mark all patients in queue for this room. +* Feature: Patients can be moved to the head/tail of queues in the corresponding dialog. + They can also be placed between other patients. +* New dialogs: Load Game, Save Game, Custom Level to cope with arbitrary number of + savegames/levels. +* New dialog: Options +* New dialog: Progress Report (Status) showing status of the current level's goals. +* Added all tooltips that were still missing. + + +-- Misc -- + +* Translations: Italian, Spanish and French: added new strings not available in vanilla TH, + Portuguese (WIP) and Dutch (WIP) +* The configuration file and saved games can now, if desired, also be stored in the user's + home directory or equivalent. + + +------------------------------------------------------------------------------- +Version Beta 2 - released 2010-03-24 +------------------------------------------------------------------------------- + +* Feature: Save / Load functionality. +* Feature: Patients and staff now have a need for heat (from radiators) in + order to stay happy. Patients will also get thirsty (build drinks machines) + and will need a bathroom sooner or later, and staff will ask for a salary + raise when unhappy. +* Feature: Machines will need repair now and then. A dialog that shows + necessarry information is displayed when the machine is clicked. +* Feature: Dynamic Information Bar in the bottom right corner of the UI added. + It shows information about entities beneath the mouse cursor. +* Feature: The training room can now be built, where doctors can increase + their skill and get additional traits if a consultant is present. +* Feature: When a patient cannot be cured or a room is missing a fax will + arrive and ask the player what to do. +* Feature: A new string system that allows us to add new (translatable) text + to the game, correct mistakes in existing languages and add new languages. +* Feature: A tutorial is offered to the player at the start of the game. +* Feature: Tooltips are displayed when hovering over buttons for some time. +* Feature: Emergencies may happen every now and then. +* Feature: Hospital reputation system. +* Feature: Humorous disease description faxes are now shown when a disease is + first diagnosed. +* Feature: Room blueprints can be resized during the build process. + +* New Dialogs: Hospital Policy, Drug Casebook, Bank Manager, Staff Management, + Town Map (work in progress), Main Menu +* Many new key shortcuts (see Hotkeys wiki page for full list). +* Dialogs can now be re-positioned by dragging them to where they are wanted. +* Added floating money signs to better indicate where money is coming from. +* Added comments from the advisor in more situations. + +* 10 new diseases. +* New treatment room: Hair Restorer +* Additional functional diagnosis rooms: General Diagnosis, Ultrascan, X-Ray +* Room queues should now re-balance themselves when new rooms are built. + +* Translation: Norwegian (bokml). + +A lot of other small improvements. +Also, a great number of bugs have been squashed. Most remaining bugs are no +longer fatal, and can be continued from. + + +------------------------------------------------------------------------------- +Version Beta 1 - released 2009-12-24 +------------------------------------------------------------------------------- + +Initial release diff -Nru corsix-th-0.61/CMake/CMakeFFmpegLibavMacros.cmake corsix-th-0.62/CMake/CMakeFFmpegLibavMacros.cmake --- corsix-th-0.61/CMake/CMakeFFmpegLibavMacros.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/CMakeFFmpegLibavMacros.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -11,12 +11,12 @@ # Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. # macro(set_component_found _component ) - if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) # message(STATUS " - ${_component} found.") set(${_component}_FOUND TRUE) - else () + else() # message(STATUS " - ${_component} not found.") - endif () + endif() endmacro() # @@ -27,7 +27,6 @@ # component's version and sets *_VERSION_STRING. # macro(find_component _component _library _header _version) - find_path(${_component}_INCLUDE_DIRS ${_header} PATH_SUFFIXES ffmpeg @@ -36,12 +35,12 @@ ) find_library(${_component}_LIBRARIES - NAMES ${_library} - PATH_SUFFIXES - lib + NAMES ${_library} + PATH_SUFFIXES + lib ) - if (${_component}_INCLUDE_DIRS AND EXISTS "${${_component}_INCLUDE_DIRS}/${_version}") + if(${_component}_INCLUDE_DIRS AND EXISTS "${${_component}_INCLUDE_DIRS}/${_version}") file(STRINGS "${${_component}_INCLUDE_DIRS}/${_version}" ${_component}_VERSION_MAJOR_LINE REGEX "^#define[ \t]+LIB${_component}_VERSION_MAJOR[ \t]+[0-9]+$") file(STRINGS "${${_component}_INCLUDE_DIRS}/${_version}" ${_component}_VERSION_MINOR_LINE REGEX "^#define[ \t]+LIB${_component}_VERSION_MINOR[ \t]+[0-9]+$") file(STRINGS "${${_component}_INCLUDE_DIRS}/${_version}" ${_component}_VERSION_PATCH_LINE REGEX "^#define[ \t]+LIB${_component}_VERSION_MICRO[ \t]+[0-9]+$") @@ -55,11 +54,12 @@ unset(${_component}_VERSION_MAJOR) unset(${_component}_VERSION_MINOR) unset(${_component}_VERSION_PATCH) - endif () + endif() + find_package_handle_standard_args(${_component} - REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS - VERSION_VAR ${_component}_VERSION_STRING) + REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS + VERSION_VAR ${_component}_VERSION_STRING + ) set_component_found(${_component}) - endmacro() diff -Nru corsix-th-0.61/CMake/CopyVcpkgLua.cmake corsix-th-0.62/CMake/CopyVcpkgLua.cmake --- corsix-th-0.61/CMake/CopyVcpkgLua.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/CopyVcpkgLua.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -2,28 +2,34 @@ add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory "${VCPKG_INSTALLED_PATH}/share/lua" - $) + $ +) add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove - $/COPYRIGHT) + $/COPYRIGHT +) add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${VCPKG_INSTALLED_PATH}/$<$:debug/>bin/lfs.dll" - $/lfs.dll) + $/lfs.dll +) add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${VCPKG_INSTALLED_PATH}/$<$:debug/>bin/lpeg.dll" - $/lpeg.dll) + $/lpeg.dll +) add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${VCPKG_INSTALLED_PATH}/$<$:debug/>bin/mime/core.dll" - $/mime/core.dll) + $/mime/core.dll +) add_custom_command(TARGET CorsixTH POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${VCPKG_INSTALLED_PATH}/$<$:debug/>bin/socket/core.dll" - $/socket/core.dll) + $/socket/core.dll +) diff -Nru corsix-th-0.61/CMake/FindDirectX.cmake corsix-th-0.62/CMake/FindDirectX.cmake --- corsix-th-0.61/CMake/FindDirectX.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindDirectX.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -#------------------------------------------------------------------- -# This file was taken from the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -#------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# Find DirectX SDK -# Define: -# DirectX_FOUND -# DirectX_INCLUDE_DIR -# DirectX_LIBRARY -# DirectX_LIBRARY_DIR -# DirectX_ROOT_DIR - -if(WIN32) # The only platform it makes sense to check for DirectX SDK - include(FindPkgMacros) - findpkg_begin(DirectX) - - # Get path, convert backslashes as ${ENV_DXSDK_DIR} - getenv_path(DXSDK_DIR) - getenv_path(DIRECTX_HOME) - getenv_path(DIRECTX_ROOT) - getenv_path(DIRECTX_BASE) - - # construct search paths - set(DirectX_PREFIX_PATH - "${DXSDK_DIR}" "${ENV_DXSDK_DIR}" - "${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}" - "${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}" - "${DIRECTX_BASE}" "${ENV_DIRECTX_BASE}" - "C:/apps_x86/Microsoft DirectX SDK*" - "C:/Program Files (x86)/Microsoft DirectX SDK*" - "C:/apps/Microsoft DirectX SDK*" - "C:/Program Files/Microsoft DirectX SDK*" - "$ENV{ProgramFiles}/Microsoft DirectX SDK*" - ) - - # Windows 8 SDK has custom layout - set(DirectX_INC_SEARCH_PATH - "C:/Program Files (x86)/Windows Kits/8.0/Include/shared" - "C:/Program Files (x86)/Windows Kits/8.0/Include/um" - ) - set(DirectX_LIB_SEARCH_PATH - "C:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um" - ) - - create_search_paths(DirectX) - # redo search if prefix path changed - clear_if_changed(DirectX_PREFIX_PATH - DirectX_LIBRARY - DirectX_INCLUDE_DIR - ) - - find_path(DirectX_INCLUDE_DIR NAMES d3d9.h HINTS ${DirectX_INC_SEARCH_PATH}) - # dlls are in DirectX_ROOT_DIR/Developer Runtime/x64|x86 - # lib files are in DirectX_ROOT_DIR/Lib/x64|x86 - if(CMAKE_CL_64) - set(DirectX_LIBPATH_SUFFIX "x64") - else(CMAKE_CL_64) - set(DirectX_LIBPATH_SUFFIX "x86") - endif(CMAKE_CL_64) - find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - find_library(DirectX_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - - - # look for dxgi (needed by both 10 and 11) - find_library(DirectX_DXGI_LIBRARY NAMES dxgi HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - - # look for d3dcompiler (needed by 11) - find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - - findpkg_finish(DirectX) - set(DirectX_LIBRARIES ${DirectX_LIBRARIES} - ${DirectX_D3DX9_LIBRARY} - ${DirectX_DXERR_LIBRARY} - ${DirectX_DXGUID_LIBRARY} - ) - - mark_as_advanced(DirectX_D3DX9_LIBRARY DirectX_DXERR_LIBRARY DirectX_DXGUID_LIBRARY - DirectX_DXGI_LIBRARY DirectX_D3DCOMPILER_LIBRARY) - - - # look for D3D11 components - if (DirectX_FOUND) - find_path(DirectX_D3D11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX_INC_SEARCH_PATH}) - get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH) - message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}") - find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY) - set(DirectX_D3D11_FOUND TRUE) - set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR}) - set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES} - ${DirectX_D3D11_LIBRARY} - ${DirectX_DXGI_LIBRARY} - ${DirectX_DXGUID_LIBRARY} - ${DirectX_D3DCOMPILER_LIBRARY} - ) - endif () - if (DirectX_D3DX11_LIBRARY) - set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES} ${DirectX_D3DX11_LIBRARY}) - endif () - if (DirectX_DXERR_LIBRARY) - set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES} ${DirectX_DXERR_LIBRARY}) - endif () - mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY) - endif () - -endif(WIN32) diff -Nru corsix-th-0.61/CMake/FindFFmpeg.cmake corsix-th-0.62/CMake/FindFFmpeg.cmake --- corsix-th-0.61/CMake/FindFFmpeg.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindFFmpeg.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -33,12 +33,12 @@ include(${CMAKE_CURRENT_LIST_DIR}/CMakeFFmpegLibavMacros.cmake) # The default components were taken from a survey over other FindFFMPEG.cmake files -if (NOT FFmpeg_FIND_COMPONENTS) +if(NOT FFmpeg_FIND_COMPONENTS) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) -endif () +endif() # Check for cached results. If there are skip the costly part. -if (NOT FFMPEG_LIBRARIES) +if(NOT FFMPEG_LIBRARIES) # Check for all possible component. find_component(AVCODEC avcodec libavcodec/avcodec.h libavcodec/version.h) @@ -50,40 +50,38 @@ find_component(SWRESAMPLE swresample libswresample/swresample.h libswresample/version.h) # Check if the required components were found and add their stuff to the FFMPEG_* vars. - foreach (_component ${FFmpeg_FIND_COMPONENTS}) - if (${_component}_FOUND) + foreach(_component ${FFmpeg_FIND_COMPONENTS}) + if(${_component}_FOUND) # message(STATUS "Required component ${_component} present.") set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) - else () + else() # message(STATUS "Required component ${_component} missing.") - endif () - endforeach () + endif() + endforeach() # Build the include path with duplicates removed. - if (FFMPEG_INCLUDE_DIRS) + if(FFMPEG_INCLUDE_DIRS) list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) - endif () + endif() # cache the vars. set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) - mark_as_advanced(FFMPEG_INCLUDE_DIRS - FFMPEG_LIBRARIES) - -endif () + mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES) +endif() # Now set the noncached _FOUND vars for the components. -foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE SWRESAMPLE) +foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE SWRESAMPLE) set_component_found(${_component}) -endforeach () +endforeach() # Compile the list of required vars set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) -foreach (_component ${FFmpeg_FIND_COMPONENTS}) +foreach(_component ${FFmpeg_FIND_COMPONENTS}) list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) -endforeach () +endforeach() # Give a nice error message if some of the required vars are missing. find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) diff -Nru corsix-th-0.61/CMake/FindLibAV.cmake corsix-th-0.62/CMake/FindLibAV.cmake --- corsix-th-0.61/CMake/FindLibAV.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindLibAV.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -33,12 +33,12 @@ include(${CMAKE_CURRENT_LIST_DIR}/CMakeFFmpegLibavMacros.cmake) # The default components were taken from a survey over other FindLIBAV.cmake files -if (NOT LibAV_FIND_COMPONENTS) +if(NOT LibAV_FIND_COMPONENTS) set(LibAV_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) -endif () +endif() # Check for cached results. If there are skip the costly part. -if (NOT LIBAV_LIBRARIES) +if(NOT LIBAV_LIBRARIES) # Check for all possible component. find_component(AVCODEC avcodec libavcodec/avcodec.h libavcodec/version.h) @@ -50,40 +50,38 @@ find_component(SWSCALE swscale libswscale/swscale.h libswscale/version.h) # Check if the required components were found and add their stuff to the LIBAV_* vars. - foreach (_component ${LibAV_FIND_COMPONENTS}) - if (${_component}_FOUND) + foreach(_component ${LibAV_FIND_COMPONENTS}) + if(${_component}_FOUND) # message(STATUS "Required component ${_component} present.") set(LIBAV_LIBRARIES ${LIBAV_LIBRARIES} ${${_component}_LIBRARIES}) list(APPEND LIBAV_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) - else () + else() # message(STATUS "Required component ${_component} missing.") - endif () - endforeach () + endif() + endforeach() # Build the include path with duplicates removed. - if (LIBAV_INCLUDE_DIRS) + if(LIBAV_INCLUDE_DIRS) list(REMOVE_DUPLICATES LIBAV_INCLUDE_DIRS) - endif () + endif() # cache the vars. set(LIBAV_INCLUDE_DIRS ${LIBAV_INCLUDE_DIRS} CACHE STRING "The LibAV include directories." FORCE) set(LIBAV_LIBRARIES ${LIBAV_LIBRARIES} CACHE STRING "The LibAV libraries." FORCE) - mark_as_advanced(LIBAV_INCLUDE_DIRS - LIBAV_LIBRARIES) - -endif () + mark_as_advanced(LIBAV_INCLUDE_DIRS LIBAV_LIBRARIES) +endif() # Now set the noncached _FOUND vars for the components. -foreach (_component AVCODEC AVDEVICE AVFILTER AVFORMAT AVRESAMPLE AVUTIL SWSCALE) +foreach(_component AVCODEC AVDEVICE AVFILTER AVFORMAT AVRESAMPLE AVUTIL SWSCALE) set_component_found(${_component}) -endforeach () +endforeach() # Compile the list of required vars set(_LibAV_REQUIRED_VARS LIBAV_LIBRARIES LIBAV_INCLUDE_DIRS) -foreach (_component ${LibAV_FIND_COMPONENTS}) +foreach(_component ${LibAV_FIND_COMPONENTS}) list(APPEND _LibAV_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) -endforeach () +endforeach() # Give a nice error message if some of the required vars are missing. find_package_handle_standard_args(LibAV DEFAULT_MSG ${_LibAV_REQUIRED_VARS}) diff -Nru corsix-th-0.61/CMake/FindLua.cmake corsix-th-0.62/CMake/FindLua.cmake --- corsix-th-0.61/CMake/FindLua.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindLua.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -# Copyright (c) 2013 Martin Felis <martin@fysx.org> -# License: Public Domain (Unlicense: http://unlicense.org/) -# Modified by Edvin "Lego3" Linge for the CorsixTH project. -# -# Try to find Lua or LuaJIT depending on the variable WITH_LUAJIT. -# Sets the following variables: -# Lua_FOUND -# LUA_INCLUDE_DIR -# LUA_LIBRARY -# -# Use it in a CMakeLists.txt script as: -# -# OPTION (WITH_LUAJIT "Use LuaJIT instead of default Lua" OFF) -# UNSET(Lua_FOUND CACHE) -# UNSET(LUA_INCLUDE_DIR CACHE) -# UNSET(LUA_LIBRARY CACHE) -# FIND_PACKAGE (Lua REQUIRED) - -SET (Lua_FOUND FALSE) - -SET (LUA_INTERPRETER_TYPE "") - -IF (WITH_LUAJIT) - SET (LUA_INTERPRETER_TYPE "LuaJIT") - SET (LUA_LIBRARY_NAME luajit-5.1 lua51) - SET (LUA_INCLUDE_DIRS include/luajit-2.0 include) -ELSE (WITH_LUAJIT) - SET (LUA_INTERPRETER_TYPE "Lua") - SET (LUA_LIBRARY_NAME lua53 lua5.3 lua-5.3 liblua.5.3.dylib lua52 lua5.2 lua-5.2 liblua.5.2.dylib lua51 lua5.1 lua-5.1 liblua.5.1.dylib lua liblua) - SET (LUA_INCLUDE_DIRS include/lua53 include/lua5.3 include/lua-5.3 include/lua52 include/lua5.2 include/lua-5.2 include/lua51 include/lua5.1 include/lua-5.1 include/lua include) -ENDIF(WITH_LUAJIT) - -FIND_PATH (LUA_INCLUDE_DIR lua.h - HINTS - ENV LUA_DIR - PATH_SUFFIXES ${LUA_INCLUDE_DIRS} - PATHS - /opt/local - /usr/local - /usr - /opt - /sw - ~/Library/Frameworks - /Library/Frameworks -) -FIND_LIBRARY (LUA_LIBRARY NAMES ${LUA_LIBRARY_NAME} - HINTS - ENV LUA_DIR - PATH_SUFFIXES lib - PATHS - /usr - /usr/local - /opt/local - /opt - /sw - ~/Library/Frameworks - /Library/Frameworks -) - -IF (NOT LUA_INCLUDE_DIR) - MESSAGE(FATAL_ERROR "Could Not Find Lua Include Dir") -ENDIF (NOT LUA_INCLUDE_DIR) - -IF (NOT LUA_LIBRARY) - MESSAGE(FATAL_ERROR "Could Not Find Lua Library") -ENDIF (NOT LUA_LIBRARY) - - -IF (LUA_INCLUDE_DIR AND LUA_LIBRARY) - SET (Lua_FOUND TRUE) -ENDIF (LUA_INCLUDE_DIR AND LUA_LIBRARY) - -IF (Lua_FOUND) - IF (NOT Lua_FIND_QUIETLY) - MESSAGE(STATUS "Found ${LUA_INTERPRETER_TYPE} library: ${LUA_LIBRARY}") - ENDIF (NOT Lua_FIND_QUIETLY) -ELSE (Lua_FOUND) - IF (Lua_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find ${LUA_INTERPRETER_TYPE}") - ENDIF (Lua_FIND_REQUIRED) -ENDIF (Lua_FOUND) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua DEFAULT_MSG LUA_LIBRARY LUA_INCLUDE_DIR) - -MARK_AS_ADVANCED ( LUA_INCLUDE_DIR LUA_LIBRARY) diff -Nru corsix-th-0.61/CMake/FindPkgMacros.cmake corsix-th-0.62/CMake/FindPkgMacros.cmake --- corsix-th-0.61/CMake/FindPkgMacros.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindPkgMacros.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -#------------------------------------------------------------------- -# This file was taken from the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -# -# FindDirectX.cmake is dependant on this file. -#------------------------------------------------------------------- - -################################################################## -# Provides some common functionality for the FindPackage modules -################################################################## - -# Begin processing of package -macro(findpkg_begin PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Looking for ${PREFIX}...") - endif () -endmacro(findpkg_begin) - -# Display a status message unless FIND_QUIETLY is set -macro(pkg_message PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS ${ARGN}) - endif () -endmacro(pkg_message) - -# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes -macro(getenv_path VAR) - set(ENV_${VAR} $ENV{${VAR}}) - # replace won't work if var is blank - if (ENV_${VAR}) - string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) - endif () -endmacro(getenv_path) - -# Construct search paths for includes and libraries from a PREFIX_PATH -macro(create_search_paths PREFIX) - foreach(dir ${${PREFIX}_PREFIX_PATH}) - set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} - ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers) - set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} - ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs) - set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH} - ${dir}/bin) - endforeach(dir) - set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) -endmacro(create_search_paths) - -# clear cache variables if a certain variable changed -macro(clear_if_changed TESTVAR) - # test against internal check variable - # HACK: Apparently, adding a variable to the cache cleans up the list - # a bit. We need to also remove any empty strings from the list, but - # at the same time ensure that we are actually dealing with a list. - list(APPEND ${TESTVAR} "") - list(REMOVE_ITEM ${TESTVAR} "") - if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") - message(STATUS "${TESTVAR} changed.") - foreach(var ${ARGN}) - set(${var} "NOTFOUND" CACHE STRING "x" FORCE) - endforeach(var) - endif () - set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) -endmacro(clear_if_changed) - -# Try to get some hints from pkg-config, if available -macro(use_pkgconfig PREFIX PKGNAME) - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(${PREFIX} ${PKGNAME}) - endif () -endmacro (use_pkgconfig) - -# Couple a set of release AND debug libraries (or frameworks) -macro(make_library_set PREFIX) - if (${PREFIX}_FWK) - set(${PREFIX} ${${PREFIX}_FWK}) - elseif (${PREFIX}_REL AND ${PREFIX}_DBG) - set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) - elseif (${PREFIX}_REL) - set(${PREFIX} ${${PREFIX}_REL}) - elseif (${PREFIX}_DBG) - set(${PREFIX} ${${PREFIX}_DBG}) - endif () -endmacro(make_library_set) - -# Generate debug names from given release names -macro(get_debug_names PREFIX) - foreach(i ${${PREFIX}}) - set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) - endforeach(i) -endmacro(get_debug_names) - -# Add the parent dir from DIR to VAR -macro(add_parent_dir VAR DIR) - get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) - set(${VAR} ${${VAR}} ${${DIR}_TEMP}) -endmacro(add_parent_dir) - -# Do the final processing for the package find. -macro(findpkg_finish PREFIX) - # skip if already processed during this run - if (NOT ${PREFIX}_FOUND) - if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) - set(${PREFIX}_FOUND TRUE) - set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) - set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") - endif () - else () - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Could not locate ${PREFIX}") - endif () - if (${PREFIX}_FIND_REQUIRED) - message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") - endif () - endif () - - mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) - endif () -endmacro(findpkg_finish) - - -# Slightly customised framework finder -macro(findpkg_framework fwk) - if(APPLE) - set(${fwk}_FRAMEWORK_PATH - ${${fwk}_FRAMEWORK_SEARCH_PATH} - ${CMAKE_FRAMEWORK_PATH} - ~/Library/Frameworks - /Library/Frameworks - /System/Library/Frameworks - /Network/Library/Frameworks - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Release - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug - ) - # These could be arrays of paths, add each individually to the search paths - foreach(i ${OGRE_PREFIX_PATH}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug) - endforeach(i) - - foreach(i ${OGRE_PREFIX_BUILD}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug) - endforeach(i) - - foreach(dir ${${fwk}_FRAMEWORK_PATH}) - set(fwkpath ${dir}/${fwk}.framework) - if(EXISTS ${fwkpath}) - set(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} - ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) - set(${fwk}_FRAMEWORK_PATH ${dir}) - if (NOT ${fwk}_LIBRARY_FWK) - set(${fwk}_LIBRARY_FWK "-framework ${fwk}") - endif () - endif(EXISTS ${fwkpath}) - endforeach(dir) - endif(APPLE) -endmacro(findpkg_framework) diff -Nru corsix-th-0.61/CMake/FindSDL2.cmake corsix-th-0.62/CMake/FindSDL2.cmake --- corsix-th-0.61/CMake/FindSDL2.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindSDL2.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -152,7 +152,7 @@ #include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) include(FindPackageHandleStandardArgs) - -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL - REQUIRED_VARS SDL_LIBRARY SDL_INCLUDE_DIR - VERSION_VAR SDL_VERSION_STRING) +find_package_handle_standard_args(SDL + REQUIRED_VARS SDL_LIBRARY SDL_INCLUDE_DIR + VERSION_VAR SDL_VERSION_STRING +) diff -Nru corsix-th-0.61/CMake/FindSDL2_mixer.cmake corsix-th-0.62/CMake/FindSDL2_mixer.cmake --- corsix-th-0.61/CMake/FindSDL2_mixer.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindSDL2_mixer.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -77,9 +77,10 @@ #include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_mixer - REQUIRED_VARS SDL_MIXER_LIBRARIES SDL_MIXER_INCLUDE_DIRS - VERSION_VAR SDL_MIXER_VERSION_STRING) +find_package_handle_standard_args(SDL_mixer + REQUIRED_VARS SDL_MIXER_LIBRARIES SDL_MIXER_INCLUDE_DIRS + VERSION_VAR SDL_MIXER_VERSION_STRING +) # for backward compatibility set(SDLMIXER_LIBRARY ${SDL_MIXER_LIBRARIES}) diff -Nru corsix-th-0.61/CMake/FindVLD.cmake corsix-th-0.62/CMake/FindVLD.cmake --- corsix-th-0.61/CMake/FindVLD.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/FindVLD.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -7,18 +7,18 @@ ## VLD_LIBRARY ## ## Stephen E. Baker 2014 -SET(VLD_FOUND FALSE) +set(VLD_FOUND FALSE) -IF(${CMAKE_SIZEOF_VOID_P} MATCHES 8) - SET (VLD_LIB_SUBDIRS lib/Win64 lib) -ELSE(${CMAKE_SIZEOF_VOID_P} MATCHES 8) - SET (VLD_LIB_SUBDIRS lib/Win32 lib) -ENDIF(${CMAKE_SIZEOF_VOID_P} MATCHES 8) +if(${CMAKE_SIZEOF_VOID_P} MATCHES 8) + set (VLD_LIB_SUBDIRS lib/Win64 lib) +else() + set (VLD_LIB_SUBDIRS lib/Win32 lib) +endif() -SET (PROG_FILES_X86_ENV "PROGRAMFILES(X86)") -SET (PROG_FILES_ENV "PROGRAMFILES") +set(PROG_FILES_X86_ENV "PROGRAMFILES(X86)") +set(PROG_FILES_ENV "PROGRAMFILES") -FIND_PATH(VLD_INCLUDE_DIR vld.h +find_path(VLD_INCLUDE_DIR vld.h HINTS ENV VLD_HOME PATH_SUFFIXES include @@ -26,9 +26,8 @@ "$ENV{${PROG_FILES_X86_ENV}}/Visual Leak Detector" "$ENV{${PROG_FILES_ENV}}/Visual Leak Detector" ) -#MESSAGE("VLD_INCLUDE_DIR=${VLD_INCLUDE_DIR}") -FIND_LIBRARY(VLD_LIBRARY NAMES vld +find_library(VLD_LIBRARY NAMES vld HINTS ENV VLD_HOME PATH_SUFFIXES ${VLD_LIB_SUBDIRS} @@ -36,16 +35,15 @@ "$ENV{${PROG_FILES_X86_ENV}}/Visual Leak Detector" "$ENV{${PROG_FILES_ENV}}/Visual Leak Detector" ) -#MESSAGE("VLD_LIBRARY=${VLD_LIBRARY}") -IF(VLD_INCLUDE_DIR AND VLD_LIBRARY) - SET(VLD_FOUND TRUE) -ENDIF(VLD_INCLUDE_DIR AND VLD_LIBRARY) +if(VLD_INCLUDE_DIR AND VLD_LIBRARY) + set(VLD_FOUND TRUE) +endif() -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(VLD DEFAULT_MSG VLD_LIBRARY VLD_INCLUDE_DIR) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(VLD DEFAULT_MSG VLD_LIBRARY VLD_INCLUDE_DIR) -MARK_AS_ADVANCED( +mark_as_advanced( VLD_INCLUDE_DIR VLD_LIBRARY ) diff -Nru corsix-th-0.61/CMake/GenerateDoc.cmake corsix-th-0.62/CMake/GenerateDoc.cmake --- corsix-th-0.61/CMake/GenerateDoc.cmake 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CMake/GenerateDoc.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,85 @@ +# Find doxygen. +find_package(Doxygen) + +# Generate build targets and the doc/index.html file. +if(DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) + add_custom_target(doc) +else() + message("Cannot locate Doxygen or lua, 'doc' target is not available") +endif() + +# Add sub-targets of the 'doc' target. +if(DOXYGEN_FOUND) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/animview.doxygen.in + ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/animview.doxygen @ONLY) + + add_custom_target(doc_animview + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/animview.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMENT "Generating API documentation for AnimView" VERBATIM + ) + add_dependencies(doc doc_animview) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/leveledit.doxygen.in + ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/leveledit.doxygen @ONLY) + + add_custom_target(doc_leveledit + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/leveledit.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMENT "Generating API documentation for LevelEdit" VERBATIM + ) + add_dependencies(doc doc_leveledit) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/corsixth_engine.doxygen.in + ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/corsixth_engine.doxygen @ONLY) + + add_custom_target(doc_corsixth_engine + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/DoxyGen/corsixth_engine.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMENT "Generating API documentation for corsixth_engine" VERBATIM + ) + add_dependencies(doc doc_corsixth_engine) +endif() + +if(LUA_PROGRAM_FOUND) + add_custom_target(doc_corsixth_lua + ${LUA_PROGRAM_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/main.lua + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/corner_right.gif ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/logo.png ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/main.css ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMENT "Generating API documentation for corsixth_lua" VERBATIM + ) + add_dependencies(doc doc_corsixth_lua) +endif() + +# Generate doc/index.html file. +if(DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "CorsixTH source code documentation\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "

CorsixTH main program source code documentation

\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
    \n") +endif() + +if(DOXYGEN_FOUND) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • CorsixTH engine documentation\n") +endif() + +if(LUA_PROGRAM_FOUND) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • CorsixTH Lua documentation\n") +endif() + +if(DOXYGEN_FOUND) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "

CorsixTH helper programs source code documentation

\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
    \n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • Animation viewer documentation\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • Level editor documentation\n") +endif() + +if(DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") +endif() diff -Nru corsix-th-0.61/CMake/PrecompiledDeps.cmake corsix-th-0.62/CMake/PrecompiledDeps.cmake --- corsix-th-0.61/CMake/PrecompiledDeps.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/PrecompiledDeps.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -38,7 +38,8 @@ CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - TEST_COMMAND "") + TEST_COMMAND "" +) unset(_DEPS_GIT_URL) unset(_DEPS_GIT_SHA) @@ -47,7 +48,8 @@ # the dependencies target set_target_properties(${_DEPS_PROJECT_NAME} PROPERTIES EXCLUDE_FROM_ALL 1 - EXCLUDE_FROM_DEFAULT_BUILD 1) + EXCLUDE_FROM_DEFAULT_BUILD 1 +) set(_DEPS_TMP_PATH ${PRECOMPILED_DEPS_BASE_DIR}/tmp) set(_DEPS_MODULES_TEMPLATE_NAME ${_DEPS_TMP_PATH}/${_DEPS_PROJECT_NAME}) @@ -57,7 +59,8 @@ message(STATUS "Getting Precompiled Dependencies...") execute_process(COMMAND ${CMAKE_COMMAND} ARGS -P ${_DEPS_MODULES_TEMPLATE_NAME}-gitclone.cmake - RESULT_VARIABLE return_value) + RESULT_VARIABLE return_value + ) if(return_value) message(FATAL_ERROR "Failed to clone precompiled dependencies.") endif() @@ -67,7 +70,8 @@ message(STATUS "Checking for Precompiled Dependency Updates...") execute_process(COMMAND ${CMAKE_COMMAND} ARGS -P ${_DEPS_MODULES_TEMPLATE_NAME}-gitupdate.cmake - RESULT_VARIABLE return_value) + RESULT_VARIABLE return_value + ) if(return_value) message(FATAL_ERROR "Failed to update precompiled dependencies.") endif() @@ -82,7 +86,8 @@ # We need user to choose which arch they are intending to compile for set(DEPS_ARCH "x86" CACHE STRING "Architecture of precompiled dependencies to use.") set_property(CACHE DEPS_ARCH - PROPERTY STRINGS "x86" "x64") + PROPERTY STRINGS "x86" "x64" + ) # Generate the folder to use set(_DEPS_FOLDER_NAME "gnu-linux-" + ${DEPS_ARCH}) else() diff -Nru corsix-th-0.61/CMake/VcpkgDeps.cmake corsix-th-0.62/CMake/VcpkgDeps.cmake --- corsix-th-0.61/CMake/VcpkgDeps.cmake 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMake/VcpkgDeps.cmake 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -set(VCPKG_COMMIT_SHA "0c14322f9fd318cab1d1cae785cf7894c4ff17b8") +set(VCPKG_COMMIT_SHA "98f9c98f8e16beb48df802549a14df997bd38198") # Setup the various paths we are using set(_VCPKG_SCRIPT_NAME "build_vcpkg_deps.ps1") @@ -51,7 +51,8 @@ set(_SCRIPT_COMMAND powershell ${_SCRIPT_DIR}/${_VCPKG_SCRIPT_NAME}) execute_process(WORKING_DIRECTORY ${VCPKG_PARENT_DIR} COMMAND ${_SCRIPT_COMMAND} ${_VCPKG_ARGS} - RESULT_VARIABLE err_val) + RESULT_VARIABLE err_val +) if(err_val) message(FATAL_ERROR "Failed to build vcpkg dependencies. " "\nIf this error persists try deleting the 'vcpkg' folder.\n") diff -Nru corsix-th-0.61/CMakeLists.txt corsix-th-0.62/CMakeLists.txt --- corsix-th-0.61/CMakeLists.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CMakeLists.txt 2018-07-21 11:13:17.000000000 +0000 @@ -11,111 +11,113 @@ # - WITH_LIBAV : Whether to use LibAV (as opposed to FFMEPG) when building movies # - WITH_VLD : Build with Visual Leak Detector (requires Visual Studio) -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +cmake_minimum_required(VERSION 3.2) -SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) -IF(CMAKE_GENERATOR MATCHES "^Visual Studio 14 2015" OR CMAKE_GENERATOR MATCHES "^Visual Studio 15 2017") - OPTION(USE_VCPKG_DEPS "Build vcpkg dependencies locally" OFF) -ENDIF() +if(CMAKE_GENERATOR MATCHES "^Visual Studio 14 2015" OR CMAKE_GENERATOR MATCHES "^Visual Studio 15 2017") + option(USE_VCPKG_DEPS "Build vcpkg dependencies locally" OFF) +endif() if(USE_VCPKG_DEPS) message("Note: Using locally built vcpkg dependencies.") include(VcpkgDeps) endif() -PROJECT(CorsixTH_Top_Level) +project(CorsixTH_Top_Level) + +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11) +check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +endif() -INCLUDE(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) -IF(COMPILER_SUPPORTS_CXX11) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -ELSEIF(COMPILER_SUPPORTS_CXX0X) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -ENDIF(COMPILER_SUPPORTS_CXX11) -IF (MINGW) +if(MINGW) set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") -ENDIF(MINGW) -INCLUDE(CheckIncludeFiles) -SET(CORSIX_TH_DONE_TOP_LEVEL_CMAKE ON) +endif() + +include(CheckIncludeFiles) +set(CORSIX_TH_DONE_TOP_LEVEL_CMAKE ON) # Dependency management -if ( UNIX AND CMAKE_COMPILER_IS_GNU) - OPTION(USE_PRECOMPILED_DEPS "Use Precompiled Dependencies" OFF) # Make *nix systems opt in +if(UNIX AND CMAKE_COMPILER_IS_GNU) + option(USE_PRECOMPILED_DEPS "Use Precompiled Dependencies" OFF) # Make *nix systems opt in endif() # Define our options -OPTION(WITH_SDL "Activate SDL Renderer" ON) # our default option -OPTION(WITH_AUDIO "Activate Sound" ON) # enabled by default -OPTION(WITH_MOVIES "Activate in game movies" ON) -OPTION(WITH_FREETYPE2 "Enhanced Font Support" ON) -OPTION(WITH_LUAJIT "Use LuaJIT instead of Lua" OFF) -OPTION(WITH_LIBAV "Use LibAV instead of FFmpeg" OFF) -OPTION(BUILD_ANIMVIEWER "Build the animation viewer as part of the build process" OFF) -IF(MSVC) - OPTION(WITH_VLD "Build with Visual Leak Detector for Visual Studio" OFF) -ENDIF(MSVC) - -IF(WITH_AUDIO) - SET(CORSIX_TH_USE_SDL_MIXER ON) - MESSAGE("Note: SDL audio is enabled (default)") -ELSE() - SET(CORSIX_TH_USE_SDL_MIXER OFF) - MESSAGE("Note: SDL audio is disabled") -ENDIF(WITH_AUDIO) - -IF(WITH_MOVIES) - IF(WITH_AUDIO) - IF(WITH_LIBAV) - SET(CORSIX_TH_USE_FFMPEG OFF) - SET(CORSIX_TH_USE_LIBAV ON) - MESSAGE("Note: LibAV video is enabled") - ELSE() - SET(CORSIX_TH_USE_FFMPEG ON) - SET(CORSIX_TH_USE_LIBAV OFF) - MESSAGE("Note: FFMPEG video is enabled (default)") - ENDIF(WITH_LIBAV) - ELSE() - SET(CORSIX_TH_USE_FFMPEG OFF) - SET(CORSIX_TH_USE_LIBAV OFF) - MESSAGE("Note: FFMPEG video disabled since it requires SDL audio.") - ENDIF(WITH_AUDIO) -ELSE() - SET(CORSIX_TH_USE_FFMPEG OFF) - SET(CORSIX_TH_USE_LIBAV OFF) - MESSAGE("Note: FFMPEG video is disabled") -ENDIF(WITH_MOVIES) - -IF(WITH_FREETYPE2) - SET(CORSIX_TH_USE_FREETYPE2 ON) - MESSAGE("Note: FreeType2 is enabled (default)") -ELSE() - SET(CORSIX_TH_USE_FREETYPE2 OFF) - MESSAGE("Note: FreeType2 is disabled") -ENDIF(WITH_FREETYPE2) - -IF(MSVC) - IF(WITH_VLD) - SET(CORSIX_TH_USE_VLD ON) - MESSAGE("Note: Visual Leak Detector is enabled") - ELSE() - SET(CORSIX_TH_USE_VLD OFF) - MESSAGE("Note: Visual Leak Detector is disabled (default)") - ENDIF(WITH_VLD) -ELSE() - SET(CORSIX_TH_USE_VLD OFF) -ENDIF(MSVC) +option(USE_SOURCE_DATADIRS "Use the source directory for loading resources. Incompatible with the install target" OFF) +option(WITH_SDL "Activate SDL Renderer" ON) # our default option +option(WITH_AUDIO "Activate Sound" ON) # enabled by default +option(WITH_MOVIES "Activate in game movies" ON) +option(WITH_FREETYPE2 "Enhanced Font Support" ON) +option(WITH_LUAJIT "Use LuaJIT instead of Lua" OFF) +option(WITH_LIBAV "Use LibAV instead of FFmpeg" OFF) +option(BUILD_ANIMVIEWER "Build the animation viewer as part of the build process" OFF) +if(MSVC) + option(WITH_VLD "Build with Visual Leak Detector for Visual Studio" OFF) +endif() + +if(WITH_AUDIO) + set(CORSIX_TH_USE_SDL_MIXER ON) + message("Note: SDL audio is enabled (default)") +else() + set(CORSIX_TH_USE_SDL_MIXER OFF) + message("Note: SDL audio is disabled") +endif() + +if(WITH_MOVIES) + if(WITH_AUDIO) + if(WITH_LIBAV) + set(CORSIX_TH_USE_FFMPEG OFF) + set(CORSIX_TH_USE_LIBAV ON) + message("Note: LibAV video is enabled") + else() + set(CORSIX_TH_USE_FFMPEG ON) + set(CORSIX_TH_USE_LIBAV OFF) + message("Note: FFMPEG video is enabled (default)") + endif() + else() + set(CORSIX_TH_USE_FFMPEG OFF) + set(CORSIX_TH_USE_LIBAV OFF) + message("Note: FFMPEG video disabled since it requires SDL audio.") + endif() +else() + set(CORSIX_TH_USE_FFMPEG OFF) + set(CORSIX_TH_USE_LIBAV OFF) + message("Note: FFMPEG video is disabled") +endif() + +if(WITH_FREETYPE2) + set(CORSIX_TH_USE_FREETYPE2 ON) + message("Note: FreeType2 is enabled (default)") +else() + set(CORSIX_TH_USE_FREETYPE2 OFF) + message("Note: FreeType2 is disabled") +endif() + +if(MSVC) + if(WITH_VLD) + set(CORSIX_TH_USE_VLD ON) + message("Note: Visual Leak Detector is enabled") + else() + set(CORSIX_TH_USE_VLD OFF) + message("Note: Visual Leak Detector is disabled (default)") + endif() +else() + set(CORSIX_TH_USE_VLD OFF) +endif() # Get precompiled dependencies before running the various find modules -if ( USE_PRECOMPILED_DEPS ) +if(USE_PRECOMPILED_DEPS) message("Note: Using precompiled dependencies.") - include( PrecompiledDeps ) + include(PrecompiledDeps) endif() -# Environment handling -CHECK_INCLUDE_FILES(inttypes.h CORSIX_TH_HAS_INTTYPES_H) +include(GNUInstallDirs) # Include individual projects message("") @@ -123,21 +125,21 @@ message("Building CorsixTH") add_subdirectory(CorsixTH) -IF(BUILD_ANIMVIEWER) +if(BUILD_ANIMVIEWER) message("Building AnimView") add_subdirectory(AnimView) -ENDIF(BUILD_ANIMVIEWER) +endif() # Documentation generation, construct 'doc' target (or a message it is disabled). # Try to find 'lua' -IF (WITH_LUAJIT) - SET (LUA_PROGRAM_NAMES luajit-2.0.3 luajit) -ELSE (WITH_LUAJIT) - SET (LUA_PROGRAM_NAMES lua53 lua5.3 lua-5.3 lua52 lua5.2 lua-5.2 lua51 lua5.1 lua-5.1 lua) -ENDIF(WITH_LUAJIT) +if(WITH_LUAJIT) + set(LUA_PROGRAM_NAMES luajit-2.0.3 luajit) +else() + set(LUA_PROGRAM_NAMES lua53 lua5.3 lua-5.3 lua52 lua5.2 lua-5.2 lua51 lua5.1 lua-5.1 lua) +endif() -find_program (LUA_PROGRAM_PATH ${LUA_PROGRAM_NAMES} +find_program(LUA_PROGRAM_PATH ${LUA_PROGRAM_NAMES} PATHS ENV LUA_DIR /opt @@ -147,90 +149,10 @@ /Library/Frameworks ) -IF (LUA_PROGRAM_PATH) - SET(LUA_PROGRAM_FOUND TRUE) -ELSE (LUA_PROGRAM_PATH) - SET(LUA_PROGRAM_FOUND FALSE) -ENDIF (LUA_PROGRAM_PATH) - -# Find doxygen. -find_package(Doxygen) - -# Generate build targets and the doc/index.html file. -IF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - add_custom_target(doc) - -ELSE (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - message("Cannot locate Doxygen or lua, 'doc' target is not available") - -ENDIF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - - -# Add sub-targets of the 'doc' target. -IF (DOXYGEN_FOUND) - add_custom_target(doc_animview - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/animview.doxygen - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc - COMMENT "Generating API documentation for AnimView" VERBATIM - ) - add_dependencies(doc doc_animview) - - - add_custom_target(doc_leveledit - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/leveledit.doxygen - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc - COMMENT "Generating API documentation for LevelEdit" VERBATIM - ) - add_dependencies(doc doc_leveledit) - - - add_custom_target(doc_corsixth_engine - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/corsixth_engine.doxygen - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc - COMMENT "Generating API documentation for corsixth_engine" VERBATIM - ) - add_dependencies(doc doc_corsixth_engine) -ENDIF (DOXYGEN_FOUND) - -IF (LUA_PROGRAM_FOUND) - add_custom_target(doc_corsixth_lua - ${LUA_PROGRAM_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/main.lua - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/corner_right.gif ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/logo.png ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LDocGen/output/main.css ${CMAKE_CURRENT_BINARY_DIR}/doc/corsixth_lua - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc - COMMENT "Generating API documentation for corsixth_lua" VERBATIM - ) - add_dependencies(doc doc_corsixth_lua) -ENDIF (LUA_PROGRAM_FOUND) - -# Generate doc/index.html file. -IF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "CorsixTH source code documentation\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "

CorsixTH main program source code documentation

\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
    \n") -ENDIF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - -IF (DOXYGEN_FOUND) - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • CorsixTH engine documentation\n") -ENDIF (DOXYGEN_FOUND) - -IF (LUA_PROGRAM_FOUND) - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • CorsixTH Lua documentation\n") -ENDIF (LUA_PROGRAM_FOUND) - -IF (DOXYGEN_FOUND) - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "

CorsixTH helper programs source code documentation

\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
    \n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • Animation viewer documentation\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
  • Level editor documentation\n") -ENDIF (DOXYGEN_FOUND) - -IF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "
\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "\n") -ENDIF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND) +if(LUA_PROGRAM_PATH) + set(LUA_PROGRAM_FOUND TRUE) +else() + set(LUA_PROGRAM_FOUND FALSE) +endif() + +include(GenerateDoc) diff -Nru corsix-th-0.61/common/rnc.cpp corsix-th-0.62/common/rnc.cpp --- corsix-th-0.61/common/rnc.cpp 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/common/rnc.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,485 @@ +/* +Copyright (c) 1997 Simon Tatham + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + Original code was from http://www.yoda.arachsys.com/dk/utils.html. While + that site and the original code do not state copyright or license, email + communication releaved the original author, and they agreed to releasing it + under the MIT license (above). + + Modifications made to the original code include: + * Const correctness + * Prebuilt CRC table + * Lua interface + * Indentation and code style + * Bit stream pointers to data + * Fix bit operations near end of stream + * Style changes to conform to CorsixTH +*/ + +#include "rnc.h" +#include +#include +#include + +static const std::uint32_t rnc_signature = 0x524E4301; /*!< "RNC\001" */ + +static const std::uint16_t rnc_crc_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, +}; + +struct bit_stream +{ + std::uint32_t bitbuf; ///< holds between 16 and 32 bits. + int bitcount; ///< how many bits does bitbuf hold? + const std::uint8_t* endpos; ///< pointer past the readable data + const std::uint8_t* p; ///< pointer in data that stream is reading. +}; + +struct huf_table +{ + int num; ///< number of nodes in the tree. + struct + { + std::uint32_t code; + int codelen; + int value; + } table[32]; +}; + +//! Calculate a CRC, the RNC way. +/*! + @param data data for which to calculate the CRC + @param len length of the data in bytes +*/ +static std::uint16_t rnc_crc(const std::uint8_t* data, std::size_t len) +{ + std::uint16_t val = 0; + + while(len--) + { + val = static_cast(val ^ *data++); + val = static_cast((val >> 8) ^ rnc_crc_table[val & 0xFF]); + } + + return val; +} + + +//! Return the big-endian 32 bit word at p. +/*! + @param p Pointer to data containing the word +*/ +static std::uint32_t blong (const std::uint8_t *p) +{ + std::uint32_t n; + n = p[0]; + n = (n << 8) + p[1]; + n = (n << 8) + p[2]; + n = (n << 8) + p[3]; + return n; +} + +//! Return the big-endian 16 bit word at p. +/*! + @param p Pointer to data containing the word +*/ +static std::uint32_t bword (const std::uint8_t *p) +{ + std::uint32_t n; + n = p[0]; + n = (n << 8) + p[1]; + return n; +} + +//! Return the little-endian 16 bit word at p. +/*! + @param p Pointer to data containing the word + */ +static std::uint32_t lword (const std::uint8_t *p) +{ + std::uint32_t n; + n = p[1]; + n = (n << 8) + p[0]; + return n; +} + +//! Mirror the bottom n bits of x. +/*! + @param x + @param n +*/ +static std::uint32_t mirror (std::uint32_t x, int n) +{ + std::uint32_t top = 1 << (n-1), bottom = 1; + while (top > bottom) + { + std::uint32_t mask = top | bottom; + std::uint32_t masked = x & mask; + if (masked != 0 && masked != mask) + { + x ^= mask; + } + top >>= 1; + bottom <<= 1; + } + return x; +} + + +//! Initialises a bit stream with the first two bytes of the packed +//! data. +/*! + @param bs Bit stream to be initialized + @param p Pointer to start of memory block the bitstream is to + traverse + @param endpos Pointer to byte after the last memory block the bitstream is + to traverse +*/ +static void bitread_init (bit_stream *bs, const std::uint8_t *p, const std::uint8_t* endpos) +{ + bs->bitbuf = lword(p); + bs->bitcount = 16; + bs->p = p; + bs->endpos = endpos; +} + +//! Fixes up a bit stream after literals have been read out of the +//! data stream and the pointer has been moved. +/*! + @param bs Bit stream to correct +*/ +static void bitread_fix (bit_stream *bs) +{ + // Remove the top 16 bits + bs->bitcount -= 16; + bs->bitbuf &= (1<bitcount)-1; + + // Replace with what is in the new current location + // in the bit stream + if(bs->p < bs->endpos - 1) + { + bs->bitbuf |= (lword(bs->p)<bitcount); + bs->bitcount += 16; + } else if (bs->p == bs->endpos - 1) { + bs->bitbuf |= (*(bs->p)<bitcount); + bs->bitcount += 16; + } +} + +//! Return a word consisting of the specified bits without advancing +//! the bit stream. +/*! + @param bs Bit stream from which to peek + @param mask A 32 bit bit mask specifying which bits to peek +*/ +static std::uint32_t bit_peek (bit_stream *bs, const std::uint32_t mask) +{ + return bs->bitbuf & mask; +} + +//! Advances the bit stream. +/*! + @param bs Bit stream to advance + @param n Number of bits to advance the stream. Must be + between 0 and 16 +*/ +static void bit_advance (bit_stream *bs, int n) +{ + bs->bitbuf >>= n; + bs->bitcount -= n; + + if (bs->bitcount < 16) + { + // At this point it is possible for bs->p to advance past + // the end of the data. In that case we simply do not read + // anything more into the buffer. If we are on the last + // byte the lword matches what is in that byte. + bs->p += 2; + + if (bs->p < (bs->endpos - 1)) + { + bs->bitbuf |= (lword(bs->p)<bitcount); + bs->bitcount += 16; + } else if (bs->p < bs->endpos) { + bs->bitbuf |= (*(bs->p)<bitcount); + bs->bitcount += 16; + } + } +} + +//! Returns bits from the bit stream matching the mask and advances it +//! n places. +/*! + @param bs Bit stream to read + @param mask A 32 bit bit mask specifying which bits to read + @param n Number of bits to advance the stream. Must be + between 0 and 16 +*/ +static std::uint32_t bit_read (bit_stream *bs, std::uint32_t mask, int n) +{ + std::uint32_t result = bit_peek(bs, mask); + bit_advance(bs, n); + return result; +} + +//! Read a Huffman table out of the bit stream given. +/*! + @param h huf_table structure to populate + @param bs Bit stream pointing to the start of the Huffman table + description +*/ +static void read_huftable(huf_table *h, bit_stream *bs) +{ + int i, j, k, num; + int leaflen[32]; + int leafmax; + std::uint32_t codeb; /* big-endian form of code. */ + + num = bit_read(bs, 0x1F, 5); + + if(num == 0) + { + return; + } + + leafmax = 1; + for(i = 0; i < num; i++) + { + leaflen[i] = bit_read(bs, 0x0F, 4); + if (leafmax < leaflen[i]) + { + leafmax = leaflen[i]; + } + } + + codeb = 0L; + k = 0; + for(i = 1; i <= leafmax; i++) + { + for(j = 0; j < num; j++) + { + if(leaflen[j] == i) + { + h->table[k].code = mirror(codeb, i); + h->table[k].codelen = i; + h->table[k].value = j; + codeb++; + k++; + } + } + codeb <<= 1; + } + h->num = k; +} + +//! Read a value out of the bit stream using the given Huffman table. +/*! + @param h Huffman table to transcribe from + @param bs bit stream + @param p input data + @return The value from the table with the matching bits, or -1 if none found. +*/ +static std::uint32_t huf_read(huf_table *h, bit_stream *bs, const std::uint8_t **p) +{ + int i; + std::uint32_t val; + std::uint32_t mask; + + // Find the current bits in the table + for (i = 0; i < h->num; i++) + { + mask = (1 << h->table[i].codelen) - 1; + if(bit_peek(bs, mask) == h->table[i].code) + { + break; + } + } + + // No match found in table (error) + if(i == h->num) + { + return -1; + } + + bit_advance(bs, h->table[i].codelen); + + val = h->table[i].value; + if (val >= 2) + { + val = 1 << (val-1); + val |= bit_read(bs, val-1, h->table[i].value - 1); + } + return val; +} + +std::size_t rnc_output_size(const std::uint8_t* input) +{ + return static_cast(blong(input + 4)); +} + +std::size_t rnc_input_size(const std::uint8_t* input) +{ + return static_cast(blong(input + 8) + rnc_header_size); +} + +//! Decompresses RNC data +/*! + @param input Pointer to compressed RNC data + @param output Pointer to allocated memory region to hold uncompressed + data. The size of output must match the value specified in the + 4 byte segment of the input header starting at the 4th byte + in Big-endian. +*/ +rnc_status rnc_unpack(const std::uint8_t* input, std::uint8_t* output) +{ + const std::uint8_t *inputend; + std::uint8_t *outputend; + bit_stream input_bs; + huf_table raw = {0}, dist = {0}, len = {0}; + std::uint32_t ch_count; + std::uint32_t ret_len; + std::uint32_t out_crc; + if(blong(input) != rnc_signature) + { + return rnc_status::file_is_not_rnc; + } + ret_len = blong(input + 4); + outputend = output + ret_len; + inputend = input + 18 + blong(input + 8); + + //skip header + input += 18; + + // Check the packed-data CRC. Also save the unpacked-data CRC + // for later. + if (rnc_crc(input, inputend - input) != bword(input - 4)) + { + return rnc_status::packed_crc_error; + } + out_crc = bword(input - 6); + + //initialize the bitstream to the input and advance past the + //first two bits as they don't have any understood use. + bitread_init(&input_bs, input, inputend); + bit_advance(&input_bs, 2); + + //process chunks + while (output < outputend) + { + read_huftable(&raw, &input_bs); //raw byte length table + read_huftable(&dist, &input_bs); //distance prior to copy table + read_huftable(&len, &input_bs); //length bytes to copy table + ch_count = bit_read(&input_bs, 0xFFFF, 16); + + while(true) + { + long length, posn; + + // Copy bit pattern to output based on lookup + // of bytes from input. + length = huf_read(&raw, &input_bs, &input); + if(length == -1) + { + return rnc_status::huf_decode_error; + } + if(length) + { + while(length--) + { + *output++ = *(input_bs.p++); + } + bitread_fix(&input_bs); + } + if(--ch_count <= 0) + { + break; + } + + // Read position to copy output to + posn = huf_read(&dist, &input_bs, &input); + if(posn == -1) + { + return rnc_status::huf_decode_error; + } + posn += 1; + + // Read length of output to copy back + length = huf_read(&len, &input_bs, &input); + if(length == -1) + { + return rnc_status::huf_decode_error; + } + length += 2; + + // Copy length bytes from output back posn + while (length > 0) + { + length--; + *output = output[-posn]; + output++; + } + } + } + + if(outputend != output) + { + return rnc_status::file_size_mismatch; + } + + // Check the unpacked-data CRC. + if (rnc_crc(outputend - ret_len, ret_len) != out_crc) + { + return rnc_status::unpacked_crc_error; + } + + return rnc_status::ok; +} diff -Nru corsix-th-0.61/common/rnc.h corsix-th-0.62/common/rnc.h --- corsix-th-0.61/common/rnc.h 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/common/rnc.h 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,48 @@ +/* +Copyright (c) 2009 Peter "Corsix" Cawley + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef CORSIX_TH_RNC_H_ +#define CORSIX_TH_RNC_H_ + +#include +#include + +/*! Result status values from #rnc_inpack. */ +enum class rnc_status +{ + ok, ///< Everything is fine + file_is_not_rnc, ///< The file does not begin with an RNC signature + huf_decode_error, ///< Error decoding the file + file_size_mismatch, ///< The file size does not match the header + packed_crc_error, ///< The compressed file does not match its checksum + unpacked_crc_error ///< The uncompressed file does not match its checksum +}; + +const std::size_t rnc_header_size = 18; + +std::size_t rnc_output_size(const std::uint8_t* input); + +std::size_t rnc_input_size(const std::uint8_t* input); + +rnc_status rnc_unpack(const std::uint8_t* input, std::uint8_t* output); + +#endif // CORSIX_TH_RNC_H_ diff -Nru corsix-th-0.61/CorsixTH/Bitmap/mkbootstrap.lua corsix-th-0.62/CorsixTH/Bitmap/mkbootstrap.lua --- corsix-th-0.61/CorsixTH/Bitmap/mkbootstrap.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Bitmap/mkbootstrap.lua 2018-07-21 11:13:17.000000000 +0000 @@ -47,9 +47,9 @@ l = f(s, l) lines[#lines + 1] = l until l == "/* Start autogenerated content */" -merge("bootstrap_font.tab", "g_aBootstrapFontTab") -merge("bootstrap_font.dat", "g_aBootstrapFontDat") -merge("bootstrap_font.pal", "g_aBootstrapFontPal") +merge("bootstrap_font.tab", "bootstrap_font_tab") +merge("bootstrap_font.dat", "bootstrap_font_dat") +merge("bootstrap_font.pal", "bootstrap_font_pal") while l ~= "/* End autogenerated content */" do l = f(s, l) end diff -Nru corsix-th-0.61/CorsixTH/Bitmap/mkfont.lua corsix-th-0.62/CorsixTH/Bitmap/mkfont.lua --- corsix-th-0.61/CorsixTH/Bitmap/mkfont.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Bitmap/mkfont.lua 2018-07-21 11:13:17.000000000 +0000 @@ -29,8 +29,8 @@ package.path = (debug.getinfo(1, "S").source:match("@(.*[" .. package.config :sub(1, 1) .. "])") or "") .. "lib_" .. package.config:sub(5, 5) .. ".lua" .. package.config:sub(3, 3) .. package.path -require "bmp" -require "spritesheet" +require("bmp") +require("spritesheet") local bitmap_name, cell_width, cell_height, space_width = ... cell_width = assert(tonumber(cell_width), "cell width must be a number") diff -Nru corsix-th-0.61/CorsixTH/Bitmap/mkraw.lua corsix-th-0.62/CorsixTH/Bitmap/mkraw.lua --- corsix-th-0.61/CorsixTH/Bitmap/mkraw.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Bitmap/mkraw.lua 2018-07-21 11:13:17.000000000 +0000 @@ -27,7 +27,7 @@ package.path = (debug.getinfo(1, "S").source:match("@(.*[" .. package.config :sub(1, 1) .. "])") or "") .. "lib_" .. package.config:sub(5, 5) .. ".lua" .. package.config:sub(3, 3) .. package.path -require "bmp" +require("bmp") local filename = ... if not filename:match("%.bmp$") then diff -Nru corsix-th-0.61/CorsixTH/Bitmap/mksheet.lua corsix-th-0.62/CorsixTH/Bitmap/mksheet.lua --- corsix-th-0.61/CorsixTH/Bitmap/mksheet.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Bitmap/mksheet.lua 2018-07-21 11:13:17.000000000 +0000 @@ -27,8 +27,8 @@ package.path = (debug.getinfo(1, "S").source:match("@(.*[" .. package.config :sub(1, 1) .. "])") or "") .. "lib_" .. package.config:sub(5, 5) .. ".lua" .. package.config:sub(3, 3) .. package.path -require "bmp" -require "spritesheet" +require("bmp") +require("spritesheet") local specfile = ... specfile = assert(loadfile(specfile)) Binary files /tmp/tmprJpyU4/86gE7cxuSB/corsix-th-0.61/CorsixTH/Campaigns/Hoppalong.map and /tmp/tmprJpyU4/mVa0JCNMN1/corsix-th-0.62/CorsixTH/Campaigns/Hoppalong.map differ diff -Nru corsix-th-0.61/CorsixTH/changelog.txt corsix-th-0.62/CorsixTH/changelog.txt --- corsix-th-0.61/CorsixTH/changelog.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/changelog.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,1071 +0,0 @@ -------------------------------------------------------------------------------- -Version 0.60 - released May 2016 -------------------------------------------------------------------------------- - ---- Highlights from this release --- - -* User campaigns - It is now possible to create a series of levels that play - together just like the original game. -* In game map editor - A new map editor is available directly from the game - menu. -* Drug price impact - Patients will now react to the price you set for - treatments. If treatments cost too much patients will opt to go home instead - and this can affect your reputation. -* Variable spawn rate - The spawn rate will now take into account your - hospital's reputation (after a date set in the level file.) -* Machine smoke is now visible when machines are close to worn out. -* Right clicking the timer is now supported like in the original game for - moving to affected patients - See issue #882 for details. -* Numpad support - The number pad can now be used to move around the map when - numlock is off, or to type numbers when numlock is on, without side effects. -* The MP3 folder can now be unset from within the game. Previously after - setting an mp3 folder it could only be removed by editing the config file by - hand. -* Uses the proper cursor for resizing rooms. -* Bins can now be placed in the hallways. -* Temperature impact has been tweaked. The initial grace period has been - removed and the overall impact has been softened. -* Custom maps can now be stored in a user directory separate from levels - shipped with the game. - ---- Notable bug fixes --- - -* Free build mode is now truly free - rooms used to cost money in this mode. -* In game movies will now work correctly on more hardware. -* Sound effects are no longer played when sound is disabled. -* VIP rewards have been tweaked to closer match expectations when the - impression is mediocre. -* Crash when a patient is selected while they walk off the map is fixed. -* A room built next to an unowned parcel no longer loses its wall when the - parcel is bought. -* Beta 1 regression that caused fired staff to continue to be paid has been - patched. -* Beta 1 regression that caused the last cured emergency patient not to count - has been patched. -* King complex patients only pay for their cure once. -* Patients will notice when a room they are waiting for becomes available. -* Properly load saves with more than one object on a tile. -* Do not get stuck in an infinite loop when no disease is available to spawn. - -------------------------------------------------------------------------------- -Version 0.50 - released July 2015 -------------------------------------------------------------------------------- - -The majority of changes in this update have been done under the hood. -Most of our third-party libraries have been updated, and especially Windows -users will notice that there is now only one executable after installation. -No more "which one should I use if I want zoom?"! - - ---- Gameplay --- - -* Fix: Crash when trying to play certain sounds from e.g. the French version. -* Fix: Potential crash from Esc-press before main menu. -* Fix: Patients could in some circumstances get really confused and try to exit - a room without putting any clothes on. - -* Added: Configuration of scroll speed. -* Change: Midi tracks will be played in the order they appear in MIDI.txt - -* Most languages have been updated. - - ---- Movies --- - -* Fix: Audio stutter in certain movies. -* Fix: The game could sometimes crash when a movie had finished. -* Support for LibAV as an alternative to FFMpeg. - - ---- Animation Viewer --- - -* Added: A vertical scroll bar to the sprite display. - - ---- CorsixTH development --- - -* We have moved to newer versions of a lot of libraries, most notably - SDL 1.2 -> SDL 2 and added support for Lua 5.2 and Lua 5.3. -* New ready-to-use Eclipse Workspace. -* Debugging Lua code using DBGp has been added. See - the Wiki for more information. -* The Windows Installer now uses NSIS 3.0 and only produces one executable - since SDL 2 handles renderer itself. -* Framework for Busted Unit Tests in Lua. -* Support for custom graphics has been improved. - - -------------------------------------------------------------------------------- -Version 0.40 - released December 2014 -------------------------------------------------------------------------------- - -It has been a while since our last release, but good things come to those who wait! -Or... in this case it's contagious diseases. Watch out for epidemics on the -later levels in the campaign! Your patients are not as good as they used to be -either, so those who are not lucky enough to get vaccinated and cured might -get a visit from the Grim Reaper. -Also, don't forget to try out the new map St. Peter's near Cawley! - -Happy gaming! - - ---- Gameplay --- - -* Added: Epidemics. You can either choose to pay a fine to the authorities or - try to cover up the epidemic by vaccinating and curing the contagious patients. - Patients going between buildings will NOT trigger the alarm to the authorities. -* Added: The Grim Reaper. Previously patients have always gone to heaven when - they die. No more! Sometimes they will instead fall down to the middle of the - earth in a Lava Hole. -* Added: People with visual diseases will no longer arrive at the beginning of - the level if that has been specified in the level file. Instead they arrive - once a certain amount of months have passed. -* Added: If you refuse VIP visits a few times he can sometimes show up anyway. - -* Change: Machine usage and explosions are now based on absolute number of uses. - A machine that goes down to 0 will explode. Previously they were percentage based. - -* Fix: The game would crash if you sacked a doctor in a room while a patient - was using some equipment in that room. -* Fix: Sometimes the emergency bonus was not correctly calculated. -* Fix: Patients could die inside a room. They will now die outside the room - unless they are just being cured. -* Fix: If winning the level at end of year the annual report would hide the - winning fax. -* Fix: If there was no queue to a room a leaving staff member would not trigger - a call for staff for the patient who had to abort their procedure in that room. -* Fix: If a handyman had pending tasks when he died in an exploding room the game - could crash. -* Fix: A surgeon that is removed in mid-operation will now get properly replaced - by a new one. -* Fix: If the GP room was built too early in the tutorial the game would crash - when building a GP room later on if debug mode was turned off. -* Fix: Patients would try to enter an exploding room. As you can imagine, - this was bad. -* Fix: Psychiatrists would become shut-ins and just wander about their office - forever. -* Fix: Patients leaving the queue to get a drink could be left to sit on a - bench forever. - - ---- User Interface --- - -* Added: Tooltips for the increase and decrease buttons in the research screen. -* Added: A sound that indicates if a screenshot was taken successfully. -* Added: Any dialog that pops up, such as the award screen, pauses the game. -* Added: 'Continue Game' in the main menu. - -* Fix: Sometimes the game would not pause on year end. -* Fix: Staff raise description was hard to read in some languages -* Fix: The current language setting is translated and consistent with the - options in the list. - - ---- Graphics --- - -* Fix: Instead of turning into a Bloaty Head, Baldness patients will die - with gracious hair. -* Fix: Patients will no longer fall through walls when dying. -* Fix: Dying Hairyitis patients should not lose their head when on the floor. - - ---- Hotkeys --- - -* Added: 'Z' temporarily moves the game at maximum speed. Release to go back - to the previous speed. -* Added: 'X' makes walls transparent until released. -* Added: Use the Numpad to change game speed. -* Added: Arrow key hotkeys in the staff management screen. -* Added: Press and hold on '+' and '-' when buying furniture to - repeat the action. - -* Change: Quick Save is now Shift+Alt+S, Quick Load is Shift+Alt+L. - - ---- Languages --- - -* Change: "Plot" is used instead of "Parcel" to indicate where a handyman has - been zoned to work in the Handyman staff dialog. - -Most languages have been updated since our last release, but if you find that -your language has not, please help us to finish it! - - ---- CorsixTH Development --- - -* Added: New flag for CMAKE: 'WITH_LUAJIT'. This way you can choose to use - either LuaJIT or Lua5.1. -* Added: CMake toolchain for building with MinGW. -* Added: New debug menu option 'Run debug Script' that executes - /Lua/debug_script.lua - - -------------------------------------------------------------------------------- -Version 0.30 - released November 2013 -------------------------------------------------------------------------------- - -This release contains a whole new Level Editor, which means that in combination -with the already existing Map Editor whole levels can now be created a lot -easier. Give it a try! We have also added many new options previously only -available by manually editing the config file to the options dialog. -Players will also notice that we have added an automatic update -check on game launch once we release the version after this one. -As usual there are of course also numerous minor tweaks here and there. - - - ---- Gameplay --- - -* Change: You can now build more than one desk in the ward. More nurses means - a slightly faster throughput. -* Change: Patients would previously queue outside toilets even though there were - free loos since it was dependent on number of people in the room. Now, as soon - as a loo becomes free another patient enters the room to use it, - even if there is a long queue for the sink). - If there is a queue for the sinks there is a chance the patient will leave - without washing their hands - but will not be happy about doing this. - -* Added: The ability to control alien behaviour - sitting, knocking doors, - only to be available through emergency or arrive like all other patients. -* Added: Winning fax opens automatically and pauses the game. -* Added: Option to automatically accept wage increase requests when they "time out". -* Added: A new option allows for your average build content for each type of room - to be remembered, so will be added for each new room built later. - -* Fix: Doctors should get stuck less often, and handymen should not crash the - game as frequently. -* Fix: It was not possible to replace a surgeon when a patient was in the room. -* Fix: Patients would sometimes get stuck inside a room when they should - have died. - - - ---- User Interface --- - -* Added: A new customization menu in the Options dialog. Most options from the - configuration file are now available for change in-game. -* Added: A new directory menu in the Options dialog. -* Added: The game does now check for a more recent version of itself when - launching. -* Added: A helpful message when the player puts more Researchers in the - research department than there are desks. -* Added: The game now does a small integrity check on the Theme Hospital - files to make sure that the most common corruptions are not present. -* Added: Confirm dialog to the quit/exit button on the main menu. - -* Fix: The tooltip for the tutorial button was incorrect since the dialog - has been visually changed. -* Fix: The announcer has had a few corrections made to his manuscripts. - He is very happy about this! - -* Removed: The settings menu is no longer available from within the game. - - - ---- Hotkeys --- - -Some hotkeys have been changed and/or added: - -* Alt + A = Toggle Announcements -* Alt + M = Toggle Music -* Alt + S = Toggle Sound Effects -* Shift and + to zoom in five steps and Shift and - to zoom out five steps at a time. - - - ---- Campaign levels --- - -* Fix: An error in level 8 made it possible to win without meeting the - reputation criterion. - - - ---- Custom levels --- - -* Change: For random emergencies each illness now has its own average number of - patients to spawn. Previously they were all the same. - -* Fix: Researching improvements was not really possible on some custom levels, - i.e. if the map creator had made it so there were no machines at the start. - - - ---- Demo files --- - -* Fix: When winning the demo level CorsixTH looked for another level to load, - showing the wrong fax options and eventually crashing. - - - ---- Languages --- - -* Added: Korean language. - -* Fix: It was not possible to dump strings for a language with unicode - characters in the name. - - - ---- Compiling --- - -* Fix: You could not compile the game with WITH_AUDIO=0 if SDL_mixer was - not present at all. -* Fix: WITH_AUDIO=OFF is now illegal in combination with WITH_MOVIES=ON. - - - -------------------------------------------------------------------------------- -Version 0.21 - released 2013-05-04 -------------------------------------------------------------------------------- - -This is mainly a bugfix release, but a few minor features are still also -introduced, see the changelog below. - - - ---- Gameplay --- - -* Fix: Staff would sometimes not go for a break. -* Fix: A few crashes related to Handymen. -* Fix: An error could occur if a fax message was removed just as it was animating - into view. -* Fix: Patients could sometimes be told to go home multiple times, - resulting in a crash. -* Fix: If a queueing patient was heading for a drinks machine just as the player - moved that machine the game would crash. - - - ---- User Interface --- - -* Added: Scrolling momentum when using the middle button. -* Added: There is now a clock in the right corner of the menu bar that - shows the real world time. It can be toggled between AM/PM and 24h - in the configuration file. - - - ---- Hotkeys --- - -* Added: Hotkeys for the Jukebox (J), Save game menu (Shift + S), - Load game menu (Shift + L), to restart the level (Shift + R) and finally - quit the current game and take you back to the opening screen (Shift + Q). - -* Change: Restart is now Shift + F10 instead of only F10. -* Change: Toggle adviser is now Shift + A instead of only A. -* Change: Key combinations will only trigger if that exact combination - is pressed. E.g. Ctrl + R will not trigger R too. -* Change: Alt + F4 is now the hotkey to quit CorsixTH. - -* Fix: Added a configuration option to have the possibility to use Shift + C - as hotkey to open the Drug casebook instead of C. This is to workaround - a bug that when you press on the volume down key on your keyboard - the Drug casebook would open. - - - ---- Map Editor --- - -* Added: Undo/Redo functionality. -* Added: Street lamps and the dead looking tree. - - - -------------------------------------------------------------------------------- -Version 0.20 - released 2013-03-24 -------------------------------------------------------------------------------- - -In this version major new features include in-game movies, objects that -occupy only the edge of a tile and the graph window. - - - ---- Main features not yet implemented --- - -* Epidemics. -* Rats (and the rat level). -* Insurance company graphs, illness graphs. -* Visual effects on patients with serious radiation and jellyitis. -* Some fullscreen animations such as the winning letter. -* Multiplayer support. - -For a (nearly) complete list, visit our Programming Ideas wiki page: -http://code.google.com/p/corsix-th/wiki/ProgrammingIdeas - - - ---- Known Issues --- - -* Emotion icons don't appear just above a humanoid's head at all times. -* Main menu/in-game may glitch when using the OpenGL version. - -For a complete list, visit the issue tracker: -http://code.google.com/p/corsix-th/issues/list - - - ---- Gameplay --- - -* Added: Radiators and other "edge tile" objects now occupy just one edge of - the tile, inline with the original game. As a result one tile corridors can - now be heated properly. An addition is that you can place many such objects - on a single tile as long as they face different directions. - -* Added: Possibility to play movies in-game. At the moment the intro movie, - advancement between levels and the win/lose movies has been added. - -* Added: The atom analyzer can now be built in the research department if it - is available on the map. - -* Added: User actions are no longer allowed by default (for new games) when - the game is paused. When trying this it might seem like it doesn't work - correctly, but we try to mimic the original as much as possible. This for - example means that a staff member being placed as you pause will disappear - from the cursor. We might change this behaviour in the future though. - -* Added: Some background sounds, coughs, phones ringing etc. - -* Change: Placing a member of staff inside a room that is already occupied - will now replace that person. - -* Fix: Earthquakes could be four times as severe as intended. Still todo: - A tremor before a coming big earthquake. - -* Fix: Crashes in certain situations involving receptionists and reception - desks. -* Fix: Patients being handled at a reception desk even if no receptionist - is present. -* Fix: Allow patients to be sent to the research room only if the corresponding - room is not yet researched (so not if it is researched but not built). -* Fix: Don't cancel a place staff action just because the player happens to - click on a door. -* Fix: The VIP would try to sit down if there was a queue for the reception desk. - The VIP will no longer ever try to sit down, and he will have priority in - the queue anyway. -* Fix: If a member of staff was done resting at the same time as he/she was - also finished using the pool table or the video game another object in the - room could get reserved indefinitely. - - - ---- User Interface --- - -* Added: You can now see in the bank statement which drug company a certain - drug was bought from. It has no effect on gameplay though. - -* Added: The adviser now tells you why the research screen can't be opened - before you have built a research department. - -* Added: The Town Map functionality has been extended inline with Theme - Hospital. For example, if you right-click somewhere in your hospital the - view will be moved there. - -* Added: Available options on open faxes now gets updated if for example a room - explodes or the player builds a research department. -* Added: Keyboard shortcuts F1 - F9 for the fullscreen windows. They are NOT the - same as in original TH but instead correspond to the order on the bottom panel. -* Added: Possibility to choose font file in the options dialog. -* Added: Player name is now customizable in the new game dialog. - -* Removed: Keyboard shortcuts F8 and F9 for debug fax and debug patients. -* Change: Don't require debug mode to be able to dump the gamelog. -* Change: The shortcut for dumping strings is now Ctrl+T instead of Ctrl+Shift+D. - -* Change: Restructured options window to make it more consistent, less clutter-y - and smaller. -* Change: It is now possible to concentrate research on operating theatre - diseases and redistribution of research is automatically done when - a category has been completely researched. -* Change: Add disease name to patients' treatment history when they are - diagnosed. -* Change: Buttons on the bottom panel for fullscreen windows are now - toggle buttons. -* Change: Reordered entries of graphs menu to correspond with order in - bottom panel. - -* Fix: Colour selection algorithm for freetype fonts resulted in unreadable text - on faxes for some languages. -* Fix: When an unanswered fax became meaningless (e.g. if you built the - required room), it was only removed if its message button was visible at the - bottom panel (not if it was queued because of 5 buttons being there already). -* Fix: Update the drug casebook if the last room of one kind explodes. -* Fix: The directory browser was not always shown if the chosen Theme Hospital - install directory was illegal. -* Fix: Settings changed in the game will be saved immediately so that they - persist to the next session regardless of how the game is shut down. -* Fix: The bottom panel is no longer always on top, making fullscreen - dialogs truly fullscreen on 640x480. -* Fix: Don't play any announcements if there is no receptionist to do it. -* Fix: The adviser would not idle again if a new message arrived as he was - idling from a previous message. -* Fix: While a player viewed the confirm dialog to delete a room he/she could - continue to edit the room and complete it again resulting in an inconsistent - game state. - - - ---- Graphics --- - -* Added: The graph dialog now actually displays graphs and statistics information. - -* Added: It is now possible to choose among three colour scales for warmth - level. Look in the top menu for this choice. - -* Added: Print some info in the command prompt when the user wants to take - a screenshot, so he can see if and why it failed. -* Added: Screenshot functionality for OpenGL version. -* Change: Screenshots get saved to a dedicated screenshot folder now, - which can be changed in the config. -* Fix: Loading a game on startup where a fullscreen window was open would - open with the font messed up. -* Fix: Taking a screenshot (Ctrl+S) is now possible under windows without - fiddling in a lua file. - - - ---- Translations --- - -* Added: The beginning of Brazilian Portuguese and Hungarian. -* Change: The "utf8" prefix has been obsolete for some time and has been - removed from all language files. - - - ---- When using Demo files --- - -* Fix: The game would crash if the player tried to open the staff management - dialog by clicking on a staff portrait in the staff dialog. - - - -------------------------------------------------------------------------------- -Version 0.11 - released 2012-11-17 -------------------------------------------------------------------------------- - -This is a bugfix release. For known issues etcetera, check out the -changelog for version 0.10 below. - - --- Gameplay -- - -* Fix: Patients were not fully diagnosed according to settings - in the policy screen. -* Fix: The game now handles a player trying to cheat into an earthquake - on levels 1-4. -* Fix: It was not possible to sell equipment in rooms if you had a negative - balance. -* Fix: Handymen could not be placed inside rooms. -* Fix: Handymen would get called to clean soot in blown up rooms. -* Fix: Machines that need to be repaired will now cancel that request if - they are blown up. -* Fix: If a cured patient was leaving a room just as it crashed because - of an earthquake the game would throw an error. -* Fix: Alien DNA could under some circumstances not have the - "concentrate research" button clicked without triggering a crash. -* Fix: A crash occurring under some circumstances if the player picked - up a staff member. - - --- User Interface -- - -* Enhancement: Since consultants are unable to learn new skills icons for - not yet fully learned skills are now removed when a doctor is promoted. -* Fix: Disabling background music no longer disables sound effects on Windows. -* Fix: Checking if a sound exists crashed the game if there was no sound - archive at all. -* Fix: If the player paused the game from the top menu bar while an earthquake - was active it would be impossible to scroll. - - --- Graphics -- - -* Fix: On a few levels some sliding doors would not animate correctly. -* Fix: Vomiting standard males had the wrong animation. - - - -------------------------------------------------------------------------------- -Version 0.10 - released 2012-09-24 -------------------------------------------------------------------------------- - --- How versions work -- - -If you have been wondering how the new version system works: -When major new features are added the second digit is increased. -When there are only fixes or smaller new features the third digit -is increased. - -In this version, for example, earthquakes have been added. - --- Not Yet Implemented -- - -* Epidemics -* Rats -* Graphs -* Visual effects on patients with serious radiation and jellyitis. -* Fullscreen animations such as the level screen and winning letter. - --- Known Issues -- - -* If the X-Ray Viewer is inaccessible in the Operating Theatre no image will - be shown on it. -* If the user exits the game via "the cross" when in windowed mode settings - are not saved. -* Radiators and other "edge tile" objects occupy a whole tile instead of - just one edge of the tile. - --- Gameplay -- - -* Added: Earthquakes have recently been reported! -* Added: Handyman priorities have been added. They can also be told to stay - and respond to calls in one building (parcel) only. -* Added: Staff's happiness will change due to more environmental factors. - -* Change: The files containing dumped strings are now created alongside the - config file instead of in the installation directory. - -* Fix: Handymen will now meander inside a room until the machine which needs - repair is free for use. -* Fix: The URL in the config file pointing to better quality music was outdated. - Note that this only affects new installations. -* Fix: Two identical entries were shown in the drug casebook if a new disease - was discovered when it was open. -* Fix: Don't crash when a saved game with the town map open is loaded. -* Fix: Too large rooms could make them unusable. -* Some graphical glitches have been fixed. - --- User Interface -- - -* Added: The Map Editor and Animation Viewer have new icons. -* Change: In debug mode all gamelog output is now also displayed in the - command prompt. -* Fix: Don't initiate a window move if it happens to be below a top menu - selection. -* Fix: Don't show the main menu under any circumstances when closing the - options menu in-game. - --- Map Editor -- - -* Fix: The "Save" and "Save As" buttons now do what they should do. -* Fix: There were some strange log messages on opening the editor. -* Added: The arrow keys can now be used to scroll the map. -* Change: Removed a lot of tiles from the palette, since maps may not - work as intended if they would be used. - -------------------------------------------------------------------------------- -Version 0.01 - released 2012-03-24 -------------------------------------------------------------------------------- - --- Not Yet Implemented -- - -* Earthquakes -* Epidemics -* Handyman priorities -* Rats -* Graphs -* Visual effects on patients with serious radiation and jellyitis. -* Fullscreen animations such as the level screen and winning letter. - --- Known Issues -- - -* If the X-Ray Viewer is inaccessible in the Operating Theatre no image will - be shown on it. -* If the user exits the game via "the cross" when in windowed mode settings - are not saved. -* Radiators and other "edge tile" objects occupy a whole tile instead of - just one edge of the tile. - --- Gameplay -- - -* Added: A host of awards given at year end. -* Added: A new mode: Free Build Mode. In this mode you don't have to worry - about money. All custom maps can be played in this mode. -* Added: Patient animations such as yawning and checking watch when waiting. - -* Change: The queue size for a room can be set to 0 to prevent patients - from going there. -* Change: Patients now spend some more time in the ward. - -* Fix: Crash when removing a room that has humanoids on their way to it. -* Fix: Patients sitting down, but about to get a soda got ordered to sit down again. -* Fix: A crash could occur if a new room was accepted when there were multiple types - of objects left to place. -* Fix: Emergencies with diseases not available on a level no longer happen. -* Fix: The VIP no longer makes staff be called to the rooms he visits. -* Fix: With multiple reception desks new patients now find their way to the - reception with the least queue size. -* Fix: The wrong amount of money was returned when selling a room. -* Fix: Aliens could not be cured on the last two levels. -* Fix: The transparent walls setting made new rooms remove outer walls. -* Fix: Sometimes patients who had left the hospital could still wait for a new room, - making said room impossible to build. -* Fix: A crash when the staff member left a room before the patient. -* Fix: Build cost of objects were not always correct. - --- User Interface -- - -* Added: The save and load dialogs can now sort both ascending and descending - and are a little more spacy. -* Added: More messages in the progress report dialog. -* Added: More advice in different situations from the adviser. -* Added: Adviser messages now has priorities, making more important messages - appear faster. - -* Change: When the mouse cursor leaves the game window it will stop scrolling - the in-game world. -* Change: The message when a crash occurs is now a little more informative, and - humanoids no longer get stuck as easily. - -* Fix: The staff management window is now updated when staff is hired or - fired from outside the window itself. -* Fix: If the desired language cannot be loaded on startup the game now - reverts to English instead of crashing. -* Fix: The game could not autosave if the save or load dialog was open. - -* The auto-scroll setting is now saved between sessions. -* The adviser can now be turned off from the top menu. -* The game uses a new icon. - --- Map Editor -- - -* Fix: The game no longer crash just because the map builder has not added any - access roads from the edge of the map. - -------------------------------------------------------------------------------- -Version Beta 8 - released 2011-09-24 -------------------------------------------------------------------------------- - --- Gameplay -- - -* Fix: Patients should manage to use benches more often now. -* Fix: Staff will never have the "waiting for patient" mood when in a training - room or a staff room anymore. -* Change: Which diagnosis rooms different patients go to have been changed - to be more like the original game. -* Change: No patients will arrive until you have both a receptionist and a reception - desk. There will be no emergencies or VIP visits either until this criterion is met. -* Added: People may now puke or pee on the floor. -* Added: Various things such as litter and plants affect patient happiness. -* Added: A doctor may now get crazy if he is waaay too tired. -* Added: VIP visits. Watch out for those picky black suit visitors! -* Added: The "guess cure" fax message will now properly pop up. - --- User Interface -- - -* Change: The save and load dialogs now look a little different. Autosaves are stored - in a separate folder and there can be up to 12 autosaves at the same time. One for - each month. The dialogs now show when a save was made, and the list can also be - sorted by this criterion. -* Added: It is now possible to cycle through owned machines by right-clicking - the machine name in the machine dialog. -* Added: Sound, announcement and music volumes and on/off settings are now - saved between sessions.s - --- Graphics -- - -* Added: Waiting patients may sometimes check their watch or start to tap their foot. -* Added: Soda machines now sell more than soda cans. This can be seen through the - litter people throw on the floor after using said machines. -* Added: (Animation Viewer) A new export function has been added. Note that there - is currently no import equivalent, so it is mostly for people to try out and - see what graphics there are in the game. In the future we hope to make it possible - to import these graphics after changing them in your favourite graphics program. - --- Translations -- - -New language: Polish - -------------------------------------------------------------------------------- -Version Beta 7 - released 2011-06-24 -------------------------------------------------------------------------------- - --- Known Issues -- - -* If the X-Ray Viewer is inaccessible in the Operating Theatre the whole - room will be unusable. -* There are still many features which are not yet implemented including trash, - earthquakes, epidemics and awards. -* The graph window doesn't show any graphs. -* Handyman priorities are not yet fully implemented. - --- Gameplay -- - -* Added: Staff severance pay. -* Added: Patients may die if they don't get treated in time. -* Added: Doctors slowly gain skill when working. -* Added: Extra objects and the number of trainees influence speed of training - in the training room. -* Added: Even with no research new machines will eventually become available. -* Added: Some patients have started littering your hospital with soda cans! - Make sure you have enough handymen to keep your hospital clean. -* Added: Modern heating systems aren't as reliable as they used to be. Prepare - for breakdowns now and then. - -* New disease: Alien DNA! Note that there are still a few glitches to fix - concerning this new disease. - -* Change: Vending maintenance costs have increased throughout the world and - as a result Sodas now cost $20, up from $15. -* Change: Heating costs are calculated on a per day basis, rather than per month. -* Change: Machine and drug improvements are now made evenly across all eligible - objects rather than maxing one at a time. -* Change: Humanoids never meander outside anymore. - -* Fix: Handymen no longer crash the game when trying to water an unreachable - plant. -* Fix: Staff resting in the staff room should keep their sofa until fully - rested if there's nothing else to do. -* Fix: The player can't hire new staff or pay bonuses without a positive balance. - --- User Interface -- - -* Added: The graph window, no graphs yet though. -* Added: Right click menu in the queue dialog. -* Added: Confirmation dialog when about to fire a member of staff. - -* Fix: If there is only one person who is in an emergency, use the singular - form in the sentence. -* Fix: The pickup item button in the edit room dialog is now fully functional. -* Fix: The pointer should no longer jump around in Linux when using SDL. - --- Graphics -- - -* Added: The scanner uses more than one animation. - -* Fix: Some objects were cut in half after a relocation. - --- Translations -- - -* Change: If the specified language is not found, try to revert to English. -* Fix: Competitor names are now translatable. - -------------------------------------------------------------------------------- -Version Beta 6 - released 2011-03-24 -------------------------------------------------------------------------------- - --- Gameplay -- - -* Feature: Staff speed! -* Added: All parts of research have been implemented, including - machine strength improvements, drug improvements and the - "concentrate research" button in the drug casebook. -* Added: Overdraft charges for having a negative balance. -* Fix: The length of a day was about half as long as it should be. -* Fix: A few occurrences of bone-idle patients have been resolved. -* Fix: Juniors were not correctly labeled as Doctors after promotion. -* Fix: Some crashes regarding receptionists. -* Fix: Never charge less than initial cost when reputation is below 500. -* Fix: Some repair animations were too short. -* Fix: Don't check winning and losing conditions so often. -* Fix: Taking loans can now make the player avoid losing. -* Fix: Level 7 had an emergency with an unavailable disease. -* Fix: Doctors on their way back to the research room or training room - will no longer answer to any calls. -* Fix: Don't crash if a patient in a machine is sent home. -* Fix: Various tweaks to the operating theatre logic. -* Fix: Don't crash if the staff window of a leaving staff member - is open when he/she leaves the world. -* Fix: Persistent data (salary, built rooms etc) are no longer lost - after restarting a level. - --- User Interface -- - -* Feature: The drug casebook now shows if you can treat a disease or not, - and in the latter case the tooltip tells you what is missing. Actual - price is shown after some time, instead of charge %. -* Feature: Press and hold on value buttons will now make the value continue - to increase until the button is released again. -* Feature: The Theme Hospital installation path can be changed from the - options menu. -* Added: The adviser will help out in a few more situations. -* Fix: Mouse position events such as moving staff around didn't work - when scrolling using the arrow keys. -* Fix: Tooltips are now updated more frequently, - most evidently in the research pane. - --- Translations -- - -* Feature: CorsixTH now supports TrueType fonts via FreeType2! -* Feature: To assist translators a new diff file is now created when you - choose the debug option "dump strings" (with languages other than English). - It contains those strings which are either found in English but not in - the given language, or found in the given language but not in English. - -* New languages: Traditional Chinese, Simplified Chinese, Russian. - -------------------------------------------------------------------------------- -Version Beta 5 - released 2010-12-24 -------------------------------------------------------------------------------- - --- Gameplay -- - -* Feature: (Some) Cheats added. Type 24328 into the fax machine to get access to them. -* Feature: Custom map "Avatar" added. -* Feature: Player's "salary" (read: score) now increases over your level progress. -* Feature: Level based interest rate. -* Feature: Level based "starting staff" (e.g. original level 5). -* Feature: "No deaths" trophy added. -* Fix: Error could occur when losing a game. -* Fix: Multiple handymen watering the same plant at the same time. -* Fix: Some placements of opposite doors/objects were wrongly forbidden. -* Fix: Error could occur when building a surgery. -* Fix: Autopsy now has an appropriate impact on research. -* Fix: Salaries for doctors were too high. -* Fix: In some cases lose conditions were not triggered. -* Fix: Research room door could disappear after autopsy. - ... and various other bugs fixed. - --- User Interface -- - -* Feature: The player is now told the reason why he lost, when he loses, instead of being left in the dark. -* Fix: Wrong winning faxes shown for levels 5-11. -* Fix: Weird scrolling behavior could occur after loading a game. -* Fix: No tutorial when playing with demo files. -* Fix: Adviser disappeared too quickly during tutorial. -* Some improvements to textboxes. -* Some improvements to windows. - ... and various other small improvements and fixes. - --- Translations -- - -* Fix: Error caused by some winning faxes in Norwegian. - -------------------------------------------------------------------------------- -Version Beta 4 - released 2010-11-12 -------------------------------------------------------------------------------- - --- Gameplay -- - -* Feature: The Research Department and research policy dialog. -* Feature: The Operating Theatre. -* Feature: Not all parcels are owned by the player from the beginning, but - can now be bought from the Town Map dialog. -* Feature: Calculate staff wages and properties for those for hire based - on the level files. - -* Added 7 new diseases related to the operating theatre. -* Added treatment room: Operating Theatre. - -* Fix: The adviser no longer complains about watering of plants all the time. -* Fix: Some crashes related to crashed rooms has been fixed. - - --- User Interface -- - -* Feature: Possibility to choose difficulty level when starting a new game. -* Feature: Zooming (only when using DirectX or OpenGL). -* Feature: The Annual Report Dialog. - -* Graphics: Improved the main menu background. -* Fix: Solved issues with non-English keyboard layouts. - - --- Translations -- - -* New languages: Finnish and Danish -* Fix: When playing the game in French it no longer crashes upon completion of a level. - - -------------------------------------------------------------------------------- -Version Beta 3 - released 2010-06-24 -------------------------------------------------------------------------------- - --- Gameplay -- - -* Feature: Swing doors (used by new diagnosis room ward). -* Feature: Plants will now droop unless they are watered by a handyman. -* Feature: Adjustable handyman priorities. -* Feature: Existing rooms can now be edited and deleted. -* Feature: Watch for initial opening of hospital at start of each level. -* Feature: Each level has its own goals, shown at the beginning of the level and - in the new status dialog. When the goals have been achieved the player may go on - to the next one. -* Feature: Not all implemented rooms and diseases appear anymore in each level, but - only those defined by the level script. -* Feature: Support for custom levels with their own maps and level scripts. -* Feature: A heating system that depends on outside temperature, adjacent tiles - and radiators among other things. - -* Added 6 new diseases -* Added treatment rooms: Jelly Vat, Decontamination -* Added diagnosis rooms: Blood Machine, Ward, Scanner - -* Fix: Staff needed in rooms is handled much better. -* Fix: Objects retain their statistics when moved. -* Fix: A horde of other bugs have also been fixed. - - --- User Interface -- - -* Feature: Savegames are no longer limited to 8 slots + autosave. -* Feature: Fullscreen mode, screen resolution and interface language can be changed - ingame. The changes are saved in the config file and preserved. -* Feature: Hovering the mouse over a room will mark all patients in queue for this room. -* Feature: Patients can be moved to the head/tail of queues in the corresponding dialog. - They can also be placed between other patients. -* New dialogs: Load Game, Save Game, Custom Level to cope with arbitrary number of - savegames/levels. -* New dialog: Options -* New dialog: Progress Report (Status) showing status of the current level's goals. -* Added all tooltips that were still missing. - - --- Misc -- - -* Translations: Italian, Spanish and French: added new strings not available in vanilla TH, - Portuguese (WIP) and Dutch (WIP) -* The configuration file and saved games can now, if desired, also be stored in the user's - home directory or equivalent. - - -------------------------------------------------------------------------------- -Version Beta 2 - released 2010-03-24 -------------------------------------------------------------------------------- - -* Feature: Save / Load functionality. -* Feature: Patients and staff now have a need for heat (from radiators) in - order to stay happy. Patients will also get thirsty (build drinks machines) - and will need a bathroom sooner or later, and staff will ask for a salary - raise when unhappy. -* Feature: Machines will need repair now and then. A dialog that shows - necessarry information is displayed when the machine is clicked. -* Feature: Dynamic Information Bar in the bottom right corner of the UI added. - It shows information about entities beneath the mouse cursor. -* Feature: The training room can now be built, where doctors can increase - their skill and get additional traits if a consultant is present. -* Feature: When a patient cannot be cured or a room is missing a fax will - arrive and ask the player what to do. -* Feature: A new string system that allows us to add new (translatable) text - to the game, correct mistakes in existing languages and add new languages. -* Feature: A tutorial is offered to the player at the start of the game. -* Feature: Tooltips are displayed when hovering over buttons for some time. -* Feature: Emergencies may happen every now and then. -* Feature: Hospital reputation system. -* Feature: Humorous disease description faxes are now shown when a disease is - first diagnosed. -* Feature: Room blueprints can be resized during the build process. - -* New Dialogs: Hospital Policy, Drug Casebook, Bank Manager, Staff Management, - Town Map (work in progress), Main Menu -* Many new key shortcuts (see Hotkeys wiki page for full list). -* Dialogs can now be re-positioned by dragging them to where they are wanted. -* Added floating money signs to better indicate where money is coming from. -* Added comments from the advisor in more situations. - -* 10 new diseases. -* New treatment room: Hair Restorer -* Additional functional diagnosis rooms: General Diagnosis, Ultrascan, X-Ray -* Room queues should now re-balance themselves when new rooms are built. - -* Translation: Norwegian (bokml). - -A lot of other small improvements. -Also, a great number of bugs have been squashed. Most remaining bugs are no -longer fatal, and can be continued from. - - -------------------------------------------------------------------------------- -Version Beta 1 - released 2009-12-24 -------------------------------------------------------------------------------- - -Initial release diff -Nru corsix-th-0.61/CorsixTH/CMakeLists.txt corsix-th-0.62/CorsixTH/CMakeLists.txt --- corsix-th-0.61/CorsixTH/CMakeLists.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/CMakeLists.txt 2018-07-21 11:13:17.000000000 +0000 @@ -1,45 +1,40 @@ # Sanity check -IF(CORSIX_TH_DONE_TOP_LEVEL_CMAKE) -ELSE(CORSIX_TH_DONE_TOP_LEVEL_CMAKE) -message(FATAL_ERROR "Please run cmake on the top-level directory, not this one.") -ENDIF(CORSIX_TH_DONE_TOP_LEVEL_CMAKE) +if(CORSIX_TH_DONE_TOP_LEVEL_CMAKE) +else() + message(FATAL_ERROR "Please run cmake on the top-level directory, not this one.") +endif() # Project Declaration -PROJECT(CorsixTH) +project(CorsixTH) -# Basic platform dependent stuff -IF(UNIX) - IF(APPLE) - # fruit goes here - add_subdirectory(SDLMain) - ELSE(APPLE) - # regular unix/linux - ENDIF(APPLE) -ELSE() - IF(WIN32) - # Win32 specific - IF(MSVC) - # We want to bind against the very latest versions of the MSVC runtimes - add_definitions(/D "_BIND_TO_CURRENT_VCLIBS_VERSION=1") - ELSE(MSVC) - IF(MSYS) - # MSYS stuff - ELSE(MSYS) - # What's left? MINGW? CYGWIN? BORLAND? - ENDIF(MSYS) - ENDIF(MSVC) - ELSE(WIN32) - # other OS (not UNIX, not 32/64 bit Windows) - ENDIF(WIN32) -ENDIF(UNIX) +if(APPLE) + add_subdirectory(SDLMain) +elseif(MSVC) + # We want to bind against the very latest versions of the MSVC runtimes + add_definitions(/D "_BIND_TO_CURRENT_VCLIBS_VERSION=1") +endif() + +if(USE_SOURCE_DATADIRS) + set(CORSIX_TH_DATADIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(CORSIX_TH_INTERPRETER_PATH ${CORSIX_TH_DATADIR}/CorsixTH.lua) +elseif(MSVC) + set(CORSIX_TH_DATADIR CorsixTH) + set(CORSIX_TH_INTERPRETER_PATH CorsixTH.lua) +elseif(APPLE) + set(CORSIX_TH_DATADIR CorsixTH.app/Contents/Resources/) + set(CORSIX_TH_INTERPRETER_PATH ${CMAKE_INSTALL_PREFIX}/${CORSIX_TH_DATADIR}/CorsixTH.lua) +else() + set(CORSIX_TH_DATADIR ${CMAKE_INSTALL_DATADIR}/corsix-th) + set(CORSIX_TH_INTERPRETER_PATH ${CMAKE_INSTALL_FULL_DATADIR}/corsix-th/CorsixTH.lua) +endif() # Modify the config.h based upon our selection of options -CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/CorsixTH/Src/config.h.in ${CMAKE_BINARY_DIR}/CorsixTH/Src/config.h) -INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/CorsixTH/Src/) +configure_file(${CMAKE_SOURCE_DIR}/CorsixTH/Src/config.h.in ${CMAKE_BINARY_DIR}/CorsixTH/Src/config.h) +include_directories(${CMAKE_BINARY_DIR}/CorsixTH/Src/) # Generate source files list # Note: Done after generating config.h -FILE(GLOB_RECURSE corsixth_source_files +file(GLOB_RECURSE corsixth_source_files ${CMAKE_SOURCE_DIR}/CorsixTH/SrcUnshared/*.cpp ${CMAKE_SOURCE_DIR}/CorsixTH/SrcUnshared/*.c ${CMAKE_SOURCE_DIR}/CorsixTH/SrcUnshared/*.h @@ -48,6 +43,8 @@ ${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.c ${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.hpp ${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.h + ${CMAKE_SOURCE_DIR}/common/rnc.cpp + ${CMAKE_SOURCE_DIR}/common/rnc.h ${CMAKE_SOURCE_DIR}/CorsixTH/Src/shaders/*.psh ${CMAKE_BINARY_DIR}/CorsixTH/Src/config.h ${CMAKE_SOURCE_DIR}/CorsixTH/Lua/api_version.lua @@ -57,9 +54,7 @@ ) # Declaration of the executable -IF(APPLE) - add_definitions(-DIS_CORSIXTH_APP) - +if(APPLE) set(corsixth_icon_file ${CMAKE_SOURCE_DIR}/CorsixTH/Icon.icns) set_source_files_properties( ${corsixth_icon_file} @@ -73,159 +68,188 @@ set_target_properties(CorsixTH PROPERTIES LINK_FLAGS_MINSIZEREL "-dead_strip") set_target_properties(CorsixTH PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks") - #Add an extra step at the end of the build process to copy the resources into the bundle. - add_custom_command(TARGET CorsixTH - POST_BUILD - COMMAND rsync -rv --include-from ${CMAKE_SOURCE_DIR}/CorsixTH/RequiredResources.txt ${CMAKE_SOURCE_DIR}/CorsixTH/ \${TARGET_BUILD_DIR}/\${FULL_PRODUCT_NAME}/Contents/MacOS - COMMAND rsync -rv ${CMAKE_SOURCE_DIR}/CorsixTH/Icon.icns \${TARGET_BUILD_DIR}/\${FULL_PRODUCT_NAME}/Contents/Resources/) - target_link_libraries(CorsixTH SDL2main) - INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/CorsixTH/SDLMain/) -ELSE() + include_directories(${CMAKE_BINARY_DIR}/CorsixTH/SDLMain/) +else() add_executable(CorsixTH ${corsixth_source_files}) -ENDIF() +endif() + +if(UNIX AND NOT APPLE) + set_target_properties(CorsixTH PROPERTIES OUTPUT_NAME corsix-th) +endif() # Add an extra step to copy built DLLs on MSVC -IF(USE_VCPKG_DEPS) - INCLUDE(CopyVcpkgLua) +if(USE_VCPKG_DEPS) + include(CopyVcpkgLua) ENDIF() -# Finding libraries +## Finding libraries # Find SDL -IF (MSVC AND USE_VCPKG_DEPS) - FIND_PACKAGE(SDL2 CONFIG REQUIRED) - TARGET_LINK_LIBRARIES(CorsixTH SDL2::SDL2) - TARGET_LINK_LIBRARIES(CorsixTH SDL2::SDL2main) -ELSE() - FIND_PACKAGE(SDL2 REQUIRED) - IF(SDL_FOUND) - INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR}) - IF(SDLMAIN_LIBRARY STREQUAL "") +if(MSVC AND USE_VCPKG_DEPS) + find_package(SDL2 CONFIG REQUIRED) + target_link_libraries(CorsixTH SDL2::SDL2) + target_link_libraries(CorsixTH SDL2::SDL2main) +else() + find_package(SDL2 REQUIRED) + if(SDL_FOUND) + include_directories(${SDL_INCLUDE_DIR}) + if(SDLMAIN_LIBRARY STREQUAL "") message(FATAL_ERROR "Error: SDL was found but SDLmain was not") message("Make sure the path is correctly defined or set the environment variable SDLDIR to the correct location") - ENDIF(SDLMAIN_LIBRARY STREQUAL "") + endif() # No need to specify sdlmain separately, the FindSDL.cmake file will take care of that. If not we get an error about it - TARGET_LINK_LIBRARIES(CorsixTH ${SDL_LIBRARY}) + target_link_libraries(CorsixTH ${SDL_LIBRARY}) message(" SDL found") - ELSE(SDL_FOUND) + else() message(FATAL_ERROR "Error: SDL library not found, it is required to build. Make sure the path is correctly defined or set the environment variable SDLDIR to the correct location") - ENDIF(SDL_FOUND) -ENDIF() + endif() +endif() + # Find Lua -FIND_PACKAGE(Lua REQUIRED) -IF(Lua_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${LUA_LIBRARY}) - INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) +find_package(Lua REQUIRED) +if(Lua_FOUND) + target_link_libraries(CorsixTH ${LUA_LIBRARY}) + include_directories(${LUA_INCLUDE_DIR}) # Special link flags needed on OSX/64bit, according to: http://luajit.org/install.html # If these are not specified, luaL_newstate() returns NULL and we get this: # Fatal error starting CorsixTH: Cannot open Lua state. - IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND LUA_INTERPRETER_TYPE STREQUAL "LuaJIT" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - TARGET_LINK_LIBRARIES(CorsixTH "-pagezero_size 10000" "-image_base 100000000") - ENDIF() + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND LUA_INTERPRETER_TYPE STREQUAL "LuaJIT" AND CMAKE_SIZEOF_VOID_P EQUAL 8) + target_link_libraries(CorsixTH "-pagezero_size 10000" "-image_base 100000000") + endif() message(" ${LUA_INTERPRETER_TYPE} found") -ELSE(Lua_FOUND) +else() message(FATAL_ERROR "Error: Lua library not found, it is required to build") -ENDIF(Lua_FOUND) +endif() # Add threading library find_package(Threads) target_link_libraries(CorsixTH ${CMAKE_THREAD_LIBS_INIT}) # Find SDL_mixer -IF(CORSIX_TH_USE_SDL_MIXER) - FIND_PACKAGE(SDL2_mixer REQUIRED) - IF(SDLMIXER_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${SDLMIXER_LIBRARY}) - INCLUDE_DIRECTORIES(${SDLMIXER_INCLUDE_DIR}) +if(CORSIX_TH_USE_SDL_MIXER) + find_package(SDL2_mixer REQUIRED) + if(SDLMIXER_FOUND) + target_link_libraries(CorsixTH ${SDLMIXER_LIBRARY}) + include_directories(${SDLMIXER_INCLUDE_DIR}) message(" SDL_mixer found") - ELSE(SDLMIXER_FOUND) + else() message(FATAL_ERROR "Error: SDL_mixer library not found, even though it was selected to be included") - ENDIF(SDLMIXER_FOUND) -ENDIF(CORSIX_TH_USE_SDL_MIXER) + endif() +endif() -message( STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}" ) +message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") # Find FFMPEG -IF(CORSIX_TH_USE_FFMPEG) - FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE REQUIRED) - IF(FFMPEG_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${FFMPEG_LIBRARIES}) - INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS}) - IF(APPLE) - TARGET_LINK_LIBRARIES(CorsixTH libz.dylib) - ENDIF() +if(CORSIX_TH_USE_FFMPEG) + find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE REQUIRED) + if(FFMPEG_FOUND) + target_link_libraries(CorsixTH ${FFMPEG_LIBRARIES}) + include_directories(${FFMPEG_INCLUDE_DIRS}) + if(APPLE) + target_link_libraries(CorsixTH libz.dylib) + endif() message(" FFmpeg found") - ELSE(FFMPEG_FOUND) + else() message(FATAL_ERROR "Error: FFmpeg library not found, even though it was selected to be included") - ENDIF(FFMPEG_FOUND) -ENDIF(CORSIX_TH_USE_FFMPEG) + endif() +endif() -IF(CORSIX_TH_USE_LIBAV) - FIND_PACKAGE(LibAV COMPONENTS AVFORMAT AVCODEC AVRESAMPLE AVUTIL SWSCALE REQUIRED) - IF(LIBAV_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${LIBAV_LIBRARIES}) - INCLUDE_DIRECTORIES(${LIBAV_INCLUDE_DIRS}) - IF(APPLE) - TARGET_LINK_LIBRARIES(CorsixTH libz.dylib) - ENDIF() +if(CORSIX_TH_USE_LIBAV) + find_package(LibAV COMPONENTS AVFORMAT AVCODEC AVRESAMPLE AVUTIL SWSCALE REQUIRED) + if(LIBAV_FOUND) + target_link_libraries(CorsixTH ${LIBAV_LIBRARIES}) + include_directories(${LIBAV_INCLUDE_DIRS}) + if(APPLE) + target_link_libraries(CorsixTH libz.dylib) + endif() message(" LibAV found") - ELSE(LIBAV_FOUND) + else() message(FATAL_ERROR "Error: LibAV library not found, even though it was selected to be included") - ENDIF(LIBAV_FOUND) -ENDIF(CORSIX_TH_USE_LIBAV) + endif() +endif() # Find Freetype2 -IF(CORSIX_TH_USE_FREETYPE2) - FIND_PACKAGE(Freetype REQUIRED) - IF(FREETYPE_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${FREETYPE_LIBRARIES}) - INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS}) - IF(APPLE) - TARGET_LINK_LIBRARIES(CorsixTH libz.dylib) - TARGET_LINK_LIBRARIES(CorsixTH libbz2.dylib) - ENDIF() +if(CORSIX_TH_USE_FREETYPE2) + find_package(Freetype REQUIRED) + if(FREETYPE_FOUND) + target_link_libraries(CorsixTH ${FREETYPE_LIBRARIES}) + include_directories(${FREETYPE_INCLUDE_DIRS}) + if(APPLE) + target_link_libraries(CorsixTH libz.dylib) + target_link_libraries(CorsixTH libbz2.dylib) + endif() message(" FreeType2 found") - ELSE(FREETYPE_FOUND) + else() message(FATAL_ERROR "Error: FreeType2 library not found, even though it was selected to be used") - ENDIF(FREETYPE_FOUND) -ENDIF(CORSIX_TH_USE_FREETYPE2) + endif() +endif() -# Find msinttypes for MSVC -IF(MSVC AND NOT CORSIX_TH_HAS_INTTYPES_H) - FIND_PATH(MSINTTYPES_INCLUDE_DIRS "inttypes.h" NO_DEFAULT_PATH) - MESSAGE(STATUS "Adding include directory: ${MSINTTYPES_INCLUDE_DIRS}") - INCLUDE_DIRECTORIES(${MSINTTYPES_INCLUDE_DIRS}) - SET(CORSIX_TH_HAS_INTTYPES_H 1) -ENDIF(MSVC AND NOT CORSIX_TH_HAS_INTTYPES_H) - -IF(MSVC AND CORSIX_TH_USE_VLD) - FIND_PACKAGE(VLD REQUIRED) - IF(VLD_FOUND) - TARGET_LINK_LIBRARIES(CorsixTH ${VLD_LIBRARY}) - INCLUDE_DIRECTORIES(CorsixTH ${VLD_INCLUDE_DIR}) +if(MSVC AND CORSIX_TH_USE_VLD) + find_package(VLD REQUIRED) + if(VLD_FOUND) + target_link_libraries(CorsixTH ${VLD_LIBRARY}) + include_directories(CorsixTH ${VLD_INCLUDE_DIR}) message(" VLD found") - ELSE(VLD_FOUND) + else() message(FATAL_ERROR "Error: VLD Library not found, it is required to build when USE_VLD is set") - ENDIF(VLD_FOUND) -ENDIF(MSVC AND CORSIX_TH_USE_VLD) + endif() +endif() + +# Launch script to facilitate out of source builds +if(USE_SOURCE_DATADIRS) + #do not generate launch script. The default is fine for this case. +elseif(XCODE) + message(WARNING "By default you will not be able to run CorsixTH from Xcode. If you do not plan to deploy then run cmake with -DUSE_SOURCE_DATADIRS. If you want to both run and deploy from Xcode then set the command line arguments in your run scheme to --interpreter=${CMAKE_CURRENT_SOURCE_DIR}/CorsixTH.lua") +elseif(APPLE) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run-corsix-th-dev.sh.in.apple ${CMAKE_CURRENT_BINARY_DIR}/run-corsixth-dev.sh @ONLY) +elseif(UNIX) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run-corsix-th-dev.sh.in ${CMAKE_CURRENT_BINARY_DIR}/run-corsixth-dev.sh @ONLY) +elseif(MSVC) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CorsixTH.vcxproj.user.in ${CMAKE_CURRENT_BINARY_DIR}/CorsixTH.vcxproj.user @ONLY) +endif() + # Declaration of the install process -IF(APPLE) - #Just use the prefix as it's sufficient to just set the prefix to /Applications on Mac. - install(TARGETS CorsixTH BUNDLE DESTINATION .) - - # Fix the OS X bundle to include required libraries (create a redistributable app) - install(CODE " - INCLUDE(BundleUtilities) - SET(BU_CHMOD_BUNDLE_ITEMS ON) - FIXUP_BUNDLE(${CMAKE_INSTALL_PREFIX}/CorsixTH.app \"\" \"\") - ") -ELSE() - install(TARGETS CorsixTH RUNTIME DESTINATION CorsixTH) - install(DIRECTORY Campaigns Lua Levels DESTINATION CorsixTH PATTERN "*.svn" EXCLUDE) - install(DIRECTORY Bitmap DESTINATION CorsixTH - FILES_MATCHING REGEX ".*\\.(tab|pal|dat|png)$" - PATTERN "*.svn" EXCLUDE) - install(FILES CorsixTH.lua ../LICENSE.txt CorsixTH.ico DESTINATION CorsixTH ) -ENDIF() +if(NOT USE_SOURCE_DATADIRS) + if(APPLE) + #Just use the prefix as it's sufficient to just set the prefix to /Applications on Mac. + install(TARGETS CorsixTH BUNDLE DESTINATION .) + elseif(MSVC) + install(TARGETS CorsixTH + RUNTIME DESTINATION ${CORSIX_TH_DATADIR} + LIBRARY DESTINATION ${CORSIX_TH_DATADIR} + ARCHIVE DESTINATION ${CORSIX_TH_DATADIR} + ) + install(FILES CorsixTH.ico DESTINATION ${CORSIX_TH_DATADIR}) + + # install dependencies + file(GLOB DLL_DEPS "${CMAKE_CURRENT_BINARY_DIR}/*.dll") + install(FILES ${DLL_DEPS} DESTINATION ${CORSIX_TH_DATADIR}) + file(GLOB LUA_DEPS "${CMAKE_CURRENT_BINARY_DIR}/*.lua") + install(FILES ${LUA_DEPS} DESTINATION ${CORSIX_TH_DATADIR}) + if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/mime") + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mime" "${CMAKE_CURRENT_BINARY_DIR}/socket" DESTINATION ${CORSIX_TH_DATADIR}) + endif() + else() + install(TARGETS CorsixTH + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + install(DIRECTORY Campaigns Lua Levels DESTINATION ${CORSIX_TH_DATADIR}) + install(DIRECTORY Bitmap DESTINATION ${CORSIX_TH_DATADIR} + FILES_MATCHING REGEX ".*\\.(tab|pal|dat|png)$" + ) + install(FILES CorsixTH.lua ../LICENSE.txt DESTINATION ${CORSIX_TH_DATADIR}) + + if(APPLE) + # Fix the OS X bundle to include required libraries (create a redistributable app) + install(CODE " + INCLUDE(BundleUtilities) + SET(BU_CHMOD_BUNDLE_ITEMS ON) + FIXUP_BUNDLE(${CMAKE_INSTALL_PREFIX}/CorsixTH.app \"\" \"\") + ") + endif() +endif() diff -Nru corsix-th-0.61/CorsixTH/CorsixTH.lua corsix-th-0.62/CorsixTH/CorsixTH.lua --- corsix-th-0.61/CorsixTH/CorsixTH.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/CorsixTH.lua 2018-07-21 11:13:17.000000000 +0000 @@ -22,14 +22,18 @@ local pathsep = package.config:sub(1, 1) local base_dir = debug.getinfo(1, "S").source:sub(2, -13) local code_dir = base_dir .. "Lua" .. pathsep +package.cpath = base_dir .. '?.so;' .. package.cpath for _, arg in ipairs{...} do local dir = arg:match"^%-%-lua%-dir=(.*)$" if dir then code_dir = dir .. pathsep end end + +package.path = code_dir .. "?.lua;" .. code_dir .. "?/init.lua;" .. package.path + local done_files = {} -local persist = require "persist" +local persist = require("persist") local save_results if table.pack then -- Lua 5.2 @@ -44,10 +48,22 @@ return ... end end -function dofile(name) - if pathsep ~= "/" then - name = name:gsub("/", pathsep) - end + +_G['corsixth'] = {} + +--! Loads and runs a lua file. +-- Similar to the built in require function with three important differenes: +-- * This function searches for --[[persistance: comments and maps the +-- following function into the persistence table. +-- * This function only searches in the Lua code directory +-- * This function is only able to load lua source files (not C modules or +-- compiled lua. +--!param name (string) +-- The name of the lua source file to run. Use dots to seperate directories, +-- and do not include the .lua file extension. +--!return The return value of whatever source file is opened. +corsixth.require = function(name) + name = name:gsub("%.", pathsep) if done_files[name] then local results = done_files[name] return unpack(results, 1, results.n) @@ -57,12 +73,11 @@ end -- Load standard library extensions -dofile "utility" +corsixth.require("utility") -- If requested run a Lua DBGp Debugger Client: if run_debugger then dofile("run_debugger")() - done_files["run_debugger"] = nil end -- Check Lua version @@ -98,21 +113,22 @@ -- it to a running server, using this CorsixTH startup arg: -debugger -- Enable strict mode -dofile "strict" +corsixth.require("strict") require = destrict(require) +dofile = destrict(dofile) -- Load the class system (required for App) -dofile "class" +corsixth.require("class") -- Load the main App class -dofile "app" +corsixth.require("app") -- Create an instance of the App class and transfer control to it strict_declare_global "TheApp" TheApp = App() TheApp:setCommandLine( - "--bitmap-dir="..base_dir.."Bitmap", - "--config-file="..dofile"config_finder", + "--bitmap-dir=" ..base_dir.. "Bitmap", + "--config-file=" .. corsixth.require("config_finder"), -- If a command line option is given twice, the later one is used, hence -- if the user gave one of the above, that will be used instead. ... diff -Nru corsix-th-0.61/CorsixTH/CorsixTH.vcxproj.user.in corsix-th-0.62/CorsixTH/CorsixTH.vcxproj.user.in --- corsix-th-0.61/CorsixTH/CorsixTH.vcxproj.user.in 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/CorsixTH.vcxproj.user.in 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,8 @@ + + + + --interpreter=@CMAKE_CURRENT_SOURCE_DIR@/CorsixTH.lua + WindowsLocalDebugger + + + diff -Nru corsix-th-0.61/CorsixTH/Lua/app.lua corsix-th-0.62/CorsixTH/Lua/app.lua --- corsix-th-0.61/CorsixTH/Lua/app.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/app.lua 2018-07-21 11:13:17.000000000 +0000 @@ -19,16 +19,16 @@ SOFTWARE. --]] local pathsep = package.config:sub(1, 1) -local rnc = require "rnc" -local lfs = require "lfs" -local TH = require "TH" -local SDL = require "sdl" -local runDebugger = dofile "run_debugger" +local rnc = require("rnc") +local lfs = require("lfs") +local TH = require("TH") +local SDL = require("sdl") +local runDebugger = corsixth.require("run_debugger") -- Increment each time a savegame break would occur -- and add compatibility code in afterLoad functions -local SAVEGAME_VERSION = 122 +local SAVEGAME_VERSION = 127 class "App" @@ -110,7 +110,7 @@ conf_chunk(self.config) end self:fixConfig() - dofile "filesystem" + corsixth.require("filesystem") local good_install_folder, error_message = self:checkInstallFolder() self.good_install_folder = good_install_folder -- self:checkLanguageFile() @@ -124,7 +124,7 @@ return false, "Cannot initialise SDL" end local compile_opts = TH.GetCompileOptions() - local api_version = dofile "api_version" + local api_version = corsixth.require("api_version") if api_version ~= compile_opts.api_version then api_version = api_version or 0 compile_opts.api_version = compile_opts.api_version or 0 @@ -153,7 +153,7 @@ self.video:setBlueFilterActive(false) SDL.wm.setIconWin32() - self.video:setCaptureMouse(self.config.capture_mouse) + self:setCaptureMouse() local caption_descs = {self.video:getRendererDetails()} if compile_opts.jit then @@ -168,8 +168,8 @@ self.video:setCaption(self.caption) -- Prereq 2: Load and initialise the graphics subsystem - dofile "persistance" - dofile "graphics" + corsixth.require("persistance") + corsixth.require("graphics") self.gfx = Graphics(self) -- Put up the loading screen @@ -212,20 +212,20 @@ return math.floor(input + 0.5) end -- Load audio - dofile "audio" + corsixth.require("audio") self.audio = Audio(self) self.audio:init() -- Load movie player - dofile "movie_player" + corsixth.require("movie_player") self.moviePlayer = MoviePlayer(self, self.audio, self.video) if good_install_folder then self.moviePlayer:init() end -- Load strings before UI and before additional Lua - dofile "strings" - dofile "string_extensions" + corsixth.require("strings") + corsixth.require("string_extensions") self.strings = Strings(self) self.strings:init() local language_load_success = self:initLanguage() @@ -236,17 +236,17 @@ end -- Load map before world - dofile "map" + corsixth.require("map") -- Load additional Lua before world if good_install_folder then self.anims = self.gfx:loadAnimations("Data", "V") self.animation_manager = AnimationManager(self.anims) self.walls = self:loadLuaFolder("walls") - dofile "entity" - dofile "entities/humanoid" - dofile "entities/object" - dofile "entities/machine" + corsixth.require("entity") + corsixth.require("entities.humanoid") + corsixth.require("entities.object") + corsixth.require("entities.machine") local objects = self:loadLuaFolder("objects") self.objects = self:loadLuaFolder("objects/machines", nil, objects) @@ -261,23 +261,23 @@ Object.processTypeDefinition(v) end - dofile "room" + corsixth.require("room") self.rooms = self:loadLuaFolder("rooms") - dofile "humanoid_action" + corsixth.require("humanoid_action") self.humanoid_actions = self:loadLuaFolder("humanoid_actions") local diseases = self:loadLuaFolder("diseases") self.diseases = self:loadLuaFolder("diagnosis", nil, diseases) -- Load world before UI - dofile "world" + corsixth.require("world") end -- Load UI - dofile "ui" + corsixth.require("ui") if good_install_folder then - dofile "game_ui" + corsixth.require("game_ui") self.ui = UI(self, true) else self.ui = UI(self, true) @@ -472,6 +472,12 @@ end end +--! Sets the mouse capture to the state set within +--! app.config.capture_mouse +function App:setCaptureMouse() + self.video:setCaptureMouse(self.config.capture_mouse) +end + --! Loads the first level of the specified campaign and prepares the world --! to be able to progress through that campaign. --!param campaign_file (string) Name of a CorsixTH Campaign definition Lua file. @@ -792,7 +798,7 @@ function App:fixConfig() -- Fill in default values for things which don't exist - local _, config_defaults = dofile "config_finder" + local _, config_defaults = corsixth.require("config_finder") for k, v in pairs(config_defaults) do if self.config[k] == nil then self.config[k] = v @@ -1146,31 +1152,35 @@ -- Do a few more checks to make sure that commonly corrupted files are OK. local corrupt = {} - if not self.using_demo_files then - local function check_corrupt(path, correct_size) - local real_path = self.fs:getFilePath(path) - -- If the file exists but is smaller than usual it is probably corrupt - if real_path then - local real_size = lfs.attributes(real_path, "size") - if real_size + 1024 < correct_size or real_size - 1024 > correct_size then - corrupt[#corrupt + 1] = path .. " (Size: " .. math.floor(real_size/1024) .. " kB / Correct: about " .. math.floor(correct_size/1024) .. " kB)" - end - else - corrupt[#corrupt + 1] = path .. " (This file is missing)" + local function check_corrupt(path, correct_size) + local real_path = self.fs:getFilePath(path) + -- If the file exists but is smaller than usual it is probably corrupt + if real_path then + local real_size = lfs.attributes(real_path, "size") + if real_size + 1024 < correct_size or real_size - 1024 > correct_size then + corrupt[#corrupt + 1] = path .. " (Size: " .. math.floor(real_size/1024) .. " kB / Correct: about " .. math.floor(correct_size/1024) .. " kB)" end + else + corrupt[#corrupt + 1] = path .. " (This file is missing)" end + end + if self.using_demo_files then + check_corrupt("ANIMS" .. pathsep .. "WINLEVEL.SMK", 243188) + check_corrupt("LEVELS" .. pathsep .. "LEVEL.L1", 163948) + check_corrupt("DATA" .. pathsep .. "BUTTON01.DAT", 252811) + else check_corrupt("ANIMS" .. pathsep .. "AREA01V.SMK", 251572) check_corrupt("ANIMS" .. pathsep .. "WINGAME.SMK", 2066656) check_corrupt("ANIMS" .. pathsep .. "WINLEVEL.SMK", 335220) check_corrupt("INTRO" .. pathsep .. "INTRO.SM4", 33616520) check_corrupt("QDATA" .. pathsep .. "FONT00V.DAT", 1024) check_corrupt("ANIMS" .. pathsep .. "LOSE1.SMK", 1009728) + end - if #corrupt ~= 0 then - table.insert(corrupt, 1, "There appears to be corrupt files in your Theme Hospital folder, " .. - "so don't be surprised if CorsixTH crashes. At least the following files are wrong:") - table.insert(corrupt, message) - end + if #corrupt ~= 0 then + table.insert(corrupt, 1, "There appears to be corrupt files in your Theme Hospital folder, " .. + "so don't be surprised if CorsixTH crashes. At least the following files are wrong:") + table.insert(corrupt, message) end return true, #corrupt ~= 0 and corrupt or nil @@ -1254,7 +1264,7 @@ local results = no_results and "" or (append_to or {}) for file in lfs.dir(path) do if file:match("%.lua$") then - local status, result = pcall(dofile, dir .. file:sub(1, -5)) + local status, result = pcall(corsixth.require, dir .. file:sub(1, -5)) if not status then print("Error loading " .. dir .. file .. ":\n" .. tostring(result)) else @@ -1291,8 +1301,10 @@ -- a specific savegame verion is from. function App:getVersion(version) local ver = version or self.savegame_version - if ver > 122 then + if ver > 127 then return "Trunk" + elseif ver > 122 then + return "v0.62" elseif ver > 111 then return "v0.61" elseif ver > 105 then @@ -1422,14 +1434,14 @@ self.world.savegame_version = new if old < 87 then - local new_object = dofile "objects/gates_to_hell" + local new_object = corsixth.require("objects.gates_to_hell") Object.processTypeDefinition(new_object) self.objects[new_object.id] = new_object self.world:newObjectType(new_object) end if old < 114 then - local rathole_type = dofile "objects/rathole" + local rathole_type = corsixth.require("objects.rathole") Object.processTypeDefinition(rathole_type) self.objects[rathole_type.id] = rathole_type self.world:newObjectType(rathole_type) @@ -1468,8 +1480,8 @@ else self.lua_socket_available = true end - local http = require "socket.http" - local url = require "socket.url" + local http = require("socket.http") + local url = require("socket.url") print("Checking for CorsixTH updates...") local update_body, status, _ = http.request(update_url) diff -Nru corsix-th-0.61/CorsixTH/Lua/audio.lua corsix-th-0.62/CorsixTH/Lua/audio.lua --- corsix-th-0.61/CorsixTH/Lua/audio.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/audio.lua 2018-07-21 11:13:17.000000000 +0000 @@ -19,10 +19,10 @@ SOFTWARE. --]] local pathsep = package.config:sub(1, 1) -local rnc = require "rnc" -local lfs = require "lfs" -local SDL = require "sdl" -local TH = require "TH" +local rnc = require("rnc") +local lfs = require("lfs") +local SDL = require("sdl") +local TH = require("TH") local ipairs = ipairs diff -Nru corsix-th-0.61/CorsixTH/Lua/class.lua corsix-th-0.62/CorsixTH/Lua/class.lua --- corsix-th-0.61/CorsixTH/Lua/class.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/class.lua 2018-07-21 11:13:17.000000000 +0000 @@ -87,6 +87,7 @@ methods_mt.__call = new_class methods_mt.__class_name = name + methods._metatable = mt _G[name] = methods end diff -Nru corsix-th-0.61/CorsixTH/Lua/config_finder.lua corsix-th-0.62/CorsixTH/Lua/config_finder.lua --- corsix-th-0.61/CorsixTH/Lua/config_finder.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/config_finder.lua 2018-07-21 11:13:17.000000000 +0000 @@ -58,7 +58,7 @@ end -- Check / create config_path -local lfs = require "lfs" +local lfs = require("lfs") local function check_dir_exists(path) if path:sub(-1) == pathsep then path = path:sub(1, -2) @@ -192,7 +192,7 @@ -- Language to use for ingame text. Between the square braces should be one of: -- Brazilian Portuguese / pt_br / br -- Chinese (simplified) / zh(s) / chi(s) --- Chinese (traditional) / zh(s) / chi(s) +-- Chinese (traditional) / zh(t) / chi(t) -- Czech / cs / cze -- Danish / da / dk -- Dutch / Nederlands / nl / dut / nld diff -Nru corsix-th-0.61/CorsixTH/Lua/date.lua corsix-th-0.62/CorsixTH/Lua/date.lua --- corsix-th-0.61/CorsixTH/Lua/date.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/date.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,330 @@ +--[[ Copyright (c) 2018 Pavel "sofo" Schoffer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +--[[ + Date class is meant to encapsulate logic around months, years, days, hours. + It should be able to do adjustments with regards to days in given month and so on. + + Date objects should be immutable and that is why date adjustments return new objects + instead of modifying the current one. +]] + +class "Date" + +---@type Date +local Date = _G["Date"] + +local month_length = { + 31, -- Jan + 28, -- Feb (29 in leap years, but TH doesn't have leap years) + 31, -- Mar + 30, -- Apr + 31, -- May + 30, -- Jun + 31, -- Jul + 31, -- Aug + 30, -- Sep + 31, -- Oct + 30, -- Nov + 31, -- Dec +} + +local hours_per_day = 50 + +-- STATIC + +--[[ Method returns the number of game hours in one day + +! This should be use everywhere we query this information + +!return (number) number of hours in a day. +]] +function Date.hoursPerDay() + return hours_per_day +end + +-- PUBLIC + +--[[ Date constructor + +! Date is initialized by setting year, month day and hour in this order +the default day is 1-01-01T00 - if any of the components isn't set the +default value is used. + +!param year (number) year of the new date +!param month (number) month of the new date +!param day (number) day of the new date +!param hour (number) hour of the new date + +!return (Date) created object. +]] +function Date:Date(year, month, day, hour) + self._year = year or 1 + self._month = month or 1 + self._day = day or 1 + self._hour = hour or 0 + self:_adjustOverflow() +end + +--[[ Returns the last day of the current month + +! This method finds the correct last day for current month of self. This number +is also the number of days within a month. Ignores leap years. + +!return (number) +]] +function Date:lastDayOfMonth() + return month_length[self._month] +end + +--[[ Adds months + +! Creates a copy of self with adjusted months. + +!param increment (number) number to adjust, can be negative + +!return (Date) +]] +function Date:plusMonths(increment) + local new_month = self._month + increment + return Date(self._year, new_month, self._day, self._hour) +end + +--[[ Adds days + +! Creates a copy of self with adjusted days. + +!param increment (number) number to adjust, can be negative + +!return (Date) +]] +function Date:plusDays(increment) + local new_day = self._day + increment + return Date(self._year, self._month, new_day, self._hour) +end + +--[[ Adds years + +! Creates a copy of self with adjusted years. + +!param increment (number) number to adjust, can be negative + +!return (Date) +]] +function Date:plusYears(increment) + local new_year = self._year + increment + return Date(new_year, self._month, self._day, self._hour) +end + +--[[ Adds hours + +! Creates a copy of self with adjusted hours. + +!param increment (number) number to adjust, can be negative + +!return (Date) +]] +function Date:plusHours(increment) + local new_hour = self._hour + increment + return Date(self._year, self._month, self._day, new_hour) +end + +--[[ Returns the month of year + +! Finds out what is a month of this year (1-12) + +!return (number) +]] +function Date:monthOfYear() + return self._month +end + +--[[ Returns the day of month + +! Finds out what is a current day in a date (1-31) + +!return (number) +]] +function Date:dayOfMonth() + return self._day +end + +--[[ Returns the year + +! Finds out what is a current year of this date (1-X) + +!return (number) +]] +function Date:year() + return self._year +end + +--[[ Returns the hour of the day + +! Finds out what is an hour of this date starting on 0 + +!return (number) +]] +function Date:hourOfDay() + return self._hour +end + +--[[ Return string representation + +! Returns string representation of the date in format y-mm-ddThh + +!return (string) +]] +function Date:tostring() + return string.format("%d-%02d-%02dT%02d", self._year, self._month, self._day, self._hour) +end + +--[[ Checks if date is a last day of a month + +! Finds out if the current day is a last day in current month with respect to +different month lengths. + +!return (boolean) +]] +function Date:isLastDayOfMonth() + return self._day == self:lastDayOfMonth() +end + +--[[ Checks if date is a last day of a year + +! Finds out if the current day is a last day in current month and current month +is a last month in a year. + +!return (boolean) +]] +function Date:isLastDayOfYear() + return self:isLastDayOfMonth() and self._month == 12 +end + +--[[ Returns the month of the game + +! Returns the number of months started since the start of the game. This +converts all the years to months and add them together with the started +months. + +!return (number) +]] +function Date:monthOfGame() + return (self._year - 1) * 12 + self._month +end + +--[[ Clone the date + +! Creates another instance of date with a same value + +!return (Date) +]] +function Date:clone() + return Date(self._year, self._month, self._day, self._hour) +end + +--[[ Checks the date + +! Checks the date with another passed as a parameter, but ignores time + +!param other (Date) The other day to be compared + +!return (boolean) +]] +function Date:isSameDay(other) + return self._year == other._year and self._month == other._month and self._day == other._day +end + +-- METAMETHODS + +local Date_mt = Date._metatable + +function Date_mt.__eq(one, other) + return one:isSameDay(other) and one._hour == other._hour +end + +function Date_mt.__lt(one, other) + if one._year == other._year then + if one._month == other._month then + if one._day == other._day then + return one._hour < other._hour + end + return one._day < other._day + end + return one._month < other._month + end + return one._year < other._year +end + +-- PRIVATE + +--[[ PRIVATE Adjusts the hours overflows + +! Method to deal with hour being more or less than valid value +]] +function Date:_adjustHoursOverflow() + while self._hour < 0 do + self._hour = self._hour + hours_per_day + self._day = self._day - 1 + end + while self._hour >= hours_per_day do + self._hour = self._hour - hours_per_day + self._day = self._day + 1 + end + self:_adjustDayOverflow() +end + +--[[ PRIVATE Adjusts the days overflows + +! Method to deal with day being more or less than valid value +]] +function Date:_adjustDayOverflow() + while self._day < 1 do + self._month = self._month - 1 + self:_adjustMonthOverflow() + self._day = self._day + self:lastDayOfMonth() + end + while self._day > self:lastDayOfMonth() do + self._day = self._day - self:lastDayOfMonth() + self._month = self._month + 1 + self:_adjustMonthOverflow() + end +end + +--[[ PRIVATE Adjusts the months overflows + +! Method to deal with month being more or less than valid value +]] +function Date:_adjustMonthOverflow() + local monthIx = self._month - 1 + self._year = self._year + math.floor(monthIx / 12) + self._month = monthIx % 12 + 1 +end + +--[[ PRIVATE Adjusts all the overflows + +! Normalize date to fix all the overflows of hours, days and months. This +method is a key to date adjustments. +]] +function Date:_adjustOverflow() + self:_adjustMonthOverflow() + self:_adjustDayOverflow() + self:_adjustHoursOverflow() +end diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/adviser.lua corsix-th-0.62/CorsixTH/Lua/dialogs/adviser.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/adviser.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/adviser.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") --! The (ideally) helpful advisor who pops up from the bottom dialog during a game. class "UIAdviser" (Window) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/bottom_panel.lua corsix-th-0.62/CorsixTH/Lua/dialogs/bottom_panel.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/bottom_panel.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/bottom_panel.lua 2018-07-21 11:13:17.000000000 +0000 @@ -206,29 +206,59 @@ function UIBottomPanel:drawDynamicInfo(canvas, x, y) if self.world:isCurrentSpeed("Pause") and not self.world.user_actions_allowed then self.pause_font:drawWrapped(canvas, _S.misc.pause, x + 10, y + 14, 255, "center") - elseif self.dynamic_info then - local info = self.dynamic_info - local font = self.white_font - for i, text in ipairs(info["text"]) do - font:drawWrapped(canvas, text, x + 20, y + 10 * i, 240) - if i == #info["text"] and info["progress"] then - local white = canvas:mapRGB(255, 255, 255) - local black = canvas:mapRGB(0, 0, 0) - local orange = canvas:mapRGB(221, 83, 0) - canvas:drawRect(white, x + 165, y + 10 * i, 100, 10) - canvas:drawRect(black, x + 166, y + 1 + 10 * i, 98, 8) - canvas:drawRect(orange, x + 166, y + 1 + 10 * i, math.floor(98 * info["progress"]), 8) - if info["dividers"] then - for _, value in ipairs(info["dividers"]) do - canvas:drawRect(white, x + 165 + math.floor(value * 100), y + 10 * i, 1, 10) - end + return + end + + if not (self.dynamic_info and self.dynamic_info["text"]) then + return + end + + local info = self.dynamic_info + local font = self.white_font + for i, text in ipairs(info["text"]) do + font:drawWrapped(canvas, text, x + 20, y + 10 * i, 240) + if i == #info["text"] and info["progress"] then + local white = canvas:mapRGB(255, 255, 255) + local black = canvas:mapRGB(0, 0, 0) + local orange = canvas:mapRGB(221, 83, 0) + canvas:drawRect(white, x + 165, y + 10 * i, 100, 10) + canvas:drawRect(black, x + 166, y + 1 + 10 * i, 98, 8) + canvas:drawRect(orange, x + 166, y + 1 + 10 * i, math.floor(98 * info["progress"]), 8) + if info["dividers"] then + for _, value in ipairs(info["dividers"]) do + canvas:drawRect(white, x + 165 + math.floor(value * 100), y + 10 * i, 1, 10) end end end end end +--! Update the information shown in the information box on the panel. +--! +--! If the info is nil then a cooldown timer is used before removing the +--! information from the display. +--! +--!param info (table) A table containing the information to display. The text +--! key is required and contains an array of lines to show. An optional +--! progress key may be given to draw a progress bar, following the text and +--! and an array of dividers may be provided to draw extra vertical lines in +--! the progress bar. +--! +--! info = { +--! text: { "He's not the saviour", "He's very naughty boy" }, +--! progress: 50, +--! dividers: { 25, 50, 75 } +--! } function UIBottomPanel:setDynamicInfo(info) + if info and not info["text"] then + self.world:gameLog("") + self.world:gameLog("Dynamic info is missing text!") + self.world:gameLog("Please report this issue including the call stack below.") + self.world:gameLog(debug.traceback()) + + return + end + if not info then self.countdown = 25 else @@ -483,9 +513,9 @@ local fps = self.ui.app:getFPS() if fps then self.dynamic_info = {text = { - ("FPS: %i"):format(math.floor(fps + 0.5)), - ("Lua GC: %.1f Kb"):format(collectgarbage"count"), - ("Entities: %i"):format(#self.ui.app.world.entities), + ("FPS: %i"):format(math.floor(fps + 0.5) or 0), + ("Lua GC: %.1f Kb"):format(collectgarbage("count") or 0), + ("Entities: %i"):format(#self.ui.app.world.entities or 0), }} self.countdown = 1 end diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/build_room.lua corsix-th-0.62/CorsixTH/Lua/dialogs/build_room.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/build_room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/build_room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") class "UIBuildRoom" (Window) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/edit_room.lua corsix-th-0.62/CorsixTH/Lua/dialogs/edit_room.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/edit_room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/edit_room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -dofile "dialogs/place_objects" +corsixth.require("dialogs.place_objects") class "UIEditRoom" (UIPlaceObjects) @@ -258,7 +258,7 @@ if (x1 == humanoid.tile_x or x2 == humanoid.tile_x) or (y1 == humanoid.tile_y or y2 == humanoid.tile_y) then -- Humanoid not in the rectangle, but might be walking into it - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() if action.name ~= "walk" then return false end @@ -293,19 +293,20 @@ humanoids_to_watch[entity] = true -- Try to make the humanoid leave the area + local current_action = entity:getCurrentAction() local meander = entity.action_queue[2] if meander and meander.name == "meander" then -- Interrupt the idle or walk, which will cause a new meander target -- to be chosen, which will be outside the blueprint rectangle meander.can_idle = false - local on_interrupt = entity.action_queue[1].on_interrupt + local on_interrupt = current_action.on_interrupt if on_interrupt then - entity.action_queue[1].on_interrupt = nil - on_interrupt(entity.action_queue[1], entity) + current_action.on_interrupt = nil + on_interrupt(current_action, entity) end - elseif entity.action_queue[1].name == "seek_room" or (meander and meander.name == "seek_room") then + elseif current_action.name == "seek_room" or (meander and meander.name == "seek_room") then -- Make sure that the humanoid doesn't stand idle waiting within the blueprint - if entity.action_queue[1].name == "seek_room" then + if current_action.name == "seek_room" then entity:queueAction(MeanderAction():setCount(1):setMustHappen(true), 0) else meander.done_walk = false @@ -356,7 +357,7 @@ -- The person might be dying (this check should probably be moved into -- isHumanoidObscuringArea, but I don't want to change too much right -- before a release). - if humanoid.action_queue[1].name == "die" then + if humanoid:getCurrentAction().name == "die" then if not humanoid.hospital then self.humanoids_to_watch[humanoid] = nil end @@ -613,10 +614,12 @@ obj.remove() break end + local obj_state = obj:getState() self.world:destroyEntity(obj) if not obj.master then self:addObjects({{ object = TheApp.objects[obj.object_type.id], + state = obj_state, qty = 1 }}) end @@ -631,7 +634,7 @@ -- backup list of objects self.objects_backup = {} for k, o in pairs(self.objects) do - self.objects_backup[k] = { object = o.object, qty = o.qty } + self.objects_backup[k] = { object = o.object, qty = o.qty, state = o.state } end UIPlaceObjects.removeAllObjects(self, true) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/annual_report.lua corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/annual_report.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/annual_report.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/annual_report.lua 2018-07-21 11:13:17.000000000 +0000 @@ -571,7 +571,7 @@ local world = self.ui.app.world -- Draw titles - font:draw(canvas, _S.menu.charts .. " " .. (world.year + 1999), x + 210, y + 30, 200, 0) + font:draw(canvas, _S.menu.charts .. " " .. (world:date():year() + 1999), x + 210, y + 30, 200, 0) font:draw(canvas, _S.high_score.categories.money, x + 140, y + 98, 170, 0) font:draw(canvas, _S.high_score.categories.salary, x + 328, y + 98, 170, 0) font:draw(canvas, _S.high_score.categories.cures, x + 140, y + 205, 170, 0) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/graphs.lua corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/graphs.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/graphs.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/graphs.lua 2018-07-21 11:13:17.000000000 +0000 @@ -25,7 +25,7 @@ ---@type UIGraphs local UIGraphs = _G["UIGraphs"] -local TH = require "TH" +local TH = require("TH") -- These values are based on the background colours of the pen symbols local colours = { diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/progress_report.lua corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/progress_report.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/progress_report.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/progress_report.lua 2018-07-21 11:13:17.000000000 +0000 @@ -226,7 +226,7 @@ self:drawMarkers(canvas, x, y) self.normal_font:draw(canvas, _S.progress_report.header .. " " .. - (world.year + 1999), x + 227, y + 40, 400, 0) + (world:date():year() + 1999), x + 227, y + 40, 400, 0) self.small_font:draw(canvas, _S.progress_report.win_criteria:upper(), x + 263, y + 172) self.small_font:draw(canvas, _S.progress_report.percentage_pop:upper() .. " " .. (hospital.population * 100) .. "%", x + 450, y + 65) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/town_map.lua corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/town_map.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/fullscreen/town_map.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/fullscreen/town_map.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") --! Town map fullscreen window (purchase land, set radiator levels, map overview). class "UITownMap" (UIFullscreen) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/furnish_corridor.lua corsix-th-0.62/CorsixTH/Lua/dialogs/furnish_corridor.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/furnish_corridor.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/furnish_corridor.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") local math_floor = math.floor diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/menu.lua corsix-th-0.62/CorsixTH/Lua/dialogs/menu.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/menu.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/menu.lua 2018-07-21 11:13:17.000000000 +0000 @@ -20,7 +20,7 @@ local ipairs, math_floor, unpack, select, assert = ipairs, math.floor, unpack, select, assert -local TH = require "TH" +local TH = require("TH") --! The ingame menu bar which sits (nominally hidden) at the top of the screen. class "UIMenuBar" (Window) @@ -636,12 +636,21 @@ end options:appendCheckItem(_S.menu_options.lock_windows, boolean_runtime_config"lock_windows") + -- Edge Scrolling options:appendCheckItem(_S.menu_options.edge_scrolling, not app.config.prevent_edge_scrolling, function(item) app.config.prevent_edge_scrolling = not item.checked end, nil, function() return not app.config.prevent_edge_scrolling end) + -- Mouse Capture + options:appendCheckItem(_S.menu_options.capture_mouse, + app.config.capture_mouse, + function(item) app.config.capture_mouse = item.checked + app:saveConfig() + app:setCaptureMouse() + end) + options:appendCheckItem(_S.menu_options.adviser_disabled, not app.config.adviser_disabled, function(item) @@ -775,7 +784,7 @@ :appendCheckItem(_S.menu_debug_overlay.byte_7, false, overlay(35, 8, 7, 7, true), "") :appendCheckItem(_S.menu_debug_overlay.parcel, false, overlay("parcel"), "") ) - :appendItem(_S.menu_debug.sprite_viewer, function() dofile "sprite_viewer" end) + :appendItem(_S.menu_debug.sprite_viewer, function() corsixth.require("sprite_viewer") end) ) end end diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/patient.lua corsix-th-0.62/CorsixTH/Lua/dialogs/patient.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/patient.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/patient.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") -- Test for hit within the view circle local --[[persistable:patient_window_is_in_view_circle]] function is_in_view_circle(x, y) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/place_objects.lua corsix-th-0.62/CorsixTH/Lua/dialogs/place_objects.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/place_objects.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/place_objects.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") local ipairs, math_floor = ipairs, math.floor @@ -510,6 +510,7 @@ self.world:prepareFootprintTilesForBuild(object_footprint, self.object_cell_x, self.object_cell_y) real_obj = self.world:newObject(object.object.id, self.object_cell_x, self.object_cell_y, self.object_orientation) + real_obj:setState(object.state) end if room then room.objects[real_obj] = true diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/place_staff.lua corsix-th-0.62/CorsixTH/Lua/dialogs/place_staff.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/place_staff.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/place_staff.lua 2018-07-21 11:13:17.000000000 +0000 @@ -20,7 +20,7 @@ local math_floor = math.floor -local TH = require "TH" +local TH = require("TH") --! Invisible window which handles placing a `Staff` member in the world. class "UIPlaceStaff" (Window) @@ -56,7 +56,7 @@ if self.staff then self.staff.pickup = false self.staff.going_to_staffroom = nil - self.staff.action_queue[1].window = nil + self.staff:getCurrentAction().window = nil self.staff:setNextAction(MeanderAction()) elseif self.profile then self.ui:tutorialStep(2, {6, 7}, 1) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/queue_dialog.lua corsix-th-0.62/CorsixTH/Lua/dialogs/queue_dialog.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/queue_dialog.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/queue_dialog.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") --! Room / door / reception desk queue visualisation dialog. class "UIQueue" (Window) diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/directory_browser.lua corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/directory_browser.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/directory_browser.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/directory_browser.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,8 +18,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local lfs = require "lfs" -local TH = require "TH" +local lfs = require("lfs") +local TH = require("TH") local lfsext = TH.lfsExt() --! A tree node representing a directory in the physical file-system. diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/file_browser.lua corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/file_browser.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/file_browser.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/file_browser.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local lfs = require "lfs" +local lfs = require("lfs") --! A tree node representing a file (or directory) in the physical file-system -- that meets a given file extension criterion. diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/file_browsers/choose_font.lua corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/file_browsers/choose_font.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/file_browsers/choose_font.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/file_browsers/choose_font.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") local lfsext = TH.lfsExt() --! Window where the user can choose a font file. diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/new_game.lua corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/new_game.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/new_game.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/new_game.lua 2018-07-21 11:13:17.000000000 +0000 @@ -195,8 +195,8 @@ function UINewGame:startGame(difficulty) self.ui.app:loadLevel(1, difficulty) -- Initiate campaign progression. The UI above may now have changed. - if TheApp.world and not TheApp.using_demo_files then - TheApp.world.campaign = "TH.campaign" + if not TheApp.using_demo_files then + TheApp.world.campaign_info = "TH.campaign" end if self.start_tutorial then TheApp.ui.start_tutorial = true diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/options.lua corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/options.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/resizables/options.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/resizables/options.lua 2018-07-21 11:13:17.000000000 +0000 @@ -54,8 +54,27 @@ blue = 218, } +-- Private functions + +--- Calculates the Y position for the dialog box in the option menu +-- and increments along the current position for the next element +-- @return The Y position to place the element at + +function UIOptions:_getOptionYPos() + -- Offset from top of options box + local STARTING_Y_POS = 15 + -- Y Height is 20 for panel size + 10 for spacing + local Y_HEIGHT = 30 + + -- Multiply by the index so that index=1 is at STARTING_Y_POS + local calculated_pos = STARTING_Y_POS + Y_HEIGHT * (self._current_option_index - 1) + self._current_option_index = self._current_option_index + 1 + return calculated_pos +end + + function UIOptions:UIOptions(ui, mode) - self:UIResizable(ui, 320, 240, col_bg) + self:UIResizable(ui, 320, 300, col_bg) local app = ui.app self.mode = mode @@ -67,6 +86,13 @@ self.default_button_sound = "selectx.wav" self.app = app + -- Tracks the current position of the object + self._current_option_index = 1 + + -- Constants for most button's width and height + local BTN_WIDTH = 135 + local BTN_HEIGHT = 20 + self:checkForAvailableLanguages() -- Set up list of resolutions @@ -90,23 +116,38 @@ -- Window parts definition -- Title - self:addBevelPanel(80, 10, 165, 20, col_caption):setLabel(_S.options_window.caption) + local title_y_pos = self:_getOptionYPos() + self:addBevelPanel(80, title_y_pos, 165, 20, col_caption):setLabel(_S.options_window.caption) .lowered = true -- Fullscreen - self:addBevelPanel(20, 45, 135, 20, col_shadow, col_bg, col_bg) + local fullscreen_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, fullscreen_y_pos, BTN_WIDTH, BTN_HEIGHT, col_shadow, col_bg, col_bg) :setLabel(_S.options_window.fullscreen):setTooltip(_S.tooltip.options_window.fullscreen).lowered = true self.fullscreen_panel = - self:addBevelPanel(165, 45, 135, 20, col_bg):setLabel(app.fullscreen and _S.options_window.option_on or _S.options_window.option_off) - self.fullscreen_button = self.fullscreen_panel:makeToggleButton(0, 0, 140, 20, nil, self.buttonFullscreen) + self:addBevelPanel(165, fullscreen_y_pos, BTN_WIDTH, BTN_HEIGHT, col_bg):setLabel(app.fullscreen and _S.options_window.option_on or _S.options_window.option_off) + self.fullscreen_button = self.fullscreen_panel:makeToggleButton(0, 0, 140, BTN_HEIGHT, nil, self.buttonFullscreen) :setToggleState(app.fullscreen):setTooltip(_S.tooltip.options_window.fullscreen_button) -- Screen resolution - self:addBevelPanel(20, 70, 135, 20, col_shadow, col_bg, col_bg) + local screen_res_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, screen_res_y_pos, BTN_WIDTH, BTN_HEIGHT, col_shadow, col_bg, col_bg) :setLabel(_S.options_window.resolution):setTooltip(_S.tooltip.options_window.resolution).lowered = true + self.resolution_panel = self:addBevelPanel(165, screen_res_y_pos, BTN_WIDTH, BTN_HEIGHT, col_bg):setLabel(app.config.width .. "x" .. app.config.height) + + self.resolution_button = self.resolution_panel:makeToggleButton(0, 0, BTN_WIDTH, BTN_HEIGHT, nil, self.dropdownResolution):setTooltip(_S.tooltip.options_window.select_resolution) + + -- Mouse capture + local capture_mouse_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, capture_mouse_y_pos, BTN_WIDTH, BTN_HEIGHT, col_shadow, col_bg, col_bg) + :setLabel(_S.options_window.capture_mouse):setTooltip(_S.tooltip.options_window.capture_mouse).lowered = true + + self.mouse_capture_panel = + self:addBevelPanel(165, capture_mouse_y_pos, BTN_WIDTH, BTN_HEIGHT, col_bg):setLabel(app.config.capture_mouse and _S.options_window.option_on or _S.options_window.option_off) + + self.mouse_capture_button = self.mouse_capture_panel:makeToggleButton(0, 0, BTN_WIDTH, BTN_HEIGHT, nil, self.buttonMouseCapture) + :setToggleState(app.config.capture_mouse):setTooltip(_S.tooltip.options_window.capture_mouse) - self.resolution_panel = self:addBevelPanel(165, 70, 135, 20, col_bg):setLabel(app.config.width .. "x" .. app.config.height) - self.resolution_button = self.resolution_panel:makeToggleButton(0, 0, 135, 20, nil, self.dropdownResolution):setTooltip(_S.tooltip.options_window.select_resolution) -- Language -- Get language name in the language to normalize display. @@ -117,30 +158,36 @@ else lang = app.config.language end - self:addBevelPanel(20, 95, 135, 20, col_shadow, col_bg, col_bg) + + local lang_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, lang_y_pos, BTN_WIDTH, BTN_HEIGHT, col_shadow, col_bg, col_bg) :setLabel(_S.options_window.language):setTooltip(_S.tooltip.options_window.language).lowered = true - self.language_panel = self:addBevelPanel(165, 95, 135, 20, col_bg):setLabel(lang) - self.language_button = self.language_panel:makeToggleButton(0, 0, 135, 20, nil, self.dropdownLanguage):setTooltip(_S.tooltip.options_window.select_language) + self.language_panel = self:addBevelPanel(165, lang_y_pos, BTN_WIDTH, BTN_HEIGHT, col_bg):setLabel(lang) + self.language_button = self.language_panel:makeToggleButton(0, 0, BTN_WIDTH, BTN_HEIGHT, nil, self.dropdownLanguage):setTooltip(_S.tooltip.options_window.select_language) -- add the Audio global switch. - self:addBevelPanel(20, 120, 135, 20, col_shadow, col_bg, col_bg) + local audio_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, audio_y_pos, BTN_WIDTH, BTN_HEIGHT, col_shadow, col_bg, col_bg) :setLabel(_S.options_window.audio):setTooltip(_S.tooltip.options_window.audio_button).lowered = true self.volume_panel = - self:addBevelPanel(165, 120, 135, 20, col_bg):setLabel(app.config.audio and _S.customise_window.option_on or _S.customise_window.option_off) - self.volume_button = self.volume_panel:makeToggleButton(0, 0, 135, 20, nil, self.buttonAudioGlobal) + self:addBevelPanel(165, audio_y_pos, BTN_WIDTH, BTN_HEIGHT, col_bg):setLabel(app.config.audio and _S.customise_window.option_on or _S.customise_window.option_off) + self.volume_button = self.volume_panel:makeToggleButton(0, 0, BTN_WIDTH, BTN_HEIGHT, nil, self.buttonAudioGlobal) :setToggleState(app.config.audio):setTooltip(_S.tooltip.options_window.audio_toggle) -- "Customise" button - self:addBevelPanel(20, 150, 135, 30, col_bg):setLabel(_S.options_window.customise) - :makeButton(0, 0, 135, 30, nil, self.buttonCustomise):setTooltip(_S.tooltip.options_window.customise_button) + local customise_y_pos = self:_getOptionYPos() + self:addBevelPanel(20, customise_y_pos, BTN_WIDTH, 30, col_bg):setLabel(_S.options_window.customise) + :makeButton(0, 0, BTN_WIDTH, 30, nil, self.buttonCustomise):setTooltip(_S.tooltip.options_window.customise_button) -- "Folders" button - self:addBevelPanel(165, 150, 135, 30, col_bg):setLabel(_S.options_window.folder) - :makeButton(0, 0, 135, 30, nil, self.buttonFolder):setTooltip(_S.tooltip.options_window.folder_button) + self:addBevelPanel(165, customise_y_pos, BTN_WIDTH, 30, col_bg):setLabel(_S.options_window.folder) + :makeButton(0, 0, BTN_WIDTH, 30, nil, self.buttonFolder):setTooltip(_S.tooltip.options_window.folder_button) -- "Back" button - self:addBevelPanel(20, 190, 280, 40, col_bg):setLabel(_S.options_window.back) + -- Give some extra space to back button. This is fine as long as it is the last button in the options menu + local back_button_y_pos = self:_getOptionYPos() + 15 + self:addBevelPanel(20, back_button_y_pos, 280, 40, col_bg):setLabel(_S.options_window.back) :makeButton(0, 0, 280, 40, nil, self.buttonBack):setTooltip(_S.tooltip.options_window.back) end @@ -226,6 +273,13 @@ self.fullscreen_panel:setLabel(self.ui.app.fullscreen and _S.options_window.option_on or _S.options_window.option_off) end +function UIOptions:buttonMouseCapture(checked) + local app = self.ui.app + app.config.capture_mouse = not app.config.capture_mouse + app:saveConfig() + app:setCaptureMouse() + self.mouse_capture_button:setLabel(app.config.capture_mouse and _S.options_window.option_on or _S.options_window.option_off) +end function UIOptions:buttonCustomise() local window = UICustomise(self.ui, "menu") @@ -346,3 +400,4 @@ self.callback(tonumber(self.width_textbox.text) or 0, tonumber(self.height_textbox.text) or 0) end end + diff -Nru corsix-th-0.61/CorsixTH/Lua/dialogs/watch.lua corsix-th-0.62/CorsixTH/Lua/dialogs/watch.lua --- corsix-th-0.61/CorsixTH/Lua/dialogs/watch.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/dialogs/watch.lua 2018-07-21 11:13:17.000000000 +0000 @@ -33,7 +33,7 @@ self.esc_closes = false self.modal_class = "open_countdown" - self.tick_rate = math.floor((100 * app.world.hours_per_day) / 13) + self.tick_rate = math.floor((100 * Date.hoursPerDay()) / 13) self.tick_timer = self.tick_rate -- Initialize tick timer self.open_timer = 12 self.ui = ui diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/humanoid.lua corsix-th-0.62/CorsixTH/Lua/entities/humanoid.lua --- corsix-th-0.61/CorsixTH/Lua/entities/humanoid.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/humanoid.lua 2018-07-21 11:13:17.000000000 +0000 @@ -359,56 +359,9 @@ end function Humanoid:dump() - local name = "humanoid" - if self.profile then - name = self.profile.name - end - print("-----------------------------------") - print("Clicked on ".. name, self) - print("Class: ", self.humanoid_class) - if self.humanoid_class == "Doctor" then - print(string.format("Skills: (%.3f) Surgeon (%.3f) Psych (%.3f) Researcher (%.3f)", - self.profile.skill or 0, - self.profile.is_surgeon or 0, - self.profile.is_psychiatrist or 0, - self.profile.is_researcher or 0)) - end - print(string.format("Warmth: %.3f Happiness: %.3f Fatigue: %.3f Thirst: %.3f Toilet_Need: %.3f Health: %.3f", - self.attributes["warmth"] or 0, - self.attributes["happiness"] or 0, - self.attributes["fatigue"] or 0, - self.attributes["thirst"] or 0, - self.attributes["toilet_need"] or 0, - self.attributes["health"] or 0)) - - print("") - print("Actions:") - for i = 1, #self.action_queue do - local action = self.action_queue[i] - local flag = - (action.must_happen and " must_happen" or " ") .. - (action.todo_interrupt and " " or " ") - if action.room_type then - print(action.name .. " - " .. action.room_type .. flag) - elseif action.object then - print(action.name .. " - " .. action.object.object_type.id .. flag) - elseif action.name == "walk" then - print(action.name .. " - going to " .. action.x .. ":" .. action.y .. flag) - elseif action.name == "queue" then - local distance = action.current_bench_distance - if distance == nil then - distance = "nil" - end - local standing = "false" - if action:isStanding() then - standing = "true" - end - print(action.name .. " - Bench distance: " .. distance .. " Standing: " .. standing) - else - print(action.name .. flag) - end - end + print("Clicked on: ") + print(self:tostring()) print("-----------------------------------") end @@ -909,3 +862,68 @@ function Humanoid:getDrawingLayer() return 4 end + +function Humanoid:getCurrentAction() + if next(self.action_queue) == nil then + error("Action queue was empty. This should never happen.\n" .. self:tostring()) + end + + return self.action_queue[1] +end + +--[[ Return string representation +! Returns string representation of the humanoid like status and action queue +!return (string) +]] +function Humanoid:tostring() + local name = self.profile and self.profile.name or nil + local class = self.humanoid_class and self.humanoid_class or "N/A" + local full_name = "humanoid" + if (name) then + full_name = full_name .. " (" .. name .. ")" + end + + local result = string.format("%s - class: %s", full_name, class) + + result = result .. string.format("\nWarmth: %.3f Happiness: %.3f Fatigue: %.3f Thirst: %.3f Toilet_Need: %.3f Health: %.3f", + self.attributes["warmth"] or 0, + self.attributes["happiness"] or 0, + self.attributes["fatigue"] or 0, + self.attributes["thirst"] or 0, + self.attributes["toilet_need"] or 0, + self.attributes["health"] or 0) + + result = result .. "\nActions: [" + for i = 1, #self.action_queue do + local action = self.action_queue[i] + local action_string = action.name + if action.room_type then + action_string = action_string .. " - " .. action.room_type + elseif action.object then + action_string = action_string .. " - " .. action.object.object_type.id + elseif action.name == "walk" then + action_string = action_string .. " - going to " .. action.x .. ":" .. action.y + elseif action.name == "queue" then + local distance = action.current_bench_distance + if distance == nil then + distance = "nil" + end + local standing = "false" + if action:isStanding() then + standing = "true" + end + action_string = action_string .. " - Bench distance: " .. distance .. " Standing: " .. standing + end + local flag = action.must_happen and " must_happen" or "" + if flag ~= "" then + action_string = action_string .. " " .. flag + end + + if i ~= 1 then + result = result .. ", " + end + result = result .. action_string + end + result = result .. "]" + return result +end diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/machine.lua corsix-th-0.62/CorsixTH/Lua/entities/machine.lua --- corsix-th-0.61/CorsixTH/Lua/entities/machine.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/machine.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") --! An `Object` which needs occasional repair (to prevent explosion). class "Machine" (Object) @@ -406,6 +406,31 @@ return Object.tick(self) end +--[[ Gets the state of a machine + +! In addition to the object implementation this includes total_usage +!return (table) state +]] +function Machine:getState() + local state = Object.getState(self) + state.total_usage = self.total_usage + + return state +end + +--[[ Sets the state of a machine + +! Adds total_usage +!param state (table) table holding the state +!return (void) +]] +function Machine:setState(state) + Object.setState(self, state) + if state then + self.total_usage = state.total_usage + end +end + -- Dummy callbacks for savegame compatibility local callbackNewRoom = --[[persistable:machine_build_callback]] function(room) end local repair_loop_callback = --[[persistable:handyman_repair_loop_callback]] function() end diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/object.lua corsix-th-0.62/CorsixTH/Lua/entities/object.lua --- corsix-th-0.61/CorsixTH/Lua/entities/object.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/object.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") --! An `Entity` which occupies at least a single map tile and does not move. class "Object" (Entity) @@ -296,7 +296,7 @@ function Object:setTile(x, y) local function coordinatesAreInFootprint(object_footprint, xpos, ypos) for _, xy in ipairs(object_footprint) do - if(xy[1] == xpos and xy[2] == ypos) then + if xy[1] == xpos and xy[2] == ypos then return true end end @@ -304,10 +304,7 @@ end local function isEmpty(table) - for _, _ in pairs(table) do - return false - end - return true + return next(table) == nil end local function getComplementaryPassableFlag(passable_flag) @@ -863,3 +860,28 @@ end end end + +--[[ Gets the state of an object + +! The state can be later used to set the state of this object. This is +useful when we would destroy and create a new object that should represent +the same object. + +!return (table) state +]] +function Object:getState() + return {times_used = self.times_used} +end + +--[[ Sets the state of an object + +! This is a complement to a pair function. IT will use the generated state +table to update it's state. +!param state (table) table holding the state +!return (void) +]] +function Object:setState(state) + if state then + self.times_used = state.times_used + end +end diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/patient.lua corsix-th-0.62/CorsixTH/Lua/entities/patient.lua --- corsix-th-0.61/CorsixTH/Lua/entities/patient.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/patient.lua 2018-07-21 11:13:17.000000000 +0000 @@ -355,7 +355,7 @@ --! Animations for when there is an earth quake function Patient:falling() - local current = self.action_queue[1] + local current = self:getCurrentAction() current.keep_reserved = true if self.falling_anim and self:canPeeOrPuke(current) and self.has_fallen == 1 then self:setNextAction(FallingAction(), 0) @@ -422,7 +422,7 @@ end function Patient:vomit() - local current = self.action_queue[1] + local current = self:getCurrentAction() --Only vomit under these conditions. Maybe I should add a vomit for patients in queues too? if self:canPeeOrPuke(current) and self.has_vomitted == 0 then self:queueAction(VomitAction(), 1) @@ -456,7 +456,7 @@ end function Patient:pee() - local current = self.action_queue[1] + local current = self:getCurrentAction() --Only pee under these conditions. As with vomit, should they also pee if in a queue? if self:canPeeOrPuke(current) then self:queueAction(PeeAction(), 1) @@ -494,20 +494,20 @@ end function Patient:checkWatch() - if self.check_watch_anim and not self.action_queue[1].is_leaving then + if self.check_watch_anim and not self:getCurrentAction().is_leaving then self:queueAction(CheckWatchAction(), 0) end end function Patient:yawn() - local action = self.action_queue[1] + local action = self:getCurrentAction() if self.yawn_anim and action.name == "idle" then self:queueAction(YawnAction(), 0) end end function Patient:tapFoot() - if self.tap_foot_anim and not self.action_queue[1].is_leaving then + if self.tap_foot_anim and not self:getCurrentAction().is_leaving then self:queueAction(TapFootAction(), 0) end end @@ -668,7 +668,7 @@ -- 1. they are being cured in this moment. dying in the last few seconds -- before the cure makes only a subtle difference for gameplay -- 2. they will leave the room soon (toilets, diagnostics) and will die then - if not self:getRoom() and not self.action_queue[1].is_leaving then + if not self:getRoom() and not self:getCurrentAction().is_leaving then self:setMood("sad6", "deactivate") self:die() end @@ -700,7 +700,7 @@ end -- Vomitings. - if self.vomit_anim and not self:getRoom() and not self.action_queue[1].is_leaving and not self.action_queue[1].is_entering then + if self.vomit_anim and not self:getRoom() and not self:getCurrentAction().is_leaving and not self:getCurrentAction().is_entering then --Nausea level is based on health then proximity to vomit is used as a multiplier. --Only a patient with a health value of less than 0.8 can be the initial vomiter, however :) local initialVomitMult = 0.002 --The initial chance of vomiting. @@ -779,8 +779,8 @@ end -- Maybe it's time to visit the loo? if self.attributes["toilet_need"] and self.attributes["toilet_need"] > 0.75 then - if self.pee_anim and not self.action_queue[1].is_leaving and - not self.action_queue[1].is_entering and not self.in_room then + if self.pee_anim and not self:getCurrentAction().is_leaving and + not self:getCurrentAction().is_entering and not self.in_room then if math.random(1, 10) < 5 then self:pee() self:changeAttribute("toilet_need", -(0.5 + math.random()*0.15)) @@ -794,7 +794,7 @@ if not self.world:findRoomNear(self, "toilets") then self.going_to_toilet = "no-toilets" -- Gets reset when a new toilet is built (then, patient will try again). -- Otherwise we can queue the action, but only if not in any rooms right now. - elseif not self:getRoom() and not self.action_queue[1].is_leaving and not self.action_queue[1].pee then + elseif not self:getRoom() and not self:getCurrentAction().is_leaving and not self:getCurrentAction().pee then self:setNextAction(SeekToiletsAction():setMustHappen(true)) self.going_to_toilet = "yes" end @@ -823,7 +823,7 @@ -- The only allowed situations to grab a soda is when queueing -- or idling/walking in the corridors -- Also make sure the walk action when leaving a room has a chance to finish. - if not self:getRoom() and not self.action_queue[1].is_leaving and not self.going_home then + if not self:getRoom() and not self:getCurrentAction().is_leaving and not self.going_home then local machine, lx, ly = self.world: findObjectNear(self, "drinks_machine", 8) @@ -864,7 +864,7 @@ -- Or, if walking or idling insert the needed actions in -- the beginning of the queue - local current = self.action_queue[1] + local current = self:getCurrentAction() if current.name == "walk" or current.name == "idle" or current.name == "seek_room" then -- Go to the machine, use it, and then continue with -- whatever he/she was doing. @@ -910,8 +910,8 @@ -- it may be a situation where he/she is not in the queue -- anymore, but should be. If this is the case for more than -- 2 ticks, go to reception - if #self.action_queue > 1 and (self.action_queue[1].name == "use_object" or - self.action_queue[1].name == "idle") and + if #self.action_queue > 1 and (self:getCurrentAction().name == "use_object" or + self:getCurrentAction().name == "idle") and self.action_queue[2].name == "queue" then local found = false for _, humanoid in ipairs(self.action_queue[2].queue) do diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/staff.lua corsix-th-0.62/CorsixTH/Lua/entities/staff.lua --- corsix-th-0.61/CorsixTH/Lua/entities/staff.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/staff.lua 2018-07-21 11:13:17.000000000 +0000 @@ -93,13 +93,13 @@ self:changeAttribute("happiness", 0.0005) end) -- Being able to rest from work and play the video game or pool will make you happy - if (self.action_queue[1].name == "use_object" and self.action_queue[1].object.object_type.id == "video_game") then + if (self:getCurrentAction().name == "use_object" and self:getCurrentAction().object.object_type.id == "video_game") then self:changeAttribute("happiness", 0.08) end - if (self.action_queue[1].name == "use_object" and self.action_queue[1].object.object_type.id == "pool_table") then + if (self:getCurrentAction().name == "use_object" and self:getCurrentAction().object.object_type.id == "pool_table") then self:changeAttribute("happiness", 0.074) end - if (self.action_queue[1].name == "use_object" and self.action_queue[1].object.object_type.id == "sofa") then + if (self:getCurrentAction().name == "use_object" and self:getCurrentAction().object.object_type.id == "sofa") then self:changeAttribute("happiness", 0.05) end @@ -262,7 +262,7 @@ end -- Picking staff members up doesn't tire them, it just tires the player. - if self.action_queue[1].name == "pickup" then + if self:getCurrentAction().name == "pickup" then tiring = false end @@ -294,8 +294,8 @@ -- Staff is in training room, the training room has a consultant, and is using lecture chair. return room and room.room_info.id == "training" and room.staff_member and - self.action_queue[1].name == "use_object" and - self.action_queue[1].object.object_type.id == "lecture_chair" + self:getCurrentAction().name == "use_object" and + self:getCurrentAction().object.object_type.id == "lecture_chair" end function Staff:isLearningOnTheJob() @@ -304,7 +304,7 @@ -- Staff is in room but not training room, staff room, or toilets; is a doctor; and is using something return room and room.room_info.id ~= "training" and room.room_info.id ~= "staff_room" and room.room_info.id ~= "toilets" and - self.humanoid_class == "Doctor" and self.action_queue[1].name == "use_object" + self.humanoid_class == "Doctor" and self:getCurrentAction().name == "use_object" end @@ -580,7 +580,7 @@ local room = self:getRoom() if (self.staffroom_needed and ((room and not room:getPatient()) or not room)) or (room and self.going_to_staffroom) then - if self.action_queue[1].name ~= "walk" and self.action_queue[1].name ~= "queue" then + if self:getCurrentAction().name ~= "walk" and self:getCurrentAction().name ~= "queue" then self.staffroom_needed = nil self:goToStaffRoom() end @@ -777,7 +777,7 @@ -- in regular rooms (diagnosis / treatment), if no patient is in sight -- or if the only one in sight is actually leaving. if self.humanoid_class ~= "Handyman" and room.door.queue:patientSize() == 0 and - not self.action_queue[1].is_leaving and + not self:getCurrentAction().is_leaving and not (room.door.reserved_for and class.is(room.door.reserved_for, Patient)) then if room:getPatientCount() == 0 then return true @@ -793,7 +793,7 @@ else -- In the corridor and not on_call (watering or going to room), the staff is free -- unless going back to the training room or research department. - local x, y = self.action_queue[1].x, self.action_queue[1].y + local x, y = self:getCurrentAction().x, self:getCurrentAction().y if x then room = self.world:getRoom(x, y) if room and (room.room_info.id == "training" or room.room_info.id == "research") then @@ -1020,5 +1020,21 @@ return weighted_skill + weighted_fatigue + weighted_happiness end +--[[ Return string representation +! Adds Doctor statistics for a "Doctor" object +!return (string) +]] +function Staff:tostring() + local result = Humanoid.tostring(self) + if self.humanoid_class == "Doctor" then + result = result .. string.format("\nSkills: (%.3f) Surgeon (%.3f) Psych (%.3f) Researcher (%.3f)", + self.profile.skill or 0, + self.profile.is_surgeon or 0, + self.profile.is_psychiatrist or 0, + self.profile.is_researcher or 0) + end + return result +end + -- Dummy callback for savegame compatibility local callbackNewRoom = --[[persistable:staff_build_staff_room_callback]] function(room) end diff -Nru corsix-th-0.61/CorsixTH/Lua/entities/vip.lua corsix-th-0.62/CorsixTH/Lua/entities/vip.lua --- corsix-th-0.61/CorsixTH/Lua/entities/vip.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entities/vip.lua 2018-07-21 11:13:17.000000000 +0000 @@ -295,17 +295,22 @@ -- check for the average queue length local sum_queue = 0 + local room_count = 0 for _, room in pairs(self.world.rooms) do - -- this can be nil if there has been a room explosion if room.door.queue then sum_queue = sum_queue + room.door.queue:size() end + if not room.crashed then + room_count = room_count + 1 + end end - if sum_queue == 0 then + if room_count == 0 then + self.vip_rating = self.vip_rating - 100 + elseif sum_queue == 0 then self.vip_rating = self.vip_rating + 6 else - local queue_ratio = sum_queue / #self.world.rooms + local queue_ratio = sum_queue / room_count local queue_ratio_rangemap = { {upper = 2, value = 6}, {upper = 5, value = 3}, diff -Nru corsix-th-0.61/CorsixTH/Lua/entity.lua corsix-th-0.62/CorsixTH/Lua/entity.lua --- corsix-th-0.61/CorsixTH/Lua/entity.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/entity.lua 2018-07-21 11:13:17.000000000 +0000 @@ -24,7 +24,7 @@ ---@type Entity local Entity = _G["Entity"] -local TH = require "TH" +local TH = require("TH") function Entity:Entity(animation) self.th = animation diff -Nru corsix-th-0.61/CorsixTH/Lua/epidemic.lua corsix-th-0.62/CorsixTH/Lua/epidemic.lua --- corsix-th-0.61/CorsixTH/Lua/epidemic.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/epidemic.lua 2018-07-21 11:13:17.000000000 +0000 @@ -547,7 +547,7 @@ Typically this is used to determine if a patient can be vaccinated @param patient (Patient) the patient we wish to determine if they are static.]] local function is_static(patient) - local action = patient.action_queue[1] + local action = patient:getCurrentAction() return action.name == "queue" or action.name == "idle" or (action.name == "use_object" and action.object.object_type.id == "bench") end @@ -599,7 +599,7 @@ local px, py = patient.tile_x, patient.tile_y -- If the patient is using a bench the best tile to use is -- directly in front of them - local action = patient.action_queue[1] + local action = patient:getCurrentAction() if action.name == "use_object" then local object_in_use = action.object if object_in_use.object_type.id == "bench" then diff -Nru corsix-th-0.61/CorsixTH/Lua/filesystem.lua corsix-th-0.62/CorsixTH/Lua/filesystem.lua --- corsix-th-0.61/CorsixTH/Lua/filesystem.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/filesystem.lua 2018-07-21 11:13:17.000000000 +0000 @@ -21,7 +21,7 @@ local pathsep = package.config:sub(1, 1) local part_pattern = "[^" .. pathsep .. "]+" -local ISO_FS = require "ISO_FS" +local ISO_FS = require("ISO_FS") --! Layer for abstracting away differences in file systems class "FileSystem" diff -Nru corsix-th-0.61/CorsixTH/Lua/game_ui.lua corsix-th-0.62/CorsixTH/Lua/game_ui.lua --- corsix-th-0.61/CorsixTH/Lua/game_ui.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/game_ui.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -dofile "ui" +corsixth.require("ui") --! Variant of UI for running games class "GameUI" (UI) @@ -26,7 +26,7 @@ ---@type GameUI local GameUI = _G["GameUI"] -local TH = require "TH" +local TH = require("TH") -- The maximum distance to shake the screen from the origin during an -- earthquake with full intensity. diff -Nru corsix-th-0.61/CorsixTH/Lua/graphics.lua corsix-th-0.62/CorsixTH/Lua/graphics.lua --- corsix-th-0.61/CorsixTH/Lua/graphics.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/graphics.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") local pathsep = package.config:sub(1, 1) local ourpath = debug.getinfo(1, "S").source:sub(2, -17) diff -Nru corsix-th-0.61/CorsixTH/Lua/hospital.lua corsix-th-0.62/CorsixTH/Lua/hospital.lua --- corsix-th-0.61/CorsixTH/Lua/hospital.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/hospital.lua 2018-07-21 11:13:17.000000000 +0000 @@ -370,7 +370,7 @@ } if hosp.balance < 2000 and hosp.balance >= -500 then hosp.world.ui.adviser:say(cashlowmessage[math.random(1, #cashlowmessage)]) - elseif hosp.balance < -2000 and hosp.world.month > 8 then + elseif hosp.balance < -2000 and hosp.world:date():monthOfYear() > 8 then -- ideally this should be linked to the lose criteria for balance hosp.world.ui.adviser:say(_A.warnings.bankruptcy_imminent) end @@ -687,7 +687,7 @@ local numberSitting = 0 local numberStanding = 0 for _, patient in ipairs(self.patients) do - local pat_action = patient.action_queue[1] + local pat_action = patient:getCurrentAction() if pat_action.name == "idle" then numberStanding = numberStanding + 1 elseif pat_action.name == "use_object" and pat_action.object.object_type.id == "bench" then @@ -700,105 +700,93 @@ -- A range of checks to help a new player. These are set days apart and will show no more than once a month function Hospital:checkFacilities() - if self.hospital and self:isPlayerHospital() then + local current_date = self.world:date() + local day = current_date:dayOfMonth() + -- All messages are shown after first 4 months if respective conditions are met + if self:isPlayerHospital() and current_date >= Date(1,5) then -- If there is no staff room, remind player of the need to build one - if self.world.day == 3 and not self:hasRoomOfType("staff_room") then - if self.world.month > 4 and not self.staff_room_msg then - self:noStaffroom_msg() - elseif self.world.year > 1 then - self:noStaffroom_msg() - end + if not self.staff_room_msg and day == 3 and not self:hasRoomOfType("staff_room") then + self:noStaffroom_msg() end -- If there is no toilet, remind player of the need to build one - if self.world.day == 8 and not self:hasRoomOfType("toilets") then - if self.world.month > 4 and not self.toilet_msg then - self:noToilet_msg() - elseif self.world.year > 1 then - self:noToilet_msg() - end - end - -- How are we for seating, if there are plenty then praise is due, if not the player is warned - -- We don't want to see praise messages about seating every month, so randomise the chances of it being shown - -- check the seating : standing ratio of waiting patients - -- find all the patients who are currently waiting around - local show_msg = math.random(1, 4) - local numberSitting, numberStanding = self:countSittingStanding() - - -- If there are patients standing then maybe the seating is in the wrong place! - -- set to 5% (standing:seated) if there are more than 50 patients or 20% if there are less than 50. - -- If this happens for 10 days in any month you are warned about seating unless you have already been warned that month - -- So there are now two checks about having enough seating, if either are called then you won't receive praise. (may need balancing) - if self.patientcount < 50 then - if numberStanding > math.min(numberSitting / 5) then - self.seating_warning = self.seating_warning + 1 - end - else - if numberStanding > math.min(numberSitting / 20) then + if not self.toilet_msg and day == 8 and not self:hasRoomOfType("toilets") then + self:noToilet_msg() + end + + if not self.bench_msg then + -- How are we for seating, if there are plenty then praise is due, if not the player is warned + -- check the seating : standing ratio of waiting patients + -- find all the patients who are currently waiting around + local numberSitting, numberStanding = self:countSittingStanding() + + -- If there are patients standing then maybe the seating is in the wrong place! + -- set to 5% (standing:seated) if there are more than 50 patients or 20% if there are less than 50. + -- If this happens for 10 days in any month you are warned about seating unless you have already been warned that month + -- So there are now two checks about having enough seating, if either are called then you won't receive praise. (may need balancing) + local number_standing_threshold = numberSitting / (self.patientcount < 50 and 5 or 20) + if numberStanding > number_standing_threshold then self.seating_warning = self.seating_warning + 1 + if self.seating_warning >= 10 then + self:warningBench() + end end - if self.seating_warning >= 10 and not self.bench_msg then - self:warningBench() - self.seating_warning = 0 - end - end - if self.world.day == 12 and show_msg == 4 and not self.bench_msg and - (self.world.year > 1 or (self.world.year == 1 and self.world.month > 4)) then - -- If there are less patients standing than sitting (1:20) and there are more benches than patients in the hospital - -- you have plenty of seating. If you have not been warned of standing patients in the last month, you could be praised. - if self.world.object_counts.bench > self.patientcount then - self:praiseBench() - -- Are there enough benches for the volume of patients in your hospital? - elseif self.world.object_counts.bench < self.patientcount then - self:warningBench() + + if day == 12 then + -- If there are less patients standing than sitting (1:20) and there are more benches than patients in the hospital + -- you have plenty of seating. If you have not been warned of standing patients in the last month, you could be praised. + + -- We don't want to see praise messages about seating every month, so randomise the chances of it being shown + local show_praise = math.random(1, 4) == 4 + if self.world.object_counts.bench > self.patientcount and show_praise then + self:praiseBench() + -- Are there enough benches for the volume of patients in your hospital? + elseif self.world.object_counts.bench < self.patientcount then + self:warningBench() + end end end - -- Make players more aware of the need for radiators and how hot or cold the patients and staff are - -- If there are no radiators remind the player from May onwards - if self.world.object_counts.radiator == 0 and self.world.month > 4 and self.world.day == 15 then + -- Make players more aware of the need for radiators + if self.world.object_counts.radiator == 0 then self.world.ui.adviser:say(_A.information.initial_general_advice.place_radiators) end - -- Now to check how warm or cold patients and staff are. So that we are not bombarded with warmth + + -- Now to check how warm or cold patients and staff are. So that we are not bombarded with warmth -- messages if we are told about patients then we won't be told about staff as well in the same month -- And unlike TH we don't want to be told that anyone is too hot or cold when the boiler is broken do we! - if not self.heating_broke then - if not self.warmth_msg and self.world.day == 15 then + if not self.warmth_msg and not self.heating_broke then + if day == 15 then local warmth = self:getAveragePatientAttribute("warmth", 0.3) -- Default value does not result in a message. - if (self.world.year > 1 or self.world.month > 4) and warmth < 0.22 then + if warmth < 0.22 then self:warningTooCold() - elseif self.world.month > 4 and warmth >= 0.36 then + elseif warmth >= 0.36 then self:warningTooHot() end end -- Are the staff warm enough? - if not self.warmth_msg and self.world.day == 20 then + if day == 20 then local avgWarmth = self:getAverageStaffAttribute("warmth", 0.25) -- Default value does not result in a message. - if (self.world.year > 1 or self.world.month > 4) and avgWarmth < 0.22 then + if avgWarmth < 0.22 then self.world.ui.adviser:say(_A.warnings.staff_very_cold) - elseif self.world.month > 4 and avgWarmth >= 0.36 then + elseif avgWarmth >= 0.36 then self.world.ui.adviser:say(_A.warnings.staff_too_hot) end end end + -- Are the patients in need of a drink - if not self.thirst_msg and self.world.day == 24 then + if not self.thirst_msg and day == 24 then local thirst = self:getAveragePatientAttribute("thirst", 0) -- Default value does not result in a message. - if self.world.year == 1 and self.world.month > 4 then - if thirst > 0.8 then - self.world.ui.adviser:say(_A.warnings.patients_very_thirsty) - elseif thirst > 0.6 then - self:warningThirst() - end - elseif self.world.year > 1 then - if thirst > 0.9 then - self.world.ui.adviser:say(_A.warnings.patients_very_thirsty) - elseif thirst > 0.6 then - self:warningThirst() - end + local thirst_threshold = current_date:year() == 1 and 0.8 or 0.9 + if thirst > thirst_threshold then + self.world.ui.adviser:say(_A.warnings.patients_very_thirsty) + elseif thirst > 0.6 then + self:warningThirst() end end + -- reset all the messages on 28th of each month - if self.world.day == 28 then + if day == 28 then self.staff_room_msg = false self.toilet_msg = false self.bench_msg = false @@ -811,7 +799,7 @@ end --! Called each tick, also called 'hours'. Check hours_per_day in ---! world.lua to see how many times per day this is. +--! date.lua to see how many times per day this is. function Hospital:tick() -- add some random background sounds, ringing phones, coughing, belching etc self:countPatients() @@ -1030,7 +1018,7 @@ if breakdown == 1 and not self.heating_broke and self.boiler_can_break and self.world.object_counts.radiator > 0 then if tonumber(self.world.map.level_number) then - if self.world.map.level_number == 1 and (self.world.month > 5 or self.world.year > 1) then + if self.world.map.level_number == 1 and (self.world:date() >= Date(1,6)) then self:boilerBreakdown() elseif self.world.map.level_number > 1 then self:boilerBreakdown() @@ -1041,22 +1029,8 @@ end -- Calculate heating cost daily. Divide the monthly cost by the number of days in that month - local month_length = { - 31, -- Jan - 28, -- Feb - 31, -- Mar - 30, -- Apr - 31, -- May - 30, -- Jun - 31, -- Jul - 31, -- Aug - 30, -- Sep - 31, -- Oct - 30, -- Nov - 31, -- Dec - } local radiators = self.world.object_counts.radiator - local heating_costs = (((self.radiator_heat * 10) * radiators) * 7.50) / month_length[self.world.month] + local heating_costs = (((self.radiator_heat * 10) * radiators) * 7.50) / self.world:date():lastDayOfMonth() self.acc_heating = self.acc_heating + heating_costs if self:isPlayerHospital() then dailyUpdateRatholes(self) end @@ -1066,6 +1040,7 @@ function Hospital:onEndMonth() -- Spend wages local wages = 0 + local current_month = self.world:date():monthOfYear() for _, staff in ipairs(self.staff) do wages = wages + staff.profile.wage end @@ -1130,10 +1105,10 @@ end -- Check for equipment getting available - self.research:checkAutomaticDiscovery(self.world.month + 12 * (self.world.year - 1)) + self.research:checkAutomaticDiscovery(self.world:date():monthOfGame()) -- Add some interesting statistics. - self.statistics[self.world.month + 1 + 12 * (self.world.year - 1)] = { + self.statistics[self.world:date():monthOfGame() + 1] = { money_in = self.money_in, money_out = self.money_out, wages = wages, @@ -1147,18 +1122,18 @@ self.money_out = 0 -- make players aware of the need for a receptionist and desk. - if (self:isPlayerHospital() and not self:hasStaffedDesk()) and self.world.year == 1 then - if self.receptionist_count ~= 0 and self.world.month > 2 and not self.receptionist_msg then + if (self:isPlayerHospital() and not self:hasStaffedDesk()) and self.world:date():year() == 1 then + if self.receptionist_count ~= 0 and current_month > 2 and not self.receptionist_msg then self.world.ui.adviser:say(_A.warnings.no_desk_6) self.receptionist_msg = true - elseif self.receptionist_count == 0 and self.world.month > 2 and self.world.object_counts["reception_desk"] ~= 0 then + elseif self.receptionist_count == 0 and current_month > 2 and self.world.object_counts["reception_desk"] ~= 0 then self.world.ui.adviser:say(_A.warnings.no_desk_7) -- self.receptionist_msg = true - elseif self.world.month == 3 then + elseif current_month == 3 then self.world.ui.adviser:say(_A.warnings.no_desk, true) - elseif self.world.month == 8 then + elseif current_month == 8 then self.world.ui.adviser:say(_A.warnings.no_desk_1, true) - elseif self.world.month == 11 then + elseif current_month == 11 then if self.visitors == 0 then self.world.ui.adviser:say(_A.warnings.no_desk_2, true) else @@ -1207,7 +1182,7 @@ -- this will replicate that. I have still to check other levels above 5 to -- see if there are other large increases. -- TODO Hall of fame and shame - if self.world.year == 3 and self.world.map.level_number == 3 then + if self.world:date():year() == 3 and self.world.map.level_number == 3 then -- adds the extra to salary in level 3 year 3 self.player_salary = self.player_salary + math.random(8000,20000) end @@ -1287,7 +1262,7 @@ local emer = self.emergency local rescued_patients = emer.cured_emergency_patients for _, patient in ipairs(self.emergency_patients) do - if patient and not patient.cured and not patient:getRoom() then + if patient and not patient.cured and not patient.dead and not patient:getRoom() then patient:die() end end @@ -1444,7 +1419,7 @@ -- The patient isn't contagious if these conditions aren't passed local reduce_months = level_config.ReduceContMonths or 14 local reduce_people = level_config.ReduceContPeepCount or 20 - local date_in_months = self.world.month + (self.world.year - 1)*12 + local date_in_months = self.world:date():monthOfGame() if potentially_contagious and date_in_months > reduce_months and self.num_visitors > reduce_people then @@ -1644,8 +1619,8 @@ ]] function Hospital:logTransaction(transaction) transaction.balance = self.balance - transaction.day = self.world.day - transaction.month = self.world.month + transaction.day = self.world:date():dayOfMonth() + transaction.month = self.world:date():monthOfYear() while #self.transactions > 20 do self.transactions[#self.transactions] = nil end diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/die.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/die.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/die.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/die.lua 2018-07-21 11:13:17.000000000 +0000 @@ -28,7 +28,7 @@ end local action_die_tick; action_die_tick = permanent"action_die_tick"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local phase = action.phase local mirror = humanoid.last_move_direction == "east" and 0 or 1 if phase == 0 then @@ -69,7 +69,7 @@ end) local action_die_tick_reaper; action_die_tick_reaper = permanent"action_die_tick_reaper"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local mirror = humanoid.last_move_direction == "east" and 0 or 1 local phase = action.phase @@ -264,42 +264,8 @@ --If this isn't done their bald head will become bloated instead of suddenly having hair: if humanoid.disease.id == "baldness" then humanoid:setLayer(0,2) end - --[[Make the patient fall over: because this animation requires two tiles make sure there's - enough space for this animation--]] - local mirror_fall - local east_tile_usable = humanoid.world:isTileEmpty(humanoid.tile_x + 1, humanoid.tile_y, true) - local south_tile_usable = humanoid.world:isTileEmpty(humanoid.tile_x, humanoid.tile_y + 1, true) - --Are the preferred fall directions usable? - if preferred_fall_direction == "east" and east_tile_usable then - humanoid.last_move_direction = "east" - mirror_fall = 0 - elseif preferred_fall_direction == "south" and south_tile_usable then - humanoid.last_move_direction = "south" - mirror_fall = 1 - else - --If the preferred direction isn't usable try the other direction: - if east_tile_usable then - humanoid.last_move_direction = "east" - mirror_fall = 0 - elseif south_tile_usable then - humanoid.last_move_direction = "south" - mirror_fall = 1 - --[[If the patient's last move direction was east or south then there could be no fall space available so this else - closure makes them walk to an accessible adjacent tile so that they can then fall on to their current tile:]]-- - else - -- Either the west or north tile will be accessible because this else closure can only be reached if the tiles adjacent to - -- the patient east and south are blocked and this game doesn't allow patients to become stuck by having all the tiles - -- adjacent to them become obstructed by objects and/or rooms: - if humanoid.world:isTileEmpty(humanoid.tile_x - 1, humanoid.tile_y, true) then - humanoid:walkTo(humanoid.tile_x - 1, humanoid.tile_y) - else - humanoid:walkTo(humanoid.tile_x, humanoid.tile_y - 1) - end - humanoid:queueAction(DieAction()) - humanoid:finishAction() - return - end - end + local mirror_fall = preferred_fall_direction == "east" and 0 or 1 + humanoid.last_move_direction = preferred_fall_direction humanoid:setAnimation(anims.fall_east, mirror_fall) diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/idle.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/idle.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/idle.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/idle.lua 2018-07-21 11:13:17.000000000 +0000 @@ -58,7 +58,7 @@ end) local action_timer = permanent"action_idle_timer"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() if action.after_use then action.after_use() action.must_happen = true diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/meander.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/meander.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/meander.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/meander.lua 2018-07-21 11:13:17.000000000 +0000 @@ -89,14 +89,15 @@ end elseif action.loop_callback then action.loop_callback() - if action ~= humanoid.action_queue[1] then + if action ~= humanoid:getCurrentAction() then return end end local procrastination - if action.can_idle and math.random(1, 3) == 1 then - procrastination = IdleAction():setCount(math.random(25, 40)):setMustHappen(action.must_happen) + if action.can_idle then + action.can_idle = false + procrastination = IdleAction():setCount(math.random(5, 40)):setMustHappen(action.must_happen) else action.can_idle = true procrastination = WalkAction(x, y):setMustHappen(action.must_happen) diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/multi_use_object.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/multi_use_object.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/multi_use_object.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/multi_use_object.lua 2018-07-21 11:13:17.000000000 +0000 @@ -69,7 +69,7 @@ return self end -local TH = require "TH" +local TH = require("TH") local orient_mirror = { north = "west", @@ -246,7 +246,7 @@ end action_multi_use_object_tick = permanent"action_multi_use_object_tick"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local use_with = action.use_with local object = action.object local phase = action.phase @@ -300,8 +300,8 @@ end use_with.th:makeVisible() - use_with.action_queue[1].on_interrupt = action.idle_interrupt - use_with.action_queue[1].must_happen = action.idle_must_happen + use_with:getCurrentAction().on_interrupt = action.idle_interrupt + use_with:getCurrentAction().must_happen = action.idle_must_happen local spec = object.object_type.orientations[object.direction] local pos = spec.finish_use_position or spec.use_position humanoid:setTilePositionSpeed(object.tile_x + pos[1], object.tile_y + pos[2]) @@ -339,19 +339,19 @@ return end end - if use_with.action_queue[1].name ~= "idle" then + if use_with:getCurrentAction().name ~= "idle" then humanoid:queueAction(IdleAction():setCount(2), 0) return else - action.idle_interrupt = use_with.action_queue[1].on_interrupt - action.idle_must_happen = use_with.action_queue[1].must_happen - use_with.action_queue[1].on_interrupt = nil - use_with.action_queue[1].must_happen = true + action.idle_interrupt = use_with:getCurrentAction().on_interrupt + action.idle_must_happen = use_with:getCurrentAction().must_happen + use_with:getCurrentAction().on_interrupt = nil + use_with:getCurrentAction().must_happen = true end action.must_happen = true if action.prolonged_usage then action.on_interrupt = action_multi_use_object_interrupt - use_with.action_queue[1].on_interrupt = --[[persistable:action_multi_use_object_use_with_interrupt]] function() + use_with:getCurrentAction().on_interrupt = --[[persistable:action_multi_use_object_use_with_interrupt]] function() if action.on_interrupt then action:on_interrupt() action.on_interrupt = nil diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/queue.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/queue.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/queue.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/queue.lua 2018-07-21 11:13:17.000000000 +0000 @@ -145,7 +145,7 @@ if index == -1 then -- Attempt to recover by assuming the person is sitting down. print("Warning: Idle not in action_queue") - if humanoid.action_queue[1].name == "use_object" then + if humanoid:getCurrentAction().name == "use_object" then -- It is likely that the person is sitting down. return action_queue_leave_bench(action, humanoid) else diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/seek_room.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/seek_room.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/seek_room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/seek_room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -298,7 +298,7 @@ local current_room = humanoid:getRoom() if not current_room or not (current_room.room_info.id == "research" and current_room:getStaffMember() and - current_room:getStaffMember().action_queue[1].name == "multi_use_object") then + current_room:getStaffMember():getCurrentAction().name == "multi_use_object") then action_seek_room_goto_room(rm, humanoid, action.diagnosis_room) end TheApp.ui.bottom_panel:removeMessage(humanoid) diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/staff_reception.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/staff_reception.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/staff_reception.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/staff_reception.lua 2018-07-21 11:13:17.000000000 +0000 @@ -53,7 +53,7 @@ end) local action_staff_reception_idle_phase = permanent"action_staff_reception_idle_phase"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local direction = humanoid.last_move_direction local anims = humanoid.walk_anims local object = action.object diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/use_object.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/use_object.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/use_object.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/use_object.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") class "UseObjectAction" (HumanoidAction) @@ -306,7 +306,7 @@ end action_use_object_tick = permanent"action_use_object_tick"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local object = action.object local phase = action.phase local oldphase = phase diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/use_screen.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/use_screen.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/use_screen.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/use_screen.lua 2018-07-21 11:13:17.000000000 +0000 @@ -41,7 +41,7 @@ screen:removeUser(humanoid) local offset = screen.object_type.orientations[screen.direction].use_position humanoid:setTile(screen.tile_x + offset[1], screen.tile_y + offset[2]) - local after_use = humanoid.action_queue[1].after_use + local after_use = humanoid:getCurrentAction().after_use if after_use then after_use() end diff -Nru corsix-th-0.61/CorsixTH/Lua/humanoid_actions/walk.lua corsix-th-0.62/CorsixTH/Lua/humanoid_actions/walk.lua --- corsix-th-0.61/CorsixTH/Lua/humanoid_actions/walk.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/humanoid_actions/walk.lua 2018-07-21 11:13:17.000000000 +0000 @@ -176,7 +176,7 @@ local flags_here, flags_there = {}, {} local action_walk_tick; action_walk_tick = permanent"action_walk_tick"( function(humanoid) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local path_x = action.path_x local path_y = action.path_y local path_index = action.path_index @@ -249,7 +249,7 @@ end) navigateDoor = function(humanoid, x1, y1, dir) - local action = humanoid.action_queue[1] + local action = humanoid:getCurrentAction() local duration = 12 local dx = x1 local dy = y1 diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/brazilian_portuguese.lua corsix-th-0.62/CorsixTH/Lua/languages/brazilian_portuguese.lua --- corsix-th-0.61/CorsixTH/Lua/languages/brazilian_portuguese.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/brazilian_portuguese.lua 2018-07-21 11:13:17.000000000 +0000 @@ -1,7 +1,7 @@ --[[ Copyright (c) 2010 Manuel "Roujin" Wolf Copyright (c) 2012 Henrique Poyatos Copyright (c) 2014 Leonardo Malaman (LeonardoGamer) -Copyright (c) 2017 Altieres Lima da Silva +Copyright (c) 2018 Altieres Lima da Silva Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -102,6 +102,7 @@ jukebox = " MAQUINA DE DISCOS (J) ", lock_windows = " TRAVAR JANELAS ", edge_scrolling = " ROLAR MARGEM ", + capture_mouse = " CAPTURAR MOUSE ", adviser_disabled = " CONSELHEIRO (SHIFT+A) ", warmth_colors = " CORES QUENTES ", wage_increase = " EXIGENCIAS SALARIAS", @@ -184,7 +185,7 @@ no_desk = "Você precisa comprar um balcäo de recepçäo e contratar uma recepcionista em algum momento!", no_desk_1 = "Se você quer que os pacientes venham ao seu hospital, você precisa contratar uma recepcionista e comprar um balcäo para recepcioná-los!", no_desk_2 = "Excelente, isso provavelmente é um recorde mundial - quase um ano e nenhum paciente! Se você deseja continuar administrando este hospital, você precisa urgente contratar uma recepcionista e comprar um balcäo para que ela possa trabalhar!", - no_desk_3 = "Brilhante, se passou quase um ano e ainda näo tem uma recepcionistas! Como quer que os pacientes apareçam? Arrume uma recepcionista e deixe de perder tempo!", + no_desk_3 = "Brilhante, se passou quase um ano e ainda näo tem uma recepcionista! Como quer que os pacientes apareçam? Arrume uma recepcionista e deixe de perder tempo!", no_desk_4 = "Uma recepcionista necessita de uma mesa para atender os pacientes que aparecem.", no_desk_5 = "Já era hora! Os pacientes começaräo a chegar logo.", no_desk_6 = "Você tem uma recepcionista, que tal se construir uma mesa de recepçäo para que possa trabalhar?", @@ -204,8 +205,8 @@ researcher_needs_desk_3 = "Cada pesquisa necessita de uma mesa para trabalhar.", nurse_needs_desk_1 = "Cada enfermeira necessita de uma mesa para trabalhar.", nurse_needs_desk_2 = "Sua enfermeira agradece que lhe tenha dado um descanso. Se pretende ter mais pessoas trabalhando na enfermaria, tem que dar a cada uma delas uma mesa para trabalhar.", - low_prices = "Você esta cobrando muito pouco pelo uso de %s. Isto trará pessoas para o seu hospital, mas você näo fará muito lucro com cada uma delas.", - high_prices = "Você esta cobrando muito pelo uso de %s. Isto trará grande lucro a curto prazo, mas no final das contas você começará a afugentar as pessoas para longe do seu hospital.", + low_prices = "Você está cobrando muito pouco pelo uso de %s. Isto trará pessoas para o seu hospital, mas você näo fará muito lucro com cada uma delas.", + high_prices = "Você está cobrando muito pelo uso de %s. Isto trará grande lucro a curto prazo, mas no final das contas você começará a afugentar as pessoas para longe do seu hospital.", fair_prices = "O preço de %s parece justo.", patient_not_paying = "Um paciente se foi sem pagar por %s porque é muito caro!", }, @@ -216,7 +217,7 @@ }, } -dynamic_info.patient.actions.no_gp_available = "Esperando que construa uma consulta" +dynamic_info.patient.actions.no_gp_available = "Esperando que construa um Consultório Geral" dynamic_info.staff.actions.heading_for = "Dirigindo-se para %s" dynamic_info.staff.actions.fired = "Despedido" dynamic_info.patient.actions.epidemic_vaccinated = "Eu näo sou mais contagioso" @@ -359,6 +360,7 @@ option_off = "Desligar", fullscreen = "Tela Cheia", resolution = "Resoluçäo", + capture_mouse = "Capturar Mouse", custom_resolution = "Personalizar...", width = "Largura", height = "Altura", @@ -376,6 +378,7 @@ fullscreen_button = "Clique para mudar para tela cheia", resolution = "A resoluçäo que o jogo deve ser executado", select_resolution = "Selecionar uma nova resoluçäo", + capture_mouse = "Clique para alternar a captura do cursor na janela do jogo", width = "Digite a largura desejada", height = "Digite a altura desejada", apply = "Aplicar a resoluçäo digitada", @@ -419,7 +422,7 @@ caption = "Localizaçäo de Pastas", data_label = "Dados do TH", font_label = "Fonte", - music_label = "MP3", + music_label = "Músicas", savegames_label = "Jogos Salvos", screenshots_label = "Capturas de Tela", -- next four are the captions for the browser window, which are called from the folder setting menu @@ -436,7 +439,7 @@ font_location = "A localizaçäo de uma fonte de letra capaz de mostrar caracteres Unicode necessários para seu idioma. Se näo for indicado, näo poderá selecionar idiomas que tenham mais caracteres dos que o jogo original tem, por exemplo, russo e chinês.", savegames_location = "A pasta de jogos salvos é localizada por padräo junto com o arquivo de configuraçäo e é utilizado para armazenar os jogos salvo. Se você näo gostar, pode selecionar outra procurando a pasta que quiser usar.", screenshots_location = "As capturas de tela säo guardadas por padräo em uma pasta junto com o arquivo de configuraçäo. Se você näo gostar, pode selecionar outra procurando a pasta que quiser usar.", - music_location = "Selecione uma pasta com seus arquivos de música em formato MP3. Necessita uma pasta já existente, entäo poderá procurá-la.", + music_location = "Selecione uma pasta com seus arquivos de música. Necessita de uma pasta já existente, entäo poderá procurá-la.", browse_data = "Procurar outra localizaçäo com uma instalaçäo do Theme Hospital. (Localizaçäo atual: %1%)", browse_font = "Procurar outro arquivo de fonte de letra. (Localizaçäo atual: %1%)", browse_saves = "Procurar outra localizaçäo para sua pasta de jogos salvos. (Localizaçäo atual: %1%) ", @@ -447,7 +450,7 @@ default = "Localizaçäo padräo", reset_to_default = "Volta a atribuir a pasta a sua localizaçäo padräo", -- original_path = "The currently chosen directory of the original Theme Hospital installation", -- where is this used, I have left if for the time being? - back = "Fechar este menu e voltar para menu de Configuraçöes", + back = "Fechar este menu e voltar para o menu de Configuraçöes", } font_location_window = { @@ -478,7 +481,7 @@ } tooltip.new_game_window = { - player_name = "Digite no nome que você deseja ser chamado no jogo", + player_name = "Digite o nome que você deseja ser chamado no jogo", difficulty = "Selecione o nível de dificuldade do jogo", easy = "Se você näo conhecer jogos de simulaçäo, esta dificuldade é para você.", medium = "Esta é a dificuldade intermediária, se você está inseguro do que deve escolher.", @@ -508,7 +511,7 @@ map_file_missing = "Näo foi possível encontrar o arquivo de mapa %s para esta fase!", minimum_screen_size = "Por favor, digite dimensöes de tela de pelo menos 640x480.", unavailable_screen_size = "O tamanho da tela que você digitou näo está disponível em tela cheia.", - alien_dna = "NOTA: Os pacientes alienígenas näo têm animaçöes para se sentar, abrir portas, bater nas portas, etc. portanto, assim como no Theme Hospital original, para fazer estas coisas aparentaräo mudar para uma imagem normal e logo voltaräo para o seu estado. Os pacientes com DNA alienígena só apareceräo se o arquivo de fase o indicar", + alien_dna = "NOTA: Os pacientes alienígenas näo têm animaçöes para se sentar, abrir portas, bater nas portas, etc. portanto, assim como no Theme Hospital original, ao fazer estas coisas aparentaräo mudar para uma imagem normal e logo voltaräo para o seu estado. Os pacientes com DNA alienígena só apareceräo se o arquivo de fase o indicar", fractured_bones = "NOTA: A animaçäo das pacientes femininas com Fraturas ósseas näo é perfeita", could_not_load_campaign = "Falha ao carregar a campanha: %s", could_not_find_first_campaign_level = "Näo foi possível encontrar o primeiro nível desta campanha: %s", @@ -533,10 +536,10 @@ very_old_save = "Houveram muitas mudanças no jogo desde que você começou a jogar este mapa. Para ter certeza que todas as funcionalidades estäo funcionando considere recomeçar o mapa.", level_lost = { "Que pena! Você fracassou. Mais sorte na próxima vez!", - "Você perdeu porque", + "Você perdeu porque:", reputation = "Sua reputaçäo caiu abaixo de %d.", balance = "Seu saldo no banco caiu abaixo de %d.", - percentage_killed = "Você matou mais de %d porcento dos pacientes.", + percentage_killed = "Você matou mais de %d por cento dos pacientes.", cheat = "Foi escolha sua ou você se enganou de botäo? Näo sabe nem trapacear direito?", }, cheat_not_possible = "Näo pode usar essa trapaça nesta fase. Näo sabe nem trapacear direito?", @@ -629,11 +632,11 @@ introduction_texts = { demo = - "Bem-vindo ao hospital de demonstraçäo! " .. + "Bem-vindo ao hospital de demonstraçäo!//" .. "Infelizmente esta versäo de demonstraçäo só possui esta fase. Entretanto, teremos aqui o suficiente para mantê-lo ocupado por enquanto! " .. "Você encontrará várias doenças que necessitaräo de salas diferentes para cura. De tempos em tempos, emergências ocorreräo. E você precisará pesquisar por salas adicionais usando o Centro de Pesquisas. " .. "Seu objetivo é ter um saldo bancário de $100.000,00, o valor do hospital em $ 70.000,00 e uma reputaçäo de 700, enquanto você cura pelo menos 75% de seus pacientes. " .. - "Certifique-se que sua reputaçäo näo fique abaixo de 300 e você näo mate mais de 40% dos seus pacientes, senäo você perde. " .. + "Certifique-se que sua reputaçäo näo fique abaixo de 300 e você näo mate mais de 40% dos seus pacientes, senäo você perde.//" .. "Boa sorte!", } @@ -730,7 +733,7 @@ rooms_long.toilets = "Banheiro" rooms_long.fracture_clinic = "Sala de Traumatologia" rooms_long.pharmacy = "Farmácia" -rooms_long.general_diag = "Consulta de Diagnóstico" +rooms_long.general_diag = "Diagnóstico Geral" rooms_long.research_room = "Centro de Pesquisa" rooms_long.scanner = "Sala de Scanner" rooms_long.electrolysis = "Sala de Eletrólise" @@ -772,7 +775,7 @@ fax.vip_visit_result.close_text = "Obrigado por visitar o hospital." fax.vip_visit_result.telegram = "Telegrama!" fax.vip_visit_result.vip_remarked_name = "Depois de visitar o seu hospital, %s declarou:" -fax.vip_visit_result.remarks.super[1] = "Que hospital eficaz! A próxima vez que esteja gravemente doente, venho aqui." +fax.vip_visit_result.remarks.super[1] = "Que hospital eficaz! A próxima vez que estiver gravemente doente, eu venho aqui." fax.vip_visit_result.remarks.super[2] = "É isto o que eu chamo de um hospital." fax.vip_visit_result.remarks.super[3] = "É um hospital excelente. E sei o que digo; visito muitos hospitais." fax.vip_visit_result.remarks.mediocre[1] = "Bom, já vi piores. Mas deveria fazer algumas melhoras." @@ -787,22 +790,22 @@ fax.vip_visit_result.remarks.good[1] = "Que hospital bem dirigido! Obrigado pelo seu convite." fax.vip_visit_result.remarks.good[2] = "Mmmm. Certamente näo é uma má instituiçäo médica." fax.vip_visit_result.remarks.good[3] = "Gostei do seu estupendo hospital. Agora, alguém quer um curry da Casa do Curry?" -fax.vip_visit_result.cash_grant = "Você foi premiado com um prêmio em dinheiro de $%d." +fax.vip_visit_result.cash_grant = "Você ganhou um prêmio em dinheiro de $%d." fax.vip_visit_result.rep_boost = "Sua reputaçäo na comunidade acaba de aumentar." fax.vip_visit_result.rep_loss = "A sua reputaçäo foi afetada em consequência" fax.disease_discovered.close_text = "Foi encontrada uma nova doença." -fax.disease_discovered.need_to_build = "Tem que construir um(a) %s para tratar isto." +fax.disease_discovered.need_to_build = "Precisa construir um(a) %s para tratar isto." fax.disease_discovered.can_cure = "Pode tratar esta doença." fax.disease_discovered.need_to_employ = "Contrate um(a) %s que possa solucionar este problema." fax.disease_discovered.need_to_build_and_employ = "Se construir uma %s e contratar um(a) %s pode ter êxito." fax.disease_discovered.discovered_name = "A sua equipe descobriu uma nova doença. É %s." fax.epidemic_result.close_text = "Bem!" fax.epidemic_result.compensation_amount = "O Governo decidiu lhe dar uma compensaçäo de %d pelos danos que estes incidente causara ao bom nome do seu hospital." -fax.epidemic_result.succeeded.part_1_name = "Chegou aos ouvidos do Inspetor de Saúde que na sua instituiçäo estava a tratar um caso maligno de %s." +fax.epidemic_result.succeeded.part_1_name = "Chegou aos ouvidos do Inspetor de Saúde que na sua instituiçäo estava tratando um caso maligno de %s." fax.epidemic_result.succeeded.part_2 = "Embora, näo fosse possível encontrar provas que comprovassem os ditos rumores..." fax.epidemic_result.hospital_evacuated = "O Ministério da Saúde näo tem outra alternativa a näo ser evacuar o seu hospital." fax.epidemic_result.failed.part_1_name = "Ao tentar esconder o fato de que enfrentavam um broto contagioso de %s" -fax.epidemic_result.failed.part_2 = "o pessoal do seu hospital é responsável por que a doença se propagou entre as pessoas que vivem perto do seu hospital." +fax.epidemic_result.failed.part_2 = "Os funcionários do seu hospital säo responsáveis pela doença que se propagou entre as pessoas que vivem perto do seu hospital." fax.epidemic_result.fine_amount = "O Governo declarou uma emergência nacional e multa-o com %d." fax.epidemic_result.rep_loss_fine_amount = "Os jornais têm feito um escândalo com isto. A sua reputaçäo será gravemente afetada. Além disso, imporá uma multa de %d." fax.emergency_result.close_text = "Aperte para sair" @@ -815,7 +818,7 @@ fax.diagnosis_failed.choices.send_home = "Enviar o paciente para casa." fax.diagnosis_failed.choices.take_chance = "Tentar uma possível cura." fax.diagnosis_failed.choices.wait = "Fazer o paciente esperar enquanto constrói mais salas de diagnóstico." -fax.diagnosis_failed.partial_diagnosis_percentage_name = "Existe %d porcento de probabilidades de descobrirmos que tipo de %s sofre esse paciente." +fax.diagnosis_failed.partial_diagnosis_percentage_name = "Existe %d por cento de probabilidades de descobrirmos que tipo de %s sofre esse paciente." fax.diagnosis_failed.situation = "Fizemos todos os nossos diagnósticos com este paciente e näo estamos seguros do que se trata." fax.disease_discovered_patient_choice.what_to_do_question = "O que quer fazer com o paciente?" fax.disease_discovered_patient_choice.choices.send_home = "Enviar o paciente para casa." @@ -823,7 +826,7 @@ fax.disease_discovered_patient_choice.choices.wait = "Faça o paciente esperar um momento no hospital." fax.disease_discovered_patient_choice.can_not_cure = "Näo pode curar esta doença." fax.disease_discovered_patient_choice.need_to_employ = "Contrate um(a) %s para corrigir esta situaçäo." -fax.disease_discovered_patient_choice.need_to_build = "Tem que construir um(a) %s para poder tratar isto." +fax.disease_discovered_patient_choice.need_to_build = "Precisa construir um(a) %s para poder tratar isto." fax.disease_discovered_patient_choice.need_to_build_and_employ = "Pode consegui-lo se construir um(a) %s e contratar um %s." fax.disease_discovered_patient_choice.guessed_percentage_name = "A sua equipe tem que averiguar o que tem um paciente. Há %d por cento de probabilidade de que seja %s" fax.disease_discovered_patient_choice.disease_name = "A sua equipe descobriu uma nova doença. É %s." @@ -1129,7 +1132,7 @@ build_room_window.pick_department = "Departamento" build_room_window.cost = "Custo: " object.bench = "Banco" -object.pharmacy_cabinet = "Primeiros-socorros" +object.pharmacy_cabinet = "Primeiros socorros" object.console = "Console" object.atom_analyser = "Analisador atômico" object.fire_extinguisher = "Extintor" @@ -1176,7 +1179,7 @@ object.inflator = "Inflador" object.toilet = "Banheiro" object.lecture_chair = "Poltrona" -object.auto_autopsy = "Máq. autoautópsias" +object.auto_autopsy = "Máq. autópsias" object.chair = "Cadeira" object.x_ray_viewer = "Máquina de raio-X" object.radiator = "Radiador" @@ -1383,34 +1386,34 @@ letter[4][2] = "Parabéns! No Ministério estamos muito impressionados pela sua capacidade como diretor do hospital. É sem dúvida, uma pessoa valiosa para o Departamento de Saúde, mas acreditamos que preferiria um trabalho mais qualificado. Receberia um salário de %d, embora a decisäo seja sua.//" letter[4][3] = "Está interessado em trabalhar no Hospital %s?" letter[5][1] = "Olá %s!//" -letter[5][2] = "Saúdo-lhe novamente. Respeitamos os seus desejos de näo deslocar do seu estupendo hospital, mas pedimos que o reconsidere. Ofereceremo-lhe um alto salário de %d se decidir ir para o outro hospital e encarregar da sua direçäo.//" +letter[5][2] = "Saudaçöes novamente. Respeitamos os seus desejos de näo querer sair do seu estupendo hospital, mas pedimos que o reconsidere. Ofereceremos para você um alto salário de %d se decidir ir para o outro hospital e se encarregar da sua direçäo.//" letter[5][3] = "Gostaria de ir agora para o Hospital %s?" letter[6][1] = "Olá %s!//" -letter[6][2] = "Receba as nossas saudaçöes. Sabemos que desfrutou muito da sua estadia nesta instituiçäo, täo agradável e bem dirigida, mas acreditamos que agora deveria pensar no seu futuro. Naturalmente, teria um salário de %d se decidisse deslocar. Vale a pena pensar.//" +letter[6][2] = "Receba as nossas saudaçöes. Sabemos que desfrutou muito da sua estadia nesta instituiçäo, täo agradável e bem dirigida, mas acreditamos que agora deveria pensar no seu futuro. Naturalmente, teria um salário de %d se decidisse sair. Vale a pena pensar.//" letter[6][3] = "Gostaria de ter um posto no Hospital %s?" letter[7][1] = "Olá %s!//" letter[7][2] = "Bom dia! O Ministério da Saúde queria saber se reconsideraria a sua decisäo de ficar no seu hospital. Compreendemos que tenha um estupendo hospital, mas acreditamos que faria muito bem em aceitar um trabalho mais estimulante, com um salário de %d.//" letter[7][3] = "Aceitaria um posto no Hospital %s?" letter[8][1] = "Olá %s!//" -letter[8][2] = "Olá, outra vez. Recebemos a sua resposta negativa na nossa última carta, em que oferecíamos um posto de direçäo num outro hospital, e um alto salário de %d. Näo obstante, acreditamos que deveria reconsiderar esta decisäo. Como verá, temos o trabalho perfeito para si.//" +letter[8][2] = "Olá, outra vez. Recebemos a sua resposta negativa na nossa última carta, em que oferecíamos um posto de direçäo em um outro hospital, e um alto salário de %d. Contudo, acreditamos que deveria reconsiderar esta decisäo. Como verá, temos o trabalho perfeito para você.//" letter[8][3] = "Aceitaria um posto no Hospital %s, por favor?" letter[9][1] = "Olá %s!//" letter[9][2] = "Demonstrou ser o melhor diretor de hospital na longa e infeliz história da medicina. O lucro que obteve näo pode ficar sem recompensa, por isso lhe oferecemos o posto de Diretor Chefe de Todos os Hospitais. Terá um salário de %d, uma apresentaçäo com todas as honras e as pessoas demonstraräo o seu reconhecimento esteja onde estiver.//" letter[9][3] = "Agradecemos por tudo o que fez e desfrute de uma longa semi-aposentadoria.//" letter[9][4] = "" letter[10][1] = "Olá %s!//" -letter[10][2] = "Parabéns por dirigir com êxito todos os hospitais que lhe atribuímos. Esta grande atuaçäo o capacita a viajar livremente por todo mundo. Receberá uma pensäo de %d e uma limousine, para poder viajar de cidade em cidade, saudando o seu incondicional público e fomentando o trabalho que realiza em todos os hospitais.//" +letter[10][2] = "Parabéns por dirigir com êxito todos os hospitais que lhe atribuímos. Esta grande atuaçäo o capacita a viajar livremente por todo mundo. Receberá uma pensäo de %d e uma limousine, para poder viajar de cidade em cidade, saudando o seu incondicional público e incentivando o trabalho que realiza em todos os hospitais.//" letter[10][3] = "Estamos orgulhosos e agradecidos pelo seu trabalho ao salvar vidas.//" letter[10][4] = "" letter[11][1] = "Olá %s!//" -letter[11][2] = "Sua carreira tem sido exemplar, e você é uma inspiraçäo para todos nós. Obrigado por dirigir täo bem tantos hospitais. Gostaríamos de lhe conceder um salário vitalício de %d, e só lhe pedimos que viaje num carro oficial descoberto de cidade em cidade, dando conferências sobre os seus rápidos lucros.//" -letter[11][3] = "É um exemplo para todos os homens de bem e uma pessoa de enorme valia.//" +letter[11][2] = "Sua carreira tem sido exemplar, e você é uma inspiraçäo para todos nós. Obrigado por dirigir täo bem tantos hospitais. Gostaríamos de lhe conceder um salário vitalício de %d, e só lhe pedimos que viaje em um carro oficial descoberto de cidade em cidade, dando conferências sobre os seus rápidos lucros.//" +letter[11][3] = "É um exemplo para todos os homens de bem e uma pessoa de enorme valor.//" letter[11][4] = "" letter[12][1] = "Olá %s!//" -letter[12][2] = "A sua bem-sucedida carreira como o melhor diretor de hospital desde Moisés está chegando ao seu fim. Você provocou tal efeito nos círculos médicos, que o Ministério quer lhe oferecer um salário de %s, só para inaugurar festas, navios e organizar entrevistas em nosso nome. Você seria um excelente relaçöes públicas!//" +letter[12][2] = "A sua bem-sucedida carreira como o melhor diretor de hospital desde Moisés está chegando ao seu fim. Você provocou tanto efeito nos círculos médicos, que o Ministério quer lhe oferecer um salário de %s, só para inaugurar festas, navios e organizar entrevistas em nosso nome. Você seria um excelente relaçöes públicas!//" letter[12][3] = "Por favor, aceite. Será fácil e irá dispor de um veículo e uma escolta policial.//" letter[12][4] = "" -place_objects_window.place_objects_in_corridor = "Coloque os objetos num corredor." +place_objects_window.place_objects_in_corridor = "Coloque os objetos em um corredor." place_objects_window.drag_blueprint = "Arraste a marca azul até que consiga o tamanho que deseja." place_objects_window.pick_up_object = "Aperte sobre um objeto para selecioná-lo ou escolher outra opçäo do diálogo." place_objects_window.place_windows = "Se quiser, coloque algumas janelas. Em seguida, aperte confirmar." @@ -1437,7 +1440,7 @@ pay_rise.regular[2] = "Estou muito cansado. Preciso de umas férias e de um aumento salarial de %d, até um total de %d. E quero já, seu tirano!" pay_rise.regular[3] = "Vamos! Trabalho como um escravo. Se me der um bônus de %d, ficarei no seu hospital." pay_rise.regular[4] = "Estou muito descontente. Exijo um aumento de %d, e um salário final de %d, caso contrário, vou embora." -pay_rise.regular[5] = "Os meus pais me disseram que os médicos ganham um bom salário, sendo assim, me dá um aumento de %d ou me dedicarei à produçäo de jogos de computador." +pay_rise.regular[5] = "Os meus pais me disseram que os médicos ganham um bom salário, sendo assim, me dê um aumento de %d ou me dedicarei à produçäo de jogos de computador." pay_rise.regular[6] = "Estou farto. Pague-me um bom salário. Será suficiente um aumento de %d." pay_rise.poached = "%s ofereceu-me um salário de %d. Se näo me pagar o mesmo, vou embora." casebook.reputation = "reputaçäo" @@ -1449,7 +1452,7 @@ casebook.cure_desc.build_room = "Sugiro que construa %s" casebook.cure_desc.hire_surgeons = "Você precisa contratar cirurgiöes." casebook.cure_desc.cure_known = "Cura." -casebook.cure_desc.hire_psychiatrists = "Você tem que contratar psiquiatras." +casebook.cure_desc.hire_psychiatrists = "Você precisa contratar psiquiatras." casebook.cure_desc.hire_nurses = "Você deve contratar algumas enfermeiras." casebook.sent_home = "rejeitados" casebook.cured = "recuperaçöes" @@ -1486,11 +1489,11 @@ menu_charts.briefing = " INSTRUÇOES " diseases.kidney_beans.cause = "Causa - Mastigar os cubos de gelo das bebidas." diseases.kidney_beans.name = "Incontinência" -diseases.kidney_beans.symptoms = "Sintomas - Dor e idas frequêntes ao banheiro." +diseases.kidney_beans.symptoms = "Sintomas - Dor e idas frequentes ao banheiro." diseases.kidney_beans.cure = "Cura - Dois cirurgiöes extraem as pedras dos rins." -diseases.ruptured_nodules.cause = "Causa - Atirar-se de cabeça à água fria." +diseases.ruptured_nodules.cause = "Causa - Fazer bungee jumping em tempo frio." diseases.ruptured_nodules.name = "Boluditis" -diseases.ruptured_nodules.symptoms = "Sintomas - Impossibilidade de sentar-se comodamente." +diseases.ruptured_nodules.symptoms = "Sintomas - Incapacidade de se sentar confortavelmente." diseases.ruptured_nodules.cure = "Cura - Dois cirurgiöes qualificados colocam certas partes com mäos firmes." diseases.fractured_bones.cause = "Causa - Queda de um lugar alto." diseases.fractured_bones.name = "Fraturas ósseas" @@ -1500,7 +1503,7 @@ diseases.jellyitis.cause = "Causa - Uma dieta rica em gelatina e muito exercício." diseases.jellyitis.name = "Gelatinitis" diseases.jellyitis.symptoms = "Sintomas - Um tremor excessivo e cair ao chäo muitas vezes." -diseases.jellyitis.cure = "Cura - Inunda-se o paciente durante um momento no banheiro gelatinoso numa consulta especial." +diseases.jellyitis.cure = "Cura - Inunda-se o paciente durante um momento no banheiro gelatinoso em uma consulta especial." diseases.discrete_itching.cause = "Causa - Insetos diminutos com os dentes afiados." diseases.discrete_itching.name = "Coceira leve" diseases.discrete_itching.symptoms = "Sintomas - Arranhar-se, o que conduz a um inchaço da parte afetada." @@ -1535,7 +1538,7 @@ diseases.pregnancy.symptoms = "Sintomas - Muita vontade de comer e um mal-estar no estômago." diseases.pregnancy.cure = "Cura - Extrai-se ao bebé na sala de operaçöes, limpa-se e entrega-se ao paciente." diseases.general_practice.name = "Clínica Geral" -diseases.tv_personalities.cause = "Causa - Ver a televisäo durante o dia." +diseases.tv_personalities.cause = "Causa - Ver televisäo durante o dia." diseases.tv_personalities.name = "Personalitis" diseases.tv_personalities.symptoms = "Sintomas - Ter a ilusäo de apresentar na televisäo um programa de cozinha." diseases.tv_personalities.cure = "Cura - Um psiquiatra perito deve convencer o paciente de que venda o seu televisor e compre um rádio." @@ -1555,7 +1558,7 @@ diseases.gut_rot.cause = "Causa - O Xarope para a tosse, a base de uísque, da Sra. McGuiver." diseases.gut_rot.name = "Ulcera gástrica" diseases.gut_rot.symptoms = "Sintomas - O paciente näo tosse, mas também näo tem paredes no estômago." -diseases.gut_rot.cure = "Cura - Uma enfermeira administra uma variada dissoluçäo de substancias químicas para revestir o estômago." +diseases.gut_rot.cure = "Cura - Uma enfermeira administra uma variada dissoluçäo de substâncias químicas para revestir o estômago." diseases.chronic_nosehair.cause = "Causa - Cheirar com desprezo aqueles que estäo pior que o paciente." diseases.chronic_nosehair.name = "Nariz peludo" diseases.chronic_nosehair.symptoms = "Sintomas - Ter tanto cabelo no nariz para fazer uma peruca." @@ -1730,7 +1733,7 @@ competitor_names[22] = "DANEEL" competitor_names[23] = "OLIVAW" competitor_names[24] = "NIC" -staff_class.handyman = "Faz-Tudo" +staff_class.handyman = "Faz-tudo" staff_class.nurse = "Enfermeira" staff_class.surgeon = "Cirurgiäo" staff_class.receptionist = "Recepcionista" @@ -1786,72 +1789,72 @@ trophy_room.happy_vips.trophies[1] = "Ganhou o Prêmio Nobel de VIP Exemplares. Todos os que visitaram o seu hospital no ano passado o elogiaram muito." trophy_room.happy_vips.trophies[2] = "A Agência de Pessoas Famosas deseja-lhe conceder o Prêmio à Celebridade por ter agradado a todos os VIP que visitaram o seu hospital." trophy_room.happy_vips.trophies[3] = "Ganhou a VIAGEM VIP por melhorar a imagem dos trabalhadores aos olhos de todos os que visitaram o seu hospital. Estupendo!" -trophy_room.gen_repairs.awards[1] = "Foi-lhe concedido um prêmio especial pela diligência dos seus faz-tudo na hora de manter as máquinas do seu hospital em bom estado. Bem feito. Tome umas férias." +trophy_room.gen_repairs.awards[1] = "Foi-lhe concedido um prêmio especial pela diligência dos seus faz-tudo na hora de manter as máquinas do seu hospital em bom estado. Muito bem. Tire umas férias." trophy_room.gen_repairs.awards[2] = "Os seus faz-tudo trabalharam melhor que os de qualquer outro hospital. Este é um importante acontecimento de felicidade." -trophy_room.gen_repairs.awards[3] = "As suas máquinas estäo num magnífico estado. A dedicaçäo dos seus faz-tudo foi extraordinária. Merecem este prestigioso prêmio. Um trabalho estupendo!" -trophy_room.gen_repairs.penalty[1] = "Os seus faz-tudo näo cuidaram bem das suas máquinas. Deveria fiscalizá-los melhor ou contratar mais para que tirem o trabalho adiante." -trophy_room.gen_repairs.penalty[2] = "Levou mal a manutençäo. O seu pessoal deveria cuidar melhor dos seus equipamentos." -trophy_room.many_cured.penalty[1] = "O seu hospital näo cura com eficácia os pacientes que o necessitam. Empresta mais atençäo às curas para que sejam mais eficazes." +trophy_room.gen_repairs.awards[3] = "As suas máquinas estäo em um magnífico estado. A dedicaçäo dos seus faz-tudo foi extraordinária. Merecem este prestigioso prêmio. Um trabalho estupendo!" +trophy_room.gen_repairs.penalty[1] = "Os seus faz-tudo näo cuidaram bem das suas máquinas. Deveria fiscalizá-los melhor ou contratar mais para que façam o trabalho melhor." +trophy_room.gen_repairs.penalty[2] = "Näo fez uma boa manutençäo. Os seus funcionários deveriam cuidar melhor dos seus equipamentos." +trophy_room.many_cured.penalty[1] = "O seu hospital näo cura com eficácia os pacientes que o necessitam. Tenha mais atençäo às curas para que sejam mais eficazes." trophy_room.many_cured.penalty[2] = "O seu hospital é o menos eficaz na hora de curar pacientes. Decepcionou o Ministério e defraudou a si mesmo. Näo diremos mais." trophy_room.many_cured.trophies[1] = "Parabéns pela concessäo do prêmio Marie Curie por ter curado quase todos os pacientes do seu hospital no ano passado." trophy_room.many_cured.trophies[2] = "A Fundaçäo Nacional de Curas deseja premiá-lo por ter curado um grande número de pacientes no ano passado, concedendo o Galardäo ao Maior Curador." trophy_room.many_cured.trophies[3] = "Foi-lhe concedido a Medalha do Paciente Säo por ter conseguido curar no seu hospital uma enorme porcentagem de pacientes no ano passado." trophy_room.many_cured.awards[1] = "Parabéns por curar um montäo de pessoas no ano passado. Um grande número de pessoas sente-se muito melhor, graças ao seu trabalho." trophy_room.many_cured.awards[2] = "Pedimos que aceite este prêmio por ter curado mais pacientes que qualquer outro hospital. Um excelente trabalho." -trophy_room.many_cured.regional[1] = "Foi-lhe concedido o prêmio a cura total por ter curado mais pessoas que todos os outros hospitais juntos." +trophy_room.many_cured.regional[1] = "Você recebeu o prêmio de cura total por ter curado mais pessoas do que todos os outros hospitais juntos." trophy_room.sold_drinks.trophies[1] = "A Associaçäo Odontológica orgulha-se de lhe conceder este troféu e esta placa por vender um montäo de bebidas em lata no seu hospital." trophy_room.sold_drinks.trophies[2] = "O seu hospital foi premiado com o prêmio Bizz-Efervescente pela Venda de Refrigerante em reconhecimento ao número de bebidas vendidas em seu hospital no ano passado." trophy_room.sold_drinks.trophies[3] = "Em nome de DK Obturaçöes Inc., você recebe o prêmio coberto de chocolate para celebrar a enorme quantidade de refrigerantes que vendeu no seu hospital este ano." -trophy_room.consistant_rep.trophies[1] = "O Conselho de ministros concedeu-lhe a Mençäo de Honra por ter alcançado o nível máximo de eficácia e reputaçäo durante o ano presente. Bem feito." +trophy_room.consistant_rep.trophies[1] = "O Conselho de ministros concedeu-lhe a Mençäo de Honra por ter alcançado o nível máximo de eficácia e reputaçäo durante o ano presente. Muito bem." trophy_room.consistant_rep.trophies[2] = "Parabéns pela concessäo do Prêmio Lençóis Limpos por ser o hospital com a melhor reputaçäo do ano. Você mereceu." trophy_room.cash = "EFETIVO" trophy_room.high_rep.penalty[1] = "Vai ser sancionado pela má reputaçäo que teve no ano passado. Procure melhorar no futuro." trophy_room.high_rep.penalty[2] = "A reputaçäo do seu hospital é a pior da área. É uma vergonha. Melhore ou consiga outro emprego." -trophy_room.high_rep.awards[1] = "Bem feito! Ganhou um pequeno prêmio por alcançar uma impressionante reputaçäo no ano passado." +trophy_room.high_rep.awards[1] = "Muito bem! Ganhou um pequeno prêmio por alcançar uma impressionante reputaçäo no ano passado." trophy_room.high_rep.awards[2] = "Maravilhoso! O seu hospital ganhou um prêmio por conseguir a melhor reputaçäo no ano passado." -trophy_room.high_rep.regional[1] = "Por favor, aceita o Prêmio Bullfrog por dirigir o melhor hospital do ano. Você mereceu, aproveite." +trophy_room.high_rep.regional[1] = "Por favor, aceite o Prêmio Bullfrog por dirigir o melhor hospital do ano. Você mereceu, aproveite." trophy_room.high_rep.regional[2] = "Este ano, a reputaçäo do seu hospital superou a do resto dos hospitais. Um estupendo lucro." trophy_room.best_value_hosp.trophies[1] = "Parabéns pela concessäo do Prêmio Lençóis Limpos por ser o hospital com a melhor reputaçäo do ano. Você mereceu." trophy_room.best_value_hosp.regional[1] = "Parabéns por ter o hospital mais valioso do jogo. Bom trabalho! Por favor, continue assim." trophy_room.best_value_hosp.penalty[1] = "Todos os hospitais da área valem mais do que o seu. Faça algo a respeito desta vergonhosa situaçäo. Consiga coisas mais caras!" trophy_room.reputation = "REPUTAÇAO" -trophy_room.happy_staff.regional_good[1] = "O seu pessoal é o mais satisfeito de todos os hospitais. Se o pessoal está contente, há mais ganhos e menos mortes. No Ministério estäo satisfeitos." -trophy_room.happy_staff.penalty[1] = "O seu pessoal deseja que saiba que estäo muito descontentes. Ter um bom pessoal é algo proveitoso. Faça com que eles estejam mais satisfeitos ou algum dia irá perdê-los." -trophy_room.happy_staff.trophies[1] = "Ganhou o Prêmio Médico Sorridente por manter o mais contente possível o seu esforçado pessoal." +trophy_room.happy_staff.regional_good[1] = "Os seus funcionários säo os mais satisfeitos de todos os hospitais. Se os funcionários estäo contentes, há mais ganhos e menos mortes. No Ministério estäo satisfeitos." +trophy_room.happy_staff.penalty[1] = "Os seus funcionários desejam que saiba que estäo muito descontentes. Ter bons funcionários é muito proveitoso. Faça com que eles estejam mais satisfeitos ou algum dia irá perdê-los." +trophy_room.happy_staff.trophies[1] = "Ganhou o Prêmio Médico Sorridente por manter o mais contente possível os seus funcionários." trophy_room.happy_staff.trophies[2] = "A Fundaçäo para a Felicidade do Pessoal Sanitário concedeu-lhe este galardäo por näo ter tido trabalhadores descontentes no seu hospital no ano passado." trophy_room.happy_staff.trophies[3] = "Concedemos a você o prêmio Monopoliza do Sorriso Radiante por manter contente todos os seus funcionários, mais à frente do cumprimento do dever, durante o ano passado." -trophy_room.happy_staff.awards[1] = "Sua equipe te concedeu um prêmio. Eles dizem que, em geral, você manda bem." +trophy_room.happy_staff.awards[1] = "Sua equipe te concedeu um prêmio. Eles dizem que, em geral, você manda muito bem." trophy_room.happy_staff.awards[2] = "Seus funcionários säo täo felizes trabalhando para você que näo conseguem tirar os sorrisos dos seus rostos. Você é um gerente magnífico." trophy_room.happy_staff.regional_bad[1] = "A sua equipe esteve muito infeliz durante o ano passado. Você deveria ter notado. Do jeito que está, as equipes dos outros hospitais estäo muito mais contentes do que a sua." trophy_room.hosp_value.penalty[1] = "O seu hospital fracassou em alcançar um valor razoável. Gerenciou mal o dinheiro. Lembre-se, um bom hospital também é um hospital caro." trophy_room.hosp_value.awards[1] = "O Ministério da Saúde gostaria de parabenizá-lo pelo impressionante valor alcançado em seu hospital." trophy_room.hosp_value.regional[1] = "É uma promessa dos negócios. O hospital é o mais valioso de toda a área." trophy_room.healthy_plants.awards[1] = "Parabéns por ganhar o galardäo do Grande Fertilizante por manter as suas plantas vivas durante o ano passado." -trophy_room.healthy_plants.trophies[1] = "Os Amigos das Plantas de Interior desejam concede-lhe o Prêmio de Saúde Verde por manter vivas as suas plantas durante os últimos doze meses." +trophy_room.healthy_plants.trophies[1] = "Os Amigos das Plantas de Interior desejam lhe conceder o Prêmio de Saúde Verde por manter vivas as suas plantas durante os últimos doze meses." trophy_room.healthy_plants.trophies[2] = "Salvem as Plantas quer concede-lhes o Prêmio do Maior Ecologista por manter vivas as plantas do seu hospital durante o ano passado." trophy_room.research.penalty[1] = "Foi pouco eficiente ao investigar curas, máquinas e remédios novos. Isto é fatal, já que o avanço tecnológico é algo fundamental." -trophy_room.research.regional_good[1] = "As suas investigaçöes conseguiram colocar o seu hospital nos últimos avanços de hoje em dia. Os seus pesquisadores merecem este prêmio. Bem feito!" -trophy_room.research.awards[1] = "As suas investigaçöes conseguiram colocar o seu hospital nos últimos avanços de hoje em dia. Os seus pesquisadores merecem este prêmio. Bem feito!" +trophy_room.research.regional_good[1] = "As suas pesquisas conseguiram colocar o seu hospital nos últimos avanços de hoje em dia. Os seus pesquisadores merecem este prêmio. Muito bem!" +trophy_room.research.awards[1] = "As suas pesquisas conseguiram colocar o seu hospital nos últimos avanços de hoje em dia. Os seus pesquisadores merecem este prêmio. Muito bem!" trophy_room.research.awards[2] = "No ano passado, descobriu mais remédios e máquinas do que se podia esperar. Por favor, aceite este prêmio de todos nós no Ministério." trophy_room.research.regional_bad[1] = "Outros hospitais säo melhores que o seu na pesquisa. No Ministério estäo furiosos, seu hospital deveria lhe conceder mais importância." trophy_room.no_deaths.penalty[1] = "O número de mortes no seu hospital, no ano passado, foi muito elevado. Empresta mais atençäo ao seu trabalho. Assegure-se de que no futuro sobreviva mais pessoas." trophy_room.no_deaths.penalty[2] = "O seu hospital é um risco para os pacientes. Supöe-se que deve curar muitas pessoas, näo deixar morrer." trophy_room.no_deaths.trophies[1] = "Ganhou o Galardäo da Queixa Ausente por manter 100%% dos seus pacientes com vida o ano passado." trophy_room.no_deaths.trophies[2] = "A Associaçäo A Vida Continua concede-lhe este prêmio pela ausência de falecimentos no seu hospital este ano." -trophy_room.no_deaths.trophies[3] = "Foi-lhe concedido o Prêmio pela Conservaçäo da Vida por ter conseguido evitar falecimentos no seu hospital durante este ano. Genial!" +trophy_room.no_deaths.trophies[3] = "Você recebeu o Prêmio pela Conservaçäo da Vida por ter conseguido evitar falecimentos no seu hospital durante este ano. Genial!" trophy_room.no_deaths.awards[1] = "Ganhou este prêmio como reconhecimento ao sob índice de falecimentos no seu hospital, este ano. É estupendo!" trophy_room.no_deaths.awards[2] = "A sua habilidade conseguiu reduzir ao mínimo o número de mortes no seu hospital. Deve estar muito feliz com este resultado." trophy_room.no_deaths.regional[1] = "No ano passado, a taxa de mortalidade do seu hospital foi inferior a dos outros. Por favor, aceite este prêmio." -trophy_room.rats_accuracy.trophies[1] = "Foi-lhe concedido o Prêmio de Disparos Certeiros Syndicate Wars por acertar em %d%% ratos no seu hospital no ano passado." +trophy_room.rats_accuracy.trophies[1] = "Você recebeu o Prêmio de Disparos Certeiros Syndicate Wars por acertar em %d%% ratos no seu hospital no ano passado." trophy_room.rats_accuracy.trophies[2] = "Este prêmio é para celebrar a sua incrível pontaria ao eliminar %d%% dos ratos que disparou no seu hospital no ano passado." trophy_room.rats_accuracy.trophies[3] = "Para celebrar o fato de que eliminou %d%% dos ratos do seu hospital, foi-lhe concedido o Troféu de Eliminador de Roedores. Parabéns!" trophy_room.emergencies.penalty[1] = "Foi muito pouco eficiente nos casos de emergência. Os pacientes de emergência merecem uma atençäo rápida e precisa, que você näo lhes deu." -trophy_room.emergencies.award[1] = "Parabéns! Ganhou este prêmio pela maneira eficaz e eficiente com a que solucionaste as emergências. Bom trabalho." +trophy_room.emergencies.award[1] = "Parabéns! Ganhou este prêmio pela maneira eficaz e eficiente com a qual solucionou as emergências. Bom trabalho." trophy_room.emergencies.award[2] = "Confrontou as emergências de uma maneira extraordinária. Ganhou este prêmio por ser o melhor na hora de lidar com uma grande quantidade de pacientes." -trophy_room.emergencies.regional_good[1] = "O Ministério reconhece que o ano passado no seu hospital, trataram-se as emergências melhor que em qualquer outro hospital e foi-lhe concedido este prêmio." +trophy_room.emergencies.regional_good[1] = "O Ministério reconhece que o ano passado no seu hospital, você tratou as emergências melhor do que qualquer outro hospital, entäo lhe concedeu este prêmio." trophy_room.emergencies.regional_bad[1] = "O seu hospital é o pior da regiäo para tratar casos de emergência. Tem a culpa de ocupar o último lugar na Liga Local de Tratamentos de Emergência." trophy_room.curesvdeaths.awards[1] = "Os meus mais sinceros parabéns. No ano passado, o número de curas foi superior ao de falecimentos no seu hospital." -trophy_room.curesvdeaths.penalty[1] = "A sua proporçäo entre curas e mortes é extremamente baixa. Deveria assegurar de que cura mais pessoas do que mata. Näo deixe o seu pessoal em mau lugar." +trophy_room.curesvdeaths.penalty[1] = "A sua proporçäo entre curas e mortes é extremamente baixa. Deveria assegurar de que cura mais pessoas do que mata. Näo deixe os seus funcionários em mau lugar." trophy_room.wait_times.award[1] = "Parabéns! No seu hospital a gente fez fila durante muito pouco tempo. Este é um acontecimento importante." trophy_room.wait_times.penalty[1] = "No seu hospital, os pacientes esperam muito tempo. Há sempre filas inaceitáveis. Poderia tratar os seus pacientes com mais eficácia se quisesse." trophy_room.happy_patients.awards[1] = "Deve estar orgulhoso de que, no ano passado, as pessoas estivesse muito contente no seu hospital." @@ -1863,12 +1866,12 @@ trophy_room.pop_percentage.awards[3] = "Brilhante! O seu hospital recebeu o maior número de pacientes que todos os outros hospitais juntos." trophy_room.pop_percentage.penalty[1] = "Teve muito poucos pacientes este ano. Para ganhar dinheiro, precisa que haja pacientes que paguem." trophy_room.pop_percentage.penalty[2] = "Todos os hospitais da área conseguiram mais pacientes do que você. Deveria estar envergonhado." -trophy_room.rats_killed.trophies[1] = "Foi-lhe concedido o Troféu Raticida por eliminar %s ratos no seu hospital no ano passado." -trophy_room.rats_killed.trophies[2] = "Merece este prêmio da Federaçäo Anti Ratos, pela sua excepcional habilidade em eliminar ratos, demonstrada ao eliminar %s exemplares." -trophy_room.rats_killed.trophies[3] = "Concedeu-lhe o Troféu Acaba com Ratos pela sua grande habilidade em eliminar %d ratos no seu hospital no ano passado." +trophy_room.rats_killed.trophies[1] = "Você recebeu o Troféu Raticida por eliminar %s ratos no seu hospital no ano passado." +trophy_room.rats_killed.trophies[2] = "Você merece este prêmio da Federaçäo Anti Ratos, pela sua excepcional habilidade em eliminar ratos, demonstrada ao eliminar %s exemplares." +trophy_room.rats_killed.trophies[3] = "Você recebeu o Troféu Acaba com Ratos pela sua grande habilidade em eliminar %d ratos no seu hospital no ano passado." trophy_room.all_cured.awards[1] = "Parabéns por ter ganho o Prêmio Marie Curie por curar a todos os pacientes do seu hospital no ano passado." trophy_room.all_cured.trophies[1] = "A Fundaçäo Curadores Nacionais premia-o por ter curado todos os pacientes do seu hospital no ano passado, concedendo-lhe o Prêmio do Maior Curador." -trophy_room.all_cured.trophies[2] = "Foi-lhe concedida a Medalha do Paciente Säo por ter conseguido curar todos os pacientes do seu hospital no ano passado." +trophy_room.all_cured.trophies[2] = "Você recebeu a Medalha do Paciente Säo por ter conseguido curar todos os pacientes do seu hospital no ano passado." graphs.cures = "Curas" graphs.reputation = "Reputaçäo" graphs.balance = "Balanço" @@ -1934,10 +1937,10 @@ tooltip.objects.scanner = "14 SCANNER" tooltip.objects.bin = "Cesto de papéis: os pacientes atiram aqui os seus desperdícios." tooltip.objects.swing_door1 = "52 PORTAS DUPLAS 1" -tooltip.objects.pool_table = "Mesa de bilhar: ajuda o seu pessoal a relaxar-se." +tooltip.objects.pool_table = "Mesa de bilhar: ajuda os seus funcionários a relaxarem." tooltip.objects.screen = "16 TELAS" tooltip.objects.cabinet = "Armário: contém fichas dos pacientes, notas e documentos sobre pesquisa." -tooltip.objects.sofa = "Sofá: Os empregados que descansam na sala de descanso sentaräo num sofá, a menos que tenham uma maneira melhor de relaxar-se." +tooltip.objects.sofa = "Sofá: Os empregados que descansam na sala de descanso sentaräo em um sofá, a menos que tenham uma maneira melhor de relaxar-se." tooltip.objects.projector = "37 PROJETORES" tooltip.objects.table2 = "12 MESAS" tooltip.objects.shower = "54 DUCHAS DESCONTAMINADORAS" @@ -1951,11 +1954,11 @@ tooltip.objects.lamp = "Abajur: ilumina e permite que o pessoal veja." tooltip.objects.bookcase = "Livraria: material de consulta para os médicos." tooltip.objects.desk = "Escritório: é fundamental para que o médico coloque o seu PC." -tooltip.objects.toilet_sink = "Pia: os seus pacientes mais limpos lavam as suas mäos sujas aqui. Se näo haver suficientes pias, os pacientes ficam infelizes." +tooltip.objects.toilet_sink = "Pia: os seus pacientes mais limpos lavam as suas mäos sujas aqui. Se näo houver suficientes pias, os pacientes ficam infelizes." tooltip.objects.gates_of_hell = "48 PORTAS DO INFERNO" tooltip.objects.swing_door2 = "53 PORTAS DUPLAS 2" tooltip.objects.cast_remover = "24 REMOVEDOR DE GESSO" -tooltip.objects.plant = "Planta: alegra os pacientes e desencarde o ar." +tooltip.objects.plant = "Planta: alegra os pacientes e purifica o ar." tooltip.objects.blood_machine = "42 TRANSFUSIOMETROS" tooltip.objects.slicer = "26 CORTADORES" tooltip.objects.x_ray = "27 RAIOS-X" @@ -1963,7 +1966,7 @@ tooltip.objects.crash_trolley = "20 CARROS" tooltip.objects.bed2 = "näo se utiliza" tooltip.objects.electrolyser = "46 ELETROLISIS" -tooltip.objects.video_game = "Videogame: deixe que o seu pessoal se divirta com o Hi-Octane." +tooltip.objects.video_game = "Videogame: deixe que os seus funcionários se divirtam com o Hi-Octane." tooltip.objects.skeleton = "Esqueleto: é utilizado para aprender e na Noite do Halloween." tooltip.objects.ultrascanner = "22 ULTRA SCANNER" tooltip.objects.op_sink1 = "33 PIAS 1 OP" @@ -1973,7 +1976,7 @@ tooltip.objects.couch = "18 POLTRONAS" tooltip.objects.inflator = "Inflador: cura a cabeça inflada." tooltip.objects.toilet = "Banheiro: a natureza uma hora chama..." -tooltip.objects.lecture_chair = "Cadeira de leitura: os médicos que estäo estudando sentam-se aqui para tomar notas, aborrecer-se e rabiscar desnecessariamente. Quantas mais cadeiras ponha, mais compridas seräo as aulas." +tooltip.objects.lecture_chair = "Cadeira de leitura: os médicos que estäo estudando sentam-se aqui para tomar notas, aborrecer-se e rabiscar desnecessariamente. Quantas mais cadeiras colocar, mais compridas as aulas seräo." tooltip.objects.auto_autopsy = "Autópsia: uma grande ajuda para descobrir novas curas." tooltip.objects.chair = "Cadeira: os pacientes sentam-se sobre ela e falam das suas doenças." tooltip.objects.x_ray_viewer = "29 TELAS DE RAIOS-X" @@ -1986,7 +1989,7 @@ tooltip.objects.table1 = "Mesa: sobre ela coloca-se um montäo de revistas para que os pacientes esperem contentes." tooltip.objects.entrance_right = "59 PORTAS ESQUERDAS DE ENTRADA" tooltip.objects.operating_table = "30 MESAS DE OPERACOES" -tooltip.objects.tv = "TV: assegura de que o seu pessoal näo perca os seus programas favoritos." +tooltip.objects.tv = "TV: assegura de que os seus funcionários näo percam os seus programas favoritos." tooltip.watch.hospital_opening = "Cronômetro de construçäo: é o tempo que resta para que o seu hospital seja declarado aberto. Se apertar o botäo IR abrirá o hospital imediatamente." tooltip.watch.epidemic = "Epidemia: tempo que resta para encobrir a epidemia. Quando este tempo expire ou um paciente contagioso abandone o seu hospital, um Inspetor de Saúde vem visitar. O botäo liga ou desliga o modo vacina. Aperte em um paciente para que uma Enfermeira o vacine." tooltip.watch.emergency = "Emergência: tempo que resta para curar todos os pacientes nas emergências." @@ -2043,20 +2046,20 @@ tooltip.rooms.training_room = "A sala de formaçäo com um consultor serve para formar outros médicos" tooltip.rooms.x_ray = "O médico usa Raio-X para diagnosticar os pacientes" tooltip.rooms.general_diag = "O médico utiliza a sala de Diagnóstico Geral para fazer um diagnóstico básico. É barato e frequentemente eficaz" -tooltip.rooms.operating_theatre = "No sala de operaçöes fazem falta dois cirurgiöes qualificados" +tooltip.rooms.operating_theatre = "Na sala de operaçöes faltam dois cirurgiöes qualificados" tooltip.rooms.ultrascan = "O médico usa o Ultra-scanner para diagnosticar os pacientes" tooltip.rooms.psychiatry = "A consulta de psiquiatria cura os pacientes loucos e ajuda a diagnosticar outros pacientes, mas requer um médico qualificado em psiquiatria." tooltip.rooms.toilets = "Construa banheiros para impedir que os pacientes armem uma confusäo no seu hospital!" tooltip.rooms.dna_fixer = "O médico usa o Reparador de DNA para curar os pacientes com DNA alienígena" tooltip.rooms.pharmacy = "Na enfermaria, a enfermeira administra remédios para curar os pacientes" -tooltip.rooms.tongue_clinic = "O médico usa o Laringologia para curar a língua comprida" +tooltip.rooms.tongue_clinic = "O médico usa a Laringologia para curar a língua comprida" tooltip.rooms.research_room = "Os médicos pesquisadores investigam remédios e máquinas novas no Centro de Pesquisa" tooltip.rooms.scanner = "O médico usa o Scanner para diagnosticar os pacientes" tooltip.rooms.electrolysis = "O médico usa a consulta de eletrólise para curar o peludismo" tooltip.policy.diag_procedure = "Se o diagnóstico de um médico é menos seguro que a porcentagem de ENVIAR PARA CASA, o paciente será enviado para casa. Se o diagnóstico for melhor que a porcentagem de TENTAR CURA, será administrado o tratamento adequado ao paciente" tooltip.policy.staff_leave = "Aperte aqui para que os funcionários livres ajudem os companheiros que precisem" tooltip.policy.close = "Fechar tela de normas" -tooltip.policy.staff_rest = "Nível de cansaço do pessoal antes de poderem descansar" +tooltip.policy.staff_rest = "Nível de cansaço dos funcionários antes de poderem descansar" tooltip.policy.diag_termination = "O diagnóstico de um paciente continuará até que os médicos estejam seguros da porcentagem de PARAR PROCESSO, ou até que sejam utilizados todos os diagnósticos" tooltip.policy.staff_stay = "Aperte aqui para assegurar que o funcionário fique nas consultas que foram atribuídas a ele" tooltip.main_menu.load_menu.empty_slot = "VAZIO" @@ -2104,8 +2107,8 @@ tooltip.casebook.deaths = "Número de falecimentos" tooltip.casebook.treatment_charge = "Preço" tooltip.casebook.cure_type.psychiatrist = "Os psiquiatras realizam este tratamento" -tooltip.casebook.cure_type.drug_percentage = "Este tratamento requer uma remédio. O seu tem uma eficácia de %d%%" -tooltip.casebook.cure_type.drug = "Este tratamento requer uma remédio" +tooltip.casebook.cure_type.drug_percentage = "Este tratamento requer um remédio. O seu tem uma eficácia de %d%%" +tooltip.casebook.cure_type.drug = "Este tratamento requer um remédio" tooltip.casebook.cure_type.machine = "É preciso de uma máquina para este tratamento" tooltip.casebook.cure_type.surgery = "Esta doença requer cirurgia" tooltip.casebook.cure_requirement.hire_staff_old = "Você precisa contratar um %s para este tratamento" @@ -2115,7 +2118,7 @@ tooltip.casebook.cure_requirement.possible = "Pode administrar este tratamento" tooltip.casebook.cure_requirement.build_room = "Você precisa construir uma consulta para dar este tratamento" tooltip.casebook.cure_requirement.hire_surgeons = "Você precisa contratar dois cirurgiöes para as operaçöes" -tooltip.casebook.cure_requirement.research_machine = "Tem que inventar alguma máquina para este tratamento." +tooltip.casebook.cure_requirement.research_machine = "Precisa inventar alguma máquina para este tratamento." tooltip.casebook.cure_requirement.ward_hire_nurse = "Você precisa de uma enfermeira que trabalhe na enfermaria para administrar este tratamento" tooltip.patient_window.center_view = "Enfocar a pessoa" tooltip.patient_window.warmth = "Quanto calor tem a pessoa" @@ -2127,10 +2130,10 @@ tooltip.patient_window.happiness = "Satisfaçäo da pessoa" tooltip.patient_window.casebook = "Ver detalhes da doença da pessoa" tooltip.patient_window.abort_diagnosis = "Colocar a pessoa em tratamento em vez de esperar que complete o diagnóstico" -tooltip.town_map.fire_extinguishers = "Alterar extintores" -tooltip.town_map.people = "Alterar pessoas" +tooltip.town_map.fire_extinguishers = "Alternar extintores" +tooltip.town_map.people = "Alternar pessoas" tooltip.town_map.balance = "Saldo" -tooltip.town_map.objects = "Alterar objetos" +tooltip.town_map.objects = "Alternar objetos" tooltip.town_map.heat_inc = "Subir aquecimento" tooltip.town_map.heating_bill = "Recibo de aquecimento" tooltip.town_map.heat_level = "Nível de aquecimento" @@ -2215,7 +2218,7 @@ tooltip.hire_staff_window.researcher = "Pesquisador" tooltip.hire_staff_window.prev_person = "Ver pessoa anterior" tooltip.hire_staff_window.salary = "Salário" -tooltip.hire_staff_window.staff_ability = "Qualificaçäo do pessoal" +tooltip.hire_staff_window.staff_ability = "Qualificaçäo dos funcionários" tooltip.hire_staff_window.doctors = "Ver os médicos que pode contratar" tooltip.hire_staff_window.next_person = "Ver pessoa seguinte" tooltip.hire_staff_window.handymen = "Ver os faz-tudo que pode contratar" @@ -2241,7 +2244,7 @@ adviser.staff_place_advice.doctors_cannot_work_in_room = "Os Médicos näo podem trabalhar em %s" adviser.staff_place_advice.only_researchers = "Os Médicos só podem trabalhar em um Centro de Pesquisa se estiverem qualificados para isso." adviser.staff_place_advice.nurses_cannot_work_in_room = "As Enfermeiras näo podem trabalhar em %s" -adviser.staff_place_advice.only_surgeons = "Os Médicos podem trabalhar em um sala de operaçöes só se estiverem qualificados para isso." +adviser.staff_place_advice.only_surgeons = "Os Médicos só podem trabalhar em uma sala de operaçöes se estiverem qualificados para isso." adviser.staff_place_advice.receptionists_only_at_desk = "As Recepcionistas só podem trabalhar na Recepçäo." adviser.staff_place_advice.only_doctors_in_room = "Apenas Médicos podem trabalhar em %s" adviser.staff_place_advice.only_nurses_in_room = "Só Enfermeiras podem trabalhar na %s" @@ -2276,7 +2279,7 @@ adviser.warnings.doctors_tired2 = "Os seus médicos estäo cansadíssimos. Precisam descansar imediatamente." adviser.warnings.queues_too_long = "Tem muitos pacientes fazendo fila." adviser.warnings.staff_unhappy = "Os seus funcionários estäo descontentes. Dê-lhes um pagamento extra ou, ainda melhor, construa uma Sala de Descanso para eles. Também poderia alterar o seu tempo de descanso na tela de Normas." -adviser.warnings.patient_leaving = "Há um paciente que parte. A causa? A má direçäo e a péssima qualidade do seu pessoal e seus equipamentos." +adviser.warnings.patient_leaving = "Há um paciente que parte. A causa? A má direçäo e a péssima qualidade dos seus funcionários e seus equipamentos." adviser.warnings.patient_stuck = "Alguém ficou bloqueado. Planeje melhor seu hospital." adviser.warnings.receptionists_tired = "As suas recepcionistas estäo extenuadas. Mande-as descansar agora mesmo." adviser.warnings.charges_too_low = "Cobra muito pouco. Terá pacientes no seu hospital, mas näo lhe contribuiräo com muitos ganhos." @@ -2318,20 +2321,20 @@ adviser.warnings.plants_dying = "As suas plantas estäo secando. Precisam de água. Consiga mais faz-tudo para que cuidem disso. Os pacientes näo gostam das plantas mortas." adviser.warnings.people_did_it_on_the_floor = "Alguns dos seus pacientes näo podem aguentar mais. Alguém vai ter que limpar sem descanso." adviser.warnings.need_staffroom = "Construa uma sala de descanso para que os seus empregados possam descansar." -adviser.warnings.plants_thirsty = "Tem que cuidar das suas plantas. Estäo secando." +adviser.warnings.plants_thirsty = "Precisa cuidar das suas plantas. Estäo secando." adviser.warnings.too_many_plants = "Tem muitas plantas. Isto parece uma selva." adviser.warnings.receptionists_tired2 = "As suas recepcionistas estäo esgotadas. Deixa que descansem agora mesmo." adviser.warnings.machine_severely_damaged = "%s está prestes a se quebrar." adviser.warnings.machinery_very_damaged = "É uma emergência! Faça com que que um faz-tudo repare as sas máquinas em seguida. Estäo a ponto de explodir!" adviser.warnings.hospital_is_rubbish = "As pessoas näo têm dúvidas em dizer que o seu hospital é uma porcaria. Já sabe que logo iräo queixar-se a outra parte." adviser.warnings.handymen_tired2 = "Os seus faz-tudo estäo destroçados. Mande-os descansar imediatamente." -adviser.warnings.machinery_damaged2 = "Deve contratar um faz-tudo para reparar as suas máquinas rapidamente." +adviser.warnings.machinery_damaged2 = "Precisa contratar um faz-tudo para reparar as suas máquinas rapidamente." adviser.warnings.staff_very_cold = "O pessoal reclama do frio. Suba o aquecimento ou coloque mais radiadores." adviser.warnings.desperate_need_for_watering = "Necessita desesperadamente contratar um faz-tudo para que cuide das suas plantas." adviser.warnings.staff_unhappy2 = "Os seus funcionários, no geral, estäo descontentes. Logo, pediräo mais dinheiro." adviser.staff_advice.too_many_nurses = "Está contratando muitas enfermeiras." adviser.staff_advice.need_handyman_litter = "Os pacientes estäo sujando o seu hospital. Contrate uma faz-tudo para se encarregar da limpeza." -adviser.staff_advice.need_nurses = "Contrate mais enfermeiras. Na enfermaria e na farmácia fazem falta enfermeiras." +adviser.staff_advice.need_nurses = "Contrate mais enfermeiras. Na enfermaria e na farmácia faltam enfermeiras." adviser.staff_advice.need_doctors = "Você precisa de mais médicos. Tente colocar os seus melhores médicos nas consultas com mais pacientes." adviser.staff_advice.too_many_doctors = "Tem muitos médicos. Alguns estäo desocupados neste momento." adviser.staff_advice.need_handyman_machines = "Terá que contratar um faz-tudo se quiser que as máquinas do seu hospital funcionem." @@ -2343,8 +2346,8 @@ adviser.praise.plants_thriving = "Muito bem. As suas plantas estäo muito viçosas. Têm um aspecto maravilhoso. Mantenha-as assim e poderá ganhar um prêmio por isto." adviser.praise.many_benches = "Agora os seus pacientes têm suficientes assentos. Muito bem!" adviser.praise.many_plants = "Fantástico! Tem muitas plantas. Os seus pacientes agradeceräo isso." -adviser.surgery_requirements.need_surgeons_ward_op = "Tem que contratar dois cirurgiöes e construir uma enfermaria e uma sala de operaçöes para realizar operaçöes." -adviser.surgery_requirements.need_surgeon_ward = "Tem que contratar um outro cirurgiäo e construir uma enfermaria para poder realizar operaçöes." +adviser.surgery_requirements.need_surgeons_ward_op = "Precisa contratar dois cirurgiöes e construir uma enfermaria e uma sala de operaçöes para realizar operaçöes." +adviser.surgery_requirements.need_surgeon_ward = "Precisa contratar um outro cirurgiäo e construir uma enfermaria para poder realizar operaçöes." adviser.multiplayer.objective_completed = "Completou o objetivo. Felicidades!" adviser.multiplayer.objective_failed = "Näo conseguiu completar o objetivo." adviser.multiplayer.everyone_failed = "Todos falharam ao satisfazer aquele último objetivo." @@ -2358,17 +2361,17 @@ adviser.research.drug_improved = "O seu Centro de Pesquisa melhorou o medicamento para %s." adviser.research.new_available = "Já pode utilizar um novo %s." adviser.research.machine_improved = "O Centro de Pesquisa trouxe melhorias para %s." -adviser.research.autopsy_discovered_rep_loss = "Foi descoberta uma máquina de autoautópsias. Aguarde uma reaçäo desfavorável das pessoas." +adviser.research.autopsy_discovered_rep_loss = "Foi descoberta uma máquina de autópsias. Aguarde uma reaçäo desfavorável das pessoas." adviser.information.emergency = "Há uma emergência! Mexa-se! Mexa-se! Mexa-se!" adviser.information.handyman_adjust = "Pode conseguir que o faz-tudo limpe melhor se estabelecer as suas prioridades." adviser.information.promotion_to_specialist = "Um dos seus Médicos foi promovido para %s." adviser.information.pay_rise = "Um funcionário ameaça se demitir. Pode atender a sua petiçäo ou despedi-lo. Clique no último ícone da esquerda para ver quem deseja demitir." -adviser.information.first_death = "Acabou de matar o primeiro paciente. Como se sente?" +adviser.information.first_death = "Acabou de matar o seu primeiro paciente. Como se sente?" adviser.information.fax_received = "O ícone que acaba de aparecer no canto inferior esquerdo do tela alerta-lhe sobre uma informaçäo importante ou de que tem que tomar uma decisäo." adviser.information.promotion_to_consultant = "Um dos seus MEDICOS converteu-se em CONSULTOR." adviser.information.patient_abducted = "Os alienígenas raptaram um dos seus pacientes." adviser.information.vip_arrived = "Cuidado! %s acaba de chegar para visitar o seu hospital! Faça com que tudo funcione bem para lhe agradar." -adviser.information.extra_items = "O equipe está mais confortável e melhora o seu rendimento se colocar objetos complementares nas salas." +adviser.information.extra_items = "Os funcionários ficam mais confortáveis e melhoram o seu rendimento se colocar objetos complementares nas salas." adviser.information.epidemic_health_inspector = "O Ministério da Saúde soube de que tem uma epidemia. Prepare-se para receber brevemente a visita de um Inspetor de Saúde." adviser.information.first_cure = "Muito bem! Acaba de curar o seu primeiro paciente." adviser.information.epidemic = "Há uma doença contagiosa no seu hospital. Tem que solucioná-la em seguida!" @@ -2377,7 +2380,7 @@ adviser.information.initial_general_advice.first_patients_thirsty = "No seu hospital as pessoas têm sede. Coloque máquinas de bebidas." adviser.information.initial_general_advice.epidemic_spreading = "Há uma doença contagiosa no seu hospital. Tente curar as pessoas infectadas antes que elas possam ir embora." adviser.information.initial_general_advice.research_now_available = "Construiu o seu primeiro centro de pesquisa. Agora pode acessar a tela de pesquisa." -adviser.information.initial_general_advice.autopsy_available = "Foi inventada uma máquina de autoautópsias. Com ela, poderá se livrar dos pacientes problemáticos e investigar os seus restos. Tome cuidado, o uso desta máquina suscita muita polêmica." +adviser.information.initial_general_advice.autopsy_available = "Foi inventada uma máquina de autópsias. Com ela, poderá se livrar dos pacientes problemáticos e investigar os seus restos. Tome cuidado, o uso desta máquina suscita muita polêmica." adviser.information.initial_general_advice.rats_have_arrived = "Os ratos invadiram o seu hospital. Tente eliminá-los com o mouse." adviser.information.initial_general_advice.surgeon_symbol = "Os médicos especializados em cirurgia levam o símbolo: {" adviser.information.initial_general_advice.machine_needs_repair = "Há uma máquina que precisa ser reparada. Encontre a máquina e aperte sobre ela. Em seguida, aperte no botäo do faz-tudo." @@ -2440,7 +2443,7 @@ adviser.tutorial.place_doctor = "Coloque o médico na consulta." adviser.tutorial.build_gps_office = "É imprescindível um médico para diagnosticar os doentes." adviser.tutorial.select_doctors = "Clique no ícone que pisca para ver os médicos que pode contratar." -adviser.tutorial.click_gps_office = "Clique na linha que pisca para escolher uma consulta." +adviser.tutorial.click_gps_office = "Clique na linha que pisca para escolher o Consultório Geral." adviser.tutorial.prev_receptionist = "Clique no ícone que pisca para ver a recepcionista disponível anterior." adviser.tutorial.information_window = "A funçäo de ajuda proporciona toda a informaçäo sobre a consulta que acaba de construir." adviser.tutorial.place_receptionist = "Mova a recepcionista e coloque-a no seu lugar." @@ -2461,7 +2464,7 @@ adviser.tutorial.room_big_enough = "A marca azul é agora suficientemente grande. Se quiser, pode movê-la ou colocá-la." adviser.tutorial.start_tutorial = "Leia as instruçöes. Quando terminar, aperte o botäo esquerdo do mouse para começar o tutorial." adviser.tutorial.place_door = "Mova o mouse ao redor das paredes marcadas de azul para colocar a porta." -adviser.tutorial.select_receptionists = "Clique no ícone que pisca para ver os recepcionistas que estäo disponíveis." +adviser.tutorial.select_receptionists = "Clique no ícone que pisca para ver as recepcionistas que estäo disponíveis." adviser.tutorial.order_one_reception = "Clique na linha que pisca com o botäo esquerdo do mouse para comprar uma Recepçäo." adviser.tutorial.place_windows = "Coloque as janelas da mesma forma que a porta. Se näo quiser janelas, näo tem que as colocar." adviser.tutorial.select_diagnosis_rooms = "Clique com o botäo esquerdo no ícone que pisca para ver a lista de salas de diagnóstico." @@ -2471,29 +2474,29 @@ adviser.room_requirements.op_need_two_surgeons = "Contrate dois cirurgiöes para que operem na sala de operaçöes." adviser.room_requirements.training_room_need_consultant = "Terá que contratar um especialista para que de conferências nesta sala de formaçäo." adviser.room_requirements.research_room_need_researcher = "Terá que contratar um médico pesquisador para que utilize o centro de pesquisa." -adviser.room_requirements.op_need_ward = "Tem que construir uma enfermaria para os pacientes que väo ser operados." -adviser.room_requirements.reception_need_receptionist = "Tem que contratar uma recepcionista para atender os seus pacientes." -adviser.room_requirements.op_need_another_surgeon = "Tem que contratar um outro cirurgiäo para poder usar o sala de operaçöes." -adviser.room_requirements.gps_office_need_doctor = "Contrate um médico para atender a consulta." +adviser.room_requirements.op_need_ward = "Precisa construir uma enfermaria para os pacientes que väo ser operados." +adviser.room_requirements.reception_need_receptionist = "Precisa contratar uma recepcionista para atender os seus pacientes." +adviser.room_requirements.op_need_another_surgeon = "Precisa contratar um outro cirurgiäo para poder usar o sala de operaçöes." +adviser.room_requirements.gps_office_need_doctor = "Contrate um médico para atender no consultório." adviser.room_requirements.ward_need_nurse = "Contrate uma enfermeira para que trabalhe na enfermaria." adviser.room_requirements.psychiatry_need_psychiatrist = "Agora que construiu uma sala de psiquiatria, precisará de um psiquiatra." introduction_texts.level15 = "Bem, estes säo os mecanismos básicos para pôr em funcionamento um hospital.//Os seus Médicos väo precisar de toda a ajuda que possam obter para diagnosticar alguns dos pacientes. Pode ajudá-los construindo outros equipamentos de diagnóstico como a sala de Diagnóstico Geral." introduction_texts.level6 = "Utilize toda a sua capacidade para conseguir um hospital que funcione bem e consiga curar muitos pacientes e que possa tratar qualquer caso que pressentem os doentes.//Está avisado de que o ambiente, aqui, é especialmente propenso a germes e infecçöes. A menos que mantenha uma escrupulosa limpeza na sua instituiçäo, terá que fazer frente a uma série de epidemias entre os pacientes. Procure obter um lucro de $20.000 e fazer o valor do seu hospital superar os $140.000. " introduction_texts.level3 = "Desta vez colocará o seu hospital em uma área rica.//O Ministério da Saúde espera que consiga curar muitos pacientes. Terá que ganhar uma boa reputaçäo para começar, mas uma vez que o hospital comece a funcionar, concentre-se em ganhar todo o dinheiro que puder. Também pode haver emergências. Produzem-se quando chega muita gente que sofre da mesma doença. Se os curar dentro de um prazo determinado, conseguirá aumentar a sua reputaçäo e ganhar um grande extra. Haverá doenças, como o complexo de rei, e deverá ter orçamento para construir uma sala de operaçöes e junto a ela, uma enfermaria. Tem que ganhar $20.000 para superar este nível." -introduction_texts.level12 = "Agora irá enfrentar o maior dos desafios. Impressionado com os seus lucros, o Ministério tem uma grande tarefa para você; querem que construa outro magnífico hospital, que tenha um excelente lucro e uma reputaçäo incrível. Também querem que compre todo o terreno que puder, cure tudo (e queremos dizer todas as doenças) e ganhe todos os prêmios. Acha que irá conseguir? Ganhe $650.000, cure 750 pessoas e consiga uma reputaçäo de 800 para ganhar este nível. " -introduction_texts.level9 = "Depois de depositar o dinheiro na conta bancária do Ministério e pagar uma nova limousine para o Ministro, agora pode dedicar a criar um bom hospital para cuidar dos doentes e necessitados. Aqui terá um montäo de problemas diferentes. Se o seu pessoal tiver uma boa formaçäo e suficientes consultas, poderá resolver qualquer situaçäo. O seu hospital terá que valer $200.000 e precisará ter $400.000 no banco. Se näo o conseguir näo poderá terminar o nível." -introduction_texts.level11 = "Tem a oportunidade de construir o hospital definitivo. Esta é uma área de enorme prestígio e o Ministério quer que este seja o melhor hospital. Esperamos que ganhe muito dinheiro, alcance uma excelente reputaçäo e que se encarregue de todos os casos que sejam apresentados. Este é um trabalho importante. Terá que ser muito hábil para completá-lo. Também deve ter em conta que foram vistos OVNIs na área. Assegure-se de que o seu pessoal esteja preparado para receber algumas visitas inesperadas. O seu hospital terá que alcançar um valor de $240.000, precisará ter $500.000 no banco e uma reputaçäo de 700." +introduction_texts.level12 = "Agora enfrentará o maior dos desafios. Impressionado com os seus lucros, o Ministério tem uma grande tarefa para você; querem que construa outro magnífico hospital, que tenha um excelente lucro e uma reputaçäo incrível. Também querem que compre todo o terreno que puder, cure tudo (e queremos dizer todas as doenças) e ganhe todos os prêmios. Acha que conseguirá? Ganhe $650.000, cure 750 pessoas e consiga uma reputaçäo de 800 para ganhar este nível. " +introduction_texts.level9 = "Depois de depositar o dinheiro na conta bancária do Ministério e pagar uma nova limousine para o Ministro, agora pode dedicar a criar um bom hospital para cuidar dos doentes e necessitados. Aqui terá um montäo de problemas diferentes. Se os seus funcionários tiverem uma boa formaçäo e suficientes consultas, poderäo resolver qualquer situaçäo. O seu hospital terá que valer $200.000 e precisará ter $400.000 no banco. Se näo o conseguir näo poderá terminar o nível." +introduction_texts.level11 = "Tem a oportunidade de construir o hospital definitivo. Esta é uma área de enorme prestígio e o Ministério quer que este seja o melhor hospital. Esperamos que ganhe muito dinheiro, alcance uma excelente reputaçäo e que se encarregue de todos os casos que sejam apresentados. Este é um trabalho importante. Terá que ser muito hábil para completá-lo. Também deve ter em conta que foram vistos OVNIs na área. Assegure-se de que os seus funcionários estejam preparados para receber algumas visitas inesperadas. O seu hospital terá que alcançar um valor de $240.000, precisará ter $500.000 no banco e uma reputaçäo de 700." introduction_texts.level14 = "Ainda tem mais um desafio: um hospital surpresa totalmente imprevisível. Se conseguir ter êxito, será o vencedor dos vencedores. E näo espere que seja fácil, porque é a tarefa mais difícil que confrontará. Boa sorte!" introduction_texts.level10 = "Além de dever curar todas as doenças que possa haver, o Ministério pede que empregue um pouco de tempo em aumentar a eficácia dos seus remédios.//Houve algumas queixas por parte do D. Salutíssimo, o Cachorro Guardiäo da Saúde, assim deve procurar com que todos os seus remédios sejam extremamente eficazes para ficar bem. Também, assegure-se de que o seu hospital tenha uma reputaçäo irrepreensível. Procure deixar morrer poucos pacientes. Como sugestäo, deveria deixar espaço para um banho gelatinoso. Para ganhar, os seus remédios deveräo ter uma eficácia de, pelo menos, 80%, tem que conseguir uma reputaçäo de 650 e guardar $500.000 no banco." introduction_texts.level5 = "Este será um hospital concorrido, que tratará casos muito variados.//Os seus médicos acabam de sair da faculdade, por isso é fundamental que construa uma sala de formaçäo para que alcancem o nível de formaçäo necessário. Só tem três especialistas para ensinar os seus funcionários inexperientes, entäo faça com que estejam contentes. Tem que ter em conta que o hospital está localizado em cima da falha geológica de San Android. Sempre há risco de terremoto. Os terremotos provocaräo danos importantes nas suas máquinas e alteraräo o bom funcionamento do seu hospital. Aumente a sua reputaçäo até 400 e consiga ganhos de $50.000 para triunfar. Também, cure 200 pacientes. " introduction_texts.level1 = "Bem-vindo ao seu primeiro hospital!//Para fazê-lo funcionar, coloque uma Recepçäo, construa um Consultório e contrate uma recepcionista e um médico. Em seguida, espere que cheguem os pacientes. Seria uma boa ideia construir uma consulta de psiquiatria e contratar um psiquiatra. Uma farmácia e uma enfermeira säo fundamentais para curar os seus pacientes. Cuidado com os casos malignos de cabeça inflada; eles säo solucionados na sala de inflatoterapia. Terá que curar 10 pessoas e assegurar de que a sua reputaçäo näo seja inferior a 200." introduction_texts.level17 = "Um último aviso. Fique de olho na sua Reputaçäo, é o que atrairá pacientes ao seu estabelecimento. Se näo matar muitas pessoas e os mantiver razoavelmente felizes näo deverá ter muitos problemas com este nível!//Agora é com você, boa sorte." -introduction_texts.level7 = "Aqui, estará sob a estrita vigilância do Ministério da Saúde, entäo faça com que suas contas reflitam excelentes lucros e aumente a sua reputaçäo.//Näo podemos permitir que haja mortes desnecessárias; Näo beneficiam nada o negócio. Certifique-se de que o seu pessoal esteja em plena forma e de ter todos os equipamentos necessários. Obtenha uma reputaçäo de 600, e um saldo bancário de $200.000." +introduction_texts.level7 = "Aqui, estará sob a estrita vigilância do Ministério da Saúde, entäo faça com que suas contas reflitam excelentes lucros e aumente a sua reputaçäo.//Näo podemos permitir que haja mortes desnecessárias; Näo beneficiam nada o negócio. Certifique-se de que os seus funcionários estejam em plena forma e de ter todos os equipamentos necessários. Obtenha uma reputaçäo de 600, e um saldo bancário de $200.000." introduction_texts.level4 = "Faça com que todos os seus pacientes estejam contentes, trate-os com a maior eficácia e tente deixar que morram o menos possíveis.//A sua reputaçäo está em jogo, entäo procure aumentá-la o máximo que puder. Näo se preocupe muito com o dinheiro; Irá ganhando à medida que cresce a sua reputaçäo. Também poderá formar os seus médicos para ampliar os seus conhecimentos. Eles poderäo curar os pacientes mais difíceis. Alcance uma reputaçäo acima de 500." introduction_texts.level18 = "" introduction_texts.level16 = "Uma vez que tenha diagnosticado algum dos pacientes, precisará construir salas de tratamento e clínicas para curá-los. Pode começar com uma Farmácia, onde precisará de uma Enfermeira que distribua os remédios." introduction_texts.level13 = "A sua incrível habilidade como diretor do hospital atraiu a atençäo da Divisäo Secreta Especial do Serviço Secreto Especial. Tenho um trabalho especial para você. Há um hospital infestado de ratos que precisa de um exterminador eficiente. Você deve matar todos os ratos que puder antes de que o pessoal de Manutençäo limpe toda a sujeira. Acha que é apto para esta missäo?" -introduction_texts.level8 = "Só depende de você construir o hospital mais rentável e eficiente possível.//As pessoas, por aqui säo bastante ricas, entäo tente arrecadar o máximo possível. Lembre-se que curar as pessoas é uma coisa muito bonita, mas o que PRECISAMOS de verdade é do dinheiro delas. Arranque todo o dinheiro destes doentes. Acumule a enorme quantia de $300.000 para completar este nível. " +introduction_texts.level8 = "Só depende de você construir o hospital mais rentável e eficiente possível.//As pessoas por aqui, säo bastante ricas, entäo tente arrecadar o máximo possível. Lembre-se que curar as pessoas é uma coisa muito bonita, mas o que PRECISAMOS de verdade é do dinheiro delas. Arranque todo o dinheiro destes doentes. Acumule a enorme quantia de $300.000 para completar este nível. " humanoid_name_starts[1] = "GOLD" humanoid_name_starts[2] = "HIGH" humanoid_name_starts[3] = "AND" @@ -2588,7 +2591,7 @@ room_descriptions.blood_machine[2] = "O transfusiômetro é um elemento do equipamento de diagnóstico que revisa as células do sangue do paciente para descobrir do que sofrem.//" room_descriptions.blood_machine[3] = "A sala de transfusöes requer um médico. Também precisa de manutençäo. " room_descriptions.fracture_clinic[1] = "Traumatologia//" -room_descriptions.fracture_clinic[2] = "Os pacientes que têm a desgraça de ter fraturas vêm aqui. O removedor de gesso emprega poderosos laser industriais para cortar os gessos mais duros, causando ao paciente só uma pequena dor.//" +room_descriptions.fracture_clinic[2] = "Os pacientes que têm a desgraça de ter fraturas vêm aqui. O removedor de gesso usa poderosos lasers industriais para cortar os gessos mais duros, causando ao paciente só uma pequena dor.//" room_descriptions.fracture_clinic[3] = "A sala de traumatologia requer uma enfermeira. Também precisa de uma manutençäo muito frequente. " room_descriptions.cardiogram[1] = "Sala de Cardiologia//" room_descriptions.cardiogram[2] = "Aqui é diagnosticado e examinado os pacientes antes que voltem para a consulta, onde porá o tratamento.//" @@ -2600,7 +2603,7 @@ room_descriptions.jelly_vat[2] = "Os pacientes que sofrem da risível doença da gelatinitis devem ir a cambalear-se para a consulta de gelatinitis e ser inundados no banheiro gelatinoso. Isto faz com que se curem de um modo que näo resulta de tudo compreensível para a profissäo médica.//" room_descriptions.jelly_vat[3] = "O banho gelatinoso requer um médico. Também precisa de uma faz-tudo para a sua manutençäo. " room_descriptions.gp[1] = "Sala de Consultório Geral//" -room_descriptions.gp[2] = "Esta é a consulta mais importante do seu hospital. Os novos pacientes säo enviados aqui para averiguar o que é que eles têm. Entäo, ou fazem outro diagnóstico ou mandam para uma consulta onde possam ser curados. Possivelmente queira construir outra consulta se a primeira tiver muito trabalho. Quanto maior for a consulta e quanto mais objetos colocar nela, maior prestígio terá o médico. O mesmo acontece com todas as consultas abertas.//" +room_descriptions.gp[2] = "Esta é a consulta mais importante do seu hospital. Os novos pacientes säo enviados aqui para averiguar o que é que eles têm. Entäo, ou fazem outro diagnóstico ou mandam para uma consulta onde possam ser curados. Possivelmente queira construir outro consultório se o primeiro tiver muito trabalho. Quanto maior for o consultório e quanto mais objetos colocar nele, maior prestígio terá o médico. O mesmo acontece com todas as consultas abertas.//" room_descriptions.gp[3] = "O consultório geral requer um médico. " room_descriptions.hair_restoration[1] = "Peloterapia//" room_descriptions.hair_restoration[2] = "Os pacientes que sofrem de calvície seräo enviados ao pêlo-restaurador desta sala. Um médico ligará o pêlo-restaurador, que, rapidamente, implantará na cabeça do paciente ar puro.//" @@ -2625,8 +2628,8 @@ room_descriptions.slack_tongue[2] = "Os pacientes que sejam diagnosticados com língua comprida na consulta seräo enviados aqui para receber tratamento. O médico utilizará uma máquina de alta tecnologia para estirar a língua e cortá-la e, com o que o paciente voltará a estar säo.//" room_descriptions.slack_tongue[3] = "A sala de laringologia requer um médico. Também precisa de uma manutençäo muito frequente. " room_descriptions.dna_fixer[1] = "Genética//" -room_descriptions.dna_fixer[2] = "Os pacientes que foram manipulados por alienígenas de outro mundo, deve ser substituído o seu DNA nesta sala. O reparador de DNA é um máquina complexa e seria sensato ter um extintor na sala, só por acaso.//" -room_descriptions.dna_fixer[3] = "O reparador de DNA requer que um faz-tudo o revise de vez em quando. Também requer um médico especializado em pesquisa para poder empregá-lo. " +room_descriptions.dna_fixer[2] = "Os pacientes que foram manipulados por alienígenas, devem ter seu DNA substituído nesta sala. O reparador de DNA é uma máquina complexa e seria sensato ter um extintor na sala, só por garantia.//" +room_descriptions.dna_fixer[3] = "O reparador de DNA requer que um faz-tudo o revise de vez em quando. Também requer um médico especializado em pesquisa para poder usá-lo. " room_descriptions.training[1] = "Sala de Formaçäo//" room_descriptions.training[2] = "Os seus residentes e médicos podem obter uma valiosa qualificaçäo extra aprendendo nesta sala. Um especialista em cirurgia, pesquisa ou psiquiatria ensinará a sua especialidade aos médicos que recebem formaçäo. Os médicos que já possuem estas especialidades veräo a sua habilidade aumentar enquanto estäo aqui.//" room_descriptions.training[3] = "A sala de formaçäo requer um especialista. " diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/czech.lua corsix-th-0.62/CorsixTH/Lua/languages/czech.lua --- corsix-th-0.61/CorsixTH/Lua/languages/czech.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/czech.lua 2018-07-21 11:13:17.000000000 +0000 @@ -3100,11 +3100,11 @@ "Vaše nemocnice musí mít hodnotu 200,000€ a budete potřebovat 400,000€ v bance. " .. "Cokoliv méně a nebudete moct dokončit úroveň.", demo = - "Vítejte v demo nemocnici!" .. - "Bohužel, demo verze obsahuje pouze tuto úroveň. Nicméně je toho více než dost, abyste se na chvilku zabavili!" .. - "Setkáte se s různými nemocemi, které potřebují různé místnosti k léčbě. Čas od času se můžou stát havárie. A budete potřebovat vyzkoumat dodatečné místnosti pomocí výzkumného oddělení." .. - "Vaším úkolem je vydělat 100,000€, mít hodnotu nemocnice ve výši 70,000€ a reputaci 700, přičemž musíte vyléčit alespoň 75% Vašich pacientů." .. - "Ujistěte se, že Vaše reputace nespadne 300 a že nezabijete více než 40% Vašich pacientů, nebo prohrajete." .. + "Vítejte v demo nemocnici!//" .. + "Bohužel, demo verze obsahuje pouze tuto úroveň. Nicméně je toho více než dost, abyste se na chvilku zabavili! " .. + "Setkáte se s různými nemocemi, které potřebují různé místnosti k léčbě. Čas od času se můžou stát havárie. A budete potřebovat vyzkoumat dodatečné místnosti pomocí výzkumného oddělení. " .. + "Vaším úkolem je vydělat 100,000€, mít hodnotu nemocnice ve výši 70,000€ a reputaci 700, přičemž musíte vyléčit alespoň 75% Vašich pacientů. " .. + "Ujistěte se, že Vaše reputace nespadne 300 a že nezabijete více než 40% Vašich pacientů, nebo prohrajete.//" .. "Hodně štěstí!", level10 = "Stejně jako zvládnutí všech nemocí, které se v této oblasti vyskytují, Ministerstvo žádá, abyste strávil nějaký čas soustředěním se na účinnost Vašich léků. " .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/dutch.lua corsix-th-0.62/CorsixTH/Lua/languages/dutch.lua --- corsix-th-0.61/CorsixTH/Lua/languages/dutch.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/dutch.lua 2018-07-21 11:13:17.000000000 +0000 @@ -1849,16 +1849,16 @@ "Als je niet teveel mensen doodt en ze redelijk gelukkig houdt, zou je niet al teveel problemen moeten hebben met dit level!//" .. "En nu mag je het zelf opknappen. Veel succes ermee!", level1 = - "Welkom in je eerste ziekenhuis!" .. + "Welkom in je eerste ziekenhuis!//" .. "Zorg dat de boel op gang komt door een receptie te plaatsen en een spreekkamer te bouwen. Neem ook een receptioniste en een arts in dienst. " .. - "Wacht dan tot er mensen langskomen." .. + "Wacht dan tot er mensen langskomen. " .. "Het is een goed idee om een psychiatrische afdeling te bouwen en een arts in te huren met de benodigde kwalificaties. " .. "Een apotheek en een zuster zijn essentieel voor het genezen van je patiënten. " .. "Kijk uit voor ernstige gevallen van plofkop. Een inflatiekliniek lost deze probleempjes op. " .. "Genees, om de spits af te bijten, 10 mensen en hou je reputatie boven de 200.", level9 = - "Nu je de kas van het ministerie flink hebt gespekt en de minister dankzij jouw donaties vrolijk in zijn splinternieuwe limousine rondrijdt, kun je nu weer terug naar je echte taak: het bouwen van een ziekenhuis dat niet alleen goed draait maar ook duidelijk om haar arme en zieke patiënten geeft." .. - "Verwacht dat er een boel problemen de kop opsteken." .. + "Nu je de kas van het ministerie flink hebt gespekt en de minister dankzij jouw donaties vrolijk in zijn splinternieuwe limousine rondrijdt, kun je nu weer terug naar je echte taak: het bouwen van een ziekenhuis dat niet alleen goed draait maar ook duidelijk om haar arme en zieke patiënten geeft. " .. + "Verwacht dat er een boel problemen de kop opsteken. " .. "Als je genoeg kamers en een goed getrainde staf hebt, zal je die problemen makkelijk het hoofd moeten kunnen bieden. " .. "Je ziekenhuis moet uiteindelijk $200,000 waard zijn. Verzamel ook een comfortabele $400.000 op je bankrekening. " .. "Met minder dan dat kun je het level niet uitspelen.", @@ -1954,11 +1954,11 @@ "Je ziekenhuis moet $240.000 waard zijn en je moet $500.000 op de bank hebben staan. Ook moet je reputatie minimaal 700 bedragen.", level18 = "", demo = - "Welkom in het demo ziekenhuis!" .. - "Jammer genoeg bevat de demo versie buiten zelfgemaakte levels alleen dit ziekenhuis, maar er is meer dan genoeg te doen om je voorlopig bezig te houden!" .. - "Je zult verschillende kwalen tegenkomen die verschillende ruimtes nodig hebben om genezen te worden, af en toe kunnen zich noodgevallen voordoen, en je zult nieuwe ruimtes uit moeten vinden met het laboratorium" .. - "Jouw doel is om $100,000 te verdienen, de waarde van je ziekenhuis te verhogen naar $70,000 en een reputatie van 700 te behalen, terwijl je 75% van je patiënten geneest" .. - "Zorg er voor dat je reputatie niet lager wordt dan 300 en dat je niet meer dan 40% van je patiënten vermoord, anders zal je ontslagen worden!" .. + "Welkom in het demo ziekenhuis!//" .. + "Jammer genoeg bevat de demo versie buiten zelfgemaakte levels alleen dit ziekenhuis, maar er is meer dan genoeg te doen om je voorlopig bezig te houden! " .. + "Je zult verschillende kwalen tegenkomen die verschillende ruimtes nodig hebben om genezen te worden, af en toe kunnen zich noodgevallen voordoen, en je zult nieuwe ruimtes uit moeten vinden met het laboratorium. " .. + "Jouw doel is om $100,000 te verdienen, de waarde van je ziekenhuis te verhogen naar $70,000 en een reputatie van 700 te behalen, terwijl je 75% van je patiënten geneest. " .. + "Zorg er voor dat je reputatie niet lager wordt dan 300 en dat je niet meer dan 40% van je patiënten vermoord, anders zal je ontslagen worden!//" .. "Succes!", } humanoid_name_starts = { diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/english.lua corsix-th-0.62/CorsixTH/Lua/languages/english.lua --- corsix-th-0.61/CorsixTH/Lua/languages/english.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/english.lua 2018-07-21 11:13:17.000000000 +0000 @@ -99,6 +99,7 @@ jukebox = " (J) JUKEBOX ", lock_windows = " LOCK WINDOWS ", edge_scrolling = " EDGE SCROLLING ", + capture_mouse = " CAPTURE MOUSE ", adviser_disabled = " (SHIFT+A) ADVISER ", warmth_colors = " WARMTH COLOURS ", wage_increase = " WAGE REQUESTS", @@ -356,6 +357,7 @@ option_off = "Off", fullscreen = "Fullscreen", resolution = "Resolution", + capture_mouse = "Capture Mouse", custom_resolution = "Custom...", width = "Width", height = "Height", @@ -373,6 +375,7 @@ fullscreen_button = "Click to toggle fullscreen mode", resolution = "The resolution the game should run in", select_resolution = "Select a new resolution", + capture_mouse = "Click to toggle capturing the cursor in the game window", width = "Enter desired screen width", height = "Enter desired screen height", apply = "Apply the entered resolution", @@ -546,7 +549,7 @@ totd_window = { tips = { "Every hospital needs a reception desk and a GP's office to get going. After that, it depends on what kind of patients are visiting your hospital. A pharmacy is always a good choice, though.", - "Machines such as the Inflation need maintenance. Employ a handyman or two to repair your machines, or you'll risk your staff and patients getting hurt.", + "Machines such as the Inflator need maintenance. Employ a handyman or two to repair your machines, or you'll risk your staff and patients getting hurt.", "After a while, your staff will get tired. Be sure to build a staff room, so they can relax.", "Place enough radiators to keep your staff and patients warm, or they will become unhappy. Use the town map to locate any spots in your hospital that need more heating.", "A doctor's skill level greatly influences the quality and speed of his diagnoses. Place a skilled doctor in your GP's office, and you won't need as many additional diagnosis rooms.", @@ -626,11 +629,11 @@ introduction_texts = { demo = - "Welcome to the demo hospital!" .. - "Unfortunately the demo version only contains this level. However, there is more than enough to do here to keep you busy for a while!" .. - "You will encounter various diseases that require different rooms to cure. From time to time, emergencies may occur. And you will need to research additional rooms using a research room." .. - "Your goal is to earn $100,000, have a hospital value of $70,000 and a reputation of 700, while having cured at least 75% of your patients." .. - "Make sure your reputation does not fall below 300 and that you don't kill off more than 40% of your patients, or you will lose." .. + "Welcome to the demo hospital!//" .. + "Unfortunately the demo version only contains this level. However, there is more than enough to do here to keep you busy for a while! " .. + "You will encounter various diseases that require different rooms to cure. From time to time, emergencies may occur. And you will need to research additional rooms using a research room. " .. + "Your goal is to earn $100,000, have a hospital value of $70,000 and a reputation of 700, while having cured at least 75% of your patients. " .. + "Make sure your reputation does not fall below 300 and that you don't kill off more than 40% of your patients, or you will lose.//" .. "Good luck!", } diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/finnish.lua corsix-th-0.62/CorsixTH/Lua/languages/finnish.lua --- corsix-th-0.61/CorsixTH/Lua/languages/finnish.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/finnish.lua 2018-07-21 11:13:17.000000000 +0000 @@ -383,11 +383,11 @@ -- 9. Level introductions introduction_texts = { demo = - "Tervetuloa demosairaalaan!" .. - "Valitettavasti demoversio sisältää ainoastaan tämän tason. Täällä on kuitenkin enemmän kuin tarpeeksi tekemistä!" .. - "Kohtaat erilaisia sairauksia, joiden hoitaminen vaatii erilaisia huoneita. Hätätilanteita saattaa tapahtua ajoittain. Lisäksi sinun pitää kehittää lisää huoneita tutkimusosaston avulla." .. - "Tavoitteesi on ansaita 100 000$, nostaa sairaalan arvo yli 70 000$:n ja maineesi yli 700:n parantaen samalla vähintään 75% potilaistasi." .. - "Pidä huoli, ettei maineesi putoa alle 300:n ja ettei yli 40 prosenttia potilaistasi pääse kuolemaan, tai häviät tason." .. + "Tervetuloa demosairaalaan!//" .. + "Valitettavasti demoversio sisältää ainoastaan tämän tason. Täällä on kuitenkin enemmän kuin tarpeeksi tekemistä! " .. + "Kohtaat erilaisia sairauksia, joiden hoitaminen vaatii erilaisia huoneita. Hätätilanteita saattaa tapahtua ajoittain. Lisäksi sinun pitää kehittää lisää huoneita tutkimusosaston avulla. " .. + "Tavoitteesi on ansaita 100 000$, nostaa sairaalan arvo yli 70 000$:n ja maineesi yli 700:n parantaen samalla vähintään 75% potilaistasi. " .. + "Pidä huoli, ettei maineesi putoa alle 300:n ja ettei yli 40 prosenttia potilaistasi pääse kuolemaan, tai häviät tason.//" .. "Onnea!", level1 = "Tervetuloa ensimmäiseen sairaalaasi!//" .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/french.lua corsix-th-0.62/CorsixTH/Lua/languages/french.lua --- corsix-th-0.61/CorsixTH/Lua/languages/french.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/french.lua 2018-07-21 11:13:17.000000000 +0000 @@ -207,7 +207,7 @@ patient_leaving_too_expensive = "Un patient part sans payer la facture pour %s. Sacrée perte !", vip_arrived = "Attention ! %s arrive pour visiter votre hôpital ! Faites en sorte de lui faire bonne impression.", first_death = "Vous venez de tuer votre premier patient. Alors, heureux ?", - promotion_to_specialist = "L'un de vos INTERNES est devenu MÉDECIN.", -- Fix the famous "Level 5 bug" + promotion_to_specialist = "L'un de vos MÉDECIN est devenu un SPÉCIALISTE.", -- Fix the famous "Level 5 bug" } buy_objects_window = { price = "Prix : ", @@ -696,7 +696,7 @@ return_to_main_menu = "Voulez-vous retourner au menu principal ou continuer la partie ?", campaign_completed = "Incroyable ! Vous avez réussi à terminer tous les niveaux. Vous pouvez maintenant vous détendre et profiter de remplir des forums sur Internet de vos réalisations. Bonne chance !", campaign_level_missing = "Désolé, mais le prochain niveau de cette campagne semble manquer. (Nom: %s)", - campaign_level_completed = "Bon travail ! Vous avez battu le niveau. Mais ce n'est pas fini!\n Aimeriez-vous un poste à l'hôpital %s ?", + campaign_level_completed = "Bon travail ! Vous avez battu le niveau. Mais ce n'est pas fini !\n Aimeriez-vous un poste à l'hôpital %s ?", } -- Installation @@ -1088,11 +1088,11 @@ -- Introduction Texts introduction_texts = { demo = - "Bienvenue dans l'hôpital de démonstration !" .. + "Bienvenue dans l'hôpital de démonstration !// " .. "Malheureusement, la version démo ne contient que ce niveau. Malgré tout, il y a assez à faire ici pour vous occuper un moment !" .. - "Vous allez rencontrer différentes maladies qui nécessitent des salles pour les soigner. De temps en temps, des urgences peuvent se produire. Et vous aurez besoin d'une salle de recherche pour trouver des nouvelles salles." .. - "Votre but est de gagner 100,000$, de faire monter la valeur de votre hôpital à 70,000$ et d'obtenir une réputation de 700, tout en ayant soigné au moins 75% de vos patients." .. - "Veillez à ce que votre réputation ne tombe pas en dessous de 300 et de ne pas tuer plus de 40% de vos patients, ou vous perdrez." .. + "Vous allez rencontrer différentes maladies qui nécessitent des salles pour les soigner. De temps en temps, des urgences peuvent se produire. Et vous aurez besoin d'une salle de recherche pour trouver des nouvelles salles. " .. + "Votre but est de gagner 100,000$, de faire monter la valeur de votre hôpital à 70,000$ et d'obtenir une réputation de 700, tout en ayant soigné au moins 75% de vos patients. " .. + "Veillez à ce que votre réputation ne tombe pas en dessous de 300 et de ne pas tuer plus de 40% de vos patients, ou vous perdrez.//" .. "Bonne chance !", level1 = "Bienvenue dans votre premier hôpital !//Démarrez l'activité en installant un bureau de réception et " .. @@ -1104,12 +1104,12 @@ level8 = "A vous de gérer l'hôpital le plus efficace et le plus rentable possible.//Les gens du coin sont bien nantis alors " .. "pompez-leur tout le fric que vous pourrez. Soigner les gens c'est bien joli mais vous avez BESOIN de l'argent que ça " .. - "rapporte. Ratissez tous ces malades ! Amassez un joli paquet de $300.000 pour terminer ce niveau. ", + "rapporte. Ratissez tous ces malades ! Amassez un joli paquet de $300.000 pour terminer ce niveau.", level12 = "Côté défi, vous allez être servi ! Impressionné par votre succès, le Ministère veut vous assigner une mission de confiance. " .. "Vous devrez construire un autre hôpital de pointe, gagner des sommes scandaleuses et vous faire une réputation fabuleuse. " .. "Vous devrez également acheter tout le terrain possible, soigner toutes les maladies (nous avons bien dit TOUTES) et remporter " .. - "toutes les récompenses. Alors, heureux ? Gagnez $650.000, soignez 750 personnes et affichez une réputation de 800 pour gagner ce niveau. ", + "toutes les récompenses. Alors, heureux ? Gagnez $650.000, soignez 750 personnes et affichez une réputation de 800 pour gagner ce niveau.", level13 = "Votre incroyable talent en tant que directeur d'hôpital a attiré l'attention de la Division Spéciale Secrète des " .. "Services Spéciaux Secrets. On vous propose un bonus : il y a un hôpital infesté de rats qui réclame un Nettoyeur efficace. " .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/german.lua corsix-th-0.62/CorsixTH/Lua/languages/german.lua --- corsix-th-0.61/CorsixTH/Lua/languages/german.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/german.lua 2018-07-21 11:13:17.000000000 +0000 @@ -630,12 +630,12 @@ introduction_texts = { demo = - "Willkommen im Demo-Krankenhaus!" .. - "Leider beinhaltet die Demo-Version nur dieses eine Level. Dafür gibt es hier aber mehr als genug zu tun, um Sie eine Weile zu beschäftigen!" .. + "Willkommen im Demo-Krankenhaus!//" .. + "Leider beinhaltet die Demo-Version nur dieses eine Level. Dafür gibt es hier aber mehr als genug zu tun, um Sie eine Weile zu beschäftigen! " .. "Sie werden diversen Krankheiten begegnen, die unterschiedliche Räume zur Behandlung benötigen. Ab und zu können auch Notfälle eintreffen. " .. - "Und Sie werden mithilfe einer Forschungsabteilung neue Räume erforschen müssen." .. - "Ihr Ziel ist es, 100.000 DM zu verdienen, einen Krankenhauswert von 70.000 DM und einen Ruf von 700 vorzuweisen, und gleichzeitig mindestens 75% der Patienten erfolgreich zu behandeln." .. - "Stellen Sie sicher, dass Ihr Ruf nicht unter 300 fällt und dass Sie nicht mehr als 40% ihrer Patienten sterben lassen, oder Sie werden verlieren." .. + "Und Sie werden mithilfe einer Forschungsabteilung neue Räume erforschen müssen. " .. + "Ihr Ziel ist es, 100.000 DM zu verdienen, einen Krankenhauswert von 70.000 DM und einen Ruf von 700 vorzuweisen, und gleichzeitig mindestens 75% der Patienten erfolgreich zu behandeln. " .. + "Stellen Sie sicher, dass Ihr Ruf nicht unter 300 fällt und dass Sie nicht mehr als 40% ihrer Patienten sterben lassen, oder Sie werden verlieren.//" .. "Viel Glück!", } diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/iberic_portuguese.lua corsix-th-0.62/CorsixTH/Lua/languages/iberic_portuguese.lua --- corsix-th-0.61/CorsixTH/Lua/languages/iberic_portuguese.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/iberic_portuguese.lua 2018-07-21 11:13:17.000000000 +0000 @@ -531,12 +531,12 @@ introduction_texts.demo = - "Bem-vindo ao hospital do demo!" .. - "Infelizmente este demo só tem este nível.Contudo existe aqui muito trabalho para te manter ocupado!" .. - "Encontrarás várias doenças que requerem salas diferentes para os seus tratamentos.Ao longo do tempo " .. - "irão ocorrer algumas emergências e precisarás de descobrir novos tratamentos atráves da sala de pesquisa." .. - "O teu objectivo é ganhar 100,000$,ter um hospital avaliado em 70,000$,uma reputação de 700 e uma cura de 75% dos pacientes." .. - "Garante que a tua reputação não cai abaixo de 300 e que não mates 40% dos teus pacientes senão perderás o nível." .. + "Bem-vindo ao hospital do demo!//" .. + "Infelizmente este demo só tem este nível.Contudo existe aqui muito trabalho para te manter ocupado! " .. + "Encontrarás várias doenças que requerem salas diferentes para os seus tratamentos.Ao longo do tempo " .. + "irão ocorrer algumas emergências e precisarás de descobrir novos tratamentos atráves da sala de pesquisa. " .. + "O teu objectivo é ganhar 100,000$,ter um hospital avaliado em 70,000$,uma reputação de 700 e uma cura de 75% dos pacientes. " .. + "Garante que a tua reputação não cai abaixo de 300 e que não mates 40% dos teus pacientes senão perderás o nível.//" .. "Boa sorte!" diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/italian.lua corsix-th-0.62/CorsixTH/Lua/languages/italian.lua --- corsix-th-0.61/CorsixTH/Lua/languages/italian.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/italian.lua 2018-07-21 11:13:17.000000000 +0000 @@ -600,12 +600,12 @@ introduction_texts = { demo = - "Benvenuto nell'ospedale demo!" .. - "Sfortunatamente la versione demo contiene solo questo livello. Ad ogni modo c'è abbastanza da fare per tenerti occupato per un bel po'!" .. + "Benvenuto nell'ospedale demo!//" .. + "Sfortunatamente la versione demo contiene solo questo livello. Ad ogni modo c'è abbastanza da fare per tenerti occupato per un bel po'! " .. "Incontrerai diverse malattie che richiederanno diverse cliniche per essere curate. Ogni tanto potrebbero presentarsi delle emergenze. " .. - "E avrai bisogno di ricercare nuove strumentazioni tramite il centro ricerche." .. - "Il tuo obiettivo è di guadagnare $100,000, avere un ospedale che valga $70,000 e una reputazione di 700, oltre che curare almeno il 75% dei tuoi pazienti." .. - "Assicurati che la tua reputazione non scenda al di sotto di 300 e di non uccidere più del 40% dei tuoi pazienti, o perderai." .. + "E avrai bisogno di ricercare nuove strumentazioni tramite il centro ricerche. " .. + "Il tuo obiettivo è di guadagnare $100,000, avere un ospedale che valga $70,000 e una reputazione di 700, oltre che curare almeno il 75% dei tuoi pazienti. " .. + "Assicurati che la tua reputazione non scenda al di sotto di 300 e di non uccidere più del 40% dei tuoi pazienti, o perderai.//" .. "Buona fortuna!", } diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/korean.lua corsix-th-0.62/CorsixTH/Lua/languages/korean.lua --- corsix-th-0.61/CorsixTH/Lua/languages/korean.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/korean.lua 2018-07-21 11:13:17.000000000 +0000 @@ -2233,11 +2233,11 @@ } introduction_texts = { demo = - "데모 병원에 오신 것을 환영합니다!" .. + "데모 병원에 오신 것을 환영합니다!//" .. "안타깝게도 데모 버전에서는 (커스텀 레벨을 제외하면) 이 레벨만 플레이할 수 있습니다. 그렇지만, 여기에도 당신을 한동안 바쁘게 할만큼의 일거리는 충분히 있습니다! " .. "당신은 치료를 위해 다른 종류의 시설을 필요로 하는 다양한 질병을 만나게 될 것입니다. 가끔은 응급 상황이 발생할지도 모릅니다. 그리고 당신은 연구실을 지어 새로운 시설들을 연구해야 할 것입니다. " .. "당신의 목표는 $100,000 를 벌고, 병원 가치를 $70,000 만큼 올리며, 평판을 700 만큼 유지하고, 방문하는 환자의 75% 이상을 완치시키는 것입니다. " .. - "당신의 평판이 300 아래로 떨어지거나 40% 이상의 환자들을 죽게 하지 마세요. 어느 하나라도 발생하면 당신은 게임에서 지게 됩니다. " .. + "당신의 평판이 300 아래로 떨어지거나 40% 이상의 환자들을 죽게 하지 마세요. 어느 하나라도 발생하면 당신은 게임에서 지게 됩니다.//" .. "행운을 바랍니다!", level1 = "당신의 첫 병원에 오신 것을 환영합니다!//" .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/norwegian.lua corsix-th-0.62/CorsixTH/Lua/languages/norwegian.lua --- corsix-th-0.61/CorsixTH/Lua/languages/norwegian.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/norwegian.lua 2018-07-21 11:13:17.000000000 +0000 @@ -3146,11 +3146,11 @@ introduction_texts = { demo = - "Velkommen til demonstrasjonssykehuset!" .. - "Uheldigvis inneholder demoversjonen kun dette nivået. Uansett så er det mer enn nok å gjöre her for å holde deg opptatt en stund!" .. - "Du vil möte på forskjellige sykdommer som krever forskjellige rom for å kureres. Fra tid til annen kan nödstilfeller oppstå. Du må også forske frem nye rom ved hjelp av en forskningsavdeling." .. - "Målet ditt er å tjene $100,000, ha et sykehus som er verdt $70,000 og et omdömme på 700, samt kurert minst 75% av pasientene." .. - "Pass på at omdömmet ditt ikke faller under 300 og at du ikke dreper mer enn 40% av pasientene, for ellers vil du tape nivået." .. + "Velkommen til demonstrasjonssykehuset!//" .. + "Uheldigvis inneholder demoversjonen kun dette nivået. Uansett så er det mer enn nok å gjöre her for å holde deg opptatt en stund! " .. + "Du vil möte på forskjellige sykdommer som krever forskjellige rom for å kureres. Fra tid til annen kan nödstilfeller oppstå. Du må også forske frem nye rom ved hjelp av en forskningsavdeling. " .. + "Målet ditt er å tjene $100,000, ha et sykehus som er verdt $70,000 og et omdömme på 700, samt kurert minst 75% av pasientene. " .. + "Pass på at omdömmet ditt ikke faller under 300 og at du ikke dreper mer enn 40% av pasientene, for ellers vil du tape nivået.//" .. "Lykke til!", level1 = diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/polish.lua corsix-th-0.62/CorsixTH/Lua/languages/polish.lua --- corsix-th-0.61/CorsixTH/Lua/languages/polish.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/polish.lua 2018-07-21 11:13:17.000000000 +0000 @@ -2884,14 +2884,14 @@ level1 = "Witaj w swoim pierwszym szpitalu!//" .. "Aby rozpocząć działalność, postaw Biurko Recepcji, zbuduj Gabinet Lekarski i zatrudnij Recepcjonistkę oraz Lekarza. " .. - "Następnie zaczekaj, aż pojawią się kolejne zadania." .. + "Następnie zaczekaj, aż pojawią się kolejne zadania. " .. "Dobrym pomysłem jest budowa Gabinetu Psychiatrycznego oraz zatrudnienie Lekarza Psychiatry. " .. "Apteka i Pielęgniarka są także niezbędne w leczeniu pacjentów. " .. "Zwróć uwagę na ciężkie przypadki Głowowzdęcia - Napowietrzalnia rozwiąże ten problem. " .. "Będziesz musiał wyleczyć 10 ludzi i upewnić się, że twoja reputacja nie spadnie poniżej 200.", level9 = "Skoro już wzbogaciłeś konto Ministerstwa oraz ufundowałeś nową limuzynę samemu Ministrowi, możesz wracać do szpitala i nieść pomoc chorym i potrzebującym. " .. - "Tutaj napotkasz wiele różnych trudności." .. + "Tutaj napotkasz wiele różnych trudności. " .. "Z dobrze wyszkolonym personelem i gabinetami, nie powinieneś się niczego obawiać. " .. "Twój szpital musi być wart 200,000 PLN, a na konto ma trafić 400,000 PLN. " .. "Ani grosza mniej, bo nie ukończysz poziomu.", @@ -2943,11 +2943,11 @@ "Musisz ustrzelić tyle szczurów, ile zdołasz, zanim Dozorcy uprzątną bałagan. " .. "Myślisz, że poradzisz sobie z zadaniem?", demo = - "Witaj w szpitalu demonstracyjnym!" .. - "Niestety wersja demo zawiera tylko ten poziom. Jednakże, jest to więcej niż wystarczająco, aby zając ci trochę czasu!" .. - "Napotkasz tutaj rozmaite choroby, które będą wymagały różnych gabinetów do ich wyleczenia. Od czasu do czasu moga tu również wystąpić nagłe wypadki. Będziesz musiał równiez wynaleźć nowe pomieszczenia przy użyciu gabinetu badawczego." .. - "Twoim celem jest zarobienie 100,000 PLN, mieć szpital warty 70,000 PLN i reputację 700, przy czym musisz wyleczyć co najmniej 75% swoich pacjentów." .. - "Upewnij się, że Twoja reputacja nie spadnie poniżej 300 oraz, że nie zabijesz więcej niż 40% pacjentów, albo przegrasz." .. + "Witaj w szpitalu demonstracyjnym!//" .. + "Niestety wersja demo zawiera tylko ten poziom. Jednakże, jest to więcej niż wystarczająco, aby zając ci trochę czasu! " .. + "Napotkasz tutaj rozmaite choroby, które będą wymagały różnych gabinetów do ich wyleczenia. Od czasu do czasu moga tu również wystąpić nagłe wypadki. Będziesz musiał równiez wynaleźć nowe pomieszczenia przy użyciu gabinetu badawczego. " .. + "Twoim celem jest zarobienie 100,000 PLN, mieć szpital warty 70,000 PLN i reputację 700, przy czym musisz wyleczyć co najmniej 75% swoich pacjentów. " .. + "Upewnij się, że Twoja reputacja nie spadnie poniżej 300 oraz, że nie zabijesz więcej niż 40% pacjentów, albo przegrasz.//" .. "Powodzenia!", level16 = "Kiedy już przebadasz część pacjentów, będziesz musiał zbudować pomieszczenia lecznicze oraz przychodnie, aby ich leczyć - " .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/russian.lua corsix-th-0.62/CorsixTH/Lua/languages/russian.lua --- corsix-th-0.61/CorsixTH/Lua/languages/russian.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/russian.lua 2018-07-21 11:13:17.000000000 +0000 @@ -2044,11 +2044,11 @@ -- 8. Письма из министерства introduction_texts = { demo = - "Добро пожаловать в демонстрационную больницу!" .. - "К сожалению демонстрационная версия содержит только этот уровень. Но этого более чем достаточно, чтобы занять вас на некоторое время!" .. - "Вы будете сталкиваться с разными заболеваниями, которые будет требовать разных кабинетов для лечения. Время от времени, будут поступать пациенты, требующие немедленного лечения. Так же вам необходимо разрабатывать новые кабинеты используя исследовательский кабинет." .. - "Ваша цель заработать $100 000, стоимость больницы должна быть $70 000, а репутация 700. Кроме того, вы должны вылечивать не менее 75% своих пациентов." .. - "Удостоверьтесь, что ваша репутация не упадет ниже 300 и вы не убиваете более 40% ваших пациентов. Иначе вы проиграете." .. + "Добро пожаловать в демонстрационную больницу!//" .. + "К сожалению демонстрационная версия содержит только этот уровень. Но этого более чем достаточно, чтобы занять вас на некоторое время! " .. + "Вы будете сталкиваться с разными заболеваниями, которые будет требовать разных кабинетов для лечения. Время от времени, будут поступать пациенты, требующие немедленного лечения. Так же вам необходимо разрабатывать новые кабинеты используя исследовательский кабинет. " .. + "Ваша цель заработать $100 000, стоимость больницы должна быть $70 000, а репутация 700. Кроме того, вы должны вылечивать не менее 75% своих пациентов. " .. + "Удостоверьтесь, что ваша репутация не упадет ниже 300 и вы не убиваете более 40% ваших пациентов. Иначе вы проиграете.//" .. "Удачи!", level1 = "Добро пожаловать в вашу первую больницу!//" .. @@ -2075,11 +2075,11 @@ "Вам придется столкнуться с синдромом Короля, а также выделить деньги на постройку палаты и операционной. " .. "Заработайте 20 000$ чтобы добиться успеха.", level4 = - "Проследите, чтобы пациенты были довольны, хорошо обслужены и не умирали." .. - "Ваша репутация имеет большое значение, так что постарайтесь поднять ее как можно выше." .. - "Не беспокойтесь о деньгах - они придут вместе с высокой репутацией." .. - "Теперь вы также можете обучать ваших докторов, чтобы повысить их навыки." .. - "Так они смогут справляться даже с самыми необчными болезнями." .. + "Проследите, чтобы пациенты были довольны, хорошо обслужены и не умирали. " .. + "Ваша репутация имеет большое значение, так что постарайтесь поднять ее как можно выше. " .. + "Не беспокойтесь о деньгах - они придут вместе с высокой репутацией. " .. + "Теперь вы также можете обучать ваших докторов, чтобы повысить их навыки. " .. + "Так они смогут справляться даже с самыми необчными болезнями. " .. "Поднимите вашу репутацию до 500.", level5 = "С таким разнообразием заболеваний, как в этой больнице, вам не придется сидеть без дела." .. diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/simplified_chinese.lua corsix-th-0.62/CorsixTH/Lua/languages/simplified_chinese.lua --- corsix-th-0.61/CorsixTH/Lua/languages/simplified_chinese.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/simplified_chinese.lua 2018-07-21 11:13:17.000000000 +0000 @@ -374,11 +374,11 @@ } introduction_texts = { demo = - "欢迎来到演示版医院!" .. - "演示版本只有当前这一个关卡. 但有一堆事情足够你忙一阵了!" .. - "你将会遇到各种疾病需要各种医疗室来救治. 紧急情况也会经常性地发生. 你需要通过研究室来研发更多的医疗室." .. - "你的目标是挣够 $100,000, 使医院的价值达到 $70,000 以及得到 700 声望值, 同时你还需要救治超过 75% 的病人." .. - "确保你的声望值不会掉到 300 以下, 你的病人死亡率不超过 40% , 否则你就完了." .. + "欢迎来到演示版医院!//" .. + "演示版本只有当前这一个关卡. 但有一堆事情足够你忙一阵了! " .. + "你将会遇到各种疾病需要各种医疗室来救治. 紧急情况也会经常性地发生. 你需要通过研究室来研发更多的医疗室. " .. + "你的目标是挣够 $100,000, 使医院的价值达到 $70,000 以及得到 700 声望值, 同时你还需要救治超过 75% 的病人. " .. + "确保你的声望值不会掉到 300 以下, 你的病人死亡率不超过 40% , 否则你就完了.//" .. "祝你好运!", } object = { diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/spanish.lua corsix-th-0.62/CorsixTH/Lua/languages/spanish.lua --- corsix-th-0.61/CorsixTH/Lua/languages/spanish.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/spanish.lua 2018-07-21 11:13:17.000000000 +0000 @@ -180,7 +180,7 @@ }, [10] = { [1] = "¡Hola, %s!//", - [2] = "Felicidades por dirigir con éxito todos los hospitales que te hemos asignado. Esta soberbia actuación te capacita para viajar libremente por todo el mundo. Recibirás una pensión de %d y una limusina, a cambio de que viajes de ciudad en ciudad, saludando a tu incondicional público y fomentando la labor que se realiza en todos los hospitales.//", + [2] = "Enhorabuena, has gestionado tus hospitales satisfactoriamente. Este logro te permitirá viajar dónde quieras, con una paga de %d y una limusina. Aunque por supuesto esperamos que en tus viajes, no defraudes a tu público y sigas promocionando los hospitales.//" }, [11] = { [1] = "¡Hola, %s!//", @@ -197,7 +197,7 @@ introduction_texts = { level1 = - "¡Bienvenido a tu primer hospital! " .. + "¡Bienvenido a tu primer hospital!//" .. "Para hacer que empiece a funcionar, coloca una recepción, construye una consulta y contrata a una recepcionista y a un médico. " .. "Luego espera a que lleguen los pacientes. " .. "Sería una buena idea que construyeras una consulta de psiquiatría y contrataras a un psiquiatra. " .. @@ -316,12 +316,12 @@ "Ahora es cosa tuya, buena suerte y todo eso.", demo = - "¡Bienvenido al hospital de demostración!" .. - "Por desgracia, la versión de demostración solo contiene este nivel. Sin embargo, tienes más que suficiente para estar entretenido por un rato." .. + "¡Bienvenido al hospital de demostración!//" .. + "Por desgracia, la versión de demostración solo contiene este nivel. Sin embargo, tienes más que suficiente para estar entretenido por un rato. " .. "Te enfrentarás a varias enfermedades que necesitan de ciertas habitaciones para su cura. De vez en cuando pueden surgir emergencias. Y necesitarás " .. - "investigar sobre las enfermedades construyendo un Departamento de investigación." .. - "Tu objetivo es ganar 100.000 dólares, que el valor de tu hospital llegue hasta 70.000 dólares y tengas una reputación de 700, con un porcentaje de pacientes curados del 75%." .. - "Procura que tu reputación no caiga por debajo de 300 y que no mates a más del 40% de tus pacientes, o fracasarás." .. + "investigar sobre las enfermedades construyendo un Departamento de investigación. " .. + "Tu objetivo es ganar 100.000 dólares, que el valor de tu hospital llegue hasta 70.000 dólares y tengas una reputación de 700, con un porcentaje de pacientes curados del 75%. " .. + "Procura que tu reputación no caiga por debajo de 300 y que no mates a más del 40% de tus pacientes, o fracasarás.//" .. "¡Buena suerte!", } diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/swedish.lua corsix-th-0.62/CorsixTH/Lua/languages/swedish.lua --- corsix-th-0.61/CorsixTH/Lua/languages/swedish.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/swedish.lua 2018-07-21 11:13:17.000000000 +0000 @@ -596,12 +596,12 @@ introduction_texts = { demo = - "Välkommen till demosjukhuset!" .. - "Tyvärr innehåller demon bara denna nivå. Ändå finns det garanterat tillräckligt att göra ett tag framöver!" .. + "Välkommen till demosjukhuset!//" .. + "Tyvärr innehåller demon bara denna nivå. Ändå finns det garanterat tillräckligt att göra ett tag framöver! " .. "Du kommer att råka ut för diverse sjukdomar som kräver olika rum för att botas. " .. - "Ibland kan olyckor hända, så att det kommer akutfall till sjukhuset. Dessutom behöver du forska för att upptäcka fler rum." .. - "Målet är att tjäna $100,000, ha ett sjukhusvärde av $70,000 och 700 i anseende, samtidigt som du botar minst 75% av patienterna." .. - "Se till att ditt anseende inte sjunker under 300 och att du inte dödar mer än 40% av dina patienter, annars förlorar du." .. + "Ibland kan olyckor hända, så att det kommer akutfall till sjukhuset. Dessutom behöver du forska för att upptäcka fler rum. " .. + "Målet är att tjäna $100,000, ha ett sjukhusvärde av $70,000 och 700 i anseende, samtidigt som du botar minst 75% av patienterna. " .. + "Se till att ditt anseende inte sjunker under 300 och att du inte dödar mer än 40% av dina patienter, annars förlorar du.//" .. "Lycka till!", } diff -Nru corsix-th-0.61/CorsixTH/Lua/languages/traditional_chinese.lua corsix-th-0.62/CorsixTH/Lua/languages/traditional_chinese.lua --- corsix-th-0.61/CorsixTH/Lua/languages/traditional_chinese.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/languages/traditional_chinese.lua 2018-07-21 11:13:17.000000000 +0000 @@ -317,11 +317,11 @@ } introduction_texts = { demo = - "Welcome to the demo hospital!" .. - "Unfortunately the demo version only contains this level. However, there is more than enough to do here to keep you busy for a while!" .. - "You will encounter various diseases that require different rooms to cure. From time to time, emergencies may occur. And you will need to research additional rooms using a research room." .. - "Your goal is to earn $100,000, have a hospital value of $70,000 and a reputation of 700, while having cured at least 75% of your patients." .. - "Make sure your reputation does not fall below 300 and that you don't kill off more than 40% of your patients, or you will lose." .. + "Welcome to the demo hospital!//" .. + "Unfortunately the demo version only contains this level. However, there is more than enough to do here to keep you busy for a while! " .. + "You will encounter various diseases that require different rooms to cure. From time to time, emergencies may occur. And you will need to research additional rooms using a research room. " .. + "Your goal is to earn $100,000, have a hospital value of $70,000 and a reputation of 700, while having cured at least 75% of your patients." .. + "Make sure your reputation does not fall below 300 and that you don't kill off more than 40% of your patients, or you will lose.//" .. "Good luck!", } object = { @@ -2820,106 +2820,106 @@ } introduction_texts = { level17 = - "最後的警告-隨時關注您的聲望-這是真正吸引病人前來就診的關鍵。" .. - "如果您沒有醫死太多的病人,且使就診病人保持快樂,則不必太擔心聲望!" .. + "最後的警告-隨時關注您的聲望-這是真正吸引病人前來就診的關鍵。 " .. + "如果您沒有醫死太多的病人,且使就診病人保持快樂,則不必太擔心聲望! " .. "決定權就在您的手中。祝您好運。", level1 = - "歡迎來到您的第一座醫院!//" .. - "首先要擺放服務台,建造一般診斷室,並雇用一名接待員和一名醫生。" .. - "隨後就可以等待開張了。" .. - "建造精神病診斷治療室並雇用一名精神病醫生是一個好主意。" .. - "藥房和護士也是治療病人所必需的。" .. - "建造一個充氣機房間就可以治療頭部腫脹患者。" .. + "歡迎來到您的第一座醫院!// " .. + "首先要擺放服務台,建造一般診斷室,並雇用一名接待員和一名醫生。 " .. + "隨後就可以等待開張了。 " .. + "建造精神病診斷治療室並雇用一名精神病醫生是一個好主意。 " .. + "藥房和護士也是治療病人所必需的。 " .. + "建造一個充氣機房間就可以治療頭部腫脹患者。 " .. "您需要治癒10個病人,並使聲望保持在200以上。", level9 = - "當填滿了衛生署的銀行帳戶並為部長大人購買了一輛轎車後,您現在又要開始新的工作了。" .. - "在這裡您要面對很多問題。" .. - "只有擁有足夠經驗充分的員工和房間,您才能夠順利過關。" .. - "醫院價值需要達到$200,000,且銀行帳戶上要有$400,000。" .. + "當填滿了衛生署的銀行帳戶並為部長大人購買了一輛轎車後,您現在又要開始新的工作了。 " .. + "在這裡您要面對很多問題。 " .. + "只有擁有足夠經驗充分的員工和房間,您才能夠順利過關。 " .. + "醫院價值需要達到$200,000,且銀行帳戶上要有$400,000。 " .. "如果無法達到上述要求,則無法勝利完成任務。", level2 = - "在該區域內還有一些其它的疾病。" .. - "建造醫院從而可以治療更多的病人,並應該考慮建造研究部門。" .. - "記住保持內部的清潔,從而使聲望盡可能地高-您將遇到患有舌頭鬆弛症的病人,因此需要建造舌頭診治房間。" .. - "您也可以建造心電圖房間來幫助診斷疾病。" .. - "這些房間都需要經過研究才能夠被建造。現在你可以購買其它土地擴展醫院-使用城鎮地圖就可以購買土地。" .. + "在該區域內還有一些其它的疾病。//" .. + "建造醫院從而可以治療更多的病人,並應該考慮建造研究部門。 " .. + "記住保持內部的清潔,從而使聲望盡可能地高-您將遇到患有舌頭鬆弛症的病人,因此需要建造舌頭診治房間。 " .. + "您也可以建造心電圖房間來幫助診斷疾病。 " .. + "這些房間都需要經過研究才能夠被建造。現在你可以購買其它土地擴展醫院-使用城鎮地圖就可以購買土地。 " .. "目標是聲望300,銀行現金為10000,且治癒40個病人。", level7 = - "在這裡您將受到衛生署的密切監察,因此要在賺錢的同時,努力提高自己的聲望。" .. - "我們無法處理太多的醫療事故-這對於醫院的運營是十分不利的。" .. - "確認所有員工都很快樂,並確認已經購買了所有需要的儀器裝備。" .. + "在這裡您將受到衛生署的密切監察,因此要在賺錢的同時,努力提高自己的聲望。 " .. + "我們無法處理太多的醫療事故-這對於醫院的運營是十分不利的。 " .. + "確認所有員工都很快樂,並確認已經購買了所有需要的儀器裝備。 " .. "聲望需要達到600,且銀行裡需要有$200,000。", level5 = - "醫院將非常繁忙,處理各種各樣的病人。" .. - "醫生都是剛剛畢業的實習醫生,因此需要建造一間培訓室對他們進行培訓,提高能力。" .. - "您只有3名專家可以幫助培訓這些員工,因此一定要讓專家快樂。" .. - "另外要注意的是,醫院的位置不是很好。" .. - "經常會發生地震。" .. - "地震將對醫院中的機器產生損壞,從而影響醫院的運營。" .. + "醫院將非常繁忙,處理各種各樣的病人。 " .. + "醫生都是剛剛畢業的實習醫生,因此需要建造一間培訓室對他們進行培訓,提高能力。 " .. + "您只有3名專家可以幫助培訓這些員工,因此一定要讓專家快樂。 " .. + "另外要注意的是,醫院的位置不是很好。 " .. + "經常會發生地震。 " .. + "地震將對醫院中的機器產生損壞,從而影響醫院的運營。 " .. "使您聲望達到400以上,現金達到$50,000。另外需要治癒200個病人。", level4 = - "使所有的病人快樂,保持治療的高效率並儘量降低死亡人數。" .. - "聲望是十分重要的,因此儘量贏得更高的聲望。" .. - "不要太多擔心收入情況-當聲望提高了,收入也自然會提高。" .. - "您需要培訓您的醫生,拓寬他們的能力。" .. - "這樣他們就可以更好的為病人服務。" .. + "使所有的病人快樂,保持治療的高效率並儘量降低死亡人數。 " .. + "聲望是十分重要的,因此儘量贏得更高的聲望。 " .. + "不要太多擔心收入情況-當聲望提高了,收入也自然會提高。 " .. + "您需要培訓您的醫生,拓寬他們的能力。 " .. + "這樣他們就可以更好的為病人服務。 " .. "勝利條件是聲望達到500以上。", level14 = - "這裡還有一個挑戰-一個充滿驚奇的醫院。" .. - "如果您能夠成功完成這個任務,則您將成為所有勝利者中的佼佼者。" .. - "不要認為完成這個任務就像吃蛋糕一樣,這將是您所遇到的最艱苦的工作。" .. + "這裡還有一個挑戰-一個充滿驚奇的醫院。 " .. + "如果您能夠成功完成這個任務,則您將成為所有勝利者中的佼佼者。 " .. + "不要認為完成這個任務就像吃蛋糕一樣,這將是您所遇到的最艱苦的工作。 " .. "祝您好運!", level15 = - "好的,下面是管理醫院的一些技巧。//" .. - "醫生需要各種幫助來診斷病人。您可以" .. + "好的,下面是管理醫院的一些技巧。// " .. + "醫生需要各種幫助來診斷病人。您可以 " .. "建造另一個診斷類房間,例如高級診斷室。", level8 = - "需要您來建造一座高效的醫院。" .. - "很多人都無事可做,因此需要適量的裁員以保持高效。" .. - "記住治癒病人是很重要的一件事情,但是您更要從中賺錢。" .. - "讓噁心嘔吐的病人靠近清潔工人。" .. + "需要您來建造一座高效的醫院。 " .. + "很多人都無事可做,因此需要適量的裁員以保持高效。 " .. + "記住治癒病人是很重要的一件事情,但是您更要從中賺錢。 " .. + "讓噁心嘔吐的病人靠近清潔工人。 " .. "需要賺取$300,000就可以過關。", level13 = - "您的高超管理技能被特殊機密部門獲知。" .. - "他們將向您提高特別獎金,因為他們有一座被老鼠困擾的醫院需要有效管理。" .. - "您必須殺死盡可能多的老鼠,並讓清潔工人打掃乾淨。" .. + "您的高超管理技能被特殊機密部門獲知。 " .. + "他們將向您提高特別獎金,因為他們有一座被老鼠困擾的醫院需要有效管理。 " .. + "您必須殺死盡可能多的老鼠,並讓清潔工人打掃乾淨。 " .. "接受這個任務?", level16 = - "當對病人完成診斷後,需要建造處理和治療類房間完成對病人的治療工作。可以從" .. + "當對病人完成診斷後,需要建造處理和治療類房間完成對病人的治療工作。可以從 " .. "建造藥房開始。在藥房中需要一名護士分配各種藥品。", level6 = - "使用您的所有知識來建造一個運行平穩的醫院,從而可以賺取利潤並處理任何問題。" .. - "您需要注意一點,醫院周圍的空氣對細菌繁殖,傳染病流行非常適宜。" .. - "如果您沒有保持醫院的清潔,則將面對傳染病的流行。" .. + "使用您的所有知識來建造一個運行平穩的醫院,從而可以賺取利潤並處理任何問題。 " .. + "您需要注意一點,醫院周圍的空氣對細菌繁殖,傳染病流行非常適宜。 " .. + "如果您沒有保持醫院的清潔,則將面對傳染病的流行。 " .. "賺取$150,000,並使醫院價值超過$140,000。", level12 = - "您現在遇到了最大的挑戰。" .. - "我們為您的成功感到由衷地高興,衛生署為您準備了一項頂級工作;他們需要有人建造另一個超級醫院,賺錢的同時獲取較高的聲望。" .. - "您可以購買任何需要的土地,治療各種疾病贏得各種獎勵。" .. - "動心了嗎?" .. + "您現在遇到了最大的挑戰。 " .. + "我們為您的成功感到由衷地高興,衛生署為您準備了一項頂級工作;他們需要有人建造另一個超級醫院,賺錢的同時獲取較高的聲望。 " .. + "您可以購買任何需要的土地,治療各種疾病贏得各種獎勵。 " .. + "動心了嗎? " .. "賺取$650,000,治癒750個病人,使聲望達到800就可以勝利過關。", level3 = - "這次您將在一個富裕地區建造醫院。" .. - "衛生署希望您能夠在這裡賺取更多的利潤。" .. - "開始時您被要求獲取好的聲望,但是一旦醫院步入正軌,就可以集中精力賺取更多的錢。" .. - "有可能會發生緊急事件。" .. - "也就是說一次會有大量病人就診,且他們的病情都一樣。" .. - "在時間限制內如果能夠治癒他們,則不僅可以拿到獎金,聲望也會提高。" .. - "一些疾病如貓王症侯群等有可能發生,因此最好建造一間手術中心和附屬病房。" .. + "這次您將在一個富裕地區建造醫院。 " .. + "衛生署希望您能夠在這裡賺取更多的利潤。 " .. + "開始時您被要求獲取好的聲望,但是一旦醫院步入正軌,就可以集中精力賺取更多的錢。 " .. + "有可能會發生緊急事件。 " .. + "也就是說一次會有大量病人就診,且他們的病情都一樣。 " .. + "在時間限制內如果能夠治癒他們,則不僅可以拿到獎金,聲望也會提高。 " .. + "一些疾病如貓王症侯群等有可能發生,因此最好建造一間手術中心和附屬病房。 " .. "勝利條件是賺取$20,000。", level10 = - "隨著您的經驗不斷增長,衛生署要求您集中精力提高藥品的治療效果。" .. - "有人對您頗有微辭,為此您必須使所有的藥物都非常有效。" .. - "另外,一定要降低醫療事故的發生次數,減少死亡人數。" .. - "作為提示,您需要為建造膠桶留一些空地。" .. + "隨著您的經驗不斷增長,衛生署要求您集中精力提高藥品的治療效果。 " .. + "有人對您頗有微辭,為此您必須使所有的藥物都非常有效。 " .. + "另外,一定要降低醫療事故的發生次數,減少死亡人數。 " .. + "作為提示,您需要為建造膠桶留一些空地。 " .. "使所有藥物的療效都達到80%%,聲望達到650且在銀行帳戶上有$500,000,這樣就可以勝利過關。", level11 = - "現在您有機會建造一座終極醫院。" .. - "該地區享有極高的聲望,因此衛生署希望能夠看到最好的醫院建造在這裡。" .. - "我們希望您能夠賺取大量的金錢,獲得很高的聲望,並能夠成功地處理任何事件。" .. - "這是一項非常重要的工作。" .. - "這需要您的努力工作。" .. - "注意一點,該區域常常會看到不明飛行物。因此請讓您的員工做好準備迎接不速之客。" .. + "現在您有機會建造一座終極醫院。 " .. + "該地區享有極高的聲望,因此衛生署希望能夠看到最好的醫院建造在這裡。 " .. + "我們希望您能夠賺取大量的金錢,獲得很高的聲望,並能夠成功地處理任何事件。 " .. + "這是一項非常重要的工作。 " .. + "這需要您的努力工作。 " .. + "注意一點,該區域常常會看到不明飛行物。因此請讓您的員工做好準備迎接不速之客。 " .. "您的醫院價值需要達到$240,000,在銀行帳戶內需要$500,000,且聲望需要達到700。", level18 = "", } diff -Nru corsix-th-0.61/CorsixTH/Lua/map.lua corsix-th-0.62/CorsixTH/Lua/map.lua --- corsix-th-0.61/CorsixTH/Lua/map.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/map.lua 2018-07-21 11:13:17.000000000 +0000 @@ -27,7 +27,7 @@ local pathsep = package.config:sub(1, 1) local math_floor, tostring, table_concat = math.floor, tostring, table.concat -local thMap = require"TH".map +local thMap = require("TH").map function Map:Map(app) self.width = false diff -Nru corsix-th-0.61/CorsixTH/Lua/movie_player.lua corsix-th-0.62/CorsixTH/Lua/movie_player.lua --- corsix-th-0.61/CorsixTH/Lua/movie_player.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/movie_player.lua 2018-07-21 11:13:17.000000000 +0000 @@ -20,7 +20,7 @@ --! Layer which handles the Lua-facing side of loading and playing video. -local TH = require "TH" +local TH = require("TH") local pathsep = package.config:sub(1, 1) class "MoviePlayer" diff -Nru corsix-th-0.61/CorsixTH/Lua/objects/door.lua corsix-th-0.62/CorsixTH/Lua/objects/door.lua --- corsix-th-0.61/CorsixTH/Lua/objects/door.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/objects/door.lua 2018-07-21 11:13:17.000000000 +0000 @@ -30,7 +30,7 @@ west = 106, } -dofile "queue" +corsixth.require("queue") class "Door" (Object) diff -Nru corsix-th-0.61/CorsixTH/Lua/objects/litter.lua corsix-th-0.62/CorsixTH/Lua/objects/litter.lua --- corsix-th-0.61/CorsixTH/Lua/objects/litter.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/objects/litter.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" +local TH = require("TH") local object = {} object.id = "litter" @@ -96,12 +96,15 @@ function Litter:remove() assert(self:isCleanable()) - self.world:removeObjectFromTile(self, self.tile_x, self.tile_y) - - local hospital = self.world:getHospital(self.tile_x, self.tile_y) - local taskIndex = hospital:getIndexOfTask(self.tile_x, self.tile_y, "cleaning", self) - hospital:removeHandymanTask(taskIndex, "cleaning") + if self.tile_x then + self.world:removeObjectFromTile(self, self.tile_x, self.tile_y) + local hospital = self.world:getHospital(self.tile_x, self.tile_y) + local taskIndex = hospital:getIndexOfTask(self.tile_x, self.tile_y, "cleaning", self) + hospital:removeHandymanTask(taskIndex, "cleaning") + else + print("Warning: Removing litter that has already been removed.") + end self.world:destroyEntity(self) end diff -Nru corsix-th-0.61/CorsixTH/Lua/objects/reception_desk.lua corsix-th-0.62/CorsixTH/Lua/objects/reception_desk.lua --- corsix-th-0.61/CorsixTH/Lua/objects/reception_desk.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/objects/reception_desk.lua 2018-07-21 11:13:17.000000000 +0000 @@ -66,7 +66,7 @@ }, } -dofile "queue" +corsixth.require("queue") class "ReceptionDesk" (Object) @@ -95,10 +95,10 @@ local queue_front = self.queue:front() local reset_timer = true if self.receptionist and queue_front then - if queue_front.action_queue[1].name == "idle" then + if queue_front:getCurrentAction().name == "idle" then self.queue_advance_timer = self.queue_advance_timer + 1 reset_timer = false - if self.queue_advance_timer >= 4 + self.world.hours_per_day * (1.0 - self.receptionist.profile.skill) then + if self.queue_advance_timer >= 4 + Date.hoursPerDay() * (1.0 - self.receptionist.profile.skill) then reset_timer = true if queue_front.next_room_to_visit then queue_front:queueAction(SeekRoomAction(queue_front.next_room_to_visit.room_info.id)) diff -Nru corsix-th-0.61/CorsixTH/Lua/persistance.lua corsix-th-0.62/CorsixTH/Lua/persistance.lua --- corsix-th-0.61/CorsixTH/Lua/persistance.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/persistance.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local persist = require "persist" +local persist = require("persist") local saved_permanents = {} strict_declare_global "permanent" @@ -103,6 +103,11 @@ permanent[v] = name .. "." .. k end end + for k, v in pairs(class._metatable) do + if type(v) == "function" then + permanent[v] = name .. "._metatable." .. k + end + end until true end -- C/class/library methods diff -Nru corsix-th-0.61/CorsixTH/Lua/room.lua corsix-th-0.62/CorsixTH/Lua/room.lua --- corsix-th-0.61/CorsixTH/Lua/room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -149,7 +149,7 @@ -- If the patient was sent home while in the room, don't -- do anything apart from removing any leading idle action. if not patient.hospital then - if patient.action_queue[1].name == "idle" then + if patient:getCurrentAction().name == "idle" then patient:finishAction() end return @@ -258,10 +258,7 @@ end return false else - for _, _ in pairs(missing) do - return false - end - return true + return next(missing) == nil end end @@ -720,7 +717,7 @@ end end - local interrupted = patient.action_queue[1] + local interrupted = patient:getCurrentAction() local on_interrupt = interrupted.on_interrupt if on_interrupt then interrupted.on_interrupt = nil @@ -888,9 +885,9 @@ end end - if humanoid.action_queue[1].name == "use_screen" then + if humanoid:getCurrentAction().name == "use_screen" then --The humanoid must be using the screen to undress because this isn't a leaving action: - humanoid.action_queue[1].after_use = nil + humanoid:getCurrentAction().after_use = nil humanoid:setNextAction(use_screen) else humanoid:setNextAction(WalkAction(sx, sy):setMustHappen(true):disableTruncate():setIsLeaving(true)) @@ -919,7 +916,7 @@ local i = 0 -- Tell all humanoids that they should leave -- If someone is entering the room right now they are also counted. - if self.door.user and self.door.user.action_queue[1].is_entering then + if self.door.user and self.door.user:getCurrentAction().is_entering then i = 1 end for humanoid, _ in pairs(self.humanoids) do diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/decontamination.lua corsix-th-0.62/CorsixTH/Lua/rooms/decontamination.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/decontamination.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/decontamination.lua 2018-07-21 11:13:17.000000000 +0000 @@ -62,7 +62,7 @@ local console, stf_x, stf_y = self.world:findObjectNear(staff, "console") local --[[persistable:decontamination_shared_loop_callback]] function loop_callback() - if staff.action_queue[1].shower_ready and patient.action_queue[1].shower_ready then + if staff:getCurrentAction().shower_ready and patient:getCurrentAction().shower_ready then staff:finishAction() patient:finishAction() end diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/dna_fixer.lua corsix-th-0.62/CorsixTH/Lua/rooms/dna_fixer.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/dna_fixer.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/dna_fixer.lua 2018-07-21 11:13:17.000000000 +0000 @@ -58,7 +58,7 @@ local --[[persistable:dna_fixer_shared_loop_callback]] function loop_callback() -- If the other humanoid has already started to idle we move on - if staff.action_queue[1].name == "idle" and patient.action_queue[1].name == "idle" then + if staff:getCurrentAction().name == "idle" and patient:getCurrentAction().name == "idle" then -- We need to change to another type before starting, to be able -- to have different animations depending on gender. patient:setType(patient.change_into) diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/electrolysis.lua corsix-th-0.62/CorsixTH/Lua/rooms/electrolysis.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/electrolysis.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/electrolysis.lua 2018-07-21 11:13:17.000000000 +0000 @@ -57,7 +57,7 @@ local --[[persistable:electrolysis_shared_loop_callback]] function loop_callback() -- If the other humanoid has already started to idle we move on - if staff.action_queue[1].name == "idle" and patient.action_queue[1].name == "idle" then + if staff:getCurrentAction().name == "idle" and patient:getCurrentAction().name == "idle" then -- Skilled doctors require less electrocutions local num_electrocutions = math.random(1, 5) * (2 - staff.profile.skill) -- We need to change to another type before starting, to be able diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/hair_restoration.lua corsix-th-0.62/CorsixTH/Lua/rooms/hair_restoration.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/hair_restoration.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/hair_restoration.lua 2018-07-21 11:13:17.000000000 +0000 @@ -56,7 +56,7 @@ local console, stf_x, stf_y = self.world:findObjectNear(staff, "console") local --[[persistable:hair_restoration_shared_loop_callback]] function loop_callback() - if staff.action_queue[1].name == "idle" and patient.action_queue[1].name == "idle" then + if staff:getCurrentAction().name == "idle" and patient:getCurrentAction().name == "idle" then local loop_callback_restore = --[[persistable:hair_restoration_loop_callback]] function(action) action.prolonged_usage = false end diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/operating_theatre.lua corsix-th-0.62/CorsixTH/Lua/rooms/operating_theatre.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/operating_theatre.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/operating_theatre.lua 2018-07-21 11:13:17.000000000 +0000 @@ -96,7 +96,7 @@ --! Returns true if an operation is ongoing function OperatingTheatreRoom:isOperating() for k, _ in pairs(self.staff_member_set) do - if k.action_queue[1].name == "multi_use_object" then + if k:getCurrentAction().name == "multi_use_object" then return true end end @@ -140,7 +140,7 @@ -- Resume operation if already ongoing if self:isOperating() then local surgeon1 = next(self.staff_member_set) - local ongoing_action = surgeon1.action_queue[1] + local ongoing_action = surgeon1:getCurrentAction() assert(ongoing_action.name == "multi_use_object") local table, table_x, table_y = self.world:findObjectNear(staff, "operating_table_b") @@ -204,7 +204,7 @@ self:dealtWithPatient(patient) -- Tell the patient that it's time to leave, but only if the first action -- is really an idle action. - if patient.action_queue[1].name == "idle" then + if patient:getCurrentAction().name == "idle" then patient:finishAction() end end diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/scanner_room.lua corsix-th-0.62/CorsixTH/Lua/rooms/scanner_room.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/scanner_room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/scanner_room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -61,7 +61,7 @@ (patient.humanoid_class == "Standard Female Patient") local --[[persistable:scanner_shared_loop_callback]] function loop_callback() - if staff.action_queue[1].scanner_ready and patient.action_queue[1].scanner_ready then + if staff:getCurrentAction().scanner_ready and patient:getCurrentAction().scanner_ready then staff:finishAction() patient:finishAction() end @@ -120,9 +120,9 @@ end function ScannerRoom:makeHumanoidLeave(humanoid) - if humanoid.action_queue[1].name == "use_object" and - humanoid.action_queue[1].object == self.world:findObjectNear(humanoid, "scanner") then - humanoid.action_queue[1].after_use = nil + if humanoid:getCurrentAction().name == "use_object" and + humanoid:getCurrentAction().object == self.world:findObjectNear(humanoid, "scanner") then + humanoid:getCurrentAction().after_use = nil end self:makeHumanoidDressIfNecessaryAndThenLeave(humanoid) diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/toilets.lua corsix-th-0.62/CorsixTH/Lua/rooms/toilets.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/toilets.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/toilets.lua 2018-07-21 11:13:17.000000000 +0000 @@ -152,8 +152,8 @@ if class.is(humanoid, Patient) then number_users = number_users + 1 - if humanoid.action_queue[1].name == "use_object" and - humanoid.action_queue[1].object.object_type.id ~= "loo" then + if humanoid:getCurrentAction().name == "use_object" and + humanoid:getCurrentAction().object.object_type.id ~= "loo" then not_using_loo = not_using_loo + 1 end end diff -Nru corsix-th-0.61/CorsixTH/Lua/rooms/x_ray_room.lua corsix-th-0.62/CorsixTH/Lua/rooms/x_ray_room.lua --- corsix-th-0.61/CorsixTH/Lua/rooms/x_ray_room.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/rooms/x_ray_room.lua 2018-07-21 11:13:17.000000000 +0000 @@ -56,7 +56,7 @@ local console, stf_x, stf_y = self.world:findObjectNear(staff, "radiation_shield") local --[[persistable:x_ray_shared_loop_callback]] function loop_callback() - if staff.action_queue[1].name == "idle" and patient.action_queue[1].name == "idle" then + if staff:getCurrentAction().name == "idle" and patient:getCurrentAction().name == "idle" then local length = math.random(2, 4) * (2 - staff.profile.skill) local loop_callback_xray = --[[persistable:x_ray_loop_callback]] function(action) diff -Nru corsix-th-0.61/CorsixTH/Lua/run_debugger.lua corsix-th-0.62/CorsixTH/Lua/run_debugger.lua --- corsix-th-0.61/CorsixTH/Lua/run_debugger.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/run_debugger.lua 2018-07-21 11:13:17.000000000 +0000 @@ -13,7 +13,7 @@ return "Can't connect debugger: LuaSocket is not available." end - local _, config = dofile("config_finder") + local _, config = corsixth.require("config_finder") local connect = dofile("debugger") local successful, error_message = pcall(connect, config.DBGp_client_idehost, diff -Nru corsix-th-0.61/CorsixTH/Lua/string_extensions.lua corsix-th-0.62/CorsixTH/Lua/string_extensions.lua --- corsix-th-0.61/CorsixTH/Lua/string_extensions.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/string_extensions.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,8 +18,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local TH = require "TH" -local lpeg = require "lpeg" +local TH = require("TH") +local lpeg = require("lpeg") local _unwrap = TH.stringProxy._unwrap function TH.stringProxy.gsub(str, patt, repl) diff -Nru corsix-th-0.61/CorsixTH/Lua/strings.lua corsix-th-0.62/CorsixTH/Lua/strings.lua --- corsix-th-0.61/CorsixTH/Lua/strings.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/strings.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,8 +18,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -local lfs = require "lfs" -local TH = require "TH" +local lfs = require("lfs") +local TH = require("TH") --! Layer which handles the loading of localised text. class "Strings" diff -Nru corsix-th-0.61/CorsixTH/Lua/ui.lua corsix-th-0.62/CorsixTH/Lua/ui.lua --- corsix-th-0.61/CorsixTH/Lua/ui.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/ui.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -dofile "window" +corsixth.require("window") --! Top-level container for all other user-interface components. class "UI" (Window) @@ -26,10 +26,10 @@ ---@type UI local UI = _G["UI"] -local TH = require "TH" -local SDL = require "sdl" +local TH = require("TH") +local SDL = require("sdl") local WM = SDL.wm -local lfs = require "lfs" +local lfs = require("lfs") local function invert(t) local r = {} diff -Nru corsix-th-0.61/CorsixTH/Lua/window.lua corsix-th-0.62/CorsixTH/Lua/window.lua --- corsix-th-0.61/CorsixTH/Lua/window.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/window.lua 2018-07-21 11:13:17.000000000 +0000 @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --]] -dofile "persistance" +corsixth.require("persistance") --! Base class for user-interface dialogs. class "Window" diff -Nru corsix-th-0.61/CorsixTH/Lua/world.lua corsix-th-0.62/CorsixTH/Lua/world.lua --- corsix-th-0.61/CorsixTH/Lua/world.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Lua/world.lua 2018-07-21 11:13:17.000000000 +0000 @@ -22,17 +22,18 @@ local ipairs, _G, table_remove = ipairs, _G, table.remove -dofile "entities/patient" -dofile "entities/staff" -dofile "entities/vip" -dofile "entities/grim_reaper" -dofile "entities/inspector" -dofile "staff_profile" -dofile "hospital" -dofile "epidemic" -dofile "calls_dispatcher" -dofile "research_department" -dofile "entity_map" +corsixth.require("entities.patient") +corsixth.require("entities.staff") +corsixth.require("entities.vip") +corsixth.require("entities.grim_reaper") +corsixth.require("entities.inspector") +corsixth.require("staff_profile") +corsixth.require("hospital") +corsixth.require("epidemic") +corsixth.require("calls_dispatcher") +corsixth.require("research_department") +corsixth.require("entity_map") +corsixth.require("date") --! Manages entities, rooms, and the date. class "World" @@ -91,14 +92,10 @@ self.next_earthquake = { active = false } -- Time - self.hours_per_day = 50 self.hours_per_tick = 1 self.tick_rate = 3 self.tick_timer = 0 - self.year = 1 - self.month = 1 -- January - self.day = 1 - self.hour = 0 + self.game_date = Date() self.room_information_dialogs_off = app.config.debug -- This is false when the game is paused. @@ -179,8 +176,9 @@ self:makeAvailableStaff(0) self:calculateSpawnTiles() + -- Next Events dates self:nextEmergency() - self:nextVip() + self.next_vip_date = self:_generateNextVipDate() -- earthquakes -- current_map_earthquakes is a counter that tracks which number of earthquake @@ -473,8 +471,6 @@ if disease.only_emergency then return false end if not disease.visuals_id then return true end - local current_month = (self.year - 1) * 12 + self.month - -- level files can delay visuals to a given month -- and / or until a given number of patients have arrived local level_config = self.map.level_config @@ -482,14 +478,14 @@ local hold_visual_peep_count = level_config.gbv.HoldVisualPeepCount -- if the month is greater than either of these values then visuals will not appear in the game - if (hold_visual_months and hold_visual_months > current_month) or + if (hold_visual_months and hold_visual_months > self.game_date:monthOfGame()) or (hold_visual_peep_count and hold_visual_peep_count > hospital.num_visitors) then return false end -- The value against #visuals_available determines from which month a disease can appear. -- 0 means it can show up anytime. - return level_config.visuals_available[disease.visuals_id].Value < current_month + return level_config.visuals_available[disease.visuals_id].Value < self.game_date:monthOfGame() end --! Spawn a patient from a spawn point for the given hospital. @@ -855,7 +851,7 @@ } function World:getDate() - return self.month, self.day + return self.game_date:monthOfYear(), self.game_date:dayOfMonth() end -- Game speeds. The second value is the number of world clicks that pass for each @@ -871,11 +867,6 @@ ["Speed Up"] = {4, 1}, } --- Return the length of the current month -function World:getCurrentMonthLength() - return month_length[self.month] -end - function World:speedUp() self:setSpeed("Speed Up") end @@ -984,35 +975,30 @@ if not lfs.attributes(dir .. "Autosaves", "modification") then lfs.mkdir(dir .. "Autosaves") end - local status, err = pcall(TheApp.save, TheApp, dir .. "Autosaves" .. pathsep .. "Autosave" .. self.month .. ".sav") + local status, err = pcall(TheApp.save, TheApp, dir .. "Autosaves" .. pathsep .. "Autosave" .. self.game_date:monthOfYear() .. ".sav") if not status then print("Error while autosaving game: " .. err) end end - if self.year == 1 and self.month == 1 and self.day == 1 and self.hour == 0 then - if not self.ui.start_tutorial then - self.ui:addWindow(UIWatch(self.ui, "initial_opening")) - self.ui:showBriefing() - end + if self.game_date == Date() and not self.ui.start_tutorial then + self.ui:addWindow(UIWatch(self.ui, "initial_opening")) + self.ui:showBriefing() end self.tick_timer = self.tick_rate - self.hour = self.hour + self.hours_per_tick -- if an earthquake is supposed to be going on, call the earthquake function if self.next_earthquake.active then self:tickEarthquake() end + local new_game_date = self.game_date:plusHours(self.hours_per_tick) -- End of day/month/year - if self.hour >= self.hours_per_day then + if self.game_date:dayOfMonth() ~= new_game_date:dayOfMonth() then for _, hospital in ipairs(self.hospitals) do hospital:onEndDay() end self:onEndDay() - self.hour = self.hour - self.hours_per_day - self.day = self.day + 1 - if self.day > month_length[self.month] then - self.day = month_length[self.month] + if self.game_date:isLastDayOfMonth() then for _, hospital in ipairs(self.hospitals) do hospital:onEndMonth() end @@ -1021,27 +1007,26 @@ -- Bail out as the game has already been ended. return end - self.day = 1 - self.month = self.month + 1 - if self.month > 12 then - self.month = 12 + + if self.game_date:isLastDayOfYear() then -- It is crucial that the annual report gets to initialize before onEndYear is called. -- Yearly statistics are reset there. self.ui:addWindow(UIAnnualReport(self.ui, self)) self:onEndYear() - self.year = self.year + 1 - self.month = 1 end end end + self.game_date = new_game_date + for i = 1, self.hours_per_tick do for _, hospital in ipairs(self.hospitals) do hospital:tick() end -- A patient might arrive to the player hospital. -- TODO: Multiplayer support. - if self.spawn_hours[self.hour + i - 1] and self.hospitals[1].opened then - for _ = 1, self.spawn_hours[self.hour + i - 1] do + local spawn_count = self.spawn_hours[self.game_date:hourOfDay() + i - 1] + if spawn_count and self.hospitals[1].opened then + for _ = 1, spawn_count do self:spawnPatient() end end @@ -1053,7 +1038,7 @@ end self.current_tick_entity = nil self.map:onTick() - self.map.th:updateTemperatures(outside_temperatures[self.month], + self.map.th:updateTemperatures(outside_temperatures[self.game_date:monthOfYear()], 0.25 + self.hospitals[1].radiator_heat * 0.3) if self.ui then self.ui:onWorldTick() @@ -1074,13 +1059,13 @@ end function World:setEndMonth() - self.day = month_length[self.month] - self.hour = self.hours_per_day - 1 + local first_day_of_next_month = Date(self.game_date:year(), self.game_date:monthOfYear() + 1) + self.game_date = first_day_of_next_month:plusHours(-1) end function World:setEndYear() - self.month = 12 - self:setEndMonth() + local first_day_of_next_year = Date(self.game_date:year() + 1) + self.game_date = first_day_of_next_year:plusHours(-1) end -- Called immediately prior to the ingame day changing. @@ -1096,30 +1081,29 @@ self.current_tick_entity = nil --check if it's time for a VIP visit - if (self.year - 1) * 12 + self.month == self.next_vip_month and - self.day == self.next_vip_day then + if self.game_date:isSameDay(self.next_vip_date) then if #self.rooms > 0 and self.ui.hospital:hasStaffedDesk() then self.hospitals[1]:createVip() else - self:nextVip() + self.next_vip_date = self:_generateNextVipDate() end end -- check if it's time for an earthquake, and the user is at least on level 5 - if (self.year - 1) * 12 + self.month == self.next_earthquake.start_month and - self.day == self.next_earthquake.start_day then + if self.game_date:monthOfGame() == self.next_earthquake.start_month and + self.game_date:dayOfMonth() == self.next_earthquake.start_day then -- warn the user that an earthquake is on the way self.next_earthquake.active = true end -- Maybe it's time for an emergency? - if (self.year - 1) * 12 + self.month == self.next_emergency_month and - self.day == self.next_emergency_day then + if self.game_date:monthOfGame() == self.next_emergency_month and + self.game_date:dayOfMonth() == self.next_emergency_day then -- Postpone it if anything clock related is already underway. if self.ui:getWindow(UIWatch) then self.next_emergency_month = self.next_emergency_month + 1 local month_of_year = 1 + ((self.next_emergency_month - 1) % 12) - self.next_emergency_day = math.random(1, month_length[month_of_year]) + self.next_emergency_day = math.random(1, Date(1, month_of_year):lastDayOfMonth()) else -- Do it only for the player hospital for now. TODO: Multiplayer local control = self.map.level_config.emergency_control @@ -1155,9 +1139,10 @@ end -- Any patients tomorrow? self.spawn_hours = {} - if self.spawn_dates[self.day] then - for _ = 1, self.spawn_dates[self.day] do - local hour = math.random(1, self.hours_per_day) + local day = self.game_date:dayOfMonth() + if self.spawn_dates[day] then + for _ = 1, self.spawn_dates[day] do + local hour = math.random(1, Date.hoursPerDay()) self.spawn_hours[hour] = self.spawn_hours[hour] and self.spawn_hours[hour] + 1 or 1 end end @@ -1183,13 +1168,13 @@ -- TODO.... this is a step closer to the way TH would check. -- What is missing is that if offer is declined then the next check should be -- either 6 months later or at the end of month 12 and then every 6 months - if self.month % 3 == 0 and self.month < 12 then + if self.game_date:monthOfYear() % 3 == 0 and self.game_date:monthOfYear() < 12 then self:checkIfGameWon() end local local_hospital = self:getLocalPlayerHospital() local_hospital.population = 0.25 - if self.month >= self.map.level_config.gbv.AllocDelay then + if self.game_date:monthOfGame() >= self.map.level_config.gbv.AllocDelay then local_hospital.population = local_hospital.population * self:getReputationImpact(local_hospital) end @@ -1197,7 +1182,7 @@ local index = 0 local popn = self.map.level_config.popn while popn[index] do - if popn[index].Month == self.month + (self.year - 1)*12 then + if popn[index].Month == self.game_date:monthOfGame() then self.monthly_spawn_increase = popn[index].Change break end @@ -1207,7 +1192,7 @@ self.spawn_rate = self.spawn_rate + self.monthly_spawn_increase self:updateSpawnDates() - self:makeAvailableStaff((self.year - 1) * 12 + self.month) + self:makeAvailableStaff(self.game_date:monthOfGame()) self.autosave_next_tick = true for _, entity in ipairs(self.entities) do if entity.checkForDeadlock then @@ -1228,7 +1213,7 @@ self.spawn_dates = {} for _ = 1, no_of_spawns do -- We are interested in the next month, pick days from it at random. - local day = math.random(1, month_length[self.month % 12 + 1]) + local day = math.random(1, self.game_date:lastDayOfMonth()) self.spawn_dates[day] = self.spawn_dates[day] and self.spawn_dates[day] + 1 or 1 end end @@ -1259,7 +1244,6 @@ -- next emergency should look like. function World:nextEmergency() local control = self.map.level_config.emergency_control - local current_month = (self.year - 1) * 12 + self.month -- Does this level use random emergencies? if control and (control[0].Random or control[0].Mean) then -- Support standard values for mean and variance @@ -1267,20 +1251,11 @@ local variance = control[0].Variance or 30 -- How many days until next emergency? local days = math.round(math.n_random(mean, variance)) - local next_month = self.month + local emergency_date = self.game_date:plusDays(days) - -- Walk forward to get the resulting month and day. - if days > month_length[next_month] - self.day then - days = days - (month_length[next_month] - self.day) - next_month = next_month + 1 - end - while days > month_length[(next_month - 1) % 12 + 1] do - days = days - month_length[(next_month - 1) % 12 + 1] - next_month = next_month + 1 - end -- Make it the same format as for "controlled" emergencies - self.next_emergency_month = next_month + (self.year - 1) * 12 - self.next_emergency_day = days + self.next_emergency_month = emergency_date:monthOfGame() + self.next_emergency_day = emergency_date:dayOfMonth() else if not self.next_emergency_no then self.next_emergency_no = 0 @@ -1293,7 +1268,7 @@ self.next_emergency_no = self.next_emergency_no + 1 end until not control[self.next_emergency_no] or - control[self.next_emergency_no].EndMonth >= current_month + control[self.next_emergency_no].EndMonth >= self.game_date:monthOfGame() end local emergency = control[self.next_emergency_no] @@ -1304,14 +1279,14 @@ else -- Generate the next month and day the emergency should occur at. -- Make sure it doesn't happen in the past. - local start = math.max(emergency.StartMonth, self.month + (self.year - 1) * 12) + local start = math.max(emergency.StartMonth, self.game_date:monthOfGame()) local next_month = math.random(start, emergency.EndMonth) self.next_emergency_month = next_month local day_start = 1 if start == emergency.EndMonth then - day_start = self.day + day_start = self.game_date:dayOfMonth() end - local day_end = month_length[(next_month - 1) % 12 + 1] + local day_end = Date(1, next_month):lastDayOfMonth() self.next_emergency_day = math.random(day_start, day_end) end end @@ -1319,24 +1294,17 @@ -- Called when it is time to have another VIP function World:nextVip() + self.next_vip_date = self:_generateNextVipDate() +end + +-- PRIVATE method to generate the next VIP date +function World:_generateNextVipDate() -- Support standard values for mean and variance local mean = 180 local variance = 30 -- How many days until next vip? local days = math.round(math.n_random(mean, variance)) - local next_month = self.month - - -- Walk forward to get the resulting month and day. - if days > month_length[next_month] - self.day then - days = days - (month_length[next_month] - self.day) - next_month = next_month + 1 - end - while days > month_length[(next_month - 1) % 12 + 1] do - days = days - month_length[(next_month - 1) % 12 + 1] - next_month = next_month + 1 - end - self.next_vip_month = next_month + (self.year - 1) * 12 - self.next_vip_day = days + return self.game_date:plusDays(days) end -- Called when it is time to have another earthquake @@ -2104,7 +2072,7 @@ self.ui.adviser:say(_A.room_requirements.reception_need_receptionist) elseif self.hospitals[1]:hasStaffOfCategory("Receptionist") and self.object_counts["reception_desk"] == 1 and - not self.hospitals[1].receptionist_msg and self.month > 3 then + not self.hospitals[1].receptionist_msg and self.game_date:monthOfGame() > 3 then self.ui.adviser:say(_A.warnings.no_desk_5) self.hospitals[1].receptionist_msg = true end @@ -2445,8 +2413,8 @@ if old < 17 then -- Added another object local pathsep = package.config:sub(1, 1) - local _, shield = pcall(dofile, "objects" .. pathsep .. "radiation_shield") - local _, shield_b = pcall(dofile, "objects" .. pathsep .. "radiation_shield_b") + local _, shield = pcall(corsixth.require, "objects" .. pathsep .. "radiation_shield") + local _, shield_b = pcall(corsixth.require, "objects" .. pathsep .. "radiation_shield_b") shield.slave_type = shield_b shield.slave_type.master_type = shield Object.processTypeDefinition(shield) @@ -2601,6 +2569,11 @@ end end end + if old < 124 then + self.game_date = Date(self.year, self.month, self.day, self.hour) + -- self.next_vip_month is number of months since the game start + self.next_vip_date = Date(1, self.next_vip_month, self.next_vip_day) + end -- Now let things inside the world react. for _, cat in pairs({self.hospitals, self.entities, self.rooms}) do @@ -2730,3 +2703,7 @@ end return true end + +function World:date() + return self.game_date:clone() +end diff -Nru corsix-th-0.61/CorsixTH/Luatest/class_test_base.lua corsix-th-0.62/CorsixTH/Luatest/class_test_base.lua --- corsix-th-0.61/CorsixTH/Luatest/class_test_base.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/class_test_base.lua 2018-07-21 11:13:17.000000000 +0000 @@ -25,3 +25,23 @@ require("non_strict") require("class") +local say = require("say") +local assert = require("luassert") + +function permanent() + return function() + return {} + end +end + +function values() + return function() + return nil + end +end + +function assertion_matches(_, arguments) + return string.match(arguments[1], arguments[2]) ~= nil +end +say:set("assertion.matches", "Expected substring fail.\n: %s\n:%s") +assert:register("assertion", "matches", assertion_matches, "assertion.matches") diff -Nru corsix-th-0.61/CorsixTH/Luatest/corsixth.lua corsix-th-0.62/CorsixTH/Luatest/corsixth.lua --- corsix-th-0.61/CorsixTH/Luatest/corsixth.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/corsixth.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,25 @@ +--[[ Copyright (c) 2017 Stephen "TheCycoONE" Baker + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +-- A stub implementation of the corsixth object to bypass the persistence +-- C++ code. + +_G['corsixth'] = {} +corsixth.require = require; diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/class_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/class_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/class_spec.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/class_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -69,4 +69,8 @@ assert.are.equal("ChildClass", class.type(child_class)) assert.are.equal("ParentClass", class.type(parent_class)) end) + + it("should make the metatable available", function() + assert.are.equal(getmetatable(parent_class), parent_class._metatable) + end) end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/date_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/date_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/date_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/date_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,185 @@ +--[[ Copyright (c) 2018 Pavel "sofo" Schoffer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +require("class_test_base") + +require("date") + +describe("Date", function() + it("can return correct month last day", function() + assert.are.equal(Date(1, 1):lastDayOfMonth(), 31) + assert.are.equal(Date(1, 2):lastDayOfMonth(), 28) + assert.are.equal(Date(1, 6):lastDayOfMonth(), 30) + assert.are.equal(Date(1, 12):lastDayOfMonth(), 31) + end) + + it("default works", function() + local date = Date(5, 12, 22, 5) + assert.are.equal(date:hourOfDay(), 5) + assert.are.equal(date:dayOfMonth(), 22) + assert.are.equal(date:monthOfYear(), 12) + assert.are.equal(date:year(), 5) + + date = Date(5, 12, 22) + assert.are.equal(date:hourOfDay(), 0) + assert.are.equal(date:dayOfMonth(), 22) + assert.are.equal(date:monthOfYear(), 12) + assert.are.equal(date:year(), 5) + + date = Date(4, 12) + assert.are.equal(date:dayOfMonth(), 1) + assert.are.equal(date:monthOfYear(), 12) + assert.are.equal(date:year(), 4) + + date = Date(24) + assert.are.equal(date:dayOfMonth(), 1) + assert.are.equal(date:monthOfYear(), 1) + assert.are.equal(date:year(), 24) + + date = Date() + assert.are.equal(date:dayOfMonth(), 1) + assert.are.equal(date:monthOfYear(), 1) + assert.are.equal(date:year(), 1) + end) + + it("cannot be wrong date", function() + local date = Date(1, 14) + assert.are.equal(date:monthOfYear(), 2) + + date = Date(1, 24) + assert.are.equal(date:monthOfYear(), 12) + end) + + it("can handle hour adjustmentse", function() + local date = Date(1, 1, 5, 50) + assert.are.equal(6, date:dayOfMonth()) + assert.are.equal(0, date:hourOfDay()) + + date = Date(1, 1, 1, 55) + assert.are.equal(2, date:dayOfMonth()) + assert.are.equal(5, date:hourOfDay()) + end) + + it("can add and read months", function() + local date = Date():plusMonths(1) + assert.are.equal(date:monthOfYear(), 2) + + date = Date(20, 12):plusMonths(1) + assert.are.equal(date:monthOfYear(), 1) + end) + + it("can handle complex adjustments", function() + local date = Date(2,2,31,55) + assert.are.equal("2-03-04T05", date:tostring()) + + date = Date(1,12,31,55) + assert.are.equal("2-01-01T05", date:tostring()) + + -- 31 - January, 28 - February, 7 - March + date = Date(1,1,66) + assert.are.equal("1-03-07T00", date:tostring()) + end) + + it("can print date", function() + local date = Date(2,12,1,6) + assert.are.equal("2-12-01T06", date:tostring()) + end) + it("can add days", function() + local date = Date(2,12,30) + -- 1 - December, 29 - January + date = date:plusDays(30) + assert.are.equal("3-01-29T00", date:tostring()) + + date = Date(1,3,15) + -- 16 - March, 30 - April, 31 - June, 13 - July + date = date:plusDays(90) + assert.are.equal("1-06-13T00", date:tostring()) + end) + it("can add years", function() + local date = Date(3, 2, 1, 6) + local expected_date = Date(8, 2, 1, 6) + + local adjusted_date = date:plusYears(5) + assert.True(expected_date == adjusted_date) + end) + it("can add hours", function() + local date = Date(1,1,1,5) + + local adjusted_date = date:plusHours(50) + assert.are.equals(2, adjusted_date:dayOfMonth()) + assert.are.equals(5, adjusted_date:hourOfDay()) + end) + it("can add negative hours", function() + local date = Date(3,1,1,0) + local expected_date = Date(2,12,31,49) + + local adjusted_date = date:plusHours(-1) + assert.True(expected_date == adjusted_date) + end) + it("can add negative days", function() + local date = Date(3,1,1) + local adjusted_date = date:plusDays(-40) + local expected_date = Date(2,11,22) + + assert.True(expected_date == adjusted_date) + end) + it("can tell the last days", function() + local date = Date(1,12,3) + assert.False(date:isLastDayOfMonth()) + assert.False(date:isLastDayOfYear()) + + date = Date(1,1,31) + assert.True(date:isLastDayOfMonth()) + assert.False(date:isLastDayOfYear()) + + date = Date(1,12,31) + assert.True(date:isLastDayOfMonth()) + assert.True(date:isLastDayOfYear()) + end) + it("get total elapsed month", function() + local date = Date(8,11,1) + assert.are.equals(95, date:monthOfGame()) + end) + it("can get compared", function() + local date1 = Date(3,2,1) + local other_date1 = Date(3,2,1) + local date2 = Date(1,2,3) + local date_with_different_hour = Date(3,2,1,40) + assert.True(date1 == other_date1) + assert.False(date1 == date2) + assert.True(date1 > date2) + assert.False(date1 < date2) + assert.True(date1 >= other_date1) + assert.False(date_with_different_hour == date1) + assert.True(date_with_different_hour > date1) + end) + it("can clone itself", function() + local origin_date = Date(12,3,2,6) + local clone_date = origin_date:clone() + assert.True(origin_date == clone_date) + end) + it("can provide hours per day", function() + assert.equals(50, Date.hoursPerDay()) + end) + it("can chack if two days are the same", function() + assert.True(Date(1,2,3,5):isSameDay(Date(1,2,3,9))) + assert.False(Date(1,2,3):isSameDay(Date(1,4,3))) + end) +end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/dialogs/bottom_pannel_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/dialogs/bottom_pannel_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/dialogs/bottom_pannel_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/dialogs/bottom_pannel_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,82 @@ +--[[ Copyright (c) 2018 Stephen E. Baker + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +describe("Bottom Panel:", function() + local bottom_panel; + local mock_canvas; + local font; + + setup(function() + require("corsixth") + require("class_test_base") + require("TH") + + require("window") + require("dialogs/bottom_panel") + end) + + before_each(function() + TheApp.world.gameLog = function() end + + font = { + draw = function() end, + drawWrapped = function() end, + } + TheApp.gfx.loadFont = function() return font end + + local mock_ui = {} + mock_ui.app = _G['TheApp'] + mock_ui.addKeyHandler = function() end + + mock_canvas = {} + + bottom_panel = UIBottomPanel(mock_ui) + + mock(font, 'draw') + mock(font, 'drawWrapped') + mock(TheApp.world, 'gameLog') + end) + + it("Set nil dynamic info", function() + bottom_panel:setDynamicInfo(nil) + bottom_panel:drawDynamicInfo(mock_canvas, 0, 0) + + assert.stub(TheApp.world.gameLog).was_not.called_with(TheApp.world, "Dynamic info is missing text!") + end) + + it("Set dynamic info without text", function() + local dynamic_info = {} + + bottom_panel:setDynamicInfo(dynamic_info) + bottom_panel:drawDynamicInfo(mock_canvas, 0, 0) + + assert.stub(TheApp.world.gameLog).was.called_with(TheApp.world, "Dynamic info is missing text!") + end) + + it("Set dynamic info with text", function() + local dynamic_info = { text = { "test text" } } + + bottom_panel:setDynamicInfo(dynamic_info) + bottom_panel:drawDynamicInfo(mock_canvas, 0, 0) + + assert.stub(TheApp.world.gameLog).was_not.called_with(TheApp.world, "Dynamic info is missing text!") + assert.stub(font.drawWrapped).was.called_with(font, mock_canvas, "test text", 20, 10, 240) + end) +end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/entities/humanoid_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/entities/humanoid_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/entities/humanoid_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/entities/humanoid_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,73 @@ +--[[ Copyright (c) 2018 Pavel "sofo" Schoffer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +require("class_test_base") + +require("entity") +require("entities.humanoid") + +describe("Humanoid:", function() + local function getHumanoid() + local animation = {setHitTestResult = function() end} + return Humanoid(animation) + end + + it("Gets the current action", function() + local humanoid = getHumanoid() + + local action1 = {name = "fake1"} + local action2 = {name = "fake2"} + humanoid:queueAction(action1) + humanoid:queueAction(action2) + + local recievedAction = humanoid:getCurrentAction() + + assert.equal(action1, recievedAction) + end) + it("Throws error if no action is queued", function() + local humanoid = getHumanoid() + + local state, error = pcall(humanoid.getCurrentAction, humanoid) + + assert.False(state) + local expected_message = "Action queue was empty. This should never happen." + assert.matches(error, expected_message) + assert.matches(error, "humanoid %-") + end) + it("Can represent itself as a string", function() + local humanoid = getHumanoid() + humanoid.humanoid_class = "class" + + local result = humanoid:tostring() + + assert.matches(result, "humanoid[ -]*class.*class") + assert.matches(result, "Warmth.*Happiness.*Fatigue") + assert.matches(result, "Actions: %[%]") + end) + it("Can add actions to a representation", function() + local humanoid = getHumanoid() + humanoid.action_queue = {{name = "A1", room_type = "room"}, {name = "A2"}} + + local result = humanoid:tostring() + + assert.matches(result, "Actions.*%[A1 %- room, A2%]") + end) + +end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/entities/machine_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/entities/machine_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/entities/machine_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/entities/machine_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,76 @@ +--[[ Copyright (c) 2014 Pavel "sofo" Schoffer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +require("class_test_base") + +require("entity") +require("entities/object") +require("entities/machine") + +describe("object.lua: ", function() + local stub_world = {map = {}} + local tile_x, tile_y, direction = 10, 10, "west" + + local function createMachineWithFakeInput() + stub(stub_world, "getLocalPlayerHospital") + stub(stub_world, "addObjectToTile") + stub(stub_world, "clearCaches") + local offset = {0, 0} + local orientation = { + render_attach_position = offset, + use_position = {0, 0} + } + local fake_object_type = { + ticks = false, + idle_animations = {west = true}, + orientations = {west = orientation} + } + return Machine(stub_world, fake_object_type, tile_x, tile_y, direction) + end + + it("can update dynamic Info", function() + local machine = createMachineWithFakeInput() + machine:updateDynamicInfo() + assert.are.equal(1, machine.times_used) + assert.are.equal(1, machine.total_usage) + end) + it("can transfer state", function() + local machine1 = createMachineWithFakeInput() + machine1:updateDynamicInfo() + local machine2 = createMachineWithFakeInput() + + machine2:setState(machine1:getState()) + + assert.are.equal(machine1.times_used, machine2.times_used) + assert.are.equal(machine1.total_usage, machine2.total_usage) + end) + it("setting null state doesn't clear values", function() + local machine = createMachineWithFakeInput() + machine:updateDynamicInfo() + + assert.are.equal(1, machine.times_used) + assert.are.equal(1, machine.total_usage) + + machine:setState(nil) + + assert.are.equal(1, machine.times_used) + assert.are.equal(1, machine.total_usage) + end) +end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/entities/object_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/entities/object_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/entities/object_spec.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/entities/object_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -21,7 +21,7 @@ require("class_test_base") require("entity") -require("entities/object") +require("entities.object") describe("object.lua: ", function() local stub_world = {map = {}} @@ -41,4 +41,13 @@ assert.are.equal(fake_object_type, object.object_type) assert.are.equal(stub_world.map, object.world.map) end) + it("can transfer state", function() + local object1 = createObjectWithFakeInput() + object1.times_used = object1.times_used + 7 + local object2 = createObjectWithFakeInput() + assert.are_not.equal(object1.times_used, object2.times_used) + + object2:setState(object1:getState()) + assert.are.equal(object1.times_used, object2.times_used) + end) end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/spec/entities/staff_spec.lua corsix-th-0.62/CorsixTH/Luatest/spec/entities/staff_spec.lua --- corsix-th-0.61/CorsixTH/Luatest/spec/entities/staff_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/spec/entities/staff_spec.lua 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,44 @@ +--[[ Copyright (c) 2018 Pavel "sofo" Schoffer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --]] + +require("class_test_base") + +require("entity") +require("entities.humanoid") +require("entities.staff") + +describe("Staff:", function() + local function getStaff() + local animation = {setHitTestResult = function() end} + return Staff(animation) + end + + it("Can represent doctor as a string", function() + local doctor = getStaff() + doctor.humanoid_class = "Doctor" + local name = "WHITMAN" + doctor.profile = {skill = 0.5, is_psychiatrist = 0.5, name = name} + + local result = doctor:tostring() + + assert.matches(result, "humanoid.*" .. name .. ".*class.*Doctor") + assert.matches(result, "Skills.*0%.5.*Psych.*0%.5") + end) +end) diff -Nru corsix-th-0.61/CorsixTH/Luatest/TH.lua corsix-th-0.62/CorsixTH/Luatest/TH.lua --- corsix-th-0.61/CorsixTH/Luatest/TH.lua 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Luatest/TH.lua 2018-07-21 11:13:17.000000000 +0000 @@ -21,13 +21,56 @@ -- A stub implementation of the TH C++ object, to be able to run -- unit tests without any backend. +TheApp = { + gfx = { + loadMainCursor = function() end, + loadSpriteTable = function() end, + loadFont = function() return { + draw = function() end, + drawWrapped = function() end, + } end, + }, + runtime_config = {}, + config = { + width = 600, + height = 800, + }, + world = { + speed = "Normal", + isCurrentSpeed = function(self, s) return s == self.speed end, + gameLog = function() end, + }, +} + +local sub_S = setmetatable({key = ''}, { + __index = function(t, k) + t.key = t.key .. '.' .. k + return t + end, + + __tostring = function(t) + return t.key + end, +}) + +_G['_S'] = setmetatable({key = ''}, { + __index = function(_, k) + sub_S.key = '_S.' .. k + return sub_S + end, + + __tostring = function(_) + return '_S' + end, +}) + return { animation = function() return { - setHitTestResult = function() end, - setAnimation = function() end, - setDrawingLayer = function() end, - setTile = function() end, - } - end, + setHitTestResult = function() end, + setAnimation = function() end, + setDrawingLayer = function() end, + setTile = function() end, + } + end } diff -Nru corsix-th-0.61/CorsixTH/RequiredResources.txt corsix-th-0.62/CorsixTH/RequiredResources.txt --- corsix-th-0.61/CorsixTH/RequiredResources.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/RequiredResources.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -# rsync compatible filter file which is used post-build -# to help with copying the required resources into the -# bundles for the Mac build. - -- .git/ -- .DS_Store -+ CorsixTH.lua -+ Lua/ -+ Lua/** -+ Levels/ -+ Levels/** -+ Bitmap/ -+ Bitmap/aux_ui.* -+ Bitmap/tree_ctrl.* -+ Bitmap/mainmenu1080.dat -+ Bitmap/mainmenu1080.pal -+ Campaigns/ -+ Campaigns/** -+ Graphics/ -+ Graphics/** -- * diff -Nru corsix-th-0.61/CorsixTH/run-corsix-th-dev.sh.in corsix-th-0.62/CorsixTH/run-corsix-th-dev.sh.in --- corsix-th-0.61/CorsixTH/run-corsix-th-dev.sh.in 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/run-corsix-th-dev.sh.in 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/sh + +"@CMAKE_CURRENT_BINARY_DIR@/corsix-th" --interpreter="@CMAKE_SOURCE_DIR@/CorsixTH/CorsixTH.lua" $@ diff -Nru corsix-th-0.61/CorsixTH/run-corsix-th-dev.sh.in.apple corsix-th-0.62/CorsixTH/run-corsix-th-dev.sh.in.apple --- corsix-th-0.61/CorsixTH/run-corsix-th-dev.sh.in.apple 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/run-corsix-th-dev.sh.in.apple 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/sh + +"@CMAKE_CURRENT_BINARY_DIR@/CorsixTH.app/Contents/MacOS/CorsixTH" --interpreter="@CMAKE_SOURCE_DIR@/CorsixTH/CorsixTH.lua" $@ diff -Nru corsix-th-0.61/CorsixTH/SDLMain/CMakeLists.txt corsix-th-0.62/CorsixTH/SDLMain/CMakeLists.txt --- corsix-th-0.61/CorsixTH/SDLMain/CMakeLists.txt 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/SDLMain/CMakeLists.txt 2018-07-21 11:13:17.000000000 +0000 @@ -1,8 +1,6 @@ -IF(APPLE) - find_package(SDL2 REQUIRED) - - set(CMAKE_OSX_ARCHITECTURES "x86_64") - include_directories(${SDL_INCLUDE_DIR}) - - add_library (SDL2main STATIC SDLMain.m) -endif(APPLE) +if(APPLE) + find_package(SDL2 REQUIRED) + set(CMAKE_OSX_ARCHITECTURES "x86_64") + include_directories(${SDL_INCLUDE_DIR}) + add_library (SDL2main STATIC SDLMain.m) +endif() diff -Nru corsix-th-0.61/CorsixTH/Src/bootstrap.cpp corsix-th-0.62/CorsixTH/Src/bootstrap.cpp --- corsix-th-0.61/CorsixTH/Src/bootstrap.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/bootstrap.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -40,8 +40,8 @@ homemade bitmap font, as we cannot rely on TH fonts being present). */ -static const int g_iBootstrapCodeLineNumStart = __LINE__ + 2; -static const char* g_sBootstrapCode[] = { +static const int first_bootstrap_code_line_number = __LINE__ + 2; +static const char* bootstrap_code[] = { "local lines, dat, tab, pal, err = {}, ...", "local function t(s) return s:gsub('\\t', ' ') end", "for s in tostring(err):gmatch'[^\\r\\n]+' do lines[#lines+1] = t(s) end", @@ -91,7 +91,7 @@ /* Start autogenerated content */ /* Data from bootstrap_font.tab inserted by mkbootstrap.lua: */ -static const std::vector g_aBootstrapFontTab = { +static const std::vector bootstrap_font_tab = { 0x52, 0x4E, 0x43, 0x01, 0x00, 0x00, 0x05, 0x46, 0x00, 0x00, 0x01, 0xE1, 0xFB, 0xF2, 0x66, 0x51, 0xBE, 0xEF, 0x0C, 0x09, 0x59, 0x60, 0x10, 0x34, 0x43, 0x54, 0xA6, 0x46, 0xA2, 0x08, 0x00, 0xA0, 0xC4, 0x01, 0xF6, 0x3D, 0x00, 0x00, 0xAF, @@ -133,7 +133,7 @@ 0x29, 0x40, 0x52, 0x7D, 0x0F }; /* Data from bootstrap_font.dat inserted by mkbootstrap.lua: */ -static const std::vector g_aBootstrapFontDat = { +static const std::vector bootstrap_font_dat = { 0x52, 0x4E, 0x43, 0x01, 0x00, 0x00, 0x13, 0x68, 0x00, 0x00, 0x05, 0xEC, 0xD3, 0x6C, 0x7E, 0xAB, 0xBE, 0xEF, 0x94, 0x90, 0x81, 0x61, 0x50, 0x34, 0x44, 0x33, 0x33, 0x53, 0x66, 0x64, 0x64, 0x26, 0x20, 0x60, 0x47, 0x1E, 0x01, 0xFF, 0x84, @@ -254,7 +254,7 @@ 0x02, 0xAC, 0x9A, 0x43, 0x10, 0xB5, 0x0A, 0xA0, 0x17, 0x1C, 0xA6, 0x00, 0x9B }; /* Data from bootstrap_font.pal inserted by mkbootstrap.lua: */ -static const std::vector g_aBootstrapFontPal = { +static const std::vector bootstrap_font_pal = { 0x52, 0x4E, 0x43, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB7, 0xFF, 0x76, 0x79, 0xBE, 0xEF, 0x90, 0x10, 0x90, 0x05, 0x01, 0x02, 0x00, 0x00, 0x20, 0x2B, 0x04, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0xB6, 0x00, 0x00, 0x00, @@ -262,7 +262,7 @@ }; /* End autogenerated content */ -// Lua reader function for loading g_sBootstrapCode +// Lua reader function for loading bootstrap_code static const char* read_bootstrap_line(lua_State *L, void *data, size_t *size) { int& iLine = *reinterpret_cast(data); @@ -274,7 +274,7 @@ } else { - const char *s = g_sBootstrapCode[iLine / 2]; + const char *s = bootstrap_code[iLine / 2]; if(s == nullptr) { *size = 0; @@ -293,20 +293,20 @@ lua_pushlstring(L, reinterpret_cast(data.data()), data.size()); } -int Bootstrap_lua_resources(lua_State *L) +int bootstrap_lua_resources(lua_State *L) { - push(L, g_aBootstrapFontDat); - push(L, g_aBootstrapFontTab); - push(L, g_aBootstrapFontPal); + push(L, bootstrap_font_dat); + push(L, bootstrap_font_tab); + push(L, bootstrap_font_pal); return 3; } -int Bootstrap_lua_error_report(lua_State *L) +int bootstrap_lua_error_report(lua_State *L) { - int iLine = -g_iBootstrapCodeLineNumStart; + int iLine = -first_bootstrap_code_line_number; if(luaT_load(L, read_bootstrap_line, &iLine, "@bootstrap.cpp", "t") == 0) { - Bootstrap_lua_resources(L); + bootstrap_lua_resources(L); lua_pushvalue(L, 1); lua_call(L, 4, 0); return 0; diff -Nru corsix-th-0.61/CorsixTH/Src/bootstrap.h corsix-th-0.62/CorsixTH/Src/bootstrap.h --- corsix-th-0.61/CorsixTH/Src/bootstrap.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/bootstrap.h 2018-07-21 11:13:17.000000000 +0000 @@ -25,9 +25,9 @@ #include "lua.hpp" //! Push onto the stack the bootstrap font data file, table file and palette. -int Bootstrap_lua_resources(lua_State *L); +int bootstrap_lua_resources(lua_State *L); //! Provide an onscreen report of the error message on the top of the stack. -int Bootstrap_lua_error_report(lua_State *L); +int bootstrap_lua_error_report(lua_State *L); #endif // CORSIX_TH_BOOTSTRAP_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/config.h.in corsix-th-0.62/CorsixTH/Src/config.h.in --- corsix-th-0.61/CorsixTH/Src/config.h.in 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/config.h.in 2018-07-21 11:13:17.000000000 +0000 @@ -23,6 +23,8 @@ #ifndef CORSIX_TH_CONFIG_H_ #define CORSIX_TH_CONFIG_H_ +#cmakedefine CORSIX_TH_INTERPRETER_PATH "@CORSIX_TH_INTERPRETER_PATH@" + /** Windows Platform SDK usage **/ // When compiling on Windows, the platform SDK should be used. However, when // using the SDL rendering engine, the platform SDK is not used for anything @@ -51,14 +53,6 @@ // Chinese are desired. #cmakedefine CORSIX_TH_USE_FREETYPE2 -/** Environment detection **/ -#if defined(__amd64__) || defined(__IA64__) || defined(__x86_64__) || \ - defined(__x86_64) || defined(_M_IA64) || defined(_IA64) || \ - defined(_M_X64) || defined(_WIN64) || defined(__ia64__) || \ - defined(__amd64) || defined (_LP64) || defined(__ia64) -#define CORSIX_TH_64BIT -#endif - #ifdef _MSC_VER #define CORSIX_TH_USE_PACK_PRAGMAS 1 #define CORSIX_TH_PACKED_FLAGS @@ -74,6 +68,11 @@ #include #include +/** Environment detection **/ +#if UINTPTR_MAX == UINT64_MAX +#define CORSIX_TH_64BIT +#endif + // We bring in the most common stddef and stdint types to avoid typing using std::size_t; using std::uint8_t; diff -Nru corsix-th-0.61/CorsixTH/Src/cp437_table.h corsix-th-0.62/CorsixTH/Src/cp437_table.h --- corsix-th-0.61/CorsixTH/Src/cp437_table.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/cp437_table.h 2018-07-21 11:13:17.000000000 +0000 @@ -1,4 +1,4 @@ -static const uint16_t g_aCP437toUnicode[0x80] = { +static const uint16_t cp437_to_unicode_table[0x80] = { /* 0x00 through 0x7F need no translation */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, diff -Nru corsix-th-0.61/CorsixTH/Src/cp936_table.h corsix-th-0.62/CorsixTH/Src/cp936_table.h --- corsix-th-0.61/CorsixTH/Src/cp936_table.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/cp936_table.h 2018-07-21 11:13:17.000000000 +0000 @@ -4,7 +4,7 @@ // 1st byte is between 0x81 and 0xFE (subtract 0x81 for table lookup) // 2nd byte is between 0x40 and 0xFE (subtract 0x40 for table lookup) // Unspecified codes are mapped to 0x003F -static const uint16_t g_aCP936toUnicode[126][191] = { +static const uint16_t cp936_to_unicode_table[126][191] = { { 0x4E02, 0x4E04, 0x4E05, 0x4E06, 0x4E0F, 0x4E12, 0x4E17, 0x4E1F, 0x4E20, 0x4E21, 0x4E23, 0x4E26, 0x4E29, 0x4E2E, 0x4E2F, 0x4E31, diff -Nru corsix-th-0.61/CorsixTH/Src/iso_fs.cpp corsix-th-0.62/CorsixTH/Src/iso_fs.cpp --- corsix-th-0.61/CorsixTH/Src/iso_fs.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/iso_fs.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -27,58 +27,58 @@ #include #include -IsoFilesystem::IsoFilesystem() +iso_filesystem::iso_filesystem() { - m_fRawFile = nullptr; - m_sError = nullptr; - m_pFiles = nullptr; - m_iNumFiles = 0; - m_iFileTableSize = 0; - m_cPathSeparator = '\\'; + raw_file = nullptr; + error = nullptr; + files = nullptr; + file_count = 0; + file_table_size = 0; + path_seperator = '\\'; } -IsoFilesystem::~IsoFilesystem() +iso_filesystem::~iso_filesystem() { - _clear(); + clear(); } -void IsoFilesystem::_clear() +void iso_filesystem::clear() { - delete[] m_sError; - m_sError = nullptr; + delete[] error; + error = nullptr; - if(m_pFiles) + if(files) { - for(size_t i = 0; i < m_iNumFiles; ++i) - delete[] m_pFiles[i].sPath; - delete[] m_pFiles; - m_pFiles = nullptr; - m_iNumFiles = 0; - m_iFileTableSize = 0; + for(size_t i = 0; i < file_count; ++i) + delete[] files[i].path; + delete[] files; + files = nullptr; + file_count = 0; + file_table_size = 0; } } -void IsoFilesystem::setPathSeparator(char cSeparator) +void iso_filesystem::set_path_separator(char cSeparator) { - m_cPathSeparator = cSeparator; + path_seperator = cSeparator; } -enum IsoVolumeDescriptorType +enum iso_volume_descriptor_type : uint8_t { - VDT_PRIVARY_VOLUME = 0x01, + vdt_privary_volume = 0x01, // Other type numbers are either reserved for future use, or are not // interesting to us. - VDT_TERMINATOR = 0xFF, + vdt_terminator = 0xFF, }; -enum IsoDirEntFlag +enum iso_dir_ent_flag : uint8_t { - DEF_HIDDEN = 0x01, - DEF_DIRECTORY = 0x02, - DEF_MULTI_EXTENT = 0x80, + def_hidden = 0x01, + def_directory = 0x02, + def_multi_extent = 0x80, }; -template static inline T ReadNativeInt(const uint8_t *p) +template static inline T read_native_int(const uint8_t *p) { // ISO 9660 commonly encodes multi-byte integers as little endian followed // by big endian. Note that the first byte of iEndianness will be a zero on @@ -87,31 +87,31 @@ return reinterpret_cast(p)[*reinterpret_cast(&iEndianness)]; } -bool IsoFilesystem::initialise(FILE* fRawFile) +bool iso_filesystem::initialise(FILE* fRawFile) { - m_fRawFile = fRawFile; - _clear(); + raw_file = fRawFile; + clear(); // Until we know better, assume that sectors are 2048 bytes. - m_iSectorSize = 2048; + sector_size = 2048; // The first 16 sectors are reserved for bootable media. // Volume descriptor records follow this, with one record per sector. - for(uint32_t iSector = 16; _seekToSector(iSector); ++iSector) + for(uint32_t iSector = 16; seek_to_sector(iSector); ++iSector) { uint8_t aBuffer[190]; - if(!_readData(sizeof(aBuffer), aBuffer)) + if(!read_data(sizeof(aBuffer), aBuffer)) break; // CD001 is a standard identifier, \x01 is a version number if(std::memcmp(aBuffer + 1, "CD001\x01", 6) == 0) { - if(aBuffer[0] == VDT_PRIVARY_VOLUME) + if(aBuffer[0] == vdt_privary_volume) { - m_iSectorSize = ReadNativeInt(aBuffer + 128); - _findHospDirectory(aBuffer + 156, 34, 0); - if(m_iNumFiles == 0) + sector_size = read_native_int(aBuffer + 128); + find_hosp_directory(aBuffer + 156, 34, 0); + if(file_count == 0) { - _setError("Could not find Theme Hospital data directory."); + set_error("Could not find Theme Hospital data directory."); return false; } else @@ -119,22 +119,22 @@ return true; } } - else if(aBuffer[0] == VDT_TERMINATOR) + else if(aBuffer[0] == vdt_terminator) break; } } - _setError("Could not find primary volume descriptor."); + set_error("Could not find primary volume descriptor."); return false; } -int IsoFilesystem::_fileNameComp(const void* lhs, const void* rhs) +int iso_filesystem::filename_compare(const void* lhs, const void* rhs) { return std::strcmp( - reinterpret_cast(lhs)->sPath, - reinterpret_cast(rhs)->sPath); + reinterpret_cast(lhs)->path, + reinterpret_cast(rhs)->path); } -char IsoFilesystem::_normalise(char c) +char iso_filesystem::normalise(char c) { if(c == '_') // underscore to hyphen return '-'; @@ -144,7 +144,7 @@ return c; } -void IsoFilesystem::_trimIdentifierVersion(const uint8_t* sIdent, uint8_t& iLength) +void iso_filesystem::trim_identifier_version(const uint8_t* sIdent, uint8_t& iLength) { for(uint8_t i = 0; i < iLength; ++i) { @@ -156,7 +156,7 @@ } } -int IsoFilesystem::_findHospDirectory(const uint8_t *pDirEnt, int iDirEntsSize, int iLevel) +int iso_filesystem::find_hosp_directory(const uint8_t *pDirEnt, int iDirEntsSize, int iLevel) { // Sanity check // Apart from at the root level, directory record arrays must take up whole @@ -176,12 +176,12 @@ continue; } - uint32_t iDataSector = ReadNativeInt(pDirEnt + 2); - uint32_t iDataLength = ReadNativeInt(pDirEnt + 10); + uint32_t iDataSector = read_native_int(pDirEnt + 2); + uint32_t iDataLength = read_native_int(pDirEnt + 10); uint8_t iFlags = pDirEnt[25]; uint8_t iIdentLength = pDirEnt[32]; - _trimIdentifierVersion(pDirEnt + 33, iIdentLength); - if(iFlags & DEF_DIRECTORY) + trim_identifier_version(pDirEnt + 33, iIdentLength); + if(iFlags & def_directory) { // The names "\x00" and "\x01" are used for the current directory // the parent directory respectively. We only want to visit these @@ -194,13 +194,13 @@ iBufferSize = iDataLength; pBuffer = new uint8_t[iBufferSize]; } - if(_seekToSector(iDataSector) && _readData(iDataLength, pBuffer)) + if(seek_to_sector(iDataSector) && read_data(iDataLength, pBuffer)) { - int iFoundLevel = _findHospDirectory(pBuffer, iDataLength, iLevel + 1); + int iFoundLevel = find_hosp_directory(pBuffer, iDataLength, iLevel + 1); if(iFoundLevel != 0) { if(iFoundLevel == 2) - _buildFileLookupTable(iDataSector, iDataLength, ""); + build_file_lookup_table(iDataSector, iDataLength, ""); delete[] pBuffer; return iFoundLevel + 1; } @@ -217,7 +217,7 @@ int i = 0; for(; i < 10; ++i) { - if(_normalise(pDirEnt[33 + i]) != sName[i]) + if(normalise(pDirEnt[33 + i]) != sName[i]) break; } if(i == 10) @@ -232,7 +232,7 @@ return 0; } -void IsoFilesystem::_buildFileLookupTable(uint32_t iSector, int iDirEntsSize, const char* sPrefix) +void iso_filesystem::build_file_lookup_table(uint32_t iSector, int iDirEntsSize, const char* sPrefix) { // Sanity check // Apart from at the root level, directory record arrays must take up whole @@ -244,7 +244,7 @@ return; uint8_t *pBuffer = new uint8_t[iDirEntsSize]; - if(!_seekToSector(iSector) || !_readData(iDirEntsSize, pBuffer)) + if(!seek_to_sector(iSector) || !read_data(iDirEntsSize, pBuffer)) { delete[] pBuffer; return; @@ -259,11 +259,11 @@ continue; } - uint32_t iDataSector = ReadNativeInt(pDirEnt + 2); - uint32_t iDataLength = ReadNativeInt(pDirEnt + 10); + uint32_t iDataSector = read_native_int(pDirEnt + 2); + uint32_t iDataLength = read_native_int(pDirEnt + 10); uint8_t iFlags = pDirEnt[25]; uint8_t iIdentLength = pDirEnt[32]; - _trimIdentifierVersion(pDirEnt + 33, iIdentLength); + trim_identifier_version(pDirEnt + 33, iIdentLength); // Build new path char *sPath = new char[iLen + iIdentLength + 2]; @@ -271,29 +271,29 @@ #ifdef _MSC_VER #pragma warning(disable: 4996) #endif - std::transform(pDirEnt + 33, pDirEnt + 33 + iIdentLength, sPath + iLen, _normalise); + std::transform(pDirEnt + 33, pDirEnt + 33 + iIdentLength, sPath + iLen, normalise); #ifdef _MSC_VER #pragma warning(default: 4996) #endif sPath[iLen + iIdentLength] = 0; - if(iFlags & DEF_DIRECTORY) + if(iFlags & def_directory) { // None of the directories which we're interested in have length 1. // This also avoids the dummy "current" and "parent" directories. if(iIdentLength > 1) { - sPath[iLen + iIdentLength] = m_cPathSeparator; + sPath[iLen + iIdentLength] = path_seperator; sPath[iLen + iIdentLength + 1] = 0; - _buildFileLookupTable(iDataSector, iDataLength, sPath); + build_file_lookup_table(iDataSector, iDataLength, sPath); } } else { - _file_t *pFile = _allocFileRecord(); - pFile->sPath = sPath; - pFile->iSector = iDataSector; - pFile->iSize = iDataLength; + file_metadata *file = allocate_file_record(); + file->path = sPath; + file->sector = iDataSector; + file->size = iDataLength; sPath = nullptr; } delete[] sPath; @@ -304,62 +304,62 @@ { // The lookup table will be ordered by the underlying ordering of the // disk, which isn't quite the ordering we want. - qsort(m_pFiles, m_iNumFiles, sizeof(_file_t), _fileNameComp); + qsort(files, file_count, sizeof(file_metadata), filename_compare); } } -IsoFilesystem::_file_t* IsoFilesystem::_allocFileRecord() +iso_filesystem::file_metadata* iso_filesystem::allocate_file_record() { - if(m_iNumFiles == m_iFileTableSize) + if(file_count == file_table_size) { - size_t iNewTableSize = m_iFileTableSize * 2 + 1; - _file_t* pNewFiles = new _file_t[iNewTableSize]; - std::memcpy(pNewFiles, m_pFiles, sizeof(_file_t) * m_iNumFiles); - delete[] m_pFiles; - m_pFiles = pNewFiles; - m_iFileTableSize = iNewTableSize; + size_t iNewTableSize = file_table_size * 2 + 1; + file_metadata* pNewFiles = new file_metadata[iNewTableSize]; + std::memcpy(pNewFiles, files, sizeof(file_metadata) * file_count); + delete[] files; + files = pNewFiles; + file_table_size = iNewTableSize; } - return m_pFiles + m_iNumFiles++; + return files + file_count++; } -void IsoFilesystem::visitDirectoryFiles(const char* sPath, +void iso_filesystem::visit_directory_files(const char* sPath, void (*fnCallback)(void*, const char*), void* pCallbackData) const { size_t iLen = std::strlen(sPath) + 1; std::vector sNormedPath(iLen); for(size_t i = 0; i < iLen; ++i) - sNormedPath[i] = _normalise(sPath[i]); + sNormedPath[i] = normalise(sPath[i]); // Inefficient (better would be to binary search for first and last files // which begin with sPath), but who cares - this isn't called often - for(size_t i = 0; i < m_iNumFiles; ++i) + for(size_t i = 0; i < file_count; ++i) { - const char *sName = m_pFiles[i].sPath; + const char *sName = files[i].path; if(std::strlen(sName) >= iLen && std::memcmp(sNormedPath.data(), sName, iLen - 1) == 0) { sName += iLen - 1; - if(*sName == m_cPathSeparator) + if(*sName == path_seperator) ++sName; - if(std::strchr(sName, m_cPathSeparator) == nullptr) + if(std::strchr(sName, path_seperator) == nullptr) fnCallback(pCallbackData, sName); } } } -IsoFilesystem::file_handle_t IsoFilesystem::findFile(const char* sPath) const +iso_filesystem::file_handle iso_filesystem::find_file(const char* sPath) const { size_t iLen = std::strlen(sPath) + 1; std::vector sNormedPath(iLen); for(size_t i = 0; i < iLen; ++i) - sNormedPath[i] = _normalise(sPath[i]); + sNormedPath[i] = normalise(sPath[i]); // Standard binary search over sorted list of files - int iLower = 0, iUpper = static_cast(m_iNumFiles); + int iLower = 0, iUpper = static_cast(file_count); while(iLower != iUpper) { int iMid = (iLower + iUpper) / 2; - int iComp = std::strcmp(sNormedPath.data(), m_pFiles[iMid].sPath); + int iComp = std::strcmp(sNormedPath.data(), files[iMid].path); if(iComp == 0) return iMid + 1; else if(iComp < 0) @@ -370,78 +370,78 @@ return 0; } -uint32_t IsoFilesystem::getFileSize(file_handle_t iFile) const +uint32_t iso_filesystem::get_file_size(file_handle iFile) const { - if(iFile <= 0 || static_cast(iFile) > m_iNumFiles) + if(iFile <= 0 || static_cast(iFile) > file_count) return 0; else - return m_pFiles[iFile - 1].iSize; + return files[iFile - 1].size; } -bool IsoFilesystem::getFileData(file_handle_t iFile, uint8_t *pBuffer) +bool iso_filesystem::get_file_data(file_handle iFile, uint8_t *pBuffer) { - if(iFile <= 0 || static_cast(iFile) > m_iNumFiles) + if(iFile <= 0 || static_cast(iFile) > file_count) { - _setError("Invalid file handle."); + set_error("Invalid file handle."); return false; } else { - return _seekToSector(m_pFiles[iFile - 1].iSector) && - _readData(m_pFiles[iFile - 1].iSize, pBuffer); + return seek_to_sector(files[iFile - 1].sector) && + read_data(files[iFile - 1].size, pBuffer); } } -const char* IsoFilesystem::getError() const +const char* iso_filesystem::get_error() const { - return m_sError; + return error; } -bool IsoFilesystem::_seekToSector(uint32_t iSector) +bool iso_filesystem::seek_to_sector(uint32_t iSector) { - if(!m_fRawFile) + if(!raw_file) { - _setError("No raw file."); + set_error("No raw file."); return false; } - if(std::fseek(m_fRawFile, m_iSectorSize * static_cast(iSector), SEEK_SET) == 0) + if(std::fseek(raw_file, sector_size * static_cast(iSector), SEEK_SET) == 0) return true; else { - _setError("Unable to seek to sector %i.", static_cast(iSector)); + set_error("Unable to seek to sector %i.", static_cast(iSector)); return false; } } -bool IsoFilesystem::_readData(uint32_t iByteCount, uint8_t *pBuffer) +bool iso_filesystem::read_data(uint32_t iByteCount, uint8_t *pBuffer) { - if(!m_fRawFile) + if(!raw_file) { - _setError("No raw file."); + set_error("No raw file."); return false; } - if(std::fread(pBuffer, 1, iByteCount, m_fRawFile) == iByteCount) + if(std::fread(pBuffer, 1, iByteCount, raw_file) == iByteCount) return true; else { - _setError("Unable to read %i bytes.", static_cast(iByteCount)); + set_error("Unable to read %i bytes.", static_cast(iByteCount)); return false; } } -void IsoFilesystem::_setError(const char* sFormat, ...) +void iso_filesystem::set_error(const char* sFormat, ...) { - if(m_sError == nullptr) + if(error == nullptr) { // None of the errors which we generate will be longer than 1024. - m_sError = new char[1024]; + error = new char[1024]; } va_list a; va_start(a, sFormat); #ifdef _MSC_VER #pragma warning(disable: 4996) #endif - std::vsprintf(m_sError, sFormat, a); + std::vsprintf(error, sFormat, a); #ifdef _MSC_VER #pragma warning(default: 4996) #endif @@ -450,21 +450,21 @@ static int l_isofs_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_isofs_set_path_separator(lua_State *L) { - IsoFilesystem *pSelf = luaT_testuserdata(L); - pSelf->setPathSeparator(luaL_checkstring(L, 2)[0]); + iso_filesystem *pSelf = luaT_testuserdata(L); + pSelf->set_path_separator(luaL_checkstring(L, 2)[0]); lua_settop(L, 1); return 1; } static int l_isofs_set_root(lua_State *L) { - IsoFilesystem *pSelf = luaT_testuserdata(L); + iso_filesystem *pSelf = luaT_testuserdata(L); FILE *fIso = *luaT_testuserdata(L, 2); if(pSelf->initialise(fIso)) { @@ -476,30 +476,30 @@ else { lua_pushnil(L); - lua_pushstring(L, pSelf->getError()); + lua_pushstring(L, pSelf->get_error()); return 2; } } static int l_isofs_read_contents(lua_State *L) { - IsoFilesystem *pSelf = luaT_testuserdata(L); + iso_filesystem *pSelf = luaT_testuserdata(L); const char* sFilename = luaL_checkstring(L, 2); - IsoFilesystem::file_handle_t iFile = pSelf->findFile(sFilename); - if(!IsoFilesystem::isHandleGood(iFile)) + iso_filesystem::file_handle iFile = pSelf->find_file(sFilename); + if(!iso_filesystem::isHandleGood(iFile)) { lua_pushnil(L); lua_pushfstring(L, "Could not find \'%s\' in .iso image", sFilename); return 2; } - void* pBuffer = lua_newuserdata(L, pSelf->getFileSize(iFile)); - if(!pSelf->getFileData(iFile, reinterpret_cast(pBuffer))) + void* pBuffer = lua_newuserdata(L, pSelf->get_file_size(iFile)); + if(!pSelf->get_file_data(iFile, reinterpret_cast(pBuffer))) { lua_pushnil(L); - lua_pushstring(L, pSelf->getError()); + lua_pushstring(L, pSelf->get_error()); return 2; } - lua_pushlstring(L, reinterpret_cast(pBuffer), pSelf->getFileSize(iFile)); + lua_pushlstring(L, reinterpret_cast(pBuffer), pSelf->get_file_size(iFile)); return 1; } @@ -513,11 +513,11 @@ static int l_isofs_list_files(lua_State *L) { - IsoFilesystem *pSelf = luaT_testuserdata(L); + iso_filesystem *pSelf = luaT_testuserdata(L); const char* sPath = luaL_checkstring(L, 2); lua_settop(L, 2); lua_newtable(L); - pSelf->visitDirectoryFiles(sPath, l_isofs_list_files_callback, L); + pSelf->visit_directory_files(sPath, l_isofs_list_files_callback, L); return 1; } @@ -535,7 +535,7 @@ lua_pushvalue(L, -1); lua_replace(L, luaT_environindex); - luaT_pushcclosure(L, luaT_stdgc, 0); + luaT_pushcclosure(L, luaT_stdgc, 0); lua_setfield(L, -2, "__gc"); // Methods table diff -Nru corsix-th-0.61/CorsixTH/Src/iso_fs.h corsix-th-0.62/CorsixTH/Src/iso_fs.h --- corsix-th-0.61/CorsixTH/Src/iso_fs.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/iso_fs.h 2018-07-21 11:13:17.000000000 +0000 @@ -33,14 +33,14 @@ searches for the Theme Hospital data files, and can then be used to read these data files. */ -class IsoFilesystem +class iso_filesystem { public: - IsoFilesystem(); - ~IsoFilesystem(); + iso_filesystem(); + ~iso_filesystem(); //! Set the character to be used between components in file paths - void setPathSeparator(char cSeparator); + void set_path_separator(char cSeparator); //! Load an .iso disk image and search for Theme Hospital data files /*! @@ -55,16 +55,16 @@ /*! Can be called after initialise() or getFileData() return false. */ - const char* getError() const; + const char* get_error() const; - typedef int file_handle_t; + using file_handle = int; //! Find a file in the loaded .iso disk image /*! If (and only if) the given file could not be found, then isHandleGood() will return false on the returned handle. */ - file_handle_t findFile(const char* sPath) const; + file_handle find_file(const char* sPath) const; //! Iterate all files of the .iso disk image within a given directory /*! @@ -74,18 +74,18 @@ of a file which is in sPath. \param pCallbackData Opaque value to be called to fnCallback. */ - void visitDirectoryFiles(const char* sPath, + void visit_directory_files(const char* sPath, void (*fnCallback)(void*, const char*), void* pCallbackData) const; //! Test if a file handle from findFile() is good or is invalid - static inline bool isHandleGood(file_handle_t x) {return x != 0;} + static inline bool isHandleGood(file_handle x) {return x != 0;} //! Get the size (in bytes) of a file in the loaded .iso disk image /*! \param iFile A file handle returned by findFile() */ - uint32_t getFileSize(file_handle_t iFile) const; + uint32_t get_file_size(file_handle iFile) const; //! Get the contents of a file in the loaded .iso disk image /*! @@ -93,35 +93,35 @@ \param pBuffer The buffer to place the resulting data in \return true on success, false on failure - call getError() for reason */ - bool getFileData(file_handle_t iFile, uint8_t *pBuffer); + bool get_file_data(file_handle iFile, uint8_t *pBuffer); private: - struct _file_t + struct file_metadata { - char *sPath; - uint32_t iSector; - uint32_t iSize; + char *path; + uint32_t sector; + uint32_t size; }; - FILE* m_fRawFile; - char* m_sError; - _file_t* m_pFiles; - size_t m_iNumFiles; - size_t m_iFileTableSize; - long m_iSectorSize; - char m_cPathSeparator; + FILE* raw_file; + char* error; + file_metadata* files; + size_t file_count; + size_t file_table_size; + long sector_size; + char path_seperator; //! Free any memory in use - void _clear(); + void clear(); //! Set the last error, printf-style - void _setError(const char* sFormat, ...); + void set_error(const char* sFormat, ...); //! Seek to a logical sector of the disk image - bool _seekToSector(uint32_t iSector); + bool seek_to_sector(uint32_t iSector); //! Read data from the disk image - bool _readData(uint32_t iByteCount, uint8_t *pBuffer); + bool read_data(uint32_t iByteCount, uint8_t *pBuffer); //! Scan the given array of directory entries for a Theme Hospital file /*! @@ -133,7 +133,7 @@ contains a Theme Hospital data file. 2 if the given array is the top-level Theme Hospital data directory. Other values otherwise. */ - int _findHospDirectory(const uint8_t *pDirEnt, int iDirEntsSize, int iLevel); + int find_hosp_directory(const uint8_t *pDirEnt, int iDirEntsSize, int iLevel); //! Build the list of Theme Hospital data files /*! @@ -142,14 +142,14 @@ \param iDirEntsSize The number of bytes in the directory entry array. \param sPrefix The path name to prepend to filenames in the directory. */ - void _buildFileLookupTable(uint32_t iSector, int iDirEntsSize, const char* sPrefix); + void build_file_lookup_table(uint32_t iSector, int iDirEntsSize, const char* sPrefix); - //! Return the next free entry in m_pFiles - _file_t* _allocFileRecord(); + //! Return the next free entry in files + file_metadata* allocate_file_record(); - static char _normalise(char c); - static int _fileNameComp(const void* lhs, const void* rhs); - static void _trimIdentifierVersion(const uint8_t* sIdent, uint8_t& iLength); + static char normalise(char c); + static int filename_compare(const void* lhs, const void* rhs); + static void trim_identifier_version(const uint8_t* sIdent, uint8_t& iLength); }; int luaopen_iso_fs(lua_State *L); diff -Nru corsix-th-0.61/CorsixTH/Src/jit_opt.h corsix-th-0.62/CorsixTH/Src/jit_opt.h --- corsix-th-0.61/CorsixTH/Src/jit_opt.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/jit_opt.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,1242 +0,0 @@ -/* -** Copyright (C) 2005-2008 Mike Pall. All rights reserved. -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -*/ - -/* -** LuaJIT's opt.lua compiled to Lua bytecode -*/ -static const uint8_t jit_opt_lua[] = { - 0x1B, 'L' , 'u' , 'a' , 0x51, 0x00, 0x01, 0x04, 0x04, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x21, 0xC3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41, 0x40, 0x00, - 0x00, 0x8A, 0x40, 0x01, 0x00, 0x89, 0xC0, 0x40, 0x81, 0x89, 0x40, 0x41, 0x82, - 0x89, 0xC0, 0x41, 0x83, 0x89, 0x40, 0x42, 0x84, 0x89, 0xC0, 0x42, 0x85, 0xC5, - 0x00, 0x03, 0x00, 0x01, 0x41, 0x03, 0x00, 0xDC, 0x80, 0x00, 0x01, 0x05, 0x81, - 0x03, 0x00, 0x46, 0xC1, 0xC3, 0x01, 0x57, 0x00, 0xC4, 0x02, 0x16, 0x00, 0x00, - 0x80, 0x42, 0x41, 0x00, 0x00, 0x42, 0x01, 0x80, 0x00, 0x81, 0x41, 0x04, 0x00, - 0x1C, 0x41, 0x80, 0x01, 0x05, 0x01, 0x03, 0x00, 0x41, 0x81, 0x04, 0x00, 0x1C, - 0x81, 0x00, 0x01, 0x45, 0xC1, 0x04, 0x00, 0x85, 0x01, 0x05, 0x00, 0xC5, 0x41, - 0x05, 0x00, 0x05, 0x82, 0x05, 0x00, 0x46, 0xC2, 0x45, 0x02, 0x86, 0x02, 0x46, - 0x02, 0xC6, 0x42, 0x46, 0x02, 0x06, 0x83, 0x46, 0x02, 0x45, 0xC3, 0x06, 0x00, - 0x86, 0x03, 0xC7, 0x01, 0xC2, 0x03, 0x80, 0x00, 0x02, 0x04, 0x80, 0x00, 0x9C, - 0x43, 0x80, 0x01, 0x81, 0x43, 0x07, 0x00, 0xE4, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x04, 0x00, 0x00, 0x00, 0x02, 0x24, 0x44, 0x00, 0x00, 0x64, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x05, 0xA4, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, - 0x00, 0x00, 0x80, 0x05, 0xE4, 0x04, 0x01, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, - 0x00, 0x80, 0x05, 0x24, 0x45, 0x01, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, 0x80, 0x03, 0x64, 0x85, 0x01, - 0x00, 0x00, 0x00, 0x80, 0x04, 0xA4, 0xC5, 0x01, 0x00, 0x00, 0x00, 0x80, 0x02, - 0x00, 0x00, 0x80, 0x05, 0xE4, 0x05, 0x02, 0x00, 0x00, 0x00, 0x80, 0x0A, 0x00, - 0x00, 0x80, 0x05, 0x0A, 0x86, 0x06, 0x00, 0x64, 0x46, 0x02, 0x00, 0x09, 0x46, - 0x06, 0x8F, 0x64, 0x86, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x46, 0x86, - 0x8F, 0x64, 0xC6, 0x02, 0x00, 0x09, 0x46, 0x06, 0x90, 0x64, 0x06, 0x03, 0x00, - 0x09, 0x46, 0x86, 0x90, 0x64, 0x46, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x09, - 0x46, 0x06, 0x91, 0x64, 0x86, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, - 0x00, 0x05, 0x09, 0x46, 0x86, 0x91, 0x64, 0xC6, 0x03, 0x00, 0x00, 0x00, 0x80, - 0x09, 0x00, 0x00, 0x00, 0x0A, 0x09, 0x46, 0x06, 0x92, 0x09, 0x06, 0x84, 0x92, - 0x09, 0x06, 0x04, 0x93, 0x64, 0x06, 0x04, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, - 0x00, 0x80, 0x02, 0x09, 0x46, 0x86, 0x93, 0x64, 0x46, 0x04, 0x00, 0x09, 0x46, - 0x06, 0x94, 0x64, 0x86, 0x04, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, - 0x0A, 0x09, 0x46, 0x86, 0x94, 0x09, 0x86, 0x05, 0x95, 0x09, 0x86, 0x85, 0x95, - 0x09, 0x86, 0x05, 0x96, 0x09, 0x86, 0x85, 0x96, 0x09, 0x86, 0x05, 0x97, 0x09, - 0x86, 0x85, 0x97, 0x09, 0x86, 0x05, 0x98, 0x09, 0x86, 0x85, 0x98, 0x64, 0xC6, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x09, 0x46, 0x06, 0x99, 0x64, 0x06, 0x05, - 0x00, 0x09, 0x46, 0x86, 0x99, 0x64, 0x46, 0x05, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x09, 0x46, 0x06, 0x9A, 0x64, 0x86, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, - 0x00, 0x80, 0x05, 0x09, 0x46, 0x86, 0x9A, 0x64, 0xC6, 0x05, 0x00, 0x00, 0x00, - 0x80, 0x05, 0x09, 0x46, 0x06, 0x9B, 0x64, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x09, 0x46, 0x86, 0x9B, 0x64, 0x46, 0x06, 0x00, 0x00, 0x00, 0x80, 0x0B, - 0x09, 0x46, 0x06, 0x9C, 0x09, 0xC6, 0x85, 0x9C, 0x64, 0x86, 0x06, 0x00, 0x00, - 0x00, 0x80, 0x08, 0x09, 0x46, 0x06, 0x9D, 0x64, 0xC6, 0x06, 0x00, 0x00, 0x00, - 0x80, 0x08, 0x09, 0x46, 0x86, 0x9D, 0x64, 0x06, 0x07, 0x00, 0x00, 0x00, 0x80, - 0x0A, 0x00, 0x00, 0x80, 0x05, 0x09, 0x46, 0x06, 0x9E, 0x09, 0x06, 0x84, 0x9E, - 0x64, 0x46, 0x07, 0x00, 0x00, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x80, 0x02, 0x00, - 0x00, 0x80, 0x05, 0x09, 0x46, 0x06, 0x9F, 0x64, 0x86, 0x07, 0x00, 0x00, 0x00, - 0x80, 0x05, 0x09, 0x46, 0x86, 0x9F, 0x64, 0xC6, 0x07, 0x00, 0x00, 0x00, 0x80, - 0x02, 0x09, 0x46, 0x06, 0xA0, 0x09, 0x06, 0x84, 0xA0, 0x64, 0x06, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x04, 0x09, - 0x46, 0x06, 0xA1, 0x64, 0x46, 0x08, 0x00, 0x09, 0x46, 0x86, 0xA1, 0x64, 0x86, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, - 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x04, - 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x05, 0x00, 0x00, 0x00, 0x06, 0x83, - 0x06, 0x80, 0x0D, 0x24, 0xC7, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x64, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, 0x04, - 0xA4, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x0E, 0x00, 0x00, 0x80, 0x0D, 0xC5, 0x07, 0x11, - 0x00, 0x25, 0x08, 0x00, 0x00, 0xDC, 0x47, 0x00, 0x00, 0xE4, 0x87, 0x09, 0x00, - 0x00, 0x00, 0x80, 0x08, 0xC7, 0x47, 0x11, 0x00, 0xE4, 0xC7, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x07, 0xC7, 0x87, 0x11, 0x00, 0x87, 0xC7, 0x11, 0x00, 0x87, 0x07, - 0x12, 0x00, 0x1E, 0x00, 0x80, 0x00, 0x49, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6F, - 0x64, 0x65, 0x73, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xAF, 0x40, - 0x04, 0x0B, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x73, 0x6C, 0x6F, - 0x74, 0x73, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x62, 0x40, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x04, 0x07, 0x00, 0x00, 0x00, 0x63, - 0x6F, 0x6E, 0x73, 0x74, 0x73, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x69, 0x40, 0x04, 0x05, 0x00, 0x00, 0x00, 0x73, 0x75, 0x62, 0x73, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x40, 0x04, 0x08, 0x00, 0x00, 0x00, - 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x6A, 0x69, 0x74, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x65, - 0x72, 0x74, 0x00, 0x04, 0x0C, 0x00, 0x00, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6F, 0x6E, 0x5F, 0x6E, 0x75, 0x6D, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xBC, 0xC3, 0x40, 0x04, 0x25, 0x00, 0x00, 0x00, 0x4C, 0x75, 0x61, 0x4A, 0x49, - 0x54, 0x20, 0x63, 0x6F, 0x72, 0x65, 0x2F, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, - 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x6D, 0x69, 0x73, - 0x6D, 0x61, 0x74, 0x63, 0x68, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x6A, 0x69, - 0x74, 0x2E, 0x75, 0x74, 0x69, 0x6C, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x74, - 0x79, 0x70, 0x65, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x67, - 0x65, 0x74, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x00, - 0x04, 0x06, 0x00, 0x00, 0x00, 0x70, 0x63, 0x61, 0x6C, 0x6C, 0x00, 0x04, 0x09, - 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x04, - 0x06, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x00, 0x04, 0x06, 0x00, - 0x00, 0x00, 0x68, 0x69, 0x6E, 0x74, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, - 0x66, 0x68, 0x69, 0x6E, 0x74, 0x73, 0x00, 0x04, 0x0D, 0x00, 0x00, 0x00, 0x67, - 0x65, 0x74, 0x6D, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x00, 0x6F, 0x66, 0x66, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xBF, 0x04, 0x05, 0x00, 0x00, 0x00, 0x4D, 0x4F, 0x56, 0x45, - 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x4B, 0x00, 0x04, - 0x09, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x42, 0x4F, 0x4F, 0x4C, 0x00, - 0x04, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x4E, 0x49, 0x4C, 0x00, - 0x04, 0x09, 0x00, 0x00, 0x00, 0x47, 0x45, 0x54, 0x55, 0x50, 0x56, 0x41, 0x4C, - 0x00, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x47, 0x45, 0x54, 0x47, 0x4C, 0x4F, 0x42, - 0x41, 0x4C, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x47, 0x45, 0x54, 0x54, 0x41, - 0x42, 0x4C, 0x45, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x53, 0x45, 0x54, 0x47, - 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x53, 0x45, - 0x54, 0x55, 0x50, 0x56, 0x41, 0x4C, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x53, - 0x45, 0x54, 0x54, 0x41, 0x42, 0x4C, 0x45, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, - 0x4E, 0x45, 0x57, 0x54, 0x41, 0x42, 0x4C, 0x45, 0x00, 0x04, 0x05, 0x00, 0x00, - 0x00, 0x53, 0x45, 0x4C, 0x46, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x41, 0x44, - 0x44, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x53, 0x55, 0x42, 0x00, 0x04, 0x04, - 0x00, 0x00, 0x00, 0x4D, 0x55, 0x4C, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x44, - 0x49, 0x56, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x4D, 0x4F, 0x44, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x00, 0x50, 0x4F, 0x57, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, - 0x4C, 0x54, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x4C, 0x45, 0x00, 0x04, 0x04, - 0x00, 0x00, 0x00, 0x55, 0x4E, 0x4D, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x4E, - 0x4F, 0x54, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x45, 0x4E, 0x00, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x43, 0x4F, 0x4E, 0x43, 0x41, 0x54, 0x00, 0x04, 0x04, - 0x00, 0x00, 0x00, 0x4A, 0x4D, 0x50, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x45, - 0x51, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x45, 0x53, 0x54, 0x00, 0x04, - 0x08, 0x00, 0x00, 0x00, 0x54, 0x45, 0x53, 0x54, 0x53, 0x45, 0x54, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x43, 0x41, 0x4C, 0x4C, 0x00, 0x04, 0x09, 0x00, 0x00, - 0x00, 0x54, 0x41, 0x49, 0x4C, 0x43, 0x41, 0x4C, 0x4C, 0x00, 0x04, 0x07, 0x00, - 0x00, 0x00, 0x52, 0x45, 0x54, 0x55, 0x52, 0x4E, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x46, 0x4F, 0x52, 0x4C, 0x4F, 0x4F, 0x50, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x46, 0x4F, 0x52, 0x50, 0x52, 0x45, 0x50, 0x00, 0x04, 0x09, 0x00, 0x00, - 0x00, 0x54, 0x46, 0x4F, 0x52, 0x4C, 0x4F, 0x4F, 0x50, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x53, 0x45, 0x54, 0x4C, 0x49, 0x53, 0x54, 0x00, 0x04, 0x06, 0x00, - 0x00, 0x00, 0x43, 0x4C, 0x4F, 0x53, 0x45, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, - 0x43, 0x4C, 0x4F, 0x53, 0x55, 0x52, 0x45, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, - 0x56, 0x41, 0x52, 0x41, 0x52, 0x47, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x6D, - 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x61, 0x74, - 0x74, 0x61, 0x63, 0x68, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x68, 0x69, 0x6E, 0x74, - 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x6C, 0x65, 0x76, 0x65, - 0x6C, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x6C, 0x65, 0x76, - 0x65, 0x6C, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0D, 0x44, 0x00, 0x00, 0x00, 0x4A, - 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x01, 0x41, - 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x02, 0x5C, 0x81, 0x81, 0x01, 0x49, 0x80, 0x40, 0x02, 0x0C, 0x41, 0x40, 0x02, - 0x17, 0xC0, 0xC0, 0x02, 0x16, 0xC0, 0x00, 0x80, 0x0C, 0xC1, 0x01, 0x02, 0x92, - 0x02, 0x00, 0x02, 0x49, 0x80, 0x40, 0x05, 0x16, 0x40, 0x0A, 0x80, 0x17, 0x00, - 0xC1, 0x02, 0x16, 0x00, 0x01, 0x80, 0x92, 0x02, 0x00, 0x02, 0xCD, 0xC2, 0x01, - 0x05, 0x49, 0x80, 0xC0, 0x05, 0x49, 0x80, 0x40, 0x05, 0x16, 0x80, 0x08, 0x80, - 0x17, 0x40, 0xC1, 0x02, 0x16, 0x40, 0x00, 0x80, 0x16, 0x80, 0x08, 0x80, 0x16, - 0x80, 0x07, 0x80, 0x5A, 0x02, 0x00, 0x00, 0x16, 0x80, 0x01, 0x80, 0x8C, 0x42, - 0x40, 0x02, 0xC6, 0x82, 0x82, 0x00, 0xDA, 0x42, 0x00, 0x00, 0x16, 0x00, 0x06, - 0x80, 0xCC, 0x40, 0xC0, 0x01, 0x89, 0x80, 0x82, 0x01, 0x16, 0x40, 0x05, 0x80, - 0x17, 0x80, 0xC1, 0x02, 0x16, 0x80, 0x01, 0x80, 0x84, 0x02, 0x80, 0x00, 0x86, - 0xC2, 0x41, 0x05, 0xC0, 0x02, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x9C, 0x82, - 0x80, 0x01, 0x0C, 0x81, 0x02, 0x02, 0x16, 0x00, 0x03, 0x80, 0x17, 0x00, 0xC2, - 0x02, 0x16, 0x40, 0x01, 0x80, 0x57, 0x00, 0x40, 0x04, 0x16, 0xC0, 0x00, 0x80, - 0x0C, 0x41, 0x40, 0x02, 0x92, 0x02, 0x00, 0x02, 0x49, 0x80, 0x40, 0x05, 0x16, - 0x00, 0x01, 0x80, 0x17, 0x40, 0xC2, 0x02, 0x16, 0x80, 0x00, 0x80, 0x17, 0x00, - 0x40, 0x04, 0x16, 0x00, 0x00, 0x80, 0x0C, 0x41, 0x40, 0x02, 0x86, 0x02, 0x81, - 0x00, 0x9A, 0x02, 0x00, 0x00, 0x16, 0x80, 0xF1, 0x7F, 0x17, 0x00, 0xC0, 0x01, - 0x16, 0x00, 0x00, 0x80, 0x5E, 0x00, 0x00, 0x01, 0x06, 0xC1, 0x00, 0x01, 0xCD, - 0x40, 0xC0, 0x01, 0x16, 0x00, 0xF0, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x0A, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x01, 0x01, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x4A, 0x4D, 0x50, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x46, 0x4F, 0x52, - 0x4C, 0x4F, 0x4F, 0x50, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x52, 0x45, 0x54, - 0x55, 0x52, 0x4E, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x43, 0x4C, 0x4F, 0x53, - 0x55, 0x52, 0x45, 0x00, 0x04, 0x0B, 0x00, 0x00, 0x00, 0x63, 0x6C, 0x6F, 0x73, - 0x75, 0x72, 0x65, 0x6E, 0x75, 0x70, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x4C, - 0x4F, 0x41, 0x44, 0x42, 0x4F, 0x4F, 0x4C, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, - 0x53, 0x45, 0x54, 0x4C, 0x49, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x01, 0x06, 0x00, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, - 0x00, 0x86, 0x01, 0x40, 0x03, 0x8C, 0x81, 0x01, 0x01, 0xC6, 0xC1, 0x80, 0x00, - 0x09, 0xC0, 0x01, 0x03, 0x80, 0x01, 0x80, 0x01, 0xCC, 0x41, 0x81, 0x01, 0xCD, - 0x41, 0xC0, 0x03, 0x01, 0x42, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x80, 0x49, 0x80, - 0xC0, 0x04, 0x9F, 0x41, 0xFF, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, 0x50, 0x45, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, - 0x05, 0x0E, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xDC, 0x80, 0x00, 0x01, 0x57, 0x00, 0xC0, 0x01, 0x16, 0xC0, 0x00, 0x80, 0x57, - 0x40, 0xC0, 0x01, 0x16, 0x40, 0x00, 0x80, 0x17, 0x80, 0xC0, 0x01, 0x16, 0xC0, - 0x00, 0x80, 0x04, 0x01, 0x80, 0x00, 0x06, 0xC1, 0x40, 0x02, 0x0C, 0x01, 0x81, - 0x00, 0x09, 0x80, 0x00, 0x02, 0x1E, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x07, 0x00, 0x00, 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x04, 0x06, - 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x05, 0x00, 0x00, - 0x00, 0x54, 0x59, 0x50, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x79, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x09, 0x1A, - 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x5C, 0x81, - 0x00, 0x01, 0x57, 0x00, 0xC0, 0x02, 0x16, 0x40, 0x00, 0x80, 0x17, 0x40, 0xC0, - 0x02, 0x16, 0xC0, 0x00, 0x80, 0x84, 0x01, 0x80, 0x00, 0x86, 0x81, 0x40, 0x03, - 0x8C, 0x81, 0x01, 0x01, 0x09, 0xC0, 0x00, 0x03, 0x19, 0x00, 0x81, 0x81, 0x16, - 0xC0, 0x02, 0x80, 0x86, 0x01, 0x81, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x03, 0xDC, 0x81, 0x00, 0x01, 0x57, 0x00, 0xC1, 0x03, 0x16, 0x40, 0x00, - 0x80, 0x17, 0x40, 0xC1, 0x03, 0x16, 0xC0, 0x00, 0x80, 0x04, 0x02, 0x80, 0x00, - 0x06, 0x82, 0x41, 0x04, 0x0C, 0x02, 0x02, 0x01, 0x09, 0x80, 0x01, 0x04, 0x1E, - 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x74, - 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, - 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, - 0x50, 0x45, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x04, 0x07, - 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x54, 0x59, 0x50, 0x45, 0x4B, 0x45, 0x59, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x08, 0x37, 0x00, 0x00, 0x00, 0x17, 0x00, 0x40, 0x01, 0x16, 0x40, - 0x00, 0x80, 0xC3, 0x00, 0x80, 0x01, 0xDE, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0xDC, 0x80, 0x00, 0x01, 0x17, 0x40, 0xC0, 0x01, - 0x16, 0x80, 0x01, 0x80, 0xC4, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x40, - 0x01, 0x00, 0x01, 0xDC, 0x80, 0x80, 0x01, 0x57, 0x00, 0xC0, 0x01, 0x16, 0x00, - 0x00, 0x80, 0xDE, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x01, 0x00, 0x01, 0x80, - 0x00, 0xDC, 0x80, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x40, 0x01, 0x80, 0x01, - 0x1C, 0x81, 0x00, 0x01, 0x17, 0x40, 0x40, 0x02, 0x16, 0xC0, 0x03, 0x80, 0x04, - 0x01, 0x80, 0x00, 0x40, 0x01, 0x80, 0x01, 0x81, 0x81, 0x00, 0x00, 0x1C, 0x81, - 0x80, 0x01, 0x44, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x02, 0x5C, 0x81, 0x00, - 0x01, 0x17, 0x40, 0xC0, 0x02, 0x16, 0x80, 0x01, 0x80, 0x44, 0x01, 0x80, 0x00, - 0x80, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x00, 0x01, 0x5C, 0x81, 0x80, 0x01, 0x57, - 0x00, 0xC0, 0x02, 0x16, 0x00, 0x00, 0x80, 0x5E, 0x01, 0x00, 0x01, 0x06, 0xC1, - 0x40, 0x00, 0x06, 0x41, 0x00, 0x02, 0x17, 0x00, 0x40, 0x02, 0x16, 0x00, 0x02, - 0x80, 0x44, 0x01, 0x00, 0x00, 0x80, 0x01, 0x80, 0x00, 0x5C, 0x81, 0x00, 0x01, - 0x17, 0x40, 0xC0, 0x02, 0x16, 0xC0, 0x00, 0x80, 0x44, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x00, 0x5C, 0x81, 0x00, 0x01, 0x00, 0x01, 0x80, 0x02, 0x1E, 0x01, - 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, - 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x5F, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x00, 0x04, 0x09, 0x00, 0x00, - 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x76, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x09, 0x17, 0x00, 0x00, 0x00, 0x06, 0x01, 0x40, 0x00, 0x52, 0x01, - 0x00, 0x01, 0x06, 0x41, 0x01, 0x02, 0x17, 0x40, 0x40, 0x02, 0x16, 0x00, 0x04, - 0x80, 0x04, 0x01, 0x00, 0x00, 0x46, 0x81, 0x40, 0x00, 0x8D, 0xC1, 0x40, 0x01, - 0x1C, 0x01, 0x81, 0x01, 0x17, 0xC0, 0x80, 0x02, 0x16, 0x80, 0x02, 0x80, 0x57, - 0x00, 0x41, 0x02, 0x16, 0x40, 0x01, 0x80, 0x57, 0x40, 0x41, 0x02, 0x16, 0xC0, - 0x00, 0x80, 0x17, 0x80, 0x41, 0x02, 0x16, 0x00, 0x01, 0x80, 0x17, 0xC0, 0x00, - 0x03, 0x16, 0x80, 0x00, 0x80, 0xC2, 0x01, 0x80, 0x00, 0x06, 0xC2, 0x80, 0x00, - 0xDE, 0x01, 0x80, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0x3F, 0x04, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x4B, - 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x42, 0x4F, 0x4F, - 0x4C, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x4F, 0x41, 0x44, 0x4E, 0x49, - 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, - 0xB7, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, 0x0C, 0x2F, 0x00, 0x00, 0x00, 0xC6, - 0x01, 0x81, 0x00, 0x06, 0x42, 0x81, 0x00, 0x17, 0x00, 0xC0, 0x03, 0x16, 0x40, - 0x00, 0x80, 0xC0, 0x01, 0x00, 0x04, 0x16, 0x80, 0x00, 0x80, 0x17, 0x00, 0x40, - 0x04, 0x16, 0x00, 0x00, 0x80, 0x00, 0x02, 0x80, 0x03, 0x44, 0x02, 0x00, 0x00, - 0x80, 0x02, 0x80, 0x03, 0x5C, 0x82, 0x00, 0x01, 0x84, 0x02, 0x00, 0x00, 0xC0, - 0x02, 0x00, 0x04, 0x9C, 0x82, 0x00, 0x01, 0x17, 0x80, 0x82, 0x04, 0x16, 0xC0, - 0x04, 0x80, 0x17, 0x40, 0xC0, 0x04, 0x16, 0x80, 0x02, 0x80, 0x57, 0x80, 0x40, - 0x03, 0x16, 0x40, 0x01, 0x80, 0xD0, 0xC2, 0xC0, 0x03, 0x17, 0x00, 0xC1, 0x05, - 0x16, 0x80, 0x00, 0x80, 0xD0, 0xC2, 0x40, 0x04, 0x57, 0x00, 0xC1, 0x05, 0x16, - 0x40, 0x00, 0x80, 0xC1, 0x41, 0x01, 0x00, 0x16, 0x00, 0x00, 0x80, 0xC1, 0xC1, - 0x00, 0x00, 0x57, 0x00, 0xC0, 0x03, 0x16, 0x00, 0x02, 0x80, 0xC4, 0x02, 0x80, - 0x00, 0xC6, 0x82, 0xC1, 0x05, 0xCC, 0xC2, 0x02, 0x01, 0x09, 0xC0, 0x81, 0x05, - 0x16, 0xC0, 0x00, 0x80, 0xC4, 0x02, 0x80, 0x00, 0xC6, 0x82, 0xC1, 0x05, 0xCC, - 0xC2, 0x02, 0x01, 0x09, 0xC0, 0xC1, 0x05, 0x57, 0x00, 0x42, 0x03, 0x16, 0x80, - 0x00, 0x80, 0x57, 0x40, 0x42, 0x03, 0x16, 0x00, 0x00, 0x80, 0x49, 0xC0, 0x81, - 0x01, 0x1E, 0x00, 0x80, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, - 0x00, 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x44, 0x49, 0x56, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE0, 0x3F, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, - 0x50, 0x45, 0x00, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, - 0x0B, 0x16, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x80, 0x00, 0x40, 0x02, 0x00, 0x01, 0x80, 0x02, 0x00, 0x02, 0x9C, - 0xC1, 0x80, 0x02, 0xDA, 0x01, 0x00, 0x00, 0x16, 0x80, 0x02, 0x80, 0x17, 0x00, - 0x81, 0x01, 0x16, 0x00, 0x02, 0x80, 0x04, 0x02, 0x80, 0x00, 0x06, 0x02, 0x40, - 0x04, 0x0C, 0x02, 0x02, 0x01, 0x09, 0x40, 0x40, 0x04, 0x17, 0x80, 0xC0, 0x02, - 0x16, 0x80, 0x00, 0x80, 0x06, 0xC2, 0x40, 0x00, 0x4C, 0x02, 0x41, 0x01, 0x09, - 0x42, 0xC1, 0x04, 0x06, 0x02, 0x81, 0x00, 0x49, 0x00, 0x82, 0x01, 0x1E, 0x00, - 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x43, 0x4F, - 0x4D, 0x42, 0x49, 0x4E, 0x45, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x76, 0x65, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x86, 0x01, 0x81, 0x00, 0x49, - 0x80, 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, - 0x01, 0x06, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC6, - 0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x02, 0x9C, 0x81, 0x80, 0x01, 0x49, 0x80, - 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xCE, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, - 0x06, 0x00, 0x00, 0x00, 0x57, 0x00, 0x40, 0x02, 0x16, 0x00, 0x00, 0x80, 0x82, - 0x41, 0x00, 0x00, 0x82, 0x01, 0x80, 0x00, 0x49, 0x80, 0x81, 0x01, 0x1E, 0x00, - 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, - 0xD4, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x80, - 0x01, 0x80, 0x01, 0xC0, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0xA0, 0x01, - 0x00, 0x80, 0x49, 0x40, 0xC0, 0x04, 0x9F, 0x41, 0xFF, 0x7F, 0x1E, 0x00, 0x80, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, - 0xD8, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x84, - 0x01, 0x00, 0x00, 0x86, 0x01, 0x40, 0x03, 0xC6, 0x41, 0x40, 0x00, 0x00, 0x02, - 0x00, 0x02, 0x9C, 0x81, 0x80, 0x01, 0x49, 0x80, 0x81, 0x01, 0x1E, 0x00, 0x80, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x75, 0x70, 0x76, - 0x61, 0x6C, 0x75, 0x65, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x75, 0x6E, - 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, - 0xDC, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x0C, 0x0B, 0x00, 0x00, 0x00, 0x84, - 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x06, 0x02, 0x40, 0x00, 0x06, 0x42, - 0x40, 0x04, 0x44, 0x02, 0x80, 0x00, 0x86, 0x82, 0x40, 0x00, 0xC0, 0x02, 0x00, - 0x02, 0x5C, 0x02, 0x80, 0x01, 0x9C, 0x81, 0x00, 0x00, 0x49, 0x80, 0x81, 0x01, - 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x65, 0x6E, - 0x76, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, - 0x00, 0x02, 0x06, 0x00, 0x0D, 0x0F, 0x00, 0x00, 0x00, 0x86, 0x01, 0x81, 0x00, - 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x80, 0x00, 0x80, - 0x02, 0x00, 0x01, 0xC0, 0x02, 0x00, 0x03, 0x00, 0x03, 0x80, 0x02, 0xDC, 0x41, - 0x00, 0x03, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x03, 0x86, 0x42, 0x81, 0x00, 0xDC, 0x81, 0x00, 0x02, 0x49, 0xC0, 0x81, 0x01, - 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, - 0x0D, 0x18, 0x00, 0x00, 0x00, 0x86, 0xC1, 0x80, 0x00, 0xC4, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x80, 0x00, 0x80, 0x02, 0x00, 0x01, 0xC0, - 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0xDC, 0x41, 0x00, 0x03, 0xC4, 0x01, - 0x80, 0x00, 0x00, 0x02, 0x00, 0x03, 0xDC, 0x81, 0x00, 0x01, 0x57, 0x00, 0xC0, - 0x03, 0x16, 0x00, 0x01, 0x80, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x03, - 0xDC, 0x81, 0x00, 0x01, 0x17, 0x40, 0xC0, 0x03, 0x16, 0x00, 0x01, 0x80, 0xC6, - 0x41, 0x81, 0x00, 0x57, 0x80, 0xC0, 0x03, 0x16, 0x40, 0x00, 0x80, 0x06, 0xC2, - 0x40, 0x00, 0x09, 0xC2, 0x01, 0x03, 0x1E, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, - 0x09, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, - 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x76, 0x61, - 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, - 0xF3, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x8A, - 0x01, 0x00, 0x00, 0x49, 0x80, 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, - 0xFA, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x0D, 0x11, 0x00, 0x00, 0x00, 0x86, - 0x01, 0x81, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, - 0x80, 0x00, 0x80, 0x02, 0x00, 0x01, 0xC0, 0x02, 0x00, 0x03, 0x00, 0x03, 0x80, - 0x02, 0xDC, 0x41, 0x00, 0x03, 0xCC, 0x01, 0xC0, 0x01, 0x49, 0x80, 0x81, 0x03, - 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x03, 0x86, - 0x42, 0x81, 0x00, 0xDC, 0x81, 0x00, 0x02, 0x49, 0xC0, 0x81, 0x01, 0x1E, 0x00, - 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x84, - 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, 0x02, - 0x00, 0x01, 0x80, 0x02, 0x80, 0x01, 0xC0, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, - 0x02, 0x41, 0x03, 0x00, 0x00, 0x9D, 0x01, 0x00, 0x04, 0x9E, 0x01, 0x00, 0x00, - 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x55, 0x4E, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, - 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x02, 0x00, 0x00, - 0x00, 0x49, 0x00, 0xC0, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, - 0x0A, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x84, - 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x46, 0x02, - 0x81, 0x00, 0x9C, 0x41, 0x00, 0x02, 0x49, 0x00, 0xC0, 0x01, 0x1E, 0x00, 0x80, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x1F, - 0x01, 0x00, 0x00, 0x02, 0x06, 0x00, 0x10, 0x2C, 0x00, 0x00, 0x00, 0xC6, 0x01, - 0x81, 0x00, 0x0C, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x02, 0x81, 0x02, 0x00, - 0x00, 0x20, 0x02, 0x04, 0x80, 0x06, 0xC3, 0x82, 0x00, 0x17, 0x40, 0xC0, 0x03, - 0x16, 0x40, 0x00, 0x80, 0xC0, 0x01, 0x00, 0x06, 0x16, 0xC0, 0x02, 0x80, 0x57, - 0x40, 0x40, 0x06, 0x16, 0x40, 0x02, 0x80, 0x44, 0x03, 0x00, 0x00, 0x80, 0x03, - 0x80, 0x03, 0x5C, 0x83, 0x00, 0x01, 0x84, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x00, - 0x06, 0x9C, 0x83, 0x00, 0x01, 0x57, 0x80, 0x83, 0x06, 0x16, 0x40, 0x00, 0x80, - 0x82, 0x01, 0x80, 0x00, 0x16, 0x00, 0x00, 0x80, 0x1F, 0x42, 0xFB, 0x7F, 0x17, - 0x40, 0xC0, 0x03, 0x16, 0x40, 0x00, 0x80, 0xC1, 0x81, 0x00, 0x00, 0x16, 0x80, - 0x03, 0x80, 0x04, 0x02, 0x80, 0x00, 0x06, 0xC2, 0x40, 0x04, 0x0C, 0x02, 0x02, - 0x01, 0x9A, 0x41, 0x00, 0x00, 0x16, 0x40, 0x00, 0x80, 0x5B, 0x42, 0x80, 0x03, - 0x16, 0x00, 0x00, 0x80, 0x42, 0x02, 0x00, 0x00, 0x09, 0x40, 0x02, 0x04, 0x04, - 0x02, 0x00, 0x00, 0x40, 0x02, 0x80, 0x03, 0x1C, 0x82, 0x00, 0x01, 0x17, 0x00, - 0x41, 0x04, 0x16, 0x00, 0x00, 0x80, 0xC1, 0x81, 0x00, 0x00, 0x49, 0xC0, 0x81, - 0x01, 0x1E, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, 0x50, 0x45, 0x00, 0x04, 0x07, 0x00, 0x00, - 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, - 0x08, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x01, 0x80, 0x16, 0x00, 0x03, 0x80, - 0x8C, 0x01, 0x01, 0x01, 0xC6, 0x41, 0x40, 0x00, 0xC6, 0x81, 0x81, 0x03, 0xDA, - 0x41, 0x00, 0x00, 0x16, 0x40, 0x00, 0x80, 0x8D, 0x81, 0x40, 0x03, 0x16, 0x40, - 0xFE, 0x7F, 0x17, 0x80, 0x00, 0x03, 0x16, 0xC0, 0x00, 0x80, 0xC4, 0x01, 0x00, - 0x00, 0xC6, 0xC1, 0xC0, 0x03, 0xCC, 0xC1, 0x01, 0x01, 0x09, 0x00, 0xC1, 0x03, - 0x1E, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x76, 0x65, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x43, 0x4F, 0x4D, 0x42, 0x49, 0x4E, 0x45, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, - 0x00, 0x01, 0x06, 0x00, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x19, 0x00, 0x01, 0x80, - 0x16, 0x40, 0x02, 0x80, 0x19, 0x40, 0x01, 0x80, 0x16, 0xC0, 0x01, 0x80, 0x84, - 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x46, 0x02, - 0x81, 0x00, 0x5A, 0x42, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0x46, 0x42, 0x81, - 0x00, 0x9C, 0x41, 0x00, 0x02, 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, 0x01, 0x06, - 0x00, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, - 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, 0x02, 0x00, 0x01, 0x80, 0x02, 0x80, 0x01, - 0xC0, 0x02, 0x80, 0x01, 0x00, 0x03, 0x80, 0x02, 0x9D, 0x01, 0x80, 0x03, 0x9E, - 0x01, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, - 0x01, 0x06, 0x00, 0x0D, 0x09, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC0, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, 0x02, 0x00, 0x01, 0x80, 0x02, - 0x80, 0x01, 0xCD, 0x02, 0x40, 0x02, 0x0D, 0x03, 0xC0, 0x02, 0x9C, 0x41, 0x80, - 0x03, 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, - 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, 0x0D, 0x09, 0x00, - 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, - 0x00, 0x40, 0x02, 0x00, 0x01, 0x80, 0x02, 0x80, 0x01, 0xCD, 0x02, 0x40, 0x02, - 0x01, 0x43, 0x00, 0x00, 0x9C, 0x41, 0x80, 0x03, 0x1E, 0x00, 0x80, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, 0x02, 0x06, 0x00, - 0x0B, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x40, 0x02, 0x16, 0x00, 0x03, 0x80, - 0x84, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, - 0x02, 0x00, 0x01, 0x80, 0x02, 0x80, 0x01, 0x9C, 0x81, 0x80, 0x02, 0x9A, 0x01, - 0x00, 0x00, 0x16, 0x00, 0x01, 0x80, 0x8D, 0x41, 0x40, 0x01, 0xC4, 0x01, 0x80, - 0x00, 0xC6, 0x81, 0xC0, 0x03, 0x8C, 0xC1, 0x01, 0x03, 0x09, 0xC0, 0x40, 0x03, - 0x1E, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, - 0x04, 0x08, 0x00, 0x00, 0x00, 0x43, 0x4F, 0x4D, 0x42, 0x49, 0x4E, 0x45, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, - 0x51, 0x01, 0x00, 0x00, 0x03, 0x06, 0x00, 0x0F, 0x37, 0x00, 0x00, 0x00, 0x84, - 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, 0x02, - 0x00, 0x01, 0x8C, 0x02, 0xC0, 0x01, 0x9C, 0xC1, 0x80, 0x02, 0x04, 0x02, 0x80, - 0x00, 0x40, 0x02, 0x80, 0x03, 0x1C, 0x82, 0x00, 0x01, 0x17, 0x40, 0x40, 0x04, - 0x16, 0xC0, 0x00, 0x80, 0x04, 0x02, 0x00, 0x01, 0x06, 0x82, 0x40, 0x04, 0x0C, - 0x02, 0x02, 0x01, 0x09, 0xC0, 0x01, 0x04, 0x06, 0xC2, 0x80, 0x00, 0x4C, 0x02, - 0xC0, 0x01, 0x46, 0x42, 0x82, 0x00, 0x84, 0x02, 0x80, 0x00, 0xC0, 0x02, 0x00, - 0x04, 0x9C, 0x82, 0x00, 0x01, 0xC4, 0x02, 0x80, 0x00, 0x00, 0x03, 0x80, 0x04, - 0xDC, 0x82, 0x00, 0x01, 0x17, 0x40, 0x40, 0x05, 0x16, 0x80, 0x00, 0x80, 0x10, - 0xC3, 0x40, 0x04, 0x17, 0x00, 0x41, 0x06, 0x16, 0x00, 0x01, 0x80, 0x17, 0x40, - 0xC0, 0x05, 0x16, 0x40, 0x01, 0x80, 0x10, 0xC3, 0xC0, 0x04, 0x57, 0x00, 0x41, - 0x06, 0x16, 0x80, 0x00, 0x80, 0x01, 0x43, 0x01, 0x00, 0x1A, 0x43, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x80, 0x01, 0xC3, 0x00, 0x00, 0x4C, 0x83, 0xC1, 0x01, 0x49, - 0x00, 0x83, 0x06, 0x17, 0x40, 0x40, 0x05, 0x16, 0xC0, 0x02, 0x80, 0x17, 0x40, - 0xC0, 0x05, 0x16, 0x40, 0x02, 0x80, 0x44, 0x03, 0x80, 0x00, 0x8C, 0xC3, 0xC0, - 0x01, 0x86, 0x83, 0x83, 0x00, 0x5C, 0x83, 0x00, 0x01, 0x17, 0x40, 0xC0, 0x06, - 0x16, 0xC0, 0x00, 0x80, 0x44, 0x03, 0x00, 0x01, 0x46, 0xC3, 0xC1, 0x06, 0x4C, - 0x43, 0x03, 0x01, 0x09, 0x00, 0x83, 0x06, 0x1E, 0x00, 0x80, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x07, - 0x00, 0x00, 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x04, 0x0B, 0x00, - 0x00, 0x00, 0x46, 0x4F, 0x52, 0x5F, 0x53, 0x54, 0x45, 0x50, 0x5F, 0x4B, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x54, 0x59, 0x50, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x55, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, 0x08, - 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x86, 0x01, 0x40, 0x03, 0x8C, - 0x81, 0x01, 0x01, 0xC6, 0xC1, 0x80, 0x00, 0x09, 0xC0, 0x01, 0x03, 0x1E, 0x00, - 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, - 0x50, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x01, 0x00, - 0x00, 0x5E, 0x01, 0x00, 0x00, 0x01, 0x06, 0x00, 0x09, 0x0B, 0x00, 0x00, 0x00, - 0x86, 0xC1, 0x80, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0xDC, - 0x81, 0x00, 0x01, 0x17, 0x00, 0xC0, 0x03, 0x16, 0xC0, 0x00, 0x80, 0xC6, 0x41, - 0x40, 0x00, 0x0C, 0x82, 0xC0, 0x01, 0x06, 0x02, 0x82, 0x00, 0xC9, 0x01, 0x02, - 0x03, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, - 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x74, - 0x61, 0x62, 0x6C, 0x65, 0x76, 0x61, 0x6C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x01, - 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x03, 0x06, 0x00, 0x0E, 0x18, 0x00, 0x00, - 0x00, 0x84, 0x01, 0x00, 0x00, 0x49, 0x80, 0x81, 0x01, 0x86, 0x01, 0x40, 0x00, - 0x9A, 0x01, 0x00, 0x00, 0x16, 0x40, 0x04, 0x80, 0x84, 0x01, 0x80, 0x00, 0x86, - 0x41, 0x40, 0x03, 0xC6, 0x81, 0x40, 0x00, 0x00, 0x02, 0x00, 0x02, 0x9C, 0x81, - 0x80, 0x01, 0xCC, 0xC1, 0x40, 0x01, 0x0C, 0x82, 0x01, 0x01, 0x41, 0xC2, 0x00, - 0x00, 0xE0, 0xC1, 0x01, 0x80, 0xC4, 0x02, 0x00, 0x01, 0x06, 0x83, 0x40, 0x00, - 0x40, 0x03, 0x00, 0x05, 0xDC, 0x82, 0x80, 0x01, 0x17, 0x00, 0xC1, 0x05, 0x16, - 0x40, 0x00, 0x80, 0x09, 0x40, 0x41, 0x80, 0x1E, 0x00, 0x80, 0x00, 0xDF, 0x81, - 0xFD, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x6E, 0x6F, 0x63, 0x6C, 0x6F, 0x73, 0x65, 0x00, 0x04, 0x0B, 0x00, - 0x00, 0x00, 0x63, 0x6C, 0x6F, 0x73, 0x75, 0x72, 0x65, 0x6E, 0x75, 0x70, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, 0x05, 0x00, 0x00, 0x00, 0x4D, 0x4F, - 0x56, 0x45, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0x0D, 0x00, - 0x00, 0x00, 0x86, 0x01, 0x40, 0x00, 0x86, 0x41, 0x40, 0x03, 0xC1, 0x81, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x02, 0x41, 0x82, 0x00, 0x00, 0xE0, 0x01, 0x01, 0x80, - 0xCC, 0x82, 0x82, 0x01, 0xCD, 0x82, 0xC0, 0x05, 0x0C, 0x83, 0x02, 0x03, 0x06, - 0x03, 0x03, 0x00, 0x49, 0x00, 0x83, 0x05, 0xDF, 0x41, 0xFE, 0x7F, 0x1E, 0x00, - 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, - 0x6D, 0x73, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00, 0xAC, 0x01, 0x00, - 0x00, 0x09, 0x01, 0x00, 0x16, 0x73, 0x00, 0x00, 0x00, 0x46, 0x00, 0x40, 0x00, - 0x5A, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0x1E, 0x00, 0x80, 0x00, 0x46, - 0x40, 0x40, 0x00, 0x84, 0x00, 0x00, 0x00, 0x86, 0x80, 0x40, 0x01, 0xC0, 0x00, - 0x80, 0x00, 0x9C, 0x80, 0x00, 0x01, 0x9A, 0x40, 0x00, 0x00, 0x16, 0xC0, 0x00, - 0x80, 0xC4, 0x00, 0x00, 0x00, 0xC6, 0xC0, 0xC0, 0x01, 0xC6, 0x00, 0xC1, 0x01, - 0xDE, 0x00, 0x00, 0x01, 0xC6, 0x40, 0x41, 0x01, 0x04, 0x01, 0x80, 0x00, 0x06, - 0x41, 0x41, 0x02, 0x58, 0xC0, 0x00, 0x02, 0x16, 0xC0, 0x04, 0x80, 0xC6, 0x80, - 0x41, 0x01, 0x04, 0x01, 0x80, 0x00, 0x06, 0x81, 0x41, 0x02, 0x58, 0xC0, 0x00, - 0x02, 0x16, 0x80, 0x03, 0x80, 0xC6, 0xC0, 0x41, 0x01, 0x04, 0x01, 0x80, 0x00, - 0x06, 0xC1, 0x41, 0x02, 0x58, 0xC0, 0x00, 0x02, 0x16, 0x40, 0x02, 0x80, 0xC6, - 0x00, 0x42, 0x01, 0x04, 0x01, 0x80, 0x00, 0x06, 0x01, 0x42, 0x02, 0x58, 0xC0, - 0x00, 0x02, 0x16, 0x00, 0x01, 0x80, 0xC6, 0x40, 0x42, 0x01, 0x04, 0x01, 0x80, - 0x00, 0x06, 0x41, 0x42, 0x02, 0x18, 0xC0, 0x00, 0x02, 0x16, 0xC0, 0x00, 0x80, - 0xC4, 0x00, 0x00, 0x00, 0xC6, 0xC0, 0xC0, 0x01, 0xC6, 0x80, 0xC2, 0x01, 0xDE, - 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0xDC, 0x80, - 0x00, 0x01, 0x09, 0x00, 0xC3, 0x85, 0x09, 0x80, 0x00, 0x81, 0x09, 0xC0, 0x80, - 0x86, 0x0A, 0x41, 0x00, 0x00, 0x46, 0xC1, 0x43, 0x01, 0x84, 0x01, 0x80, 0x01, - 0x09, 0x81, 0x81, 0x02, 0x09, 0x00, 0x01, 0x87, 0x0A, 0x01, 0x00, 0x00, 0x41, - 0x01, 0x04, 0x00, 0x86, 0xC1, 0x41, 0x01, 0xC1, 0x01, 0x04, 0x00, 0x60, 0x81, - 0x00, 0x80, 0x4D, 0x02, 0x44, 0x04, 0x86, 0x02, 0x02, 0x00, 0x09, 0x81, 0x82, - 0x04, 0x5F, 0xC1, 0xFE, 0x7F, 0x41, 0x41, 0x04, 0x00, 0x81, 0x81, 0x04, 0x00, - 0xC1, 0x41, 0x04, 0x00, 0x60, 0xC1, 0x01, 0x80, 0x44, 0x02, 0x00, 0x02, 0x80, - 0x02, 0x80, 0x00, 0xC0, 0x02, 0x00, 0x04, 0x5C, 0xC2, 0x80, 0x01, 0x9A, 0x42, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0x16, 0x40, 0x00, 0x80, 0x09, 0x41, 0x02, - 0x04, 0x5F, 0x81, 0xFD, 0x7F, 0x41, 0x01, 0x04, 0x00, 0x86, 0x41, 0x41, 0x01, - 0xC1, 0x01, 0x04, 0x00, 0x60, 0x41, 0x05, 0x80, 0x46, 0x02, 0x82, 0x01, 0x5A, - 0x02, 0x00, 0x00, 0x16, 0x80, 0x03, 0x80, 0x44, 0x02, 0x80, 0x02, 0x80, 0x02, - 0x80, 0x00, 0xC0, 0x02, 0x00, 0x04, 0x5C, 0x82, 0x81, 0x01, 0x84, 0x03, 0x00, - 0x03, 0x86, 0x43, 0x02, 0x07, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, - 0x40, 0x04, 0x00, 0x04, 0x80, 0x04, 0x00, 0x05, 0xC0, 0x04, 0x80, 0x05, 0x00, - 0x05, 0x00, 0x06, 0x40, 0x05, 0x80, 0x04, 0x9C, 0x43, 0x00, 0x04, 0x16, 0xC0, - 0x00, 0x80, 0x44, 0x02, 0x80, 0x03, 0x46, 0xC2, 0xC4, 0x04, 0x4C, 0x42, 0x02, - 0x04, 0x09, 0x00, 0xC5, 0x04, 0x5F, 0x01, 0xFA, 0x7F, 0x46, 0xC1, 0x42, 0x00, - 0x5A, 0x01, 0x00, 0x00, 0x16, 0x80, 0x00, 0x80, 0x44, 0x01, 0x00, 0x04, 0x46, - 0x41, 0xC5, 0x02, 0x09, 0x00, 0xC3, 0x02, 0x09, 0x80, 0xC5, 0x85, 0x09, 0x80, - 0x45, 0x81, 0x09, 0x80, 0xC5, 0x86, 0x09, 0x80, 0x45, 0x87, 0x1E, 0x00, 0x80, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6F, - 0x70, 0x74, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, - 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x73, 0x00, 0x04, 0x07, - 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x00, 0x04, 0x0F, 0x00, - 0x00, 0x00, 0x43, 0x4F, 0x4D, 0x50, 0x49, 0x4C, 0x45, 0x52, 0x5F, 0x45, 0x52, - 0x52, 0x4F, 0x52, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, - 0x63, 0x6F, 0x64, 0x65, 0x73, 0x00, 0x04, 0x0B, 0x00, 0x00, 0x00, 0x73, 0x74, - 0x61, 0x63, 0x6B, 0x73, 0x6C, 0x6F, 0x74, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, - 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, - 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x73, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x73, - 0x75, 0x62, 0x73, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x54, 0x4F, 0x4F, 0x4C, - 0x41, 0x52, 0x47, 0x45, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x63, - 0x6C, 0x6F, 0x73, 0x65, 0x00, 0x01, 0x01, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6C, - 0x69, 0x76, 0x65, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, - 0x65, 0x76, 0x61, 0x6C, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x65, 0x6E, 0x76, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0xC0, 0x04, 0x08, 0x00, 0x00, 0x00, 0x43, 0x4F, 0x4D, 0x42, 0x49, 0x4E, - 0x45, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x4E, 0x4F, 0x43, 0x4C, - 0x4F, 0x53, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, - 0x01, 0x00, 0x00, 0xBD, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x08, 0x1C, 0x00, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x19, 0x00, 0xC0, 0x00, 0x16, 0x00, 0x00, - 0x80, 0x1E, 0x00, 0x80, 0x00, 0x44, 0x00, 0x80, 0x00, 0x84, 0x00, 0x00, 0x01, - 0xC0, 0x00, 0x00, 0x00, 0x5C, 0xC0, 0x80, 0x01, 0x5A, 0x40, 0x00, 0x00, 0x16, - 0x40, 0x03, 0x80, 0xC5, 0x40, 0x00, 0x00, 0xC6, 0x80, 0xC0, 0x01, 0xCB, 0xC0, - 0xC0, 0x01, 0x41, 0x01, 0x01, 0x00, 0x80, 0x01, 0x00, 0x01, 0xC1, 0x41, 0x01, - 0x00, 0xDC, 0x40, 0x80, 0x02, 0xC4, 0x00, 0x80, 0x01, 0xC6, 0x80, 0xC1, 0x01, - 0x04, 0x01, 0x00, 0x02, 0xDC, 0x40, 0x00, 0x01, 0xC3, 0x00, 0x80, 0x01, 0xC8, - 0x00, 0x80, 0x02, 0x16, 0x80, 0x00, 0x80, 0x9A, 0x00, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x80, 0x9E, 0x00, 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x00, 0x00, 0x69, 0x6F, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x73, 0x74, 0x64, - 0x65, 0x72, 0x72, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x00, 0x04, 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x45, 0x52, 0x52, 0x4F, 0x52, - 0x3A, 0x20, 0x6A, 0x69, 0x74, 0x2E, 0x6F, 0x70, 0x74, 0x20, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6C, 0x65, 0x64, 0x3A, 0x20, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xCB, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x09, 0x26, 0x00, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x00, 0x46, 0x40, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC1, 0x80, 0x00, - 0x00, 0x5C, 0xC0, 0x80, 0x01, 0x5A, 0x40, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, - 0x40, 0x00, 0x00, 0x00, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x55, - 0x00, 0x81, 0x01, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x01, 0x01, 0x00, 0x40, 0x01, - 0x80, 0x00, 0xDC, 0xC0, 0x80, 0x01, 0xDA, 0x40, 0x00, 0x00, 0x16, 0x00, 0x04, - 0x80, 0x45, 0x01, 0x00, 0x00, 0x46, 0x41, 0xC1, 0x02, 0x80, 0x01, 0x00, 0x02, - 0xC1, 0x81, 0x01, 0x00, 0x01, 0xC2, 0x01, 0x00, 0x5C, 0x81, 0x00, 0x02, 0x57, - 0x00, 0xC2, 0x02, 0x16, 0xC0, 0x00, 0x80, 0x45, 0x41, 0x02, 0x00, 0x80, 0x01, - 0x00, 0x02, 0xC1, 0x81, 0x02, 0x00, 0x5C, 0x41, 0x80, 0x01, 0x41, 0xC1, 0x02, - 0x00, 0x80, 0x01, 0x80, 0x00, 0xC1, 0x01, 0x03, 0x00, 0x55, 0xC1, 0x81, 0x02, - 0x5E, 0x01, 0x00, 0x01, 0x46, 0x41, 0x43, 0x02, 0x80, 0x01, 0x00, 0x01, 0x5C, - 0x41, 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x04, 0x07, - 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x04, 0x06, 0x00, - 0x00, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x00, 0x04, 0x0C, 0x00, 0x00, 0x00, - 0x5E, 0x28, 0x2E, 0x2D, 0x29, 0x3D, 0x28, 0x2E, 0x2A, 0x29, 0x24, 0x00, 0x04, - 0x09, 0x00, 0x00, 0x00, 0x6A, 0x69, 0x74, 0x2E, 0x6F, 0x70, 0x74, 0x5F, 0x00, - 0x04, 0x08, 0x00, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x00, - 0x04, 0x04, 0x00, 0x00, 0x00, 0x73, 0x75, 0x62, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, - 0x40, 0x04, 0x08, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, - 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x19, 0x00, 0x00, 0x00, - 0x6F, 0x70, 0x74, 0x69, 0x6D, 0x69, 0x7A, 0x65, 0x72, 0x20, 0x61, 0x64, 0x64, - 0x2D, 0x6F, 0x6E, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, 0x00, 0x04, - 0x0B, 0x00, 0x00, 0x00, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x66, 0x6F, 0x75, 0x6E, - 0x64, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x00, 0xEB, 0x01, - 0x00, 0x00, 0x08, 0x01, 0x00, 0x06, 0x3B, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x00, 0x5A, 0x40, 0x00, 0x00, 0x16, 0x80, 0x01, 0x80, 0x44, 0x00, 0x80, 0x00, - 0x46, 0x00, 0xC0, 0x00, 0x84, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x80, 0x01, 0x5C, - 0x40, 0x80, 0x01, 0x42, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x00, 0x57, 0x40, - 0x40, 0x00, 0x16, 0x40, 0x00, 0x80, 0x17, 0x80, 0x40, 0x00, 0x16, 0x80, 0x00, - 0x80, 0x44, 0x00, 0x80, 0x02, 0x48, 0x00, 0x00, 0x02, 0x16, 0x40, 0x07, 0x80, - 0x45, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x5C, 0x80, 0x00, 0x01, 0x5A, - 0x00, 0x00, 0x00, 0x16, 0x80, 0x02, 0x80, 0x58, 0x00, 0xC1, 0x00, 0x16, 0x80, - 0x00, 0x80, 0x90, 0x40, 0xC1, 0x00, 0x57, 0x00, 0x41, 0x01, 0x16, 0xC0, 0x00, - 0x80, 0x85, 0x80, 0x01, 0x00, 0xC1, 0xC0, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, - 0x9C, 0x40, 0x80, 0x01, 0x48, 0x00, 0x00, 0x02, 0x16, 0x40, 0x03, 0x80, 0x84, - 0x00, 0x00, 0x02, 0x17, 0x00, 0x42, 0x01, 0x16, 0x40, 0x00, 0x80, 0x84, 0x00, - 0x80, 0x02, 0x88, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, - 0x00, 0x9C, 0x80, 0x00, 0x01, 0x9A, 0x00, 0x00, 0x00, 0x16, 0xC0, 0x00, 0x80, - 0xC5, 0x80, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x41, 0x01, 0x01, 0x00, 0xDC, - 0x40, 0x80, 0x01, 0x44, 0x00, 0x80, 0x03, 0x5A, 0x40, 0x00, 0x00, 0x16, 0xC0, - 0x01, 0x80, 0x44, 0x00, 0x00, 0x02, 0x19, 0x40, 0x80, 0x84, 0x16, 0x00, 0x01, - 0x80, 0x44, 0x00, 0x00, 0x03, 0x81, 0x80, 0x02, 0x00, 0x5C, 0x40, 0x00, 0x01, - 0x42, 0x00, 0x80, 0x00, 0x48, 0x00, 0x80, 0x03, 0x1E, 0x00, 0x80, 0x00, 0x0B, - 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x74, 0x74, 0x61, 0x63, - 0x68, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, - 0x00, 0x74, 0x6F, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x3F, 0x04, 0x06, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, - 0x04, 0x14, 0x00, 0x00, 0x00, 0x62, 0x61, 0x64, 0x20, 0x6F, 0x70, 0x74, 0x69, - 0x6D, 0x69, 0x7A, 0x65, 0x72, 0x20, 0x6C, 0x65, 0x76, 0x65, 0x6C, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x04, 0x07, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x6C, 0x69, - 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x01, 0x00, - 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x00, 0xF8, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 -}; - -/* -** LuaJIT's opt_inline.lua compiled to Lua bytecode -*/ -static const uint8_t jit_opt_inline_lua[] = { - 0x1B, 'L' , 'u' , 'a' , 0x51, 0x00, 0x01, 0x04, 0x04, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x1F, 0xF0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x40, 0x00, - 0x00, 0x1C, 0x80, 0x00, 0x01, 0x45, 0x80, 0x00, 0x00, 0x86, 0xC0, 0x40, 0x00, - 0x57, 0x00, 0x41, 0x01, 0x16, 0x00, 0x00, 0x80, 0x82, 0x40, 0x00, 0x00, 0x82, - 0x00, 0x80, 0x00, 0xC1, 0x40, 0x01, 0x00, 0x5C, 0x40, 0x80, 0x01, 0x45, 0x00, - 0x00, 0x00, 0x81, 0x80, 0x01, 0x00, 0x5C, 0x80, 0x00, 0x01, 0x85, 0xC0, 0x01, - 0x00, 0xC5, 0x00, 0x02, 0x00, 0x05, 0x41, 0x02, 0x00, 0x46, 0x81, 0xC2, 0x00, - 0x86, 0xC1, 0xC2, 0x00, 0xC5, 0x01, 0x03, 0x00, 0xC6, 0x41, 0xC3, 0x03, 0x05, - 0x02, 0x03, 0x00, 0x06, 0x82, 0x43, 0x04, 0x45, 0x02, 0x03, 0x00, 0x46, 0xC2, - 0xC3, 0x04, 0x86, 0x02, 0x44, 0x00, 0xC2, 0x02, 0x80, 0x00, 0x02, 0x03, 0x80, - 0x00, 0x9C, 0x42, 0x80, 0x01, 0x8A, 0x02, 0x00, 0x00, 0xC5, 0x42, 0x04, 0x00, - 0x0A, 0x03, 0x00, 0x00, 0x64, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x83, - 0x03, 0x00, 0x08, 0x64, 0x44, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, - 0x80, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x08, 0xA4, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x08, 0xE4, 0xC4, 0x00, 0x00, 0x24, 0x05, 0x01, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x80, 0x05, 0x64, 0x45, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x83, 0x05, 0x00, - 0x0B, 0xC5, 0x85, 0x04, 0x00, 0x01, 0xC4, 0x04, 0x00, 0xC0, 0x03, 0x80, 0x0B, - 0x80, 0x03, 0x00, 0x0B, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x05, 0x00, 0x01, - 0x46, 0x05, 0x00, 0x41, 0x86, 0x05, 0x00, 0xA4, 0x86, 0x01, 0x00, 0x00, 0x00, - 0x80, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, - 0x08, 0xC1, 0xC5, 0x05, 0x00, 0x01, 0x06, 0x06, 0x00, 0x41, 0x86, 0x05, 0x00, - 0xA4, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x0A, 0x9C, 0x45, 0x80, 0x02, 0x03, 0x04, 0x00, 0x08, 0x80, 0x05, - 0x80, 0x08, 0xC1, 0x45, 0x02, 0x00, 0x01, 0x46, 0x06, 0x00, 0x41, 0x86, 0x06, - 0x00, 0xA4, 0x06, 0x02, 0x00, 0x00, 0x00, 0x80, 0x0A, 0x9C, 0x45, 0x80, 0x02, - 0x80, 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x01, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, - 0x06, 0x07, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, - 0x07, 0x00, 0x01, 0x86, 0x05, 0x00, 0x41, 0x06, 0x07, 0x00, 0x9C, 0x45, 0x00, - 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x07, 0x00, 0x01, 0x06, 0x07, 0x00, - 0x41, 0xC6, 0x07, 0x00, 0x80, 0x06, 0x80, 0x09, 0x9C, 0x45, 0x80, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0x05, 0x08, 0x00, 0x01, 0x46, 0x08, 0x00, 0x41, 0x46, - 0x06, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x02, - 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x86, 0x08, 0x00, 0xA4, 0x46, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x9C, 0x45, 0x80, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x08, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x06, - 0x09, 0x00, 0x80, 0x06, 0x80, 0x09, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, - 0x08, 0xC1, 0x85, 0x00, 0x00, 0x01, 0x46, 0x09, 0x00, 0x41, 0x86, 0x09, 0x00, - 0xA4, 0x86, 0x02, 0x00, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, - 0xC5, 0x09, 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, 0x46, 0x0A, 0x00, 0x9C, 0x45, - 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x0A, 0x00, 0x01, 0xC6, 0x06, - 0x00, 0x41, 0x06, 0x07, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, - 0xC1, 0x05, 0x00, 0x00, 0x01, 0x86, 0x05, 0x00, 0x41, 0xC6, 0x06, 0x00, 0x9C, - 0x45, 0x00, 0x02, 0x81, 0xC5, 0x0A, 0x00, 0xC5, 0xC5, 0x0A, 0x00, 0x01, 0x04, - 0x0B, 0x00, 0xC0, 0x03, 0x80, 0x0B, 0x80, 0x03, 0x00, 0x0B, 0xDA, 0x03, 0x00, - 0x00, 0x16, 0x00, 0x04, 0x80, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x0B, 0x00, - 0x01, 0x46, 0x09, 0x00, 0x41, 0x86, 0x0B, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x0B, 0x00, 0x01, 0x46, 0x09, 0x00, 0x41, 0x06, - 0x0C, 0x00, 0xA4, 0xC6, 0x02, 0x00, 0x9C, 0x45, 0x80, 0x02, 0x03, 0x04, 0x00, - 0x08, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x0C, 0x00, 0x01, 0x86, 0x0C, 0x00, - 0x41, 0xC6, 0x0C, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x81, 0x05, 0x03, 0x00, 0xC5, - 0x05, 0x03, 0x00, 0x01, 0x04, 0x0D, 0x00, 0xC0, 0x03, 0x80, 0x0B, 0x80, 0x03, - 0x00, 0x0B, 0xDA, 0x03, 0x00, 0x00, 0x16, 0x40, 0x11, 0x80, 0x80, 0x05, 0x80, - 0x08, 0xC1, 0x45, 0x0D, 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, 0xC6, 0x06, 0x00, - 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x03, 0x00, 0x01, - 0xC6, 0x06, 0x00, 0x41, 0x86, 0x0D, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, - 0x80, 0x08, 0xC1, 0xC5, 0x0D, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, 0x06, 0x0E, - 0x00, 0x9C, 0x45, 0x00, 0x02, 0x03, 0x04, 0x00, 0x08, 0x80, 0x05, 0x80, 0x08, - 0xC1, 0x45, 0x0E, 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, 0xC6, 0x06, 0x00, 0xA4, - 0x06, 0x03, 0x00, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, - 0x0E, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, 0xC6, 0x0E, 0x00, 0x9C, 0x45, 0x00, - 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x0F, 0x00, 0x01, 0xC6, 0x06, 0x00, - 0x41, 0xC6, 0x06, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, - 0x45, 0x0F, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, 0xC6, 0x06, 0x00, 0x9C, 0x45, - 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x0F, 0x00, 0x01, 0xC6, 0x06, - 0x00, 0x41, 0xC6, 0x06, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, - 0xC1, 0xC5, 0x0F, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, 0x06, 0x10, 0x00, 0x9C, - 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x10, 0x00, 0x01, 0x46, - 0x09, 0x00, 0x41, 0x86, 0x10, 0x00, 0xA4, 0x46, 0x03, 0x00, 0x9C, 0x45, 0x80, - 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x03, 0x00, 0x01, 0x46, 0x09, 0x00, - 0x41, 0xC6, 0x10, 0x00, 0xA4, 0x86, 0x03, 0x00, 0x9C, 0x45, 0x80, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x03, 0x00, 0x01, 0xC6, 0x0E, 0x00, 0x41, 0x06, - 0x11, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x11, - 0x00, 0x01, 0x86, 0x11, 0x00, 0x41, 0xC6, 0x11, 0x00, 0xA4, 0xC6, 0x03, 0x00, - 0x9C, 0x45, 0x80, 0x02, 0x81, 0x05, 0x12, 0x00, 0xC5, 0x05, 0x12, 0x00, 0x01, - 0x44, 0x12, 0x00, 0xC0, 0x03, 0x80, 0x0B, 0x80, 0x03, 0x00, 0x0B, 0xDA, 0x03, - 0x00, 0x00, 0x16, 0xC0, 0x05, 0x80, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x12, - 0x00, 0x01, 0xC6, 0x12, 0x00, 0x41, 0x06, 0x13, 0x00, 0x9C, 0x45, 0x00, 0x02, - 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x13, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, - 0x86, 0x05, 0x00, 0xA4, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x80, 0x01, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x13, - 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, 0x86, 0x05, 0x00, 0x9C, 0x45, 0x00, 0x02, - 0x03, 0x04, 0x00, 0x08, 0x80, 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x13, 0x00, 0x01, - 0xC6, 0x06, 0x00, 0x41, 0x06, 0x14, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x81, 0x45, - 0x14, 0x00, 0xC5, 0x45, 0x14, 0x00, 0x01, 0x84, 0x14, 0x00, 0xC0, 0x03, 0x80, - 0x0B, 0x80, 0x03, 0x00, 0x0B, 0xDA, 0x03, 0x00, 0x00, 0x16, 0x80, 0x24, 0x80, - 0x80, 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x14, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, - 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, - 0x15, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, - 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x15, 0x00, 0x01, 0x06, 0x15, 0x00, - 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, - 0xC5, 0x15, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, - 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x16, 0x00, 0x01, 0x06, 0x15, - 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, - 0xC1, 0x45, 0x16, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, - 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x16, 0x00, 0x01, 0x06, - 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, - 0x08, 0xC1, 0xC5, 0x16, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, - 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x17, 0x00, 0x01, - 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, - 0x80, 0x08, 0xC1, 0x45, 0x17, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, - 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x17, 0x00, - 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x17, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, - 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x18, - 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, - 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x18, 0x00, 0x01, 0x06, 0x0A, 0x00, 0x41, - 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, - 0x18, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x06, 0x15, 0x00, 0x80, 0x06, 0x80, - 0x09, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x18, 0x00, - 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0x05, 0x19, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x46, - 0x19, 0x00, 0xA4, 0x46, 0x04, 0x00, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, - 0x08, 0xC1, 0x85, 0x19, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x46, 0x19, 0x00, - 0x9C, 0x45, 0x00, 0x02, 0x03, 0x04, 0x00, 0x08, 0x80, 0x05, 0x80, 0x08, 0xC1, - 0xC5, 0x19, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x06, 0x1A, 0x00, 0x80, 0x06, - 0x80, 0x09, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x1A, - 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, 0x06, 0x1A, 0x00, 0x80, 0x06, 0x80, 0x09, - 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x1A, 0x00, 0x01, - 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, - 0x80, 0x08, 0xC1, 0xC5, 0x1A, 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x15, - 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x1B, 0x00, - 0x01, 0x46, 0x1B, 0x00, 0x41, 0x06, 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0x85, 0x1B, 0x00, 0x01, 0xC6, 0x1B, 0x00, 0x41, 0x06, - 0x15, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x05, 0x1C, - 0x00, 0x01, 0x06, 0x15, 0x00, 0x41, 0x46, 0x19, 0x00, 0x9C, 0x45, 0x00, 0x02, - 0x80, 0x05, 0x80, 0x08, 0xC1, 0x45, 0x1C, 0x00, 0x01, 0x06, 0x07, 0x00, 0x41, - 0xC6, 0x1B, 0x00, 0x80, 0x06, 0x80, 0x09, 0x9C, 0x45, 0x80, 0x02, 0x80, 0x05, - 0x80, 0x08, 0xC1, 0x85, 0x1C, 0x00, 0x01, 0xC6, 0x12, 0x00, 0x41, 0x06, 0x0A, - 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, 0x05, 0x80, 0x08, 0xC1, 0xC5, 0x1C, 0x00, - 0x01, 0x06, 0x15, 0x00, 0x41, 0x06, 0x1D, 0x00, 0xA4, 0x86, 0x04, 0x00, 0x9C, - 0x45, 0x80, 0x02, 0x81, 0x45, 0x1D, 0x00, 0xC5, 0x45, 0x1D, 0x00, 0x03, 0x04, - 0x00, 0x08, 0xC0, 0x03, 0x80, 0x0B, 0x80, 0x03, 0x00, 0x0B, 0xDA, 0x03, 0x00, - 0x00, 0x16, 0x40, 0x02, 0x80, 0x80, 0x05, 0x80, 0x08, 0xC1, 0x85, 0x1D, 0x00, - 0x01, 0xC6, 0x1D, 0x00, 0x41, 0x06, 0x1E, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x80, - 0x05, 0x80, 0x08, 0xC1, 0x45, 0x1E, 0x00, 0x01, 0xC6, 0x06, 0x00, 0x41, 0xC6, - 0x12, 0x00, 0x9C, 0x45, 0x00, 0x02, 0x8A, 0x05, 0x02, 0x00, 0x89, 0xC5, 0x5E, - 0xBD, 0x89, 0x45, 0x5F, 0xBE, 0x89, 0xC5, 0x5F, 0xBF, 0x89, 0x05, 0x60, 0x86, - 0x89, 0x45, 0x60, 0xA4, 0x89, 0xC5, 0x60, 0xC1, 0x89, 0x45, 0x61, 0xC2, 0x89, - 0xC5, 0x61, 0xC3, 0xCA, 0x45, 0x02, 0x00, 0xC9, 0x05, 0xE2, 0x90, 0xC9, 0x45, - 0xE2, 0x8D, 0xC9, 0x85, 0x62, 0x8B, 0xC9, 0xC5, 0xE2, 0x99, 0xC9, 0x45, 0x63, - 0xC6, 0xC9, 0xC5, 0x63, 0xC7, 0xC9, 0x05, 0x64, 0xAA, 0xC9, 0x05, 0x64, 0x94, - 0xC9, 0x85, 0xE4, 0xC8, 0x0A, 0xC6, 0x01, 0x00, 0x09, 0xC6, 0xE4, 0x90, 0x09, - 0xC6, 0xD2, 0x8D, 0x4A, 0x06, 0x00, 0x00, 0x09, 0x46, 0x06, 0x8B, 0x09, 0x06, - 0x65, 0xAA, 0x09, 0x46, 0x65, 0x94, 0x64, 0xC6, 0x04, 0x00, 0x09, 0x46, 0x06, - 0xCB, 0x45, 0x46, 0x04, 0x00, 0x09, 0x46, 0x06, 0x99, 0x64, 0x06, 0x05, 0x00, - 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x0B, 0xA4, 0x46, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x80, 0x0C, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, - 0x02, 0xE4, 0x86, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0D, 0x24, 0xC7, 0x05, 0x00, 0x00, - 0x00, 0x80, 0x0D, 0x45, 0xC7, 0x25, 0x00, 0xA5, 0x07, 0x00, 0x00, 0x5C, 0x47, - 0x00, 0x00, 0x47, 0x03, 0x26, 0x00, 0x07, 0x47, 0x26, 0x00, 0x1E, 0x00, 0x80, - 0x00, 0x9A, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x6A, 0x69, 0x74, - 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x00, - 0x04, 0x0C, 0x00, 0x00, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, - 0x6E, 0x75, 0x6D, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC, 0xC3, 0x40, - 0x04, 0x25, 0x00, 0x00, 0x00, 0x4C, 0x75, 0x61, 0x4A, 0x49, 0x54, 0x20, 0x63, - 0x6F, 0x72, 0x65, 0x2F, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x6D, 0x69, 0x73, 0x6D, 0x61, 0x74, - 0x63, 0x68, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x6A, 0x69, 0x74, 0x2E, 0x75, - 0x74, 0x69, 0x6C, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, - 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x67, 0x65, 0x74, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x00, 0x04, 0x06, 0x00, - 0x00, 0x00, 0x68, 0x69, 0x6E, 0x74, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, - 0x66, 0x68, 0x69, 0x6E, 0x74, 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x73, - 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x73, 0x75, - 0x62, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x67, 0x73, 0x75, 0x62, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x6F, 0x66, 0x66, 0x00, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x63, 0x6F, - 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x00, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x5F, 0x47, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x70, 0x61, 0x69, 0x72, - 0x73, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x2E, 0x2E, 0x30, 0x00, 0x04, 0x02, - 0x00, 0x00, 0x00, 0x54, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x69, 0x70, 0x61, - 0x69, 0x72, 0x73, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x2E, 0x2E, 0x49, 0x00, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x2E, 0x2E, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x54, 0x2E, 0x3F, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x53, 0x00, 0x04, 0x02, - 0x00, 0x00, 0x00, 0x2E, 0x00, 0x04, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, - 0x6D, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x0D, 0x00, - 0x00, 0x00, 0x73, 0x65, 0x74, 0x6D, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6C, - 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x54, 0x54, 0x3F, 0x00, 0x04, 0x09, - 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x04, - 0x02, 0x00, 0x00, 0x00, 0x42, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x54, 0x2E, - 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x73, 0x65, 0x74, 0x00, - 0x04, 0x04, 0x00, 0x00, 0x00, 0x54, 0x2E, 0x2E, 0x00, 0x04, 0x02, 0x00, 0x00, - 0x00, 0x2A, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x2E, 0x2E, 0x2A, 0x00, 0x04, - 0x09, 0x00, 0x00, 0x00, 0x74, 0x6F, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x00, - 0x04, 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x2E, - 0x49, 0x3F, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x74, 0x6F, 0x73, 0x74, 0x72, - 0x69, 0x6E, 0x67, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x72, 0x6F, - 0x75, 0x74, 0x69, 0x6E, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x41, 0x04, 0x06, 0x00, 0x00, 0x00, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x00, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x2E, 0x2A, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, - 0x72, 0x65, 0x73, 0x75, 0x6D, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x52, - 0x2E, 0x2A, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x77, 0x72, 0x61, 0x70, 0x00, - 0x04, 0x02, 0x00, 0x00, 0x00, 0x43, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x46, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x6C, 0x65, 0x6E, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x53, 0x49, - 0x49, 0x3F, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x72, 0x00, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x49, 0x2A, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, - 0x62, 0x79, 0x74, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, - 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x53, 0x49, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x00, 0x04, 0x06, 0x00, 0x00, - 0x00, 0x75, 0x70, 0x70, 0x65, 0x72, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x6C, - 0x6F, 0x77, 0x65, 0x72, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, - 0x6D, 0x61, 0x74, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x53, 0x2E, 0x2A, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x69, 0x6E, 0x64, 0x00, 0x04, 0x07, 0x00, - 0x00, 0x00, 0x53, 0x53, 0x49, 0x3F, 0x2E, 0x3F, 0x00, 0x04, 0x05, 0x00, 0x00, - 0x00, 0x53, 0x53, 0x49, 0x3F, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x53, 0x53, - 0x47, 0x49, 0x3F, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x61, 0x74, - 0x63, 0x68, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x43, 0x30, 0x30, 0x00, 0x04, - 0x03, 0x00, 0x00, 0x00, 0x53, 0x53, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x74, - 0x61, 0x62, 0x6C, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x41, 0x04, 0x07, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x73, 0x65, 0x72, 0x74, 0x00, - 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x49, - 0x3F, 0x2E, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6D, 0x6F, 0x76, - 0x65, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x6E, 0x00, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x63, 0x61, 0x74, 0x00, 0x04, 0x08, - 0x00, 0x00, 0x00, 0x54, 0x53, 0x3F, 0x49, 0x3F, 0x49, 0x3F, 0x00, 0x04, 0x05, - 0x00, 0x00, 0x00, 0x6D, 0x61, 0x74, 0x68, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x14, 0x41, 0x04, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x6F, 0x67, 0x00, - 0x04, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x6C, - 0x6F, 0x67, 0x31, 0x30, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x65, 0x78, 0x70, - 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x73, 0x69, 0x6E, 0x68, 0x00, 0x04, 0x05, - 0x00, 0x00, 0x00, 0x63, 0x6F, 0x73, 0x68, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, - 0x74, 0x61, 0x6E, 0x68, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x61, 0x73, 0x69, - 0x6E, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x61, 0x63, 0x6F, 0x73, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x6E, 0x00, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x73, 0x69, 0x6E, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x73, - 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x74, 0x61, 0x6E, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x63, 0x65, 0x69, 0x6C, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x66, - 0x6C, 0x6F, 0x6F, 0x72, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x61, 0x62, 0x73, - 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x73, 0x71, 0x72, 0x74, 0x00, 0x04, 0x05, - 0x00, 0x00, 0x00, 0x66, 0x6D, 0x6F, 0x64, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, - 0x4E, 0x4E, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x6E, 0x32, - 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x69, 0x6E, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x4E, 0x4E, 0x2A, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, - 0x78, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x64, 0x65, 0x67, 0x00, 0x04, 0x04, - 0x00, 0x00, 0x00, 0x72, 0x61, 0x64, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6D, - 0x6F, 0x64, 0x66, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x00, 0x04, - 0x06, 0x00, 0x00, 0x00, 0x66, 0x72, 0x65, 0x78, 0x70, 0x00, 0x04, 0x03, 0x00, - 0x00, 0x00, 0x4E, 0x49, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x70, 0x6F, 0x77, - 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x65, 0x78, 0x70, 0x00, 0x04, - 0x0B, 0x00, 0x00, 0x00, 0x72, 0x61, 0x6E, 0x64, 0x6F, 0x6D, 0x73, 0x65, 0x65, - 0x64, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72, 0x61, 0x6E, 0x64, 0x6F, 0x6D, - 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x49, 0x3F, 0x49, 0x3F, 0x00, 0x04, 0x03, - 0x00, 0x00, 0x00, 0x69, 0x6F, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x69, - 0x6E, 0x65, 0x73, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x43, 0x30, 0x30, 0x53, - 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x53, 0x3F, 0x00, 0x04, 0x05, 0x00, 0x00, - 0x00, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x6E, 0x69, - 0x6C, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x00, 0x04, 0x02, 0x00, 0x00, - 0x00, 0x62, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x6E, 0x75, 0x6D, 0x62, 0x65, - 0x72, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x02, 0x00, 0x00, - 0x00, 0x73, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x74, 0x00, 0x04, 0x09, 0x00, - 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x02, - 0x00, 0x00, 0x00, 0x66, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, - 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x75, 0x00, - 0x04, 0x07, 0x00, 0x00, 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, - 0x02, 0x00, 0x00, 0x00, 0x72, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x62, - 0x30, 0x5D, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x73, 0x30, 0x5D, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x74, 0x30, 0x5D, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x5B, 0x66, 0x30, 0x5D, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x55, - 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x75, 0x30, 0x5D, 0x00, 0x04, 0x02, - 0x00, 0x00, 0x00, 0x52, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x72, 0x30, - 0x5D, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x5B, 0x6E, 0x30, 0x5D, 0x00, 0x04, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x5B, 0x73, - 0x74, 0x66, 0x30, 0x5D, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, - 0x02, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x6D, 0x6F, - 0x64, 0x75, 0x6C, 0x65, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, - 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x08, 0x18, 0x00, 0x00, - 0x00, 0x84, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x01, 0x9A, 0x00, 0x00, 0x00, - 0x16, 0xC0, 0x02, 0x80, 0xC6, 0x00, 0x40, 0x01, 0x06, 0x41, 0x40, 0x01, 0xDA, - 0x00, 0x00, 0x00, 0x16, 0x40, 0x01, 0x80, 0x40, 0x01, 0x80, 0x01, 0x81, 0x81, - 0x00, 0x00, 0xC0, 0x01, 0x00, 0x02, 0x55, 0xC1, 0x81, 0x02, 0x5E, 0x01, 0x00, - 0x01, 0x16, 0x00, 0x02, 0x80, 0x1E, 0x01, 0x00, 0x01, 0x16, 0x80, 0x01, 0x80, - 0x17, 0xC0, 0xC0, 0x00, 0x16, 0x80, 0x00, 0x80, 0xC1, 0x00, 0x01, 0x00, 0xDE, - 0x00, 0x00, 0x01, 0x16, 0x40, 0x00, 0x80, 0xC1, 0x40, 0x01, 0x00, 0xDE, 0x00, - 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x6C, 0x69, 0x62, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x2E, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0A, 0x00, - 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x00, 0x04, - 0x02, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x08, 0x18, - 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x44, 0x01, 0x80, 0x00, 0x80, 0x01, - 0x00, 0x00, 0x1C, 0x81, 0x80, 0x01, 0x1A, 0x01, 0x00, 0x00, 0x16, 0x80, 0x02, - 0x80, 0x44, 0x01, 0x00, 0x01, 0x8A, 0x81, 0x01, 0x00, 0xC4, 0x01, 0x80, 0x01, - 0x89, 0xC1, 0x01, 0x80, 0x89, 0x01, 0x80, 0x80, 0xC4, 0x01, 0x00, 0x02, 0x89, - 0xC1, 0x01, 0x81, 0x89, 0x41, 0x80, 0x81, 0x89, 0x81, 0x00, 0x82, 0x89, 0xC1, - 0x80, 0x82, 0x49, 0x81, 0x01, 0x02, 0x44, 0x01, 0x00, 0x02, 0x5A, 0x01, 0x00, - 0x00, 0x16, 0x80, 0x00, 0x80, 0x44, 0x01, 0x00, 0x02, 0x4C, 0x81, 0xC1, 0x02, - 0x48, 0x01, 0x00, 0x02, 0x1E, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, - 0x08, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x62, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x69, 0x64, 0x78, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, - 0x75, 0x6C, 0x74, 0x73, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, - 0x73, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, - 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, - 0x03, 0x05, 0x00, 0x08, 0x12, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x8A, - 0x81, 0x01, 0x00, 0xC4, 0x01, 0x80, 0x00, 0x89, 0xC1, 0x01, 0x80, 0x89, 0x01, - 0x80, 0x80, 0xC4, 0x01, 0x00, 0x01, 0x89, 0xC1, 0x01, 0x81, 0x89, 0x81, 0x80, - 0x81, 0x89, 0xC1, 0x00, 0x82, 0x89, 0x01, 0x81, 0x82, 0x49, 0x81, 0x81, 0x00, - 0x44, 0x01, 0x00, 0x01, 0x5A, 0x01, 0x00, 0x00, 0x16, 0x80, 0x00, 0x80, 0x44, - 0x01, 0x00, 0x01, 0x4C, 0x81, 0xC1, 0x02, 0x48, 0x01, 0x00, 0x01, 0x1E, 0x00, - 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x6C, 0x69, - 0x62, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x6E, 0x61, - 0x6D, 0x65, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x00, 0x04, - 0x08, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x73, 0x00, 0x04, - 0x05, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, 0x73, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, - 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x04, 0x00, - 0x00, 0x00, 0x8C, 0x01, 0xC0, 0x01, 0x86, 0x81, 0x81, 0x00, 0x49, 0x80, 0x81, - 0x01, 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x13, 0x2A, 0x00, - 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, 0x16, 0x80, 0x08, 0x80, 0x44, 0x01, 0x00, - 0x00, 0x46, 0x01, 0xC0, 0x02, 0x86, 0x41, 0x40, 0x00, 0xC0, 0x01, 0x80, 0x02, - 0x00, 0x02, 0x00, 0x03, 0x4C, 0x82, 0x40, 0x01, 0xDC, 0x01, 0x81, 0x01, 0x17, - 0xC0, 0xC0, 0x03, 0x16, 0x40, 0x06, 0x80, 0x8C, 0x02, 0x41, 0x01, 0x8C, 0x42, - 0x02, 0x05, 0xC0, 0x02, 0x80, 0x02, 0x00, 0x03, 0x00, 0x03, 0x40, 0x03, 0x00, - 0x05, 0xDC, 0x42, 0x81, 0x01, 0x17, 0x40, 0xC1, 0x05, 0x16, 0x40, 0x04, 0x80, - 0x17, 0xC0, 0x00, 0x06, 0x16, 0xC0, 0x03, 0x80, 0x19, 0x00, 0x41, 0x07, 0x16, - 0x40, 0x03, 0x80, 0xC0, 0x03, 0x80, 0x02, 0x00, 0x04, 0x00, 0x03, 0x4C, 0x84, - 0x40, 0x05, 0xDC, 0x03, 0x81, 0x01, 0x17, 0xC0, 0xC0, 0x07, 0x16, 0xC0, 0x01, - 0x80, 0x8C, 0x44, 0x84, 0x04, 0x17, 0x80, 0x41, 0x09, 0x16, 0x00, 0x01, 0x80, - 0x84, 0x04, 0x80, 0x00, 0x86, 0xC4, 0x41, 0x09, 0x8C, 0x84, 0x04, 0x05, 0x09, - 0x00, 0x01, 0x09, 0x1E, 0x00, 0x80, 0x00, 0x44, 0x01, 0x00, 0x01, 0x49, 0x40, - 0x81, 0x01, 0x42, 0x01, 0x80, 0x00, 0x5E, 0x01, 0x00, 0x01, 0x1E, 0x00, 0x80, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x66, 0x75, - 0x6E, 0x63, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, - 0x04, 0x00, 0x00, 0x00, 0x4A, 0x4D, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x04, 0x09, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4F, 0x52, - 0x4C, 0x4F, 0x4F, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC0, 0x04, 0x07, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x4C, 0x49, 0x4E, 0x45, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x00, 0x02, 0x04, 0x00, 0x09, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x40, - 0x01, 0x06, 0x01, 0x81, 0x00, 0x43, 0x01, 0x00, 0x03, 0xC4, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x02, 0xDC, 0x81, 0x00, 0x01, 0x17, 0x40, 0xC0, 0x03, 0x16, - 0x00, 0x02, 0x80, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x02, 0xDC, 0xC1, - 0x00, 0x01, 0x80, 0x01, 0x00, 0x04, 0x40, 0x01, 0x80, 0x03, 0x17, 0x80, 0x40, - 0x03, 0x16, 0x40, 0x00, 0x80, 0xC6, 0xC1, 0x40, 0x00, 0x86, 0x01, 0x81, 0x03, - 0xDB, 0x41, 0x80, 0x02, 0x16, 0x00, 0x00, 0x80, 0xC1, 0x01, 0x01, 0x00, 0x49, - 0xC0, 0x81, 0x01, 0xCC, 0x01, 0xC0, 0x01, 0x49, 0x80, 0x81, 0x03, 0x1E, 0x00, - 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x3F, 0x04, 0x06, 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, - 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x76, 0x61, - 0x6C, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, - 0x0D, 0x0F, 0x00, 0x00, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x40, 0x02, 0x80, 0x00, 0x80, 0x02, 0x80, 0x01, 0xCC, 0x02, 0xC0, 0x01, 0xDC, - 0x41, 0x80, 0x02, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, - 0x80, 0x00, 0x80, 0x02, 0x00, 0x01, 0xC0, 0x02, 0x80, 0x01, 0x00, 0x03, 0x00, - 0x03, 0xDD, 0x01, 0x00, 0x03, 0xDE, 0x01, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x99, 0x00, - 0x00, 0x00, 0x03, 0x07, 0x00, 0x0F, 0x1E, 0x00, 0x00, 0x00, 0xCC, 0x01, 0xC0, - 0x01, 0xC6, 0xC1, 0x81, 0x00, 0x0C, 0x42, 0xC0, 0x01, 0x49, 0x00, 0x40, 0x04, - 0x03, 0x02, 0x00, 0x04, 0x44, 0x02, 0x00, 0x00, 0x80, 0x02, 0x80, 0x03, 0x5C, - 0x82, 0x00, 0x01, 0x17, 0x80, 0xC0, 0x04, 0x16, 0x00, 0x02, 0x80, 0x44, 0x02, - 0x80, 0x00, 0x80, 0x02, 0x80, 0x03, 0xC1, 0x02, 0x00, 0x00, 0x5C, 0x82, 0x80, - 0x01, 0x00, 0x02, 0x80, 0x04, 0x17, 0xC0, 0x40, 0x04, 0x16, 0x40, 0x00, 0x80, - 0x46, 0x02, 0x41, 0x00, 0x06, 0xC2, 0x81, 0x04, 0x4C, 0x42, 0xC1, 0x01, 0x49, - 0x00, 0x82, 0x04, 0x44, 0x02, 0x00, 0x01, 0x80, 0x02, 0x00, 0x00, 0xC0, 0x02, - 0x80, 0x00, 0x00, 0x03, 0x00, 0x01, 0x40, 0x03, 0x80, 0x01, 0x80, 0x03, 0x00, - 0x03, 0x5D, 0x02, 0x00, 0x03, 0x5E, 0x02, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x04, 0x06, 0x00, 0x00, - 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, - 0x74, 0x61, 0x62, 0x6C, 0x65, 0x76, 0x61, 0x6C, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, - 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x0B, 0x07, 0x00, - 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, - 0x00, 0x40, 0x02, 0x80, 0x01, 0x80, 0x02, 0x80, 0x01, 0x9C, 0x41, 0x80, 0x02, - 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, - 0x0A, 0x11, 0x00, 0x00, 0x00, 0x8C, 0x01, 0xC0, 0x01, 0x86, 0x81, 0x81, 0x00, - 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0xDC, 0x81, 0x00, 0x01, 0x17, - 0x40, 0xC0, 0x03, 0x16, 0x80, 0x01, 0x80, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, - 0x00, 0x03, 0x4C, 0x82, 0xC0, 0x01, 0x46, 0x42, 0x82, 0x00, 0xDC, 0x81, 0x80, - 0x01, 0xDA, 0x41, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0xC1, 0xC1, 0x00, 0x00, - 0x49, 0xC0, 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, 0x06, 0x00, 0x00, 0x00, - 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x0C, 0x10, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x80, 0x02, - 0x01, 0x02, 0x00, 0x00, 0xA0, 0x41, 0x02, 0x80, 0x8C, 0x42, 0x82, 0x01, 0x8D, - 0x02, 0x40, 0x05, 0x19, 0x00, 0x81, 0x04, 0x16, 0xC0, 0x00, 0x80, 0xCC, 0x42, - 0x82, 0x01, 0xC6, 0xC2, 0x82, 0x00, 0xDA, 0x42, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x80, 0xC3, 0x02, 0x80, 0x05, 0x49, 0xC0, 0x02, 0x05, 0x9F, 0x01, 0xFD, 0x7F, - 0x1E, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0x00, - 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x09, 0x00, 0x00, - 0x00, 0x49, 0x00, 0xC0, 0x01, 0x81, 0x41, 0x00, 0x00, 0xCD, 0x41, 0xC0, 0x02, - 0x01, 0x42, 0x00, 0x00, 0xA0, 0x41, 0x00, 0x80, 0x8C, 0x42, 0x82, 0x01, 0x49, - 0x80, 0x40, 0x05, 0x9F, 0x01, 0xFF, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xCB, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x08, 0x00, 0x00, 0x00, 0x81, 0x01, - 0x00, 0x00, 0xCD, 0x41, 0xC0, 0x02, 0x01, 0x42, 0x00, 0x00, 0xA0, 0x41, 0x00, - 0x80, 0x8C, 0x42, 0x82, 0x01, 0x49, 0x40, 0x40, 0x05, 0x9F, 0x01, 0xFF, 0x7F, - 0x1E, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, 0xD7, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x0B, 0x00, 0x00, 0x00, 0x49, 0x00, 0xC0, - 0x01, 0x8C, 0x01, 0xC0, 0x01, 0x49, 0x00, 0x40, 0x03, 0x81, 0x41, 0x00, 0x00, - 0xCD, 0x01, 0xC0, 0x02, 0x01, 0x02, 0x00, 0x00, 0xA0, 0x41, 0x00, 0x80, 0x8C, - 0x42, 0x82, 0x01, 0x49, 0x80, 0x40, 0x05, 0x9F, 0x01, 0xFF, 0x7F, 0x1E, 0x00, - 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0x00, - 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x08, 0x00, 0x00, - 0x00, 0x81, 0x01, 0x00, 0x00, 0xCD, 0x41, 0xC0, 0x02, 0x01, 0x42, 0x00, 0x00, - 0xA0, 0x41, 0x00, 0x80, 0x8C, 0x42, 0x82, 0x01, 0x49, 0x80, 0x40, 0x05, 0x9F, - 0x01, 0xFF, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0x3F, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x0A, 0x09, 0x00, 0x00, 0x00, 0x8C, 0x01, 0xC0, 0x01, 0xC6, 0x41, 0x40, - 0x00, 0xC6, 0x81, 0xC0, 0x03, 0xCD, 0xC1, 0xC0, 0x03, 0x01, 0xC2, 0x00, 0x00, - 0xA0, 0x01, 0x00, 0x80, 0x49, 0x00, 0xC1, 0x04, 0x9F, 0x41, 0xFF, 0x7F, 0x1E, - 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x00, 0x04, 0x0B, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x73, 0x6C, - 0x6F, 0x74, 0x73, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, - 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x0A, 0x12, - 0x00, 0x00, 0x00, 0x19, 0x40, 0x01, 0x80, 0x16, 0x80, 0x03, 0x80, 0x8C, 0x01, - 0xC0, 0x01, 0x86, 0x81, 0x81, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x03, 0xDC, 0x81, 0x00, 0x01, 0x17, 0x40, 0xC0, 0x03, 0x16, 0x40, 0x01, 0x80, - 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x03, 0x41, 0x02, 0x00, 0x00, 0xDC, - 0x81, 0x80, 0x01, 0xDA, 0x41, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0xC1, 0x81, - 0x00, 0x00, 0x49, 0xC0, 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, 0x06, 0x00, - 0x00, 0x00, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x0F, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x8C, 0x01, - 0xC0, 0x01, 0x86, 0x81, 0x81, 0x00, 0x9A, 0x41, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x80, 0x81, 0x41, 0x00, 0x00, 0x49, 0x80, 0x81, 0x01, 0x1E, 0x00, 0x80, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x80, 0x16, 0x00, 0x00, - 0x80, 0x49, 0x40, 0xC0, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x06, 0x0B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x84, 0x00, - 0x00, 0x00, 0xC6, 0x40, 0x40, 0x00, 0x01, 0x81, 0x00, 0x00, 0x44, 0x01, 0x80, - 0x00, 0x9C, 0x80, 0x00, 0x02, 0xC1, 0xC0, 0x00, 0x00, 0x55, 0xC0, 0x80, 0x00, - 0x09, 0x40, 0x00, 0x82, 0x5E, 0x00, 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x04, 0x05, 0x00, - 0x00, 0x00, 0x61, 0x72, 0x67, 0x73, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x2E, - 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x30, 0x2A, 0x24, 0x00, 0x04, 0x09, 0x00, - 0x00, 0x00, 0x61, 0x72, 0x67, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, - 0x07, 0x07, 0x00, 0x12, 0x4F, 0x00, 0x00, 0x00, 0xC6, 0x01, 0x40, 0x00, 0xDA, - 0x01, 0x00, 0x00, 0x16, 0xC0, 0x06, 0x80, 0x57, 0x40, 0xC0, 0x02, 0x16, 0x40, - 0x06, 0x80, 0x01, 0x82, 0x00, 0x00, 0x41, 0xC2, 0x00, 0x00, 0x80, 0x02, 0x80, - 0x02, 0xC1, 0xC2, 0x00, 0x00, 0x60, 0xC2, 0x01, 0x80, 0x40, 0x03, 0x00, 0x04, - 0x84, 0x03, 0x00, 0x00, 0xC4, 0x03, 0x80, 0x00, 0x0C, 0x04, 0x03, 0x02, 0x06, - 0x04, 0x04, 0x01, 0xDC, 0x83, 0x00, 0x01, 0x86, 0xC3, 0x03, 0x07, 0x15, 0x82, - 0x83, 0x06, 0x5F, 0x82, 0xFD, 0x7F, 0x44, 0x02, 0x00, 0x01, 0x80, 0x02, 0x00, - 0x04, 0xC6, 0x02, 0x41, 0x00, 0xDA, 0x42, 0x00, 0x00, 0x16, 0x80, 0x00, 0x80, - 0xC4, 0x02, 0x80, 0x01, 0x00, 0x03, 0x00, 0x00, 0xDC, 0x82, 0x00, 0x01, 0x5C, - 0x82, 0x80, 0x01, 0x5A, 0x42, 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0xC3, 0x01, - 0x80, 0x03, 0x06, 0x42, 0x41, 0x00, 0x57, 0x80, 0x41, 0x04, 0x16, 0x80, 0x05, - 0x80, 0x57, 0x40, 0x40, 0x03, 0x16, 0x00, 0x05, 0x80, 0x54, 0x02, 0x00, 0x04, - 0x18, 0x80, 0x81, 0x04, 0x16, 0x00, 0x00, 0x80, 0xC3, 0x01, 0x80, 0x03, 0x41, - 0xC2, 0x00, 0x00, 0x94, 0x02, 0x00, 0x04, 0xC1, 0xC2, 0x00, 0x00, 0x60, 0xC2, - 0x02, 0x80, 0x44, 0x03, 0x00, 0x02, 0x80, 0x03, 0x00, 0x04, 0xC0, 0x03, 0x00, - 0x06, 0x00, 0x04, 0x00, 0x06, 0x5C, 0x83, 0x00, 0x02, 0x57, 0xC0, 0xC1, 0x06, - 0x16, 0x00, 0x01, 0x80, 0x8C, 0x03, 0x03, 0x02, 0x8D, 0xC3, 0x40, 0x07, 0xC4, - 0x03, 0x80, 0x02, 0xC6, 0x43, 0x83, 0x07, 0x89, 0xC0, 0x03, 0x07, 0x5F, 0x82, - 0xFC, 0x7F, 0x46, 0x02, 0x42, 0x00, 0x5A, 0x02, 0x00, 0x00, 0x16, 0xC0, 0x02, - 0x80, 0x80, 0x02, 0x80, 0x04, 0xC0, 0x02, 0x80, 0x00, 0x00, 0x03, 0x00, 0x01, - 0x40, 0x03, 0x80, 0x01, 0x80, 0x03, 0x00, 0x02, 0xC0, 0x03, 0x80, 0x02, 0x00, - 0x04, 0x00, 0x03, 0x40, 0x04, 0x80, 0x03, 0x9C, 0x82, 0x00, 0x04, 0x9A, 0x02, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x80, 0xC3, 0x01, 0x80, 0x03, 0xDA, 0x01, 0x00, - 0x00, 0x16, 0xC0, 0x00, 0x80, 0x84, 0x02, 0x00, 0x03, 0x86, 0x42, 0x42, 0x05, - 0x8C, 0x82, 0x82, 0x01, 0x49, 0xC0, 0x01, 0x05, 0x1E, 0x00, 0x80, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF, 0x04, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x04, 0x09, 0x00, - 0x00, 0x00, 0x61, 0x72, 0x67, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x00, 0x04, 0x08, - 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x73, 0x00, 0x04, 0x02, - 0x00, 0x00, 0x00, 0x2A, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x04, - 0x08, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x04, - 0x07, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x4C, 0x49, 0x4E, 0x45, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x01, 0x00, 0x00, 0x7C, 0x01, 0x00, 0x00, - 0x04, 0x06, 0x00, 0x10, 0x31, 0x00, 0x00, 0x00, 0x86, 0xC1, 0x80, 0x00, 0xC4, - 0x01, 0x00, 0x00, 0xC6, 0x01, 0xC0, 0x03, 0xCC, 0xC1, 0x01, 0x01, 0x09, 0x80, - 0x81, 0x03, 0xC4, 0x01, 0x80, 0x00, 0x00, 0x02, 0x00, 0x03, 0xDC, 0x81, 0x00, - 0x01, 0x17, 0x40, 0xC0, 0x03, 0x16, 0x80, 0x07, 0x80, 0xC4, 0x01, 0x00, 0x01, - 0xC6, 0x81, 0x81, 0x03, 0xDA, 0x01, 0x00, 0x00, 0x16, 0x40, 0x02, 0x80, 0x04, - 0x02, 0x80, 0x01, 0x40, 0x02, 0x80, 0x03, 0x80, 0x02, 0x00, 0x00, 0xC0, 0x02, - 0x80, 0x00, 0x00, 0x03, 0x00, 0x01, 0x40, 0x03, 0x80, 0x01, 0x80, 0x03, 0x00, - 0x02, 0xC0, 0x03, 0x80, 0x02, 0x1C, 0x42, 0x00, 0x04, 0x1E, 0x00, 0x80, 0x00, - 0x06, 0x82, 0x40, 0x00, 0x17, 0x00, 0x02, 0x03, 0x16, 0x40, 0x03, 0x80, 0x06, - 0xC2, 0x40, 0x00, 0x06, 0x02, 0x41, 0x04, 0x1A, 0x42, 0x00, 0x00, 0x16, 0x40, - 0x02, 0x80, 0x57, 0x40, 0x41, 0x02, 0x16, 0xC0, 0x00, 0x80, 0x06, 0xC2, 0x40, - 0x00, 0x06, 0x82, 0x41, 0x04, 0x17, 0x00, 0x02, 0x02, 0x16, 0xC0, 0x00, 0x80, - 0x04, 0x02, 0x00, 0x00, 0x06, 0xC2, 0x41, 0x04, 0x0C, 0x02, 0x02, 0x01, 0x09, - 0x00, 0x42, 0x04, 0xC0, 0x01, 0x80, 0x01, 0x0C, 0x42, 0x81, 0x01, 0x0D, 0x42, - 0x42, 0x04, 0x41, 0x42, 0x02, 0x00, 0xE0, 0x01, 0x00, 0x80, 0x49, 0x80, 0x42, - 0x05, 0xDF, 0x41, 0xFF, 0x7F, 0x1E, 0x00, 0x80, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x00, 0x00, 0x00, 0x54, 0x59, 0x50, 0x45, 0x00, 0x04, 0x09, 0x00, - 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x05, - 0x00, 0x00, 0x00, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x69, 0x73, - 0x76, 0x61, 0x72, 0x61, 0x72, 0x67, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0xBF, 0x04, 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, - 0x73, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x4C, 0x49, 0x4E, 0x45, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, - 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x40, 0x00, 0x00, 0x1C, - 0x80, 0x00, 0x01, 0x46, 0x80, 0x40, 0x00, 0x84, 0x00, 0x00, 0x00, 0x5C, 0x40, - 0x00, 0x01, 0x1E, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x00, 0x04, 0x08, 0x00, - 0x00, 0x00, 0x6A, 0x69, 0x74, 0x2E, 0x6F, 0x70, 0x74, 0x00, 0x04, 0x10, 0x00, - 0x00, 0x00, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x5F, 0x63, 0x61, 0x6C, 0x6C, - 0x68, 0x69, 0x6E, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff -Nru corsix-th-0.61/CorsixTH/Src/lua_rnc.cpp corsix-th-0.62/CorsixTH/Src/lua_rnc.cpp --- corsix-th-0.61/CorsixTH/Src/lua_rnc.cpp 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/lua_rnc.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,75 @@ +#include "lua_rnc.h" +#include "../../common/rnc.h" +#include "th_lua.h" + +//! Provides lua function to decompress RNC data +/*! + @param L Lua state where the function is called from. In lua a call + to this function has one parameter which is the RNC compressed data. + The return value is the decompressed data. +*/ +static int l_decompress(lua_State *L) +{ + size_t inlen; + const uint8_t* in = reinterpret_cast(luaL_checklstring(L, 1, &inlen)); + + // Verify that the data contains an RNC signature, and that the input + // size matches the size specified in the data header. + if(inlen < rnc_header_size || inlen != rnc_input_size(in)) + { + lua_pushnil(L); + lua_pushliteral(L, "Input is not RNC compressed data"); + return 2; + } + uint32_t outlen = rnc_output_size(in); + + // Allocate scratch area as Lua userdata so that if something horrible + // happens, it'll be cleaned up by Lua's GC. Remember that most Lua API + // calls can throw errors, so they all have to be wrapped with code to + // detect errors and free the buffer if said buffer was not managed by Lua. + void* outbuf = lua_newuserdata(L, outlen); + + lua_pushnil(L); + switch(rnc_unpack(in, (uint8_t*)outbuf)) + { + case rnc_status::ok: + lua_pushlstring(L, (const char*)outbuf, outlen); + return 1; + + case rnc_status::file_is_not_rnc: + lua_pushliteral(L, "Input is not RNC compressed data"); + break; + + case rnc_status::huf_decode_error: + lua_pushliteral(L, "Invalid Huffman coding"); + break; + + case rnc_status::file_size_mismatch: + lua_pushliteral(L, "Size mismatch"); + break; + + case rnc_status::packed_crc_error: + lua_pushliteral(L, "Incorrect packed CRC"); + break; + + case rnc_status::unpacked_crc_error: + lua_pushliteral(L, "Incorrect unpacked CRC"); + break; + + default: + lua_pushliteral(L, "Unknown error decompressing RNC data"); + break; + } + return 2; +} + +static const std::vector rnclib = { + {"decompress", l_decompress}, + {nullptr, nullptr} +}; + +int luaopen_rnc(lua_State *L) +{ + luaT_register(L, "rnc", rnclib); + return 1; +} diff -Nru corsix-th-0.61/CorsixTH/Src/lua_rnc.h corsix-th-0.62/CorsixTH/Src/lua_rnc.h --- corsix-th-0.61/CorsixTH/Src/lua_rnc.h 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/lua_rnc.h 2018-07-21 11:13:17.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef CORSIX_TH_LUA_RNC +#define CORSIX_TH_LUA_RNC + +#include "th_lua.h" + +int luaopen_rnc(lua_State *L); + +#endif diff -Nru corsix-th-0.61/CorsixTH/Src/main.cpp corsix-th-0.62/CorsixTH/Src/main.cpp --- corsix-th-0.61/CorsixTH/Src/main.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/main.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -25,10 +25,9 @@ extern "C" { int luaopen_random(lua_State *L); } -#include "rnc.h" #include "th_lua.h" +#include "lua_rnc.h" #include "lua_sdl.h" -#include "jit_opt.h" #include "persist_lua.h" #include "iso_fs.h" #include @@ -40,7 +39,7 @@ #endif // End of config file checking -int CorsixTH_lua_main_no_eval(lua_State *L) +int lua_main_no_eval(lua_State *L) { // assert(_VERSION == LUA_VERSION) size_t iLength; @@ -58,42 +57,6 @@ // math.random* = Mersenne twister variant luaT_cpcall(L, luaopen_random, nullptr); - // package.preload["jit.opt"] = load(jit_opt_lua) - // package.preload["jit.opt_inline"] = load(jit_opt_inline_lua) - lua_getglobal(L, "package"); - lua_getfield(L, -1, "preload"); - luaL_loadbuffer(L, (const char*)jit_opt_lua, sizeof(jit_opt_lua), - "jit/opt.luac"); - lua_setfield(L, -2, "jit.opt"); - luaL_loadbuffer(L, (const char*)jit_opt_inline_lua, - sizeof(jit_opt_inline_lua), "jit/opt_inline.luac"); - lua_setfield(L, -2, "jit.opt_inline"); - lua_pop(L, 2); - - // if registry._LOADED.jit then - // require"jit.opt".start() - // else - // print "Notice: ..." - // end - // (this could be done in Lua rather than here, but ideally the optimiser - // should be turned on before any Lua code is loaded) - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, -1, "jit"); - if(lua_type(L, -1) == LUA_TNIL) - { - lua_pop(L, 2); - } - else - { - lua_pop(L, 2); - lua_getglobal(L, "require"); - lua_pushliteral(L, "jit.opt"); - lua_call(L, 1, 1); - lua_getfield(L, -1, "start"); - lua_call(L, 0, 0); - lua_pop(L, 1); - } - // Fill in package.preload table so that calls to require("X") from Lua // will call the appropriate luaopen_X function in C. #define PRELOAD(name, fn) \ @@ -128,59 +91,27 @@ } } - // Code to try several variations on finding CorsixTH.lua: - // CorsixTH.lua - // CorsixTH/CorsixTH.lua - // ../CorsixTH.lua - // ../CorsixTH/CorsixTH.lua - // ../../CorsixTH.lua - // ../../CorsixTH/CorsixTH.lua - // ../../../CorsixTH.lua - // ../../../CorsixTH/CorsixTH.lua - // It is simpler to write this in Lua than in C. - const char sLuaCorsixTHLua[] = - "local name, sep, code = \"CorsixTH.lua\", package.config:sub(1, 1)\n" - "local root = (... or \"\"):match(\"^(.*[\"..sep..\"])\") or \"\"\n" -#ifdef __APPLE__ // Darrell: Search inside the bundle first. - // There's probably a better way of doing this. -#if defined(IS_CORSIXTH_APP) - "code = loadfile(\"CorsixTH.app/Contents/Resources/\"..name)\n" - "if code then return code end\n" -#endif -#endif - "for num_dotdot = 0, 3 do\n" - " for num_dir = 0, 1 do\n" - " code = loadfile(root..(\"..\"..sep):rep(num_dotdot)..\n" - " (\"CorsixTH\"..sep):rep(num_dir)..name)\n" - " if code then return code end \n" - " end \n" - "end \n" - "return loadfile(name)"; - - // return assert(loadfile"CorsixTH.lua")(...) if(!bGotScriptFile) { lua_getglobal(L, "assert"); - luaL_loadbuffer(L, sLuaCorsixTHLua, std::strlen(sLuaCorsixTHLua), - "@main.cpp (l_main bootstrap)"); - if(lua_gettop(L) == 2) - lua_pushnil(L); - else - lua_pushvalue(L, 1); + lua_getglobal(L, "loadfile"); + lua_pushstring(L, CORSIX_TH_INTERPRETER_PATH); + bGotScriptFile = true; } + lua_call(L, 1, 2); lua_call(L, 2, 1); lua_insert(L, 1); return lua_gettop(L); } -int CorsixTH_lua_main(lua_State *L) +int lua_main(lua_State *L) { - lua_call(L, CorsixTH_lua_main_no_eval(L) - 1, LUA_MULTRET); + lua_call(L, lua_main_no_eval(L) - 1, LUA_MULTRET); return lua_gettop(L); } -int CorsixTH_lua_stacktrace(lua_State *L) +int lua_stacktrace(lua_State *L) { // err = tostring(err) lua_settop(L, 1); @@ -203,7 +134,7 @@ return 1; } -int CorsixTH_lua_panic(lua_State *L) +int lua_panic(lua_State *L) { std::fprintf(stderr, "A Lua error has occurred in CorsixTH outside of protected " "mode!!\n"); diff -Nru corsix-th-0.61/CorsixTH/Src/main.h corsix-th-0.62/CorsixTH/Src/main.h --- corsix-th-0.61/CorsixTH/Src/main.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/main.h 2018-07-21 11:13:17.000000000 +0000 @@ -33,14 +33,14 @@ transfers control to CorsixTH.lua as soon as possible (so that as little as possible behaviour is hardcoded into C rather than Lua). */ -int CorsixTH_lua_main(lua_State *L); +int lua_main(lua_State *L); //! Alternative lua mode entry point /*! Behaves like CorsixTH_lua_main, except that it doesn't transfer control over to Lua scripts - it just prepares everything for them and loads them. */ -int CorsixTH_lua_main_no_eval(lua_State *L); +int lua_main_no_eval(lua_State *L); //! Process a caught error before returning it to the caller /*! @@ -49,7 +49,7 @@ processing the error, the caller receives LUA_ERRERR rather than panicking while processing it itself. */ -int CorsixTH_lua_stacktrace(lua_State *L); +int lua_stacktrace(lua_State *L); //! Process an uncaught Lua error before aborting /*! @@ -57,6 +57,6 @@ which can be done when they do, but at least the user should be informed, and the error message printed. */ -int CorsixTH_lua_panic(lua_State *L); +int lua_panic(lua_State *L); #endif // CORSIX_TH_MAIN_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/persist_lua.cpp corsix-th-0.62/CorsixTH/Src/persist_lua.cpp --- corsix-th-0.61/CorsixTH/Src/persist_lua.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/persist_lua.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -32,7 +32,7 @@ #pragma warning(disable: 4996) // Disable "std::strcpy unsafe" warnings under MSVC #endif -enum PersistTypes +enum persist_type { // LUA_TNIL = 0, // LUA_TBOOLEAN, // Used for false @@ -70,18 +70,19 @@ can be more efficient to use this structure, which can load them without concatenating them. Sample usage is: - LoadMultiBuffer_t ls; + load_multi_buffer ls; ls.s[0] = lua_tolstring(L, -2, &ls.i[0]); ls.s[1] = lua_tolstring(L, -1, &ls.i[1]); lua_load(L, LoadMultiBuffer_t::load_fn, &ls, "chunk name"); */ -struct LoadMultiBuffer_t +class load_multi_buffer { +public: const char *s[3]; size_t i[3]; int n; - LoadMultiBuffer_t() + load_multi_buffer() { s[0] = s[1] = s[2] = nullptr; i[0] = i[1] = i[2] = 0; @@ -90,7 +91,7 @@ static const char* load_fn(lua_State *L, void *ud, size_t *size) { - LoadMultiBuffer_t *pThis = reinterpret_cast(ud); + load_multi_buffer *pThis = reinterpret_cast(ud); for( ; pThis->n < 3; ++pThis->n) { @@ -108,9 +109,9 @@ //! Basic implementation of persistance interface /*! - self - Instance of LuaPersistBasicWriter allocated as a Lua userdata + self - Instance of lua_persist_basic_writer allocated as a Lua userdata self metatable: - __gc - ~LuaPersistBasicWriter (via l_crude_gc) + __gc - ~lua_persist_basic_writer (via l_crude_gc) ":" - [1] - pre-populated prototype persistance names ":" - "" @@ -123,25 +124,24 @@ upvalue 1 - permanents table upvalue 2 - self */ -class LuaPersistBasicWriter : public LuaPersistWriter +class lua_persist_basic_writer : public lua_persist_writer { public: - LuaPersistBasicWriter(lua_State *L) - : m_L(L), - m_data() + lua_persist_basic_writer(lua_State *L) + : L(L), + data() { } - ~LuaPersistBasicWriter() + ~lua_persist_basic_writer() { } - lua_State* getStack() override + lua_State* get_stack() override { - return m_L; + return L; } void init() { - lua_State *L = m_L; lua_createtable(L, 1, 8); // Environment lua_pushvalue(L, 2); // Permanent objects lua_rawseti(L, -2, 1); @@ -153,42 +153,40 @@ lua_setmetatable(L, -2); lua_setfenv(L, 1); lua_createtable(L, 1, 4); // Metatable - luaT_pushcclosure(L, l_crude_gc, 0); + luaT_pushcclosure(L, l_crude_gc, 0); lua_setfield(L, -2, "__gc"); lua_pushvalue(L, luaT_upvalueindex(1)); // Prototype persistance names lua_rawseti(L, -2, 1); lua_setmetatable(L, 1); - m_iNextIndex = 1; - m_iDataLength = 0; - m_bHadError = false; + next_index = 1; + data_size = 0; + had_error = false; } int finish() { - if(getError() != nullptr) + if(get_error() != nullptr) { - lua_pushnil(m_L); - lua_pushstring(m_L, getError()); - lua_getmetatable(m_L, 1); - lua_getfield(m_L, -1, "err"); - lua_replace(m_L, -2); + lua_pushnil(L); + lua_pushstring(L, get_error()); + lua_getmetatable(L, 1); + lua_getfield(L, -1, "err"); + lua_replace(L, -2); return 3; } else { - lua_pushlstring(m_L, m_data.c_str(), m_data.length()); + lua_pushlstring(L, data.c_str(), data.length()); return 1; } } - void fastWriteStackObject(int iIndex) override + void fast_write_stack_object(int iIndex) override { - lua_State *L = m_L; - if(lua_type(L, iIndex) != LUA_TUSERDATA) { - writeStackObject(iIndex); + write_stack_object(iIndex); return; } @@ -207,25 +205,25 @@ if(!lua_isnil(L, -1) || !lua_isnil(L, -2)) { lua_pop(L, 3); - writeStackObject(iIndex); + write_stack_object(iIndex); return; } lua_pop(L, 2); // Save the index to the cache lua_pushvalue(L, iIndex); - lua_pushnumber(L, (lua_Number)(m_iNextIndex++)); + lua_pushnumber(L, (lua_Number)(next_index++)); lua_settable(L, -3); - if(!_checkThatUserdataCanBeDepersisted(iIndex)) + if(!check_that_userdata_can_be_depersisted(iIndex)) return; // Write type, metatable, and then environment uint8_t iType = LUA_TUSERDATA; - writeByteStream(&iType, 1); - writeStackObject(-1); + write_byte_stream(&iType, 1); + write_stack_object(-1); lua_getfenv(L, iIndex); - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 1); // Write the raw data @@ -243,14 +241,12 @@ lua_pop(L, 2); } } - writeVUInt((uint64_t)0x42); // sync marker + write_uint((uint64_t)0x42); // sync marker lua_pop(L, 1); } - void writeStackObject(int iIndex) override + void write_stack_object(int iIndex) override { - lua_State *L = m_L; - // Convert index from relative to absolute if(iIndex < 0 && iIndex > LUA_REGISTRYINDEX) iIndex = lua_gettop(L) + 1 + iIndex; @@ -260,7 +256,7 @@ if(iType == LUA_TNIL || iType == LUA_TNONE) { uint8_t iByte = LUA_TNIL; - writeByteStream(&iByte, 1); + write_byte_stream(&iByte, 1); } else if(iType == LUA_TBOOLEAN) { @@ -269,7 +265,7 @@ iByte = PERSIST_TTRUE; else iByte = LUA_TBOOLEAN; - writeByteStream(&iByte, 1); + write_byte_stream(&iByte, 1); } else if(iType == LUA_TNUMBER) { @@ -280,16 +276,16 @@ // NB: 16383 = 2^14-1, which is the maximum value which // can fit into two bytes of VUInt. uint8_t iByte = PERSIST_TINTEGER; - writeByteStream(&iByte, 1); + write_byte_stream(&iByte, 1); uint16_t iValue = (uint16_t)fValue; - writeVUInt(iValue); + write_uint(iValue); } else { // Other numbers are written as an 8 byte double uint8_t iByte = LUA_TNUMBER; - writeByteStream(&iByte, 1); - writeByteStream(reinterpret_cast(&fValue), sizeof(double)); + write_byte_stream(&iByte, 1); + write_byte_stream(reinterpret_cast(&fValue), sizeof(double)); } } else @@ -307,19 +303,18 @@ // would have been called, and the appropriate data written, and 0 // would be returned. Otherwise, the index would be returned, which // we offset by the number of types, and then write. - writeVUInt(iValue + PERSIST_TCOUNT - 1); + write_uint(iValue + PERSIST_TCOUNT - 1); } } } - int writeObjectRaw() + int write_object_raw() { - lua_State *L = m_L; uint8_t iType; // Save the index to the cache lua_pushvalue(L, 2); - lua_pushnumber(L, (lua_Number)(m_iNextIndex++)); + lua_pushnumber(L, (lua_Number)(next_index++)); lua_settable(L, 1); // Lookup the object in the permanents table @@ -330,14 +325,14 @@ // Object is in the permanents table. uint8_t iType = PERSIST_TPERMANENT; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); // Replace self's environment with self (for call to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); lua_replace(L, 1); // Write the key corresponding to the permanent object - writeStackObject(-1); + write_stack_object(-1); } else { @@ -352,12 +347,12 @@ case LUA_TSTRING: { iType = LUA_TSTRING; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); // Strings are simple: length and then bytes (not null terminated) size_t iLength; const char *sString = lua_tolstring(L, 2, &iLength); - writeVUInt(iLength); - writeByteStream(reinterpret_cast(sString), iLength); + write_uint(iLength); + write_byte_stream(reinterpret_cast(sString), iLength); break; } case LUA_TTABLE: { @@ -375,21 +370,21 @@ if(lua_getmetatable(L, iTable)) { iType = PERSIST_TTABLE_WITH_META; - writeByteStream(&iType, 1); - writeStackObject(-1); + write_byte_stream(&iType, 1); + write_stack_object(-1); lua_pop(L, 1); } else { iType = LUA_TTABLE; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); } // Write the children as key, value pairs lua_pushnil(L); while(lua_next(L, iTable)) { - writeStackObject(-2); + write_stack_object(-2); // The naive thing to do now would be writeStackObject(-1) // but this can easily lead to Lua's C call stack limit // being hit. To reduce the likelihood of this happening, @@ -406,7 +401,7 @@ lua_checkstack(L, 10); iTable += 2; lua_pushvalue(L, iTable); - lua_pushnumber(L, (lua_Number)(m_iNextIndex++)); + lua_pushnumber(L, (lua_Number)(next_index++)); lua_settable(L, 2); goto table_reentry; table_resume: iTable -= 2; @@ -414,18 +409,18 @@ else { lua_pop(L, 2); - writeStackObject(-1); + write_stack_object(-1); } } else - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 1); } // Write a nil to mark the end of the children (as nil is the // only value which cannot be used as a key in a table). iType = LUA_TNIL; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); if(iTable != 3) goto table_resume; break; } @@ -433,13 +428,13 @@ case LUA_TFUNCTION: if(lua_iscfunction(L, 2)) { - setErrorObject(2); - setError("Cannot persist C functions"); + set_error_object(2); + set_error("Cannot persist C functions"); } else { iType = LUA_TFUNCTION; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); // Replace self's environment with self (for calls to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); @@ -450,37 +445,37 @@ lua_Debug proto_info; lua_pushvalue(L, 2); lua_getinfo(L, ">Su", &proto_info); - writePrototype(&proto_info, 2); + write_prototype(&proto_info, 2); // Write the values of the upvalues // If available, also write the upvalue IDs (so that in // the future, we could hypothetically rejoin shared // upvalues). An ID is just an opaque sequence of bytes. - writeVUInt(proto_info.nups); + write_uint(proto_info.nups); #if LUA_VERSION_NUM >= 502 - writeVUInt(sizeof(void*)); + write_uint(sizeof(void*)); #else - writeVUInt(0); + write_uint(0); #endif for(int i = 1; i <= proto_info.nups; ++i) { lua_getupvalue(L, 2, i); - writeStackObject(-1); + write_stack_object(-1); #if LUA_VERSION_NUM >= 502 void *pUpvalueID = lua_upvalueid(L, 2, i); - writeByteStream((uint8_t*)&pUpvalueID, sizeof(void*)); + write_byte_stream((uint8_t*)&pUpvalueID, sizeof(void*)); #endif } // Write the environment table lua_getfenv(L, 2); - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 1); } break; case LUA_TUSERDATA: - if(!_checkThatUserdataCanBeDepersisted(2)) + if(!check_that_userdata_can_be_depersisted(2)) break; // Replace self's environment with self (for calls to writeStackObject) @@ -489,10 +484,10 @@ // Write type, metatable, and then environment iType = LUA_TUSERDATA; - writeByteStream(&iType, 1); - writeStackObject(-1); + write_byte_stream(&iType, 1); + write_stack_object(-1); lua_getfenv(L, 2); - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 1); // Write the raw data @@ -508,11 +503,11 @@ lua_call(L, 2, 0); } } - writeVUInt((uint64_t)0x42); // sync marker + write_uint((uint64_t)0x42); // sync marker break; default: - setError(lua_pushfstring(L, "Cannot persist %s values", luaL_typename(L, 2))); + set_error(lua_pushfstring(L, "Cannot persist %s values", luaL_typename(L, 2))); break; } } @@ -520,10 +515,8 @@ return 1; } - bool _checkThatUserdataCanBeDepersisted(int iIndex) + bool check_that_userdata_can_be_depersisted(int iIndex) { - lua_State *L = m_L; - if(lua_getmetatable(L, iIndex)) { lua_getfield(L, -1, "__depersist_size"); @@ -532,7 +525,7 @@ if(static_cast(lua_tointeger(L, -1)) != static_cast(lua_objlen(L, iIndex))) { - setError(lua_pushfstring(L, "__depersist_size is " + set_error(lua_pushfstring(L, "__depersist_size is " "incorrect (%d vs. %d)", (int)lua_objlen(L, iIndex), (int)lua_tointeger(L, -1))); return false; @@ -543,7 +536,7 @@ lua_getfield(L, -3, "__depersist"); if(lua_isnil(L, -1) || lua_isnil(L, -2)) { - setError("Can only persist non-empty userdata" + set_error("Can only persist non-empty userdata" " if they have __persist and __depersist " "metamethods"); return false; @@ -555,7 +548,7 @@ { if(lua_objlen(L, iIndex) != 0) { - setError("Can only persist non-empty userdata if " + set_error("Can only persist non-empty userdata if " "they have a __depersist_size metafield"); return false; } @@ -566,7 +559,7 @@ { if(lua_objlen(L, iIndex) != 0) { - setError("Can only persist userdata without a metatable" + set_error("Can only persist userdata without a metatable" " if their size is zero"); return false; } @@ -575,16 +568,14 @@ return true; } - void writePrototype(lua_Debug *pProtoInfo, int iInstanceIndex) + void write_prototype(lua_Debug *pProtoInfo, int iInstanceIndex) { - lua_State *L = m_L; - // Sanity checks if(pProtoInfo->source[0] != '@') { // @ denotes that the source was a file // (http://www.lua.org/manual/5.1/manual.html#lua_Debug) - setError("Can only persist Lua functions defined in source files"); + set_error("Can only persist Lua functions defined in source files"); return; } if(std::strcmp(pProtoInfo->what, "Lua") != 0) @@ -594,7 +585,7 @@ // Hence "Lua" and "main" should be the only values seen. // NB: Chunks are not functions defined *in* source files, because // chunks *are* source files. - setError(lua_pushfstring(L, "Cannot persist entire Lua chunks (%s)", pProtoInfo->source + 1)); + set_error(lua_pushfstring(L, "Cannot persist entire Lua chunks (%s)", pProtoInfo->source + 1)); lua_pop(L, 1); return; } @@ -609,23 +600,23 @@ { uint64_t iValue = (uint64_t)lua_tonumber(L, -1); lua_pop(L, 3); - writeVUInt(iValue + PERSIST_TCOUNT - 1); + write_uint(iValue + PERSIST_TCOUNT - 1); return; } lua_pop(L, 1); lua_pushvalue(L, -1); - lua_pushnumber(L, (lua_Number)m_iNextIndex++); + lua_pushnumber(L, (lua_Number)next_index++); lua_rawset(L, -4); uint8_t iType = PERSIST_TPROTOTYPE; - writeByteStream(&iType, 1); + write_byte_stream(&iType, 1); // Write upvalue names - writeVUInt(pProtoInfo->nups); + write_uint(pProtoInfo->nups); for(int i = 1; i <= pProtoInfo->nups; ++i) { lua_pushstring(L, lua_getupvalue(L, iInstanceIndex, i)); - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 2); } @@ -635,45 +626,44 @@ lua_rawget(L, -2); if(lua_isnil(L, -1)) { - setError(lua_pushfstring(L, "Lua functions must be given a unique " + set_error(lua_pushfstring(L, "Lua functions must be given a unique " "persistable name in order to be persisted (attempt to persist" " %s:%d)", pProtoInfo->source + 1, pProtoInfo->linedefined)); lua_pop(L, 2); return; } - writeStackObject(-1); + write_stack_object(-1); lua_pop(L, 2); } - void writeByteStream(const uint8_t *pBytes, size_t iCount) override + void write_byte_stream(const uint8_t *pBytes, size_t iCount) override { - if(m_bHadError) + if(had_error) { // If an error occurred, then silently fail to write any // data. return; } - m_data.append(reinterpret_cast(pBytes), iCount); + data.append(reinterpret_cast(pBytes), iCount); } - void setError(const char *sError) override + void set_error(const char *sError) override { // If multiple errors occur, only record the first. - if (m_bHadError) { + if (had_error) { return; } - m_bHadError = true; + had_error = true; // Use the written data buffer to store the error message - m_data.assign(sError); + data.assign(sError); } - void setErrorObject(int iStackObject) + void set_error_object(int iStackObject) { - if(m_bHadError) + if(had_error) return; - lua_State *L = m_L; lua_pushvalue(L, iStackObject); lua_getmetatable(L, luaT_upvalueindex(2)); @@ -682,31 +672,31 @@ lua_pop(L, 1); } - const char* getError() + const char* get_error() { - if(m_bHadError) - return m_data.c_str(); + if(had_error) + return data.c_str(); else return nullptr; } private: - lua_State *m_L; - uint64_t m_iNextIndex; - std::string m_data; - size_t m_iDataLength; - bool m_bHadError; + lua_State *L; + uint64_t next_index; + std::string data; + size_t data_size; + bool had_error; }; static int l_writer_mt_index(lua_State *L) { - return reinterpret_cast( - lua_touserdata(L, luaT_upvalueindex(2)))->writeObjectRaw(); + return reinterpret_cast( + lua_touserdata(L, luaT_upvalueindex(2)))->write_object_raw(); } //! Basic implementation of depersistance interface /*! - self - Instance of LuaPersistBasicReader allocated as a Lua userdata + self - Instance of lua_persist_basic_reader allocated as a Lua userdata self environment: [-3] - self [-2] - pre-populated prototype persistance code @@ -716,38 +706,37 @@ [ 0] - permanents table - self metatable: - __gc - ~LuaPersistBasicReader (via l_crude_gc) + __gc - ~lua_persist_basic_reader (via l_crude_gc) - */ -class LuaPersistBasicReader : public LuaPersistReader +class lua_persist_basic_reader : public lua_persist_reader { public: - LuaPersistBasicReader(lua_State *L) - : m_L(L), - m_stringBuffer() + lua_persist_basic_reader(lua_State *L) + : L(L), + string_buffer() { } - ~LuaPersistBasicReader() + ~lua_persist_basic_reader() { } - lua_State* getStack() override + lua_State* get_stack() override { - return m_L; + return L; } - void setError(const char *sError) override + void set_error(const char *sError) override { - m_bHadError = true; - m_stringBuffer.assign(sError); + had_error = true; + string_buffer.assign(sError); } void init(const uint8_t *pData, size_t iLength) { - lua_State *L = m_L; - m_pData = pData; - m_iDataBufferLength = iLength; - m_iNextIndex = 1; - m_bHadError = false; + data = pData; + data_buffer_size = iLength; + next_index = 1; + had_error = false; lua_createtable(L, 32, 0); // Environment lua_pushvalue(L, 2); lua_rawseti(L, -2, 0); @@ -759,20 +748,19 @@ lua_rawseti(L, -2, -3); lua_setfenv(L, 1); lua_createtable(L, 0, 1); // Metatable - luaT_pushcclosure(L, l_crude_gc, 0); + luaT_pushcclosure(L, l_crude_gc, 0); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, 1); } - bool readStackObject() override + bool read_stack_object() override { uint64_t iIndex; - if(!readVUInt(iIndex)) + if(!read_uint(iIndex)) { - setError("Expected stack object"); + set_error("Expected stack object"); return false; } - lua_State *L = m_L; if(lua_type(L, 1) != LUA_TTABLE) { // Ensure that index #1 is self environment @@ -791,7 +779,7 @@ } if(lua_isnil(L, -1)) { - setError("Cycle while depersisting permanent object key or userdata metatable"); + set_error("Cycle while depersisting permanent object key or userdata metatable"); return false; } } @@ -804,18 +792,18 @@ lua_pushnil(L); break; case PERSIST_TPERMANENT: { - uint64_t iOldIndex = m_iNextIndex; - ++m_iNextIndex; // Temporary marker + uint64_t iOldIndex = next_index; + ++next_index; // Temporary marker lua_rawgeti(L, 1, 0); // Permanents table - if(!readStackObject()) + if(!read_stack_object()) return false; lua_gettable(L, -2); lua_replace(L, -2); // Replace marker with actual object - uint64_t iNewIndex = m_iNextIndex; - m_iNextIndex = iOldIndex; - saveStackObject(); - m_iNextIndex = iNewIndex; + uint64_t iNewIndex = next_index; + next_index = iOldIndex; + save_stack_object(); + next_index = iNewIndex; break; } case LUA_TBOOLEAN: lua_pushboolean(L, 0); @@ -825,71 +813,71 @@ break; case LUA_TSTRING: { size_t iLength; - if(!readVUInt(iLength)) + if(!read_uint(iLength)) return false; - if(!readByteStream(m_stringBuffer, iLength)) + if(!read_byte_stream(string_buffer, iLength)) return false; - lua_pushlstring(L, m_stringBuffer.c_str(), m_stringBuffer.length()); - saveStackObject(); + lua_pushlstring(L, string_buffer.c_str(), string_buffer.length()); + save_stack_object(); break; } case LUA_TTABLE: lua_newtable(L); - saveStackObject(); + save_stack_object(); if(!lua_checkstack(L, 8)) return false; - if(!readTableContents()) + if(!read_table_contents()) return false; break; case PERSIST_TTABLE_WITH_META: lua_newtable(L); - saveStackObject(); + save_stack_object(); if(!lua_checkstack(L, 8)) return false; - if(!readStackObject()) + if(!read_stack_object()) return false; lua_setmetatable(L, -2); - if(!readTableContents()) + if(!read_table_contents()) return false; break; case LUA_TNUMBER: { double fValue; - if(!readByteStream(reinterpret_cast(&fValue), sizeof(double))) + if(!read_byte_stream(reinterpret_cast(&fValue), sizeof(double))) return false; lua_pushnumber(L, fValue); break; } case LUA_TFUNCTION: { if(!lua_checkstack(L, 8)) return false; - uint64_t iOldIndex = m_iNextIndex; - ++m_iNextIndex; // Temporary marker - if(!readStackObject()) + uint64_t iOldIndex = next_index; + ++next_index; // Temporary marker + if(!read_stack_object()) return false; lua_call(L, 0, 2); // Replace marker with closure - uint64_t iNewIndex = m_iNextIndex; - m_iNextIndex = iOldIndex; - saveStackObject(); - m_iNextIndex = iNewIndex; + uint64_t iNewIndex = next_index; + next_index = iOldIndex; + save_stack_object(); + next_index = iNewIndex; // Set upvalues lua_insert(L, -2); int iNups, i; - if(!readVUInt(iNups)) + if(!read_uint(iNups)) return false; size_t iIDSize; - if(!readVUInt(iIDSize)) + if(!read_uint(iIDSize)) return false; for(i = 0; i < iNups; ++i) { - if(!readStackObject()) + if(!read_stack_object()) return false; // For now, just skip over the upvalue IDs. In the future, // the ID may be used to rejoin shared upvalues. - if(!readByteStream(nullptr, iIDSize)) + if(!read_byte_stream(nullptr, iIDSize)) return false; } lua_call(L, iNups, 0); // Read environment - if(!readStackObject()) + if(!read_stack_object()) return false; lua_setfenv(L, -2); break; } @@ -897,10 +885,10 @@ if(!lua_checkstack(L, 8)) return false; - uint64_t iOldIndex = m_iNextIndex; - ++m_iNextIndex; // Temporary marker + uint64_t iOldIndex = next_index; + ++next_index; // Temporary marker int iNups; - if(!readVUInt(iNups)) + if(!read_uint(iNups)) return false; if(iNups == 0) lua_pushliteral(L, "return function() end,"); @@ -912,11 +900,11 @@ { if(i != 0) lua_pushliteral(L, ","); - if(!readStackObject()) + if(!read_stack_object()) return false; if(lua_type(L, -1) != LUA_TSTRING) { - setError("Upvalue name not a string"); + set_error("Upvalue name not a string"); return false; } } @@ -927,7 +915,7 @@ lua_concat(L, 5); } // Fetch name and then lookup filename and code - if(!readStackObject()) + if(!read_stack_object()) return false; lua_pushliteral(L, "@"); @@ -938,7 +926,7 @@ if(lua_isnil(L, -1)) { - setError(lua_pushfstring(L, "Unable to depersist prototype" + set_error(lua_pushfstring(L, "Unable to depersist prototype" " \'%s\'", lua_tostring(L, -3))); return false; } @@ -950,10 +938,10 @@ lua_replace(L, -2); lua_remove(L, -3); // Construct the closure factory - LoadMultiBuffer_t ls; + load_multi_buffer ls; ls.s[0] = lua_tolstring(L, -3, &ls.i[0]); ls.s[1] = lua_tolstring(L, -1, &ls.i[1]); - if(luaT_load(L, LoadMultiBuffer_t::load_fn, &ls, lua_tostring(L, -2), "bt") != 0) + if(luaT_load(L, load_multi_buffer::load_fn, &ls, lua_tostring(L, -2), "bt") != 0) { // Should never happen lua_error(L); @@ -962,31 +950,31 @@ lua_replace(L, -4); lua_pop(L, 2); // Replace marker with closure factory - uint64_t iNewIndex = m_iNextIndex; - m_iNextIndex = iOldIndex; - saveStackObject(); - m_iNextIndex = iNewIndex; + uint64_t iNewIndex = next_index; + next_index = iOldIndex; + save_stack_object(); + next_index = iNewIndex; break; } case LUA_TUSERDATA: { bool bHasSetMetatable = false; - uint64_t iOldIndex = m_iNextIndex; - ++m_iNextIndex; // Temporary marker + uint64_t iOldIndex = next_index; + ++next_index; // Temporary marker // Read metatable - if(!readStackObject()) + if(!read_stack_object()) return false; lua_getfield(L, -1, "__depersist_size"); if(!lua_isnumber(L, -1)) { - setError("Userdata missing __depersist_size metafield"); + set_error("Userdata missing __depersist_size metafield"); return false; } lua_newuserdata(L, (size_t)lua_tonumber(L, -1)); lua_replace(L, -2); // Replace marker with userdata - uint64_t iNewIndex = m_iNextIndex; - m_iNextIndex = iOldIndex; - saveStackObject(); - m_iNextIndex = iNewIndex; + uint64_t iNewIndex = next_index; + next_index = iOldIndex; + save_stack_object(); + next_index = iNewIndex; // Perform immediate initialisation lua_getfield(L, -2, "__pre_depersist"); if(lua_isnil(L, -1)) @@ -1006,7 +994,7 @@ lua_call(L, 1, 0); } // Read environment - if(!readStackObject()) + if(!read_stack_object()) return false; lua_setfenv(L, -2); // Set metatable and read the raw data @@ -1036,17 +1024,17 @@ } lua_replace(L, -2); uint64_t iSyncMarker; - if(!readVUInt(iSyncMarker)) + if(!read_uint(iSyncMarker)) return false; if(iSyncMarker != 0x42) { - setError("sync fail"); + set_error("sync fail"); return false; } break; } case PERSIST_TINTEGER: { uint16_t iValue; - if(!readVUInt(iValue)) + if(!read_uint(iValue)) return false; lua_pushinteger(L, iValue); break; } @@ -1076,7 +1064,7 @@ } lua_pushliteral(L, "\'"); lua_concat(L, 3); - setError(lua_tostring(L, -1)); + set_error(lua_tostring(L, -1)); lua_pop(L, 1); return false; } @@ -1084,36 +1072,34 @@ return true; } - void saveStackObject() + void save_stack_object() { - lua_State *L = m_L; - if(m_iNextIndex < (uint64_t)INT_MAX) + if(next_index < (uint64_t)INT_MAX) { lua_pushvalue(L, -1); - lua_rawseti(L, 1, (int)m_iNextIndex); + lua_rawseti(L, 1, (int)next_index); } else { - lua_pushnumber(L, (lua_Number)m_iNextIndex); + lua_pushnumber(L, (lua_Number)next_index); lua_pushvalue(L, -2); lua_rawset(L, 1); } - ++m_iNextIndex; + ++next_index; } - bool readTableContents() + bool read_table_contents() { - lua_State *L = m_L; while(true) { - if(!readStackObject()) + if(!read_stack_object()) return false; if(lua_type(L, -1) == LUA_TNIL) { lua_pop(L, 1); return true; } - if(!readStackObject()) + if(!read_stack_object()) return false; // NB: lua_rawset used rather than lua_settable to avoid invoking // any metamethods, as they may not have been designed to be called @@ -1124,12 +1110,11 @@ bool finish() { - lua_State *L = m_L; // Ensure that all data has been read - if(m_iDataBufferLength != 0) + if(data_buffer_size != 0) { - setError(lua_pushfstring(L, "%d bytes of data remain unpersisted", (int)m_iDataBufferLength)); + set_error(lua_pushfstring(L, "%d bytes of data remain unpersisted", (int)data_buffer_size)); return false; } @@ -1157,60 +1142,60 @@ return true; } - bool readByteStream(uint8_t *pBytes, size_t iCount) override + bool read_byte_stream(uint8_t *pBytes, size_t iCount) override { - if(iCount > m_iDataBufferLength) + if(iCount > data_buffer_size) { - setError(lua_pushfstring(m_L, + set_error(lua_pushfstring(L, "End of input reached while attempting to read %d byte%s", (int)iCount, iCount == 1 ? "" : "s")); - lua_pop(m_L, 1); + lua_pop(L, 1); return false; } if(pBytes != nullptr) - std::memcpy(pBytes, m_pData, iCount); + std::memcpy(pBytes, data, iCount); - m_pData += iCount; - m_iDataBufferLength -= iCount; + data += iCount; + data_buffer_size -= iCount; return true; } - bool readByteStream(std::string& bytes, size_t iCount) + bool read_byte_stream(std::string& bytes, size_t iCount) { - if(iCount > m_iDataBufferLength) { - setError(lua_pushfstring(m_L, + if(iCount > data_buffer_size) { + set_error(lua_pushfstring(L, "End of input reached while attempting to read %d byte%s", (int)iCount, iCount == 1 ? "" : "s")); - lua_pop(m_L, 1); + lua_pop(L, 1); return false; } - bytes.assign(reinterpret_cast(m_pData), iCount); + bytes.assign(reinterpret_cast(data), iCount); - m_pData += iCount; - m_iDataBufferLength -= iCount; + data += iCount; + data_buffer_size -= iCount; return true; } - const uint8_t* getPointer() {return m_pData;} - uint64_t getObjectCount() {return m_iNextIndex;} + const uint8_t* get_pointer() {return data;} + uint64_t get_object_count() {return next_index;} - const char* getError() + const char* get_error() { - if(m_bHadError) - return m_stringBuffer.c_str(); + if(had_error) + return string_buffer.c_str(); else return nullptr; } private: - lua_State *m_L; - uint64_t m_iNextIndex; - const uint8_t* m_pData; - size_t m_iDataBufferLength; - std::string m_stringBuffer; - bool m_bHadError; + lua_State *L; + uint64_t next_index; + const uint8_t* data; + size_t data_buffer_size; + std::string string_buffer; + bool had_error; }; static int l_dump_toplevel(lua_State *L) @@ -1218,10 +1203,10 @@ luaL_checktype(L, 2, LUA_TTABLE); lua_settop(L, 2); lua_pushvalue(L, 1); - LuaPersistBasicWriter *pWriter = new (lua_newuserdata(L, sizeof(LuaPersistBasicWriter))) LuaPersistBasicWriter(L); + lua_persist_basic_writer *pWriter = new (lua_newuserdata(L, sizeof(lua_persist_basic_writer))) lua_persist_basic_writer(L); lua_replace(L, 1); pWriter->init(); - pWriter->writeStackObject(3); + pWriter->write_stack_object(3); return pWriter->finish(); } @@ -1232,16 +1217,16 @@ luaL_checktype(L, 2, LUA_TTABLE); lua_settop(L, 2); lua_pushvalue(L, 1); - LuaPersistBasicReader *pReader = new (lua_newuserdata(L, sizeof(LuaPersistBasicReader))) LuaPersistBasicReader(L); + lua_persist_basic_reader *pReader = new (lua_newuserdata(L, sizeof(lua_persist_basic_reader))) lua_persist_basic_reader(L); lua_replace(L, 1); pReader->init(pData, iDataLength); - if(!pReader->readStackObject() || !pReader->finish()) + if(!pReader->read_stack_object() || !pReader->finish()) { - int iNumObjects = (int)pReader->getObjectCount(); - int iNumBytes = (int)(pReader->getPointer() - pData); + int iNumObjects = (int)pReader->get_object_count(); + int iNumBytes = (int)(pReader->get_pointer() - pData); lua_pushnil(L); lua_pushfstring(L, "%s after %d objects (%d bytes)", - pReader->getError() ? pReader->getError() : "Error while depersisting", + pReader->get_error() ? pReader->get_error() : "Error while depersisting", iNumObjects, iNumBytes); return 2; } @@ -1251,7 +1236,7 @@ } } -static int CalculateLineNumber(const char *sStart, const char *sPosition) +static int calculate_line_number(const char *sStart, const char *sPosition) { int iLine = 1; for(; sStart != sPosition; ++sStart) @@ -1275,7 +1260,7 @@ return iLine; } -static const char* FindFunctionEnd(lua_State *L, const char* sStart) +static const char* find_function_end(lua_State *L, const char* sStart) { const char* sEnd = sStart; while(sEnd) @@ -1284,12 +1269,12 @@ if(sEnd) { sEnd += 3; - LoadMultiBuffer_t ls; + load_multi_buffer ls; ls.s[0] = "return function"; ls.i[0] = sizeof("return function") - 1; ls.s[1] = sStart; ls.i[1] = sEnd - sStart; - if(luaT_load(L, LoadMultiBuffer_t::load_fn, &ls, "", "bt") == 0) + if(luaT_load(L, load_multi_buffer::load_fn, &ls, "", "bt") == 0) { lua_pop(L, 1); return sEnd; @@ -1377,9 +1362,9 @@ const char *sNameEnd = std::strstr(sPosition, "]]"); if(sNameEnd) { - int iLineNumber = CalculateLineNumber(sFile, sNameEnd); + int iLineNumber = calculate_line_number(sFile, sNameEnd); const char *sFunctionArgs = std::strchr(sNameEnd + 2, '('); - const char *sFunctionEnd = FindFunctionEnd(L, sFunctionArgs); + const char *sFunctionEnd = find_function_end(L, sFunctionArgs); if((sNameEnd - sPosition) == 1 && *sPosition == ':') { // --[[persistable::]] means take the existing name of the function diff -Nru corsix-th-0.61/CorsixTH/Src/persist_lua.h corsix-th-0.62/CorsixTH/Src/persist_lua.h --- corsix-th-0.61/CorsixTH/Src/persist_lua.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/persist_lua.h 2018-07-21 11:13:17.000000000 +0000 @@ -27,34 +27,34 @@ #include #include -template struct LuaPersistVInt {}; -template <> struct LuaPersistVInt {typedef unsigned int T;}; +template struct lua_persist_int {}; +template <> struct lua_persist_int {typedef unsigned int T;}; //! Interface used for persisting Lua objects /*! When userdata are persisted, they get an instance of this interface for writing binary data and other Lua objects. */ -class LuaPersistWriter +class lua_persist_writer { public: - virtual ~LuaPersistWriter() = default; + virtual ~lua_persist_writer() = default; - virtual lua_State* getStack() = 0; - virtual void writeStackObject(int iIndex) = 0; - virtual void writeByteStream(const uint8_t *pBytes, size_t iCount) = 0; - virtual void setError(const char *sError) = 0; + virtual lua_State* get_stack() = 0; + virtual void write_stack_object(int iIndex) = 0; + virtual void write_byte_stream(const uint8_t *pBytes, size_t iCount) = 0; + virtual void set_error(const char *sError) = 0; - // writeStackObject for userdata without growing the Lua call stack + // write_stack_object for userdata without growing the Lua call stack // The given index should be a userdata whose __persist metamethod supports // fast persistance (being called with extra arguments and the wrong // environment / upvalues). - virtual void fastWriteStackObject(int iIndex) = 0; + virtual void fast_write_stack_object(int iIndex) = 0; // Writes an unsigned integer as a variable number of bytes // Endian independant and underlying type size independant template - void writeVUInt(T tValue) + void write_uint(T tValue) { T tTemp(tValue); int iNumBytes; @@ -63,7 +63,7 @@ if(iNumBytes == 1) { uint8_t iByte = (uint8_t)tValue; - writeByteStream(&iByte, 1); + write_byte_stream(&iByte, 1); } else { @@ -74,32 +74,32 @@ tValue /= (T)0x80; bytes[iNumBytes - 1 - i] = 0x80 | (0x7F & (uint8_t)tValue); } - writeByteStream(bytes.data(), iNumBytes); + write_byte_stream(bytes.data(), iNumBytes); } } template - void writeVInt(T tValue) + void write_int(T tValue) { - typename LuaPersistVInt::T tValueToWrite; + typename lua_persist_int::T tValueToWrite; if(tValue >= 0) { - tValueToWrite = (typename LuaPersistVInt::T)tValue; + tValueToWrite = (typename lua_persist_int::T)tValue; tValueToWrite <<= 1; } else { - tValueToWrite = (typename LuaPersistVInt::T)(-(tValue + 1)); + tValueToWrite = (typename lua_persist_int::T)(-(tValue + 1)); tValueToWrite <<= 1; tValueToWrite |= 1; } - writeVUInt(tValueToWrite); + write_uint(tValueToWrite); } template - void writeVFloat(T fValue) + void write_float(T fValue) { - writeByteStream(reinterpret_cast(&fValue), sizeof(T)); + write_byte_stream(reinterpret_cast(&fValue), sizeof(T)); } }; @@ -108,26 +108,26 @@ When userdata are depersisted, they get an instance of this interface for reading binary data and other Lua objects. */ -class LuaPersistReader +class lua_persist_reader { public: - virtual ~LuaPersistReader() = default; + virtual ~lua_persist_reader() = default; - virtual lua_State* getStack() = 0; - virtual bool readStackObject() = 0; - virtual bool readByteStream(uint8_t *pBytes, size_t iCount) = 0; - virtual void setError(const char *sError) = 0; + virtual lua_State* get_stack() = 0; + virtual bool read_stack_object() = 0; + virtual bool read_byte_stream(uint8_t *pBytes, size_t iCount) = 0; + virtual void set_error(const char *sError) = 0; - // Reads an integer previously written by LuaPersistWriter::writeVUInt() + // Reads an integer previously written by lua_persist_writer::write_uint() template - bool readVUInt(T& tValue) + bool read_uint(T& tValue) { T tTemp(0); uint8_t iByte; while(true) { - if(!readByteStream(&iByte, 1)) + if(!read_byte_stream(&iByte, 1)) return false; if(iByte & 0x80) { @@ -146,10 +146,10 @@ } template - bool readVInt(T& tValue) + bool read_int(T& tValue) { - typename LuaPersistVInt::T tWrittenValue; - if(!readVUInt(tWrittenValue)) + typename lua_persist_int::T tWrittenValue; + if(!read_uint(tWrittenValue)) return false; if(tWrittenValue & 1) tValue = (-(T)(tWrittenValue >> 1)) - 1; @@ -159,9 +159,9 @@ } template - bool readVFloat(T& fValue) + bool read_float(T& fValue) { - if(!readByteStream(reinterpret_cast(&fValue), sizeof(T))) + if(!read_byte_stream(reinterpret_cast(&fValue), sizeof(T))) return false; return true; } diff -Nru corsix-th-0.61/CorsixTH/Src/rnc.cpp corsix-th-0.62/CorsixTH/Src/rnc.cpp --- corsix-th-0.61/CorsixTH/Src/rnc.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/rnc.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,561 +0,0 @@ -/* -Copyright (c) 1997 Simon Tatham - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Original code was from http://www.yoda.arachsys.com/dk/utils.html. While - that site and the original code do not state copyright or license, email - communication releaved the original author, and they agreed to releasing it - under the MIT license (above). - - Modifications made to the original code include: - * Const correctness - * Prebuilt CRC table - * Lua interface - * Indentation and code style - * Bit stream pointers to data - * Fix bit operations near end of stream - * Style changes to conform to CorsixTH -*/ - -#include "config.h" -#include "rnc.h" -#include "th_lua.h" -#include - -/*! Result status values from #rnc_inpack. */ -enum class rnc_status -{ - ok, ///< Everything is fine - file_is_not_rnc, ///< The file does not begin with an RNC signature - huf_decode_error, ///< Error decoding the file - file_size_mismatch, ///< The file size does not match the header - packed_crc_error, ///< The compressed file does not match its checksum - unpacked_crc_error ///< The uncompressed file does not match its checksum -}; - -static const uint32_t rnc_signature = 0x524E4301; /*!< "RNC\001" */ - -static const uint16_t rnc_crc_table[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, -}; - -struct bit_stream -{ - uint32_t bitbuf; ///< holds between 16 and 32 bits. - int bitcount; ///< how many bits does bitbuf hold? - const uint8_t* endpos; ///< final position that can be read. - const uint8_t* p; ///< pointer in data that stream is reading. -}; - -struct huf_table -{ - int num; ///< number of nodes in the tree. - struct - { - uint32_t code; - int codelen; - int value; - } table[32]; -}; - -//! Calculate a CRC, the RNC way. -/*! - @param data data for which to calculate the CRC - @param len length of the data in bytes -*/ -static uint16_t rnc_crc(const uint8_t* data, size_t len) -{ - uint16_t val = 0; - - while(len--) - { - val = static_cast(val ^ *data++); - val = static_cast((val >> 8) ^ rnc_crc_table[val & 0xFF]); - } - - return val; -} - - -//! Return the big-endian 32 bit word at p. -/*! - @param p Pointer to data containing the word -*/ -static uint32_t blong (const uint8_t *p) -{ - uint32_t n; - n = p[0]; - n = (n << 8) + p[1]; - n = (n << 8) + p[2]; - n = (n << 8) + p[3]; - return n; -} - -//! Return the big-endian 16 bit word at p. -/*! - @param p Pointer to data containing the word -*/ -static uint32_t bword (const uint8_t *p) -{ - uint32_t n; - n = p[0]; - n = (n << 8) + p[1]; - return n; -} - -//! Return the little-endian 16 bit word at p. -/*! - @param p Pointer to data containing the word - */ -static uint32_t lword (const uint8_t *p) -{ - uint32_t n; - n = p[1]; - n = (n << 8) + p[0]; - return n; -} - -//! Mirror the bottom n bits of x. -/*! - @param x - @param n -*/ -static uint32_t mirror (uint32_t x, int n) -{ - uint32_t top = 1 << (n-1), bottom = 1; - while (top > bottom) - { - uint32_t mask = top | bottom; - uint32_t masked = x & mask; - if (masked != 0 && masked != mask) - { - x ^= mask; - } - top >>= 1; - bottom <<= 1; - } - return x; -} - - -//! Initialises a bit stream with the first two bytes of the packed -//! data. -/*! - @param bs Bit stream to be initialized - @param p Pointer to start of memory block the bitstream is to - traverse - @param endpos Pointer to end of memory block the bitstream is - to traverse -*/ -static void bitread_init (bit_stream *bs, const uint8_t *p, const uint8_t* endpos) -{ - bs->bitbuf = lword (p); - bs->bitcount = 16; - bs->p = p; - bs->endpos = endpos; -} - -//! Fixes up a bit stream after literals have been read out of the -//! data stream and the pointer has been moved. -/*! - @param bs Bit stream to correct -*/ -static void bitread_fix (bit_stream *bs) -{ - // Remove the top 16 bits - bs->bitcount -= 16; - bs->bitbuf &= (1<bitcount)-1; - - // Replace with what is in the new current location - // in the bit stream - if(bs->p < bs->endpos) - { - bs->bitbuf |= (lword(bs->p)<bitcount); - bs->bitcount += 16; - } - else if(bs->p == bs->endpos) - { - bs->bitbuf |= (*(bs->p)<bitcount); - bs->bitcount += 8; - } -} - -//! Return a word consisting of the specified bits without advancing -//! the bit stream. -/*! - @param bs Bit stream from which to peek - @param mask A 32 bit bit mask specifying which bits to peek -*/ -static uint32_t bit_peek (bit_stream *bs, const uint32_t mask) -{ - return bs->bitbuf & mask; -} - -//! Advances the bit stream. -/*! - @param bs Bit stream to advance - @param n Number of bits to advance the stream. Must be - between 0 and 16 -*/ -static void bit_advance (bit_stream *bs, int n) -{ - bs->bitbuf >>= n; - bs->bitcount -= n; - - if (bs->bitcount < 16) - { - // At this point it is possible for bs->p to advance past - // the end of the data. In that case we simply do not read - // anything more into the buffer. If we are on the last - // byte the lword matches what is in that byte. - bs->p += 2; - - if(bs->p < bs->endpos) - { - bs->bitbuf |= (lword(bs->p)<bitcount); - bs->bitcount += 16; - } - else if (bs->p == bs->endpos) - { - bs->bitbuf |= (*(bs->p)<bitcount); - bs->bitcount += 8; - } - } -} - -//! Returns bits from the bit stream matching the mask and advances it -//! n places. -/*! - @param bs Bit stream to read - @param mask A 32 bit bit mask specifying which bits to read - @param n Number of bits to advance the stream. Must be - between 0 and 16 -*/ -static uint32_t bit_read (bit_stream *bs, uint32_t mask, int n) -{ - uint32_t result = bit_peek(bs, mask); - bit_advance(bs, n); - return result; -} - -//! Read a Huffman table out of the bit stream given. -/*! - @param h huf_table structure to populate - @param bs Bit stream pointing to the start of the Huffman table - description -*/ -static void read_huftable(huf_table *h, bit_stream *bs) -{ - int i, j, k, num; - int leaflen[32]; - int leafmax; - uint32_t codeb; /* big-endian form of code. */ - - num = bit_read(bs, 0x1F, 5); - - if(num == 0) - { - return; - } - - leafmax = 1; - for(i = 0; i < num; i++) - { - leaflen[i] = bit_read(bs, 0x0F, 4); - if (leafmax < leaflen[i]) - { - leafmax = leaflen[i]; - } - } - - codeb = 0L; - k = 0; - for(i = 1; i <= leafmax; i++) - { - for(j = 0; j < num; j++) - { - if(leaflen[j] == i) - { - h->table[k].code = mirror(codeb, i); - h->table[k].codelen = i; - h->table[k].value = j; - codeb++; - k++; - } - } - codeb <<= 1; - } - h->num = k; -} - -//! Read a value out of the bit stream using the given Huffman table. -/*! - @param h Huffman table to transcribe from - @param bs bit stream - @param p input data - @return The value from the table with the matching bits, or -1 if none found. -*/ -static uint32_t huf_read(huf_table *h, bit_stream *bs, const uint8_t **p) -{ - int i; - uint32_t val; - uint32_t mask; - - // Find the current bits in the table - for (i = 0; i < h->num; i++) - { - mask = (1 << h->table[i].codelen) - 1; - if(bit_peek(bs, mask) == h->table[i].code) - { - break; - } - } - - // No match found in table (error) - if(i == h->num) - { - return -1; - } - - bit_advance(bs, h->table[i].codelen); - - val = h->table[i].value; - if (val >= 2) - { - val = 1 << (val-1); - val |= bit_read(bs, val-1, h->table[i].value - 1); - } - return val; -} - -//! Decompresses RNC data -/*! - @param input Pointer to compressed RNC data - @param output Pointer to allocated memory region to hold uncompressed - data. The size of output must match the value specified in the - 4 byte segment of the input header starting at the 4th byte - in Big-endian. -*/ -static rnc_status rnc_unpack(const uint8_t* input, uint8_t* output) -{ - const uint8_t *inputend; - uint8_t *outputend; - bit_stream input_bs; - huf_table raw = {0}, dist = {0}, len = {0}; - uint32_t ch_count; - uint32_t ret_len; - uint32_t out_crc; - if(blong(input) != rnc_signature) - { - return rnc_status::file_is_not_rnc; - } - ret_len = blong(input + 4); - outputend = output + ret_len; - inputend = input + 18 + blong(input + 8); - - //skip header - input += 18; - - // Check the packed-data CRC. Also save the unpacked-data CRC - // for later. - if(rnc_crc(input, inputend-input) != bword(input - 4)) - { - return rnc_status::packed_crc_error; - } - out_crc = bword(input - 6); - - //initialize the bitstream to the input and advance past the - //first two bytes as they don't have any understood use. - bitread_init(&input_bs, input, inputend); - bit_advance(&input_bs, 2); - - //process chunks - while (output < outputend) - { - read_huftable(&raw, &input_bs); //raw byte length table - read_huftable(&dist, &input_bs); //distance prior to copy table - read_huftable(&len, &input_bs); //length bytes to copy table - ch_count = bit_read(&input_bs, 0xFFFF, 16); - - while(true) - { - long length, posn; - - // Copy bit pattern to output based on lookup - // of bytes from input. - length = huf_read(&raw, &input_bs, &input); - if(length == -1) - { - return rnc_status::huf_decode_error; - } - if(length) - { - while(length--) - { - *output++ = *(input_bs.p++); - } - bitread_fix(&input_bs); - } - if(--ch_count <= 0) - { - break; - } - - // Read position to copy output to - posn = huf_read(&dist, &input_bs, &input); - if(posn == -1) - { - return rnc_status::huf_decode_error; - } - posn += 1; - - // Read length of output to copy back - length = huf_read(&len, &input_bs, &input); - if(length == -1) - { - return rnc_status::huf_decode_error; - } - length += 2; - - // Copy length bytes from output back posn - while(length--) - { - *output = output[-posn]; - output++; - } - } - } - - if(outputend != output) - { - return rnc_status::file_size_mismatch; - } - - // Check the unpacked-data CRC. - if(rnc_crc(outputend - ret_len, ret_len) != out_crc) - { - return rnc_status::unpacked_crc_error; - } - - return rnc_status::ok; -} - -//! Provides lua function to decompress RNC data -/*! - @param L Lua state where the function is called from. In lua a call - to this function has one parameter which is the RNC compressed data. - The return value is the decompressed data. -*/ -static int l_decompress(lua_State *L) -{ - size_t inlen; - const uint8_t* in = reinterpret_cast(luaL_checklstring(L, 1, &inlen)); - - // Verify that the data contains an RNC signature, and that the input - // size matches the size specified in the data header. - if(inlen < 18 || blong(in) != rnc_signature || blong(in + 8) != (inlen - 18)) - { - lua_pushnil(L); - lua_pushliteral(L, "Input is not RNC compressed data"); - return 2; - } - uint32_t outlen = blong(in + 4); - - // Allocate scratch area as Lua userdata so that if something horrible - // happens, it'll be cleaned up by Lua's GC. Remember that most Lua API - // calls can throw errors, so they all have to be wrapped with code to - // detect errors and free the buffer if said buffer was not managed by Lua. - void* outbuf = lua_newuserdata(L, outlen); - - lua_pushnil(L); - switch(rnc_unpack(in, (uint8_t*)outbuf)) - { - case rnc_status::ok: - lua_pushlstring(L, (const char*)outbuf, outlen); - return 1; - - case rnc_status::file_is_not_rnc: - lua_pushliteral(L, "Input is not RNC compressed data"); - break; - - case rnc_status::huf_decode_error: - lua_pushliteral(L, "Invalid Huffman coding"); - break; - - case rnc_status::file_size_mismatch: - lua_pushliteral(L, "Size mismatch"); - break; - - case rnc_status::packed_crc_error: - lua_pushliteral(L, "Incorrect packed CRC"); - break; - - case rnc_status::unpacked_crc_error: - lua_pushliteral(L, "Incorrect unpacked CRC"); - break; - - default: - lua_pushliteral(L, "Unknown error decompressing RNC data"); - break; - } - return 2; -} - -static const std::vector rnclib = { - {"decompress", l_decompress}, - {nullptr, nullptr} -}; - -int luaopen_rnc(lua_State *L) -{ - luaT_register(L, "rnc", rnclib); - return 1; -} diff -Nru corsix-th-0.61/CorsixTH/Src/rnc.h corsix-th-0.62/CorsixTH/Src/rnc.h --- corsix-th-0.61/CorsixTH/Src/rnc.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/rnc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* -Copyright (c) 2009 Peter "Corsix" Cawley - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef CORSIX_TH_RNC_H_ -#define CORSIX_TH_RNC_H_ -#include "lua.hpp" - -int luaopen_rnc(lua_State *L); - -#endif // CORSIX_TH_RNC_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/run_length_encoder.cpp corsix-th-0.62/CorsixTH/Src/run_length_encoder.cpp --- corsix-th-0.61/CorsixTH/Src/run_length_encoder.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/run_length_encoder.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -25,79 +25,79 @@ #include #include -IntegerRunLengthEncoder::IntegerRunLengthEncoder() +integer_run_length_encoder::integer_run_length_encoder() { - m_pBuffer = nullptr; - m_pOutput = nullptr; - _clean(); + buffer = nullptr; + output = nullptr; + clean(); } -IntegerRunLengthEncoder::~IntegerRunLengthEncoder() +integer_run_length_encoder::~integer_run_length_encoder() { - _clean(); + clean(); } -void IntegerRunLengthEncoder::_clean() +void integer_run_length_encoder::clean() { - delete[] m_pBuffer; - delete[] m_pOutput; - m_pBuffer = nullptr; - m_pOutput = nullptr; - m_iRecordSize = 0; - m_iBufferSize = 0; - m_iBufferSizeUsed = 0; - m_iBufferOffset = 0; - m_iOutputSize = 0; - m_iOutputSizeUsed = 0; - m_iObjectSize = 0; - m_iObjectCount = 0; + delete[] buffer; + delete[] output; + buffer = nullptr; + output = nullptr; + record_size = 0; + buffer_capacity = 0; + buffer_size = 0; + buffer_offset = 0; + output_capacity = 0; + output_size = 0; + object_size = 0; + object_copies = 0; } -bool IntegerRunLengthEncoder::initialise(size_t iRecordSize) +bool integer_run_length_encoder::initialise(size_t iRecordSize) { - _clean(); - m_iRecordSize = iRecordSize; + clean(); + record_size = iRecordSize; // Buffer must hold at least 7 + 2 * 8 records, as the maximum object size // is 8 records, 2 of which are needed to detect a repeat, and 7 for the // offset at which the objects are found. - m_iBufferSize = iRecordSize * 8 * 4; - m_iBufferSizeUsed = 0; - m_iBufferOffset = 0; - m_pBuffer = new (std::nothrow) uint32_t[m_iBufferSize]; - if(!m_pBuffer) + buffer_capacity = iRecordSize * 8 * 4; + buffer_size = 0; + buffer_offset = 0; + buffer = new (std::nothrow) uint32_t[buffer_capacity]; + if(!buffer) return false; - m_iOutputSize = iRecordSize * 32; - m_iOutputSizeUsed = 0; - m_pOutput = new (std::nothrow) uint32_t[m_iOutputSize]; - if(!m_pOutput) + output_capacity = iRecordSize * 32; + output_size = 0; + output = new (std::nothrow) uint32_t[output_capacity]; + if(!output) return false; - m_iObjectSize = 0; - m_iObjectCount = 0; + object_size = 0; + object_copies = 0; return true; } -void IntegerRunLengthEncoder::write(uint32_t iValue) +void integer_run_length_encoder::write(uint32_t iValue) { - m_pBuffer[(m_iBufferOffset + m_iBufferSizeUsed) % m_iBufferSize] = iValue; - if(++m_iBufferSizeUsed == m_iBufferSize) - _flush(false); + buffer[(buffer_offset + buffer_size) % buffer_capacity] = iValue; + if(++buffer_size == buffer_capacity) + flush(false); } -void IntegerRunLengthEncoder::finish() +void integer_run_length_encoder::finish() { - if(m_iBufferSizeUsed != 0) - _flush(true); + if(buffer_size != 0) + flush(true); } -void IntegerRunLengthEncoder::_flush(bool bAll) +void integer_run_length_encoder::flush(bool bAll) { do { - if(m_iObjectSize == 0) + if(object_size == 0) { // Decide on the size of the next object // Want the object size which gives most object repeats, then for @@ -110,9 +110,9 @@ for(size_t iOffset = 0; iOffset < iNumRecords; ++iOffset) { size_t iNumRepeats = 0; - size_t iObjSize = iNumRecords * m_iRecordSize; - while(iObjSize * (iOffset + iNumRepeats + 1) <= m_iBufferSizeUsed - && _areRangesEqual(0, iNumRepeats, iOffset, iObjSize)) + size_t iObjSize = iNumRecords * record_size; + while(iObjSize * (iOffset + iNumRepeats + 1) <= buffer_size + && are_ranges_equal(0, iNumRepeats, iOffset, iObjSize)) { ++iNumRepeats; } @@ -129,52 +129,52 @@ { // No repeats were found, so the best we can do is output // a large non-repeating blob. - _output(std::min(m_iBufferSizeUsed, 8 * m_iRecordSize), 1); + move_object_to_output(std::min(buffer_size, 8 * record_size), 1); } else { if(iBestOffset != 0) - _output(iBestOffset * m_iRecordSize, 1); + move_object_to_output(iBestOffset * record_size, 1); // Mark the object as the current one, and remove all but the // last instance of it from the buffer. On the next flush, the // new data might continue the same object, hence why the // object isn't output just yet. - m_iObjectSize = iBestSize; - m_iObjectCount = iBestRepeats - 1; - m_iBufferOffset = (m_iBufferOffset + m_iObjectSize * m_iObjectCount) % m_iBufferSize; - m_iBufferSizeUsed -= m_iObjectSize * m_iObjectCount; + object_size = iBestSize; + object_copies = iBestRepeats - 1; + buffer_offset = (buffer_offset + object_size * object_copies) % buffer_capacity; + buffer_size -= object_size * object_copies; } } else { // Try to match more of the current object - while(m_iObjectSize * 2 <= m_iBufferSizeUsed && - _areRangesEqual(0, 1, 0, m_iObjectSize)) + while(object_size * 2 <= buffer_size && + are_ranges_equal(0, 1, 0, object_size)) { - ++m_iObjectCount; - m_iBufferOffset = (m_iBufferOffset + m_iObjectSize) % m_iBufferSize; - m_iBufferSizeUsed -= m_iObjectSize; + ++object_copies; + buffer_offset = (buffer_offset + object_size) % buffer_capacity; + buffer_size -= object_size; } // Write data - if(m_iObjectSize * 2 <= m_iBufferSizeUsed || bAll) + if(object_size * 2 <= buffer_size || bAll) { - _output(m_iObjectSize, m_iObjectCount + 1); - m_iObjectSize = 0; - m_iObjectCount = 0; + move_object_to_output(object_size, object_copies + 1); + object_size = 0; + object_copies = 0; } } - } while(bAll && m_iBufferSizeUsed != 0); + } while(bAll && buffer_size != 0); } -bool IntegerRunLengthEncoder::_areRangesEqual(size_t iObjIdx1, size_t iObjIdx2, +bool integer_run_length_encoder::are_ranges_equal(size_t iObjIdx1, size_t iObjIdx2, size_t iOffset, size_t iObjSize) const { - iObjIdx1 = m_iBufferOffset + iOffset * m_iRecordSize + iObjIdx1 * iObjSize; - iObjIdx2 = m_iBufferOffset + iOffset * m_iRecordSize + iObjIdx2 * iObjSize; + iObjIdx1 = buffer_offset + iOffset * record_size + iObjIdx1 * iObjSize; + iObjIdx2 = buffer_offset + iOffset * record_size + iObjIdx2 * iObjSize; for(size_t i = 0; i < iObjSize; ++i) { - if(m_pBuffer[(iObjIdx1 + i) % m_iBufferSize] - != m_pBuffer[(iObjIdx2 + i) % m_iBufferSize]) + if(buffer[(iObjIdx1 + i) % buffer_capacity] + != buffer[(iObjIdx2 + i) % buffer_capacity]) { return false; } @@ -182,146 +182,146 @@ return true; } -bool IntegerRunLengthEncoder::_output(size_t iObjSize, size_t iObjCount) +bool integer_run_length_encoder::move_object_to_output(size_t iObjSize, size_t iObjCount) { // Grow the output array if needed - if(m_iOutputSize - m_iOutputSizeUsed <= iObjSize) + if(output_capacity - output_size <= iObjSize) { - size_t iNewSize = (m_iOutputSize + iObjSize) * 2; + size_t iNewSize = (output_capacity + iObjSize) * 2; uint32_t *pNewOutput = new (std::nothrow) uint32_t[iNewSize]; if(!pNewOutput) return false; #ifdef _MSC_VER #pragma warning(disable: 4996) #endif - std::copy(m_pOutput, m_pOutput + m_iOutputSizeUsed, pNewOutput); + std::copy(output, output + output_size, pNewOutput); #ifdef _MSC_VER #pragma warning(default: 4996) #endif - delete[] m_pOutput; - m_pOutput = pNewOutput; - m_iOutputSize = iNewSize; + delete[] output; + output = pNewOutput; + output_capacity = iNewSize; } - size_t iHeader = (iObjSize / m_iRecordSize - 1) + 8 * (iObjCount - 1); - m_pOutput[m_iOutputSizeUsed++] = static_cast(iHeader); + size_t iHeader = (iObjSize / record_size - 1) + 8 * (iObjCount - 1); + output[output_size++] = static_cast(iHeader); // Move the object from the buffer to the output for(size_t i = 0; i < iObjSize; ++i) { - m_pOutput[m_iOutputSizeUsed++] = m_pBuffer[m_iBufferOffset]; - m_iBufferOffset = (m_iBufferOffset + 1) % m_iBufferSize; + output[output_size++] = buffer[buffer_offset]; + buffer_offset = (buffer_offset + 1) % buffer_capacity; } - m_iBufferSizeUsed -= iObjSize; + buffer_size -= iObjSize; return true; } -uint32_t* IntegerRunLengthEncoder::getOutput(size_t *pCount) const +uint32_t* integer_run_length_encoder::get_output(size_t *pCount) const { if(pCount) - *pCount = m_iOutputSizeUsed; - return m_pOutput; + *pCount = output_size; + return output; } -void IntegerRunLengthEncoder::pumpOutput(LuaPersistWriter *pWriter) const +void integer_run_length_encoder::pump_output(lua_persist_writer *pWriter) const { - pWriter->writeVUInt(m_iOutputSizeUsed); - for(size_t i = 0; i < m_iOutputSizeUsed; ++i) + pWriter->write_uint(output_size); + for(size_t i = 0; i < output_size; ++i) { - pWriter->writeVUInt(m_pOutput[i]); + pWriter->write_uint(output[i]); } } -IntegerRunLengthDecoder::IntegerRunLengthDecoder() +integer_run_length_decoder::integer_run_length_decoder() { - m_pBuffer = nullptr; - _clean(); + buffer = nullptr; + clean(); } -IntegerRunLengthDecoder::~IntegerRunLengthDecoder() +integer_run_length_decoder::~integer_run_length_decoder() { - _clean(); + clean(); } -void IntegerRunLengthDecoder::_clean() +void integer_run_length_decoder::clean() { - delete[] m_pBuffer; - m_pBuffer = nullptr; - m_pReader = nullptr; - m_pInput = nullptr; - m_pInputEnd = nullptr; - m_iNumReadsRemaining = 0; - m_iRepeatCount = 0; - m_iRecordSize = 0; - m_iObjectIndex = 0; - m_iObjectSize = 0; + delete[] buffer; + buffer = nullptr; + reader = nullptr; + input = nullptr; + input_end = nullptr; + reads_remaining = 0; + object_copies = 0; + record_size = 0; + object_index = 0; + object_size = 0; } -bool IntegerRunLengthDecoder::initialise(size_t iRecordSize, LuaPersistReader *pReader) +bool integer_run_length_decoder::initialise(size_t iRecordSize, lua_persist_reader *pReader) { - _clean(); + clean(); - m_pBuffer = new (std::nothrow) uint32_t[9 * iRecordSize]; - if(!m_pBuffer) + buffer = new (std::nothrow) uint32_t[9 * iRecordSize]; + if(!buffer) return false; - m_pReader = pReader; - m_iRecordSize = iRecordSize; - return pReader->readVUInt(m_iNumReadsRemaining); + reader = pReader; + record_size = iRecordSize; + return pReader->read_uint(reads_remaining); } -bool IntegerRunLengthDecoder::initialise(size_t iRecordSize, const uint32_t *pInput, size_t iCount) +bool integer_run_length_decoder::initialise(size_t iRecordSize, const uint32_t *pInput, size_t iCount) { - _clean(); + clean(); - m_pBuffer = new (std::nothrow) uint32_t[9 * iRecordSize]; - if(!m_pBuffer) + buffer = new (std::nothrow) uint32_t[9 * iRecordSize]; + if(!buffer) return false; - m_pInput = pInput; - m_pInputEnd = pInput + iCount; - m_iRecordSize = iRecordSize; + input = pInput; + input_end = pInput + iCount; + record_size = iRecordSize; return true; } -uint32_t IntegerRunLengthDecoder::read() +uint32_t integer_run_length_decoder::read() { - if(m_iRepeatCount == 0) + if(object_copies == 0) { uint32_t iHeader = 0; - if(m_pReader) + if(reader) { - m_pReader->readVUInt(iHeader); - --m_iNumReadsRemaining; + reader->read_uint(iHeader); + --reads_remaining; } else - iHeader = *(m_pInput++); - m_iObjectSize = m_iRecordSize * (1 + (iHeader & 7)); - m_iRepeatCount = (iHeader / 8) + 1; - if(m_pReader) + iHeader = *(input++); + object_size = record_size * (1 + (iHeader & 7)); + object_copies = (iHeader / 8) + 1; + if(reader) { - for(size_t i = 0; i < m_iObjectSize; ++i) + for(size_t i = 0; i < object_size; ++i) { - m_pReader->readVUInt(m_pBuffer[i]); - --m_iNumReadsRemaining; + reader->read_uint(buffer[i]); + --reads_remaining; } } else { - for(size_t i = 0; i < m_iObjectSize; ++i) - m_pBuffer[i] = *(m_pInput++); + for(size_t i = 0; i < object_size; ++i) + buffer[i] = *(input++); } } - uint32_t iValue = m_pBuffer[m_iObjectIndex]; - if(++m_iObjectIndex == m_iObjectSize) + uint32_t iValue = buffer[object_index]; + if(++object_index == object_size) { - m_iObjectIndex = 0; - --m_iRepeatCount; + object_index = 0; + --object_copies; } return iValue; } -bool IntegerRunLengthDecoder::isFinished() const +bool integer_run_length_decoder::is_finished() const { - if(m_pReader) - return m_iNumReadsRemaining == 0 && m_iRepeatCount == 0; + if(reader) + return reads_remaining == 0 && object_copies == 0; else - return m_pInput == m_pInputEnd && m_iRepeatCount == 0; + return input == input_end && object_copies == 0; } diff -Nru corsix-th-0.61/CorsixTH/Src/run_length_encoder.h corsix-th-0.62/CorsixTH/Src/run_length_encoder.h --- corsix-th-0.61/CorsixTH/Src/run_length_encoder.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/run_length_encoder.h 2018-07-21 11:13:17.000000000 +0000 @@ -24,8 +24,8 @@ #define CORSIX_TH_RLE_H_ #include "config.h" -class LuaPersistReader; -class LuaPersistWriter; +class lua_persist_reader; +class lua_persist_writer; //! Encoder for reducing the amount of space to store a sequence of integers /*! @@ -39,11 +39,11 @@ * Object - One or more records. Each object has an associated repeat count. */ -class IntegerRunLengthEncoder +class integer_run_length_encoder { public: - IntegerRunLengthEncoder(); - ~IntegerRunLengthEncoder(); + integer_run_length_encoder(); + ~integer_run_length_encoder(); //! (Re-)initialise the encoder /*! @@ -63,72 +63,72 @@ */ void finish(); - uint32_t* getOutput(size_t *pCount) const; - void pumpOutput(LuaPersistWriter *pWriter) const; + uint32_t* get_output(size_t *pCount) const; + void pump_output(lua_persist_writer *pWriter) const; private: - void _clean(); + void clean(); //! Reduce the amount of data in the buffer /*! - \param bAll If true, will reduce m_iBufferSizeUsed to zero. - If false, will reduce m_iBufferSizeUsed by some amount. + \param bAll If true, will reduce buffer_size to zero. + If false, will reduce buffer_size by some amount. */ - void _flush(bool bAll); + void flush(bool bAll); - bool _areRangesEqual(size_t iObjIdx1, size_t iObjIdx2, size_t iOffset, size_t iObjSize) const; - bool _output(size_t iObjSize, size_t iObjCount); + bool are_ranges_equal(size_t iObjIdx1, size_t iObjIdx2, size_t iOffset, size_t iObjSize) const; + bool move_object_to_output(size_t iObjSize, size_t iObjCount); //! A circular fixed-size buffer holding the most recent input - uint32_t* m_pBuffer; + uint32_t* buffer; //! A variable-length array holding the output sequence - uint32_t* m_pOutput; + uint32_t* output; //! The number of integers in a record - size_t m_iRecordSize; + size_t record_size; //! The maximum number of integers stored in the buffer - size_t m_iBufferSize; + size_t buffer_capacity; //! The current number of integers stored in the buffer - size_t m_iBufferSizeUsed; - //! The index into m_pBuffer of the 1st integer - size_t m_iBufferOffset; + size_t buffer_size; + //! The index into buffer of the 1st integer + size_t buffer_offset; //! The maximum number of integers storable in the output (before the //! output array has to be resized). - size_t m_iOutputSize; + size_t output_capacity; //! The current number of integers stored in the output - size_t m_iOutputSizeUsed; + size_t output_size; //! The number of integers in the current object (multiple of record size) - size_t m_iObjectSize; + size_t object_size; //! The number of copies of the current object already seen and removed //! from the buffer. - size_t m_iObjectCount; + size_t object_copies; }; -class IntegerRunLengthDecoder +class integer_run_length_decoder { public: - IntegerRunLengthDecoder(); - ~IntegerRunLengthDecoder(); + integer_run_length_decoder(); + ~integer_run_length_decoder(); - bool initialise(size_t iRecordSize, LuaPersistReader *pReader); + bool initialise(size_t iRecordSize, lua_persist_reader *pReader); bool initialise(size_t iRecordSize, const uint32_t *pInput, size_t iCount); uint32_t read(); - bool isFinished() const; + bool is_finished() const; private: - void _clean(); + void clean(); - uint32_t* m_pBuffer; - LuaPersistReader* m_pReader; - const uint32_t* m_pInput; + uint32_t* buffer; + lua_persist_reader* reader; + const uint32_t* input; union { - const uint32_t* m_pInputEnd; - size_t m_iNumReadsRemaining; + const uint32_t* input_end; + size_t reads_remaining; }; - size_t m_iRepeatCount; - size_t m_iRecordSize; - size_t m_iObjectIndex; - size_t m_iObjectSize; + size_t object_copies; + size_t record_size; + size_t object_index; + size_t object_size; }; #endif // CORSIX_TH_RLE_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/sdl_audio.cpp corsix-th-0.62/CorsixTH/Src/sdl_audio.cpp --- corsix-th-0.61/CorsixTH/Src/sdl_audio.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/sdl_audio.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -31,16 +31,17 @@ #endif #include -struct music_t +class music { +public: Mix_Music* pMusic; - music_t() + music() { pMusic = nullptr; } - ~music_t() + ~music() { if(pMusic) { @@ -76,17 +77,21 @@ } } -struct load_music_async_t +struct load_music_async_data { lua_State* L; Mix_Music* music; SDL_RWops* rwop; char* err; + SDL_Thread* thread; }; int l_load_music_async_callback(lua_State *L) { - load_music_async_t *async = (load_music_async_t*)lua_touserdata(L, 1); + load_music_async_data *async = (load_music_async_data*)lua_touserdata(L, 1); + + // Frees resources allocated to the thread + SDL_WaitThread(async->thread, nullptr); // Replace light UD with full UD lua_pushvalue(L, 1); @@ -118,7 +123,7 @@ else { lua_rawgeti(L, 2, 2); - music_t* pLMusic = (music_t*)lua_touserdata(L, -1); + music* pLMusic = (music*)lua_touserdata(L, -1); pLMusic->pMusic = async->music; async->music = nullptr; } @@ -136,7 +141,8 @@ static int load_music_async_thread(void* arg) { - load_music_async_t *async = (load_music_async_t*)arg; + load_music_async_data *async = (load_music_async_data*)arg; + async->music = Mix_LoadMUS_RW(async->rwop, 1); async->rwop = nullptr; if(async->music == nullptr) @@ -160,7 +166,7 @@ SDL_RWops* rwop = SDL_RWFromConstMem(pData, (int)iLength); lua_settop(L, 2); - load_music_async_t *async = luaT_new(L, load_music_async_t); + load_music_async_data *async = luaT_new(L, load_music_async_data); lua_pushlightuserdata(L, async); lua_pushvalue(L, -2); lua_settable(L, LUA_REGISTRYINDEX); @@ -171,7 +177,7 @@ lua_createtable(L, 2, 0); lua_pushvalue(L, 2); lua_rawseti(L, -2, 1); - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); lua_pushvalue(L, 1); luaT_setenvfield(L, -2, "data"); lua_rawseti(L, -2, 2); @@ -189,7 +195,7 @@ call the callback and remove the new entries from the registry. */ - SDL_CreateThread(load_music_async_thread, "music_thread", async); + async->thread = SDL_CreateThread(load_music_async_thread, "music_thread", async); return 0; } @@ -206,7 +212,7 @@ lua_pushstring(L, Mix_GetError()); return 2; } - music_t* pLMusic = luaT_stdnew(L, luaT_environindex, true); + music* pLMusic = luaT_stdnew(L, luaT_environindex, true); pLMusic->pMusic = pMusic; lua_pushvalue(L, 1); luaT_setenvfield(L, -2, "data"); @@ -228,7 +234,7 @@ static int l_play_music(lua_State *L) { - music_t* pLMusic = luaT_testuserdata(L, -1); + music* pLMusic = luaT_testuserdata(L, -1); if(Mix_PlayMusic(pLMusic->pMusic, static_cast(luaL_optinteger(L, 2, 1))) != 0) { lua_pushnil(L); @@ -264,7 +270,7 @@ size_t iLength, iMidLength; const uint8_t *pData = luaT_checkfile(L, 1, &iLength); - uint8_t *pMidData = TranscodeXmiToMid(pData, iLength, &iMidLength); + uint8_t *pMidData = transcode_xmi_to_midi(pData, iLength, &iMidLength); if(pMidData == nullptr) { lua_pushnil(L); @@ -305,7 +311,7 @@ lua_pushvalue(L, -1); lua_replace(L, luaT_environindex); lua_pushvalue(L, luaT_environindex); - luaT_pushcclosure(L, luaT_stdgc, 1); + luaT_pushcclosure(L, luaT_stdgc, 1); lua_setfield(L, -2, "__gc"); lua_pushvalue(L, 1); lua_setfield(L, -2, "__index"); diff -Nru corsix-th-0.61/CorsixTH/Src/th.cpp corsix-th-0.62/CorsixTH/Src/th.cpp --- corsix-th-0.61/CorsixTH/Src/th.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -25,30 +25,30 @@ #include #include -THLinkList::THLinkList() +link_list::link_list() { - m_drawingLayer = 0; - m_pPrev = nullptr; - m_pNext = nullptr; + drawing_layer = 0; + prev = nullptr; + next = nullptr; } -THLinkList::~THLinkList() +link_list::~link_list() { - removeFromList(); + remove_from_list(); } -void THLinkList::removeFromList() +void link_list::remove_from_list() { - if(m_pPrev != nullptr) + if(prev != nullptr) { - m_pPrev->m_pNext = m_pNext; + prev->next = next; } - if(m_pNext != nullptr) + if(next != nullptr) { - m_pNext->m_pPrev = m_pPrev; - m_pNext = nullptr; + next->prev = prev; + next = nullptr; } - m_pPrev = nullptr; + prev = nullptr; } #include "cp437_table.h" @@ -110,7 +110,7 @@ } else { - utf8encode(sOut, g_aCP437toUnicode[cChar - 0x80]); + utf8encode(sOut, cp437_to_unicode_table[cChar - 0x80]); } } while(cChar != 0); } @@ -133,7 +133,7 @@ ++sIn; if(0x40 <= cChar2 && cChar2 <= 0xFE) { - utf8encode(sOut, g_aCP936toUnicode[cChar1-0x81][cChar2-0x40]); + utf8encode(sOut, cp936_to_unicode_table[cChar1-0x81][cChar2-0x40]); // The Theme Hospital string tables seem to like following a // multibyte character with a superfluous space. cChar2 = *sIn; @@ -151,7 +151,7 @@ } while(cChar1 != 0); } -THStringList::THStringList(const uint8_t* data, size_t length) +th_string_list::th_string_list(const uint8_t* data, size_t length) { if(length < 2) throw std::invalid_argument("length must be 2 or larger"); @@ -205,22 +205,22 @@ *sDataOut = 0; } -THStringList::~THStringList() +th_string_list::~th_string_list() {} -size_t THStringList::getSectionCount() +size_t th_string_list::get_section_count() { return sections.size(); } -size_t THStringList::getSectionSize(size_t section) +size_t th_string_list::get_section_size(size_t section) { return section < sections.size() ? sections[section].size() : 0; } -const char* THStringList::getString(size_t section, size_t index) +const char* th_string_list::get_string(size_t section, size_t index) { - if(index < getSectionSize(section)) + if(index < get_section_size(section)) { return sections[section][index]; } diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx.cpp corsix-th-0.62/CorsixTH/Src/th_gfx.cpp --- corsix-th-0.61/CorsixTH/Src/th_gfx.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -32,35 +32,35 @@ #include /** Data retrieval class, simulating sequential access to the data, keeping track of available length. */ -class Input +class memory_reader { public: - Input(const uint8_t *pData, size_t iLength) + memory_reader(const uint8_t *pData, size_t iLength) { - m_pData = pData; - m_iLength = iLength; + data = pData; + remaining_bytes = iLength; } - const uint8_t *m_pData; ///< Pointer to the remaining data. - size_t m_iLength; ///< Remaining number of bytes. + const uint8_t *data; ///< Pointer to the remaining data. + size_t remaining_bytes; ///< Remaining number of bytes. //! Can \a iSize bytes be read from the file? /*! @param iSize Number of bytes that are queried. @return Whether the requested number of bytes is still available. */ - inline bool Available(size_t iSize) + bool are_bytes_available(size_t iSize) { - return iSize <= m_iLength; + return iSize <= remaining_bytes; } //! Is EOF reached? /*! @return Whether EOF has been reached. */ - inline bool AtEOF() + bool is_at_end_of_file() { - return m_iLength == 0; + return remaining_bytes == 0; } //! Get an 8 bit value from the file. @@ -68,13 +68,13 @@ @return Read 8 bit value. @pre There should be at least a byte available for reading. */ - inline uint8_t Uint8() + uint8_t read_uint8() { - assert(m_iLength > 0); + assert(remaining_bytes > 0); - uint8_t iVal = *m_pData; - m_pData++; - m_iLength--; + uint8_t iVal = *data; + data++; + remaining_bytes--; return iVal; } @@ -83,10 +83,10 @@ @return Read 16 bit value. @pre There should be at least 2 bytes available for reading. */ - inline uint16_t Uint16() + uint16_t read_uint16() { - uint16_t iVal = Uint8(); - uint16_t iVal2 = Uint8(); + uint16_t iVal = read_uint8(); + uint16_t iVal2 = read_uint8(); return static_cast(iVal | (iVal2 << 8)); } @@ -95,9 +95,9 @@ @return The read signed 16 bit value. @pre There should be at least 2 bytes available for reading. */ - inline int Int16() + int read_int16() { - int val = Uint16(); + int val = read_uint16(); if (val < 0x7FFF) return val; @@ -110,86 +110,86 @@ @return Read 32 bit value. @pre There should be at least 4 bytes available for reading. */ - inline uint32_t Uint32() + uint32_t read_uint32() { - uint32_t iVal = Uint16(); - uint32_t iVal2 = Uint16(); + uint32_t iVal = read_uint16(); + uint32_t iVal2 = read_uint16(); return iVal | (iVal2 << 16); } - //! Load string from the input. + //! Load string from the memory_reader. /*! @param [out] pStr String to load. @return Whether the string could be loaded. */ - inline bool String(std::string *pStr) + bool read_string(std::string *pStr) { char buff[256]; - if (AtEOF()) + if (is_at_end_of_file()) return false; - size_t iLength = Uint8(); - if (!Available(iLength)) + size_t iLength = read_uint8(); + if (!are_bytes_available(iLength)) return false; size_t idx; for (idx = 0; idx < iLength; idx++) - buff[idx] = Uint8(); + buff[idx] = read_uint8(); buff[idx] = '\0'; *pStr = std::string(buff); return true; } }; -THAnimationManager::THAnimationManager() +animation_manager::animation_manager() { - m_vFirstFrames.clear(); - m_vFrames.clear(); - m_vElementList.clear(); - m_vElements.clear(); - m_vCustomSheets.clear(); + first_frames.clear(); + frames.clear(); + element_list.clear(); + elements.clear(); + custom_sheets.clear(); - m_pSpriteSheet = nullptr; + sheet = nullptr; - m_iAnimationCount = 0; - m_iFrameCount = 0; - m_iElementListCount = 0; - m_iElementCount = 0; + animation_count = 0; + frame_count = 0; + element_list_count = 0; + element_count = 0; } -THAnimationManager::~THAnimationManager() +animation_manager::~animation_manager() { - for (size_t i = 0; i < m_vCustomSheets.size(); i++) - delete m_vCustomSheets[i]; + for (size_t i = 0; i < custom_sheets.size(); i++) + delete custom_sheets[i]; } -void THAnimationManager::setSpriteSheet(THSpriteSheet* pSpriteSheet) +void animation_manager::set_sprite_sheet(sprite_sheet* pSpriteSheet) { - m_pSpriteSheet = pSpriteSheet; + sheet = pSpriteSheet; } -bool THAnimationManager::loadFromTHFile( +bool animation_manager::load_from_th_file( const uint8_t* pStartData, size_t iStartDataLength, const uint8_t* pFrameData, size_t iFrameDataLength, const uint8_t* pListData, size_t iListDataLength, const uint8_t* pElementData, size_t iElementDataLength) { - size_t iAnimationCount = iStartDataLength / sizeof(th_anim_t); - size_t iFrameCount = iFrameDataLength / sizeof(th_frame_t); + size_t iAnimationCount = iStartDataLength / sizeof(th_animation_properties); + size_t iFrameCount = iFrameDataLength / sizeof(th_frame_properties); size_t iListCount = iListDataLength / 2; - size_t iElementCount = iElementDataLength / sizeof(th_element_t); + size_t iElementCount = iElementDataLength / sizeof(th_element_properties); if(iAnimationCount == 0 || iFrameCount == 0 || iListCount == 0 || iElementCount == 0) return false; // Start offset of the file data into the vectors. - size_t iAnimationStart = m_iAnimationCount; - size_t iFrameStart = m_iFrameCount; - size_t iListStart = m_iElementListCount; - size_t iElementStart = m_iElementCount; + size_t iAnimationStart = animation_count; + size_t iFrameStart = frame_count; + size_t iListStart = element_list_count; + size_t iElementStart = element_count; - // Original data file cannot must start at offset 0 due to the hard-coded animation numbers in the Lua code. + // Original data file must start at offset 0 due to the hard-coded animation numbers in the Lua code. if (iAnimationStart > 0 || iFrameStart > 0 || iListStart > 0 || iElementStart > 0) return false; @@ -197,39 +197,39 @@ return false; // Create new space for the data. - m_vFirstFrames.reserve(iAnimationStart + iAnimationCount); - m_vFrames.reserve(iFrameStart + iFrameCount); - m_vElementList.reserve(iListStart + iListCount + 1); - m_vElements.reserve(iElementStart + iElementCount); + first_frames.reserve(iAnimationStart + iAnimationCount); + frames.reserve(iFrameStart + iFrameCount); + element_list.reserve(iListStart + iListCount + 1); + elements.reserve(iElementStart + iElementCount); // Read animations. for(size_t i = 0; i < iAnimationCount; ++i) { - size_t iFirstFrame = reinterpret_cast(pStartData)[i].frame; + size_t iFirstFrame = reinterpret_cast(pStartData)[i].first_frame; if(iFirstFrame > iFrameCount) iFirstFrame = 0; iFirstFrame += iFrameStart; - m_vFirstFrames.push_back(iFirstFrame); + first_frames.push_back(iFirstFrame); } // Read frames. for(size_t i = 0; i < iFrameCount; ++i) { - const th_frame_t* pFrame = reinterpret_cast(pFrameData) + i; + const th_frame_properties* pFrame = reinterpret_cast(pFrameData) + i; - frame_t oFrame; - oFrame.iListIndex = iListStart + (pFrame->list_index < iListCount ? pFrame->list_index : 0); - oFrame.iNextFrame = iFrameStart + (pFrame->next < iFrameCount ? pFrame->next : 0); - oFrame.iSound = pFrame->sound; - oFrame.iFlags = pFrame->flags; + frame oFrame; + oFrame.list_index = iListStart + (pFrame->list_index < iListCount ? pFrame->list_index : 0); + oFrame.next_frame = iFrameStart + (pFrame->next < iFrameCount ? pFrame->next : 0); + oFrame.sound = pFrame->sound; + oFrame.flags = pFrame->flags; // Bounding box fields initialised later - oFrame.iMarkerX = 0; - oFrame.iMarkerY = 0; - oFrame.iSecondaryMarkerX = 0; - oFrame.iSecondaryMarkerY = 0; + oFrame.marker_x = 0; + oFrame.marker_y = 0; + oFrame.secondary_marker_x = 0; + oFrame.secondary_marker_y = 0; - m_vFrames.push_back(oFrame); + frames.push_back(oFrame); } // Read element list. @@ -245,49 +245,49 @@ iElmNumber = static_cast(iElmNumber + iElementStart); } - m_vElementList.push_back(iElmNumber); + element_list.push_back(iElmNumber); } - m_vElementList.push_back(0xFFFF); + element_list.push_back(0xFFFF); // Read elements. - size_t iSpriteCount = m_pSpriteSheet->getSpriteCount(); + size_t iSpriteCount = sheet->get_sprite_count(); for(size_t i = 0; i < iElementCount; ++i) { - const th_element_t* pTHElement = reinterpret_cast(pElementData) + i; + const th_element_properties* pTHElement = reinterpret_cast(pElementData) + i; - element_t oElement; - oElement.iSprite = pTHElement->table_position / 6; - oElement.iFlags = pTHElement->flags & 0xF; - oElement.iX = static_cast(pTHElement->offx) - 141; - oElement.iY = static_cast(pTHElement->offy) - 186; - oElement.iLayer = static_cast(pTHElement->flags >> 4); // High nibble, layer of the element. - if(oElement.iLayer > 12) - oElement.iLayer = 6; // Nothing lives on layer 6 - oElement.iLayerId = pTHElement->layerid; - if (oElement.iSprite < iSpriteCount) { - oElement.pSpriteSheet = m_pSpriteSheet; + element oElement; + oElement.sprite = pTHElement->table_position / 6; + oElement.flags = pTHElement->flags & 0xF; + oElement.x = static_cast(pTHElement->offx) - 141; + oElement.y = static_cast(pTHElement->offy) - 186; + oElement.layer = static_cast(pTHElement->flags >> 4); // High nibble, layer of the element. + if(oElement.layer > 12) + oElement.layer = 6; // Nothing lives on layer 6 + oElement.layer_id = pTHElement->layerid; + if (oElement.sprite < iSpriteCount) { + oElement.element_sprite_sheet = sheet; } else { - oElement.pSpriteSheet = nullptr; + oElement.element_sprite_sheet = nullptr; } - m_vElements.push_back(oElement); + elements.push_back(oElement); } // Compute bounding box of the animations using the sprite sheet. for(size_t i = 0; i < iFrameCount; ++i) { - setBoundingBox(m_vFrames[iFrameStart + i]); + set_bounding_box(frames[iFrameStart + i]); } - m_iAnimationCount += iAnimationCount; - m_iFrameCount += iFrameCount; - m_iElementListCount += iListCount + 1; - m_iElementCount += iElementCount; - - assert(m_vFirstFrames.size() == m_iAnimationCount); - assert(m_vFrames.size() == m_iFrameCount); - assert(m_vElementList.size() == m_iElementListCount); - assert(m_vElements.size() == m_iElementCount); + animation_count += iAnimationCount; + frame_count += iFrameCount; + element_list_count += iListCount + 1; + element_count += iElementCount; + + assert(first_frames.size() == animation_count); + assert(frames.size() == frame_count); + assert(element_list.size() == element_list_count); + assert(elements.size() == element_count); return true; } @@ -297,7 +297,7 @@ @param [inout] iLeft Left value to check and update. @param iRight Second value to check. */ -inline static void _setmin(int& iLeft, int iRight) +static void set_left_to_min(int& iLeft, int iRight) { if(iRight < iLeft) iLeft = iRight; @@ -308,41 +308,41 @@ @param [inout] iLeft Left value to check and update. @param iRight Second value to check. */ -inline static void _setmax(int& iLeft, int iRight) +static void set_left_to_max(int& iLeft, int iRight) { if(iRight > iLeft) iLeft = iRight; } -void THAnimationManager::setBoundingBox(frame_t &oFrame) +void animation_manager::set_bounding_box(frame &oFrame) { - oFrame.iBoundingLeft = INT_MAX; - oFrame.iBoundingRight = INT_MIN; - oFrame.iBoundingTop = INT_MAX; - oFrame.iBoundingBottom = INT_MIN; - size_t iListIndex = oFrame.iListIndex; + oFrame.bounding_left = INT_MAX; + oFrame.bounding_right = INT_MIN; + oFrame.bounding_top = INT_MAX; + oFrame.bounding_bottom = INT_MIN; + size_t iListIndex = oFrame.list_index; for(; ; ++iListIndex) { - uint16_t iElement = m_vElementList[iListIndex]; - if(iElement >= m_vElements.size()) + uint16_t iElement = element_list[iListIndex]; + if(iElement >= elements.size()) break; - element_t& oElement = m_vElements[iElement]; - if(oElement.pSpriteSheet == nullptr) + element& oElement = elements[iElement]; + if(oElement.element_sprite_sheet == nullptr) continue; unsigned int iWidth, iHeight; - oElement.pSpriteSheet->getSpriteSizeUnchecked(oElement.iSprite, &iWidth, &iHeight); - _setmin(oFrame.iBoundingLeft , oElement.iX); - _setmin(oFrame.iBoundingTop , oElement.iY); - _setmax(oFrame.iBoundingRight , oElement.iX - 1 + (int)iWidth); - _setmax(oFrame.iBoundingBottom, oElement.iY - 1 + (int)iHeight); + oElement.element_sprite_sheet->get_sprite_size_unchecked(oElement.sprite, &iWidth, &iHeight); + set_left_to_min(oFrame.bounding_left , oElement.x); + set_left_to_min(oFrame.bounding_top , oElement.y); + set_left_to_max(oFrame.bounding_right , oElement.x - 1 + (int)iWidth); + set_left_to_max(oFrame.bounding_bottom, oElement.y - 1 + (int)iHeight); } } -void THAnimationManager::setCanvas(THRenderTarget *pCanvas) +void animation_manager::set_canvas(render_target *pCanvas) { - m_pCanvas = pCanvas; + canvas = pCanvas; } //! Load the header. @@ -350,64 +350,64 @@ @param [inout] input Data to read. @return Number of consumed bytes, a negative number indicates an error. */ -static int loadHeader(Input &input) +static int load_header(memory_reader &input) { static const uint8_t aHdr[] = {'C', 'T', 'H', 'G', 1, 2}; - if (!input.Available(6)) + if (!input.are_bytes_available(6)) return false; for (int i = 0; i < 6; i++) { - if (input.Uint8() != aHdr[i]) + if (input.read_uint8() != aHdr[i]) return false; } return true; } -size_t THAnimationManager::loadElements(Input &input, THSpriteSheet *pSpriteSheet, +size_t animation_manager::load_elements(memory_reader &input, sprite_sheet *pSpriteSheet, size_t iNumElements, size_t &iLoadedElements, size_t iElementStart, size_t iElementCount) { size_t iFirst = iLoadedElements + iElementStart; - size_t iSpriteCount = pSpriteSheet->getSpriteCount(); + size_t iSpriteCount = pSpriteSheet->get_sprite_count(); while (iNumElements > 0) { - if (iLoadedElements >= iElementCount || !input.Available(12)) + if (iLoadedElements >= iElementCount || !input.are_bytes_available(12)) return SIZE_MAX; - size_t iSprite = input.Uint32(); - int iX = input.Int16(); - int iY = input.Int16(); - uint8_t iLayerClass = input.Uint8(); - uint8_t iLayerId = input.Uint8(); - uint32_t iFlags = input.Uint16(); + size_t iSprite = input.read_uint32(); + int iX = input.read_int16(); + int iY = input.read_int16(); + uint8_t iLayerClass = input.read_uint8(); + uint8_t iLayerId = input.read_uint8(); + uint32_t iFlags = input.read_uint16(); if (iLayerClass > 12) iLayerClass = 6; // Nothing lives on layer 6 - element_t oElement; - oElement.iSprite = iSprite; - oElement.iFlags = iFlags; - oElement.iX = iX; - oElement.iY = iY; - oElement.iLayer = iLayerClass; - oElement.iLayerId = iLayerId; - if (oElement.iSprite >= iSpriteCount) - oElement.pSpriteSheet = nullptr; + element oElement; + oElement.sprite = iSprite; + oElement.flags = iFlags; + oElement.x = iX; + oElement.y = iY; + oElement.layer = iLayerClass; + oElement.layer_id = iLayerId; + if (oElement.sprite >= iSpriteCount) + oElement.element_sprite_sheet = nullptr; else - oElement.pSpriteSheet = pSpriteSheet; + oElement.element_sprite_sheet = pSpriteSheet; - m_vElements.push_back(oElement); + elements.push_back(oElement); iLoadedElements++; iNumElements--; } return iFirst; } -size_t THAnimationManager::makeListElements(size_t iFirstElement, size_t iNumElements, - size_t &iLoadedListElements, - size_t iListStart, size_t iListCount) +size_t animation_manager::make_list_elements(size_t iFirstElement, size_t iNumElements, + size_t &iLoadedListElements, + size_t iListStart, size_t iListCount) { size_t iFirst = iLoadedListElements + iListStart; @@ -418,13 +418,13 @@ while (iNumElements > 0) { - m_vElementList.push_back(static_cast(iFirstElement)); + element_list.push_back(static_cast(iFirstElement)); iLoadedListElements++; iFirstElement++; iNumElements--; } // Add 0xFFFF. - m_vElementList.push_back(0xFFFF); + element_list.push_back(0xFFFF); iLoadedListElements++; return iFirst; @@ -438,48 +438,48 @@ @param iLoaded Number of loaded frames. @return The shifted first frame, or 0xFFFFFFFFu. */ -static uint32_t shiftFirst(uint32_t iFirst, size_t iLength, - size_t iStart, size_t iLoaded) +static uint32_t shift_first(uint32_t iFirst, size_t iLength, + size_t iStart, size_t iLoaded) { if (iFirst == 0xFFFFFFFFu || iFirst + iLength > iLoaded) return 0xFFFFFFFFu; return iFirst + static_cast(iStart); } -void THAnimationManager::fixNextFrame(uint32_t iFirst, size_t iLength) +void animation_manager::fix_next_frame(uint32_t iFirst, size_t iLength) { if (iFirst == 0xFFFFFFFFu) return; - frame_t &oFirst = m_vFrames[iFirst]; - oFirst.iFlags |= 0x1; // Start of animation flag. + frame &oFirst = frames[iFirst]; + oFirst.flags |= 0x1; // Start of animation flag. - frame_t &oLast = m_vFrames[iFirst + iLength - 1]; - oLast.iNextFrame = iFirst; // Loop last frame back to the first. + frame &oLast = frames[iFirst + iLength - 1]; + oLast.next_frame = iFirst; // Loop last frame back to the first. } -bool THAnimationManager::loadCustomAnimations(const uint8_t* pData, size_t iDataLength) +bool animation_manager::load_custom_animations(const uint8_t* pData, size_t iDataLength) { - Input input(pData, iDataLength); + memory_reader input(pData, iDataLength); - if (!loadHeader(input)) + if (!load_header(input)) return false; - if (!input.Available(5*4)) + if (!input.are_bytes_available(5*4)) return false; - size_t iAnimationCount = input.Uint32(); - size_t iFrameCount = input.Uint32(); - size_t iElementCount = input.Uint32(); - size_t iSpriteCount = input.Uint32(); - input.Uint32(); // Total number of bytes sprite data is not used. + size_t iAnimationCount = input.read_uint32(); + size_t iFrameCount = input.read_uint32(); + size_t iElementCount = input.read_uint32(); + size_t iSpriteCount = input.read_uint32(); + input.read_uint32(); // Total number of bytes sprite data is not used. // Every element is referenced once, and one 0xFFFF for every frame. size_t iListCount = iElementCount + iFrameCount; - size_t iFrameStart = m_iFrameCount; - size_t iListStart = m_iElementListCount; - size_t iElementStart = m_iElementCount; + size_t iFrameStart = frame_count; + size_t iListStart = element_list_count; + size_t iElementStart = element_count; if (iAnimationCount == 0 || iFrameCount == 0 || iElementCount == 0 || iSpriteCount == 0) return false; @@ -488,15 +488,15 @@ return false; // Create new space for the elements. - m_vFirstFrames.reserve(m_vFirstFrames.size() + iAnimationCount * 4); // Be optimistic in reservation. - m_vFrames.reserve(iFrameStart + iFrameCount); - m_vElementList.reserve(iListStart + iListCount); - m_vElements.reserve(iElementStart + iElementCount); + first_frames.reserve(first_frames.size() + iAnimationCount * 4); // Be optimistic in reservation. + frames.reserve(iFrameStart + iFrameCount); + element_list.reserve(iListStart + iListCount); + elements.reserve(iElementStart + iElementCount); // Construct a sprite sheet for the sprites to be loaded. - THSpriteSheet *pSheet = new THSpriteSheet; - pSheet->setSpriteCount(iSpriteCount, m_pCanvas); - m_vCustomSheets.push_back(pSheet); + sprite_sheet *pSheet = new sprite_sheet; + pSheet->set_sprite_count(iSpriteCount, canvas); + custom_sheets.push_back(pSheet); size_t iLoadedFrames = 0; size_t iLoadedListElements = 0; @@ -506,75 +506,75 @@ // Read the blocks of the file, until hitting EOF. for (;;) { - if (input.AtEOF()) + if (input.is_at_end_of_file()) break; // Read identification bytes at the start of each block, and dispatch loading. - if (!input.Available(2)) + if (!input.are_bytes_available(2)) return false; - int first = input.Uint8(); - int second = input.Uint8(); + int first = input.read_uint8(); + int second = input.read_uint8(); // Recognized a grouped animation block, load it. if (first == 'C' && second == 'A') { - AnimationKey oKey; + animation_key oKey; - if (!input.Available(2+4)) + if (!input.are_bytes_available(2+4)) return false; - oKey.iTilesize = input.Uint16(); - size_t iNumFrames = input.Uint32(); + oKey.tile_size = input.read_uint16(); + size_t iNumFrames = input.read_uint32(); if (iNumFrames == 0) return false; - if (!input.String(&oKey.sName)) + if (!input.read_string(&oKey.name)) return false; - if (!input.Available(4*4)) + if (!input.are_bytes_available(4*4)) return false; - uint32_t iNorthFirst = input.Uint32(); - uint32_t iEastFirst = input.Uint32(); - uint32_t iSouthFirst = input.Uint32(); - uint32_t iWestFirst = input.Uint32(); - - iNorthFirst = shiftFirst(iNorthFirst, iNumFrames, iFrameStart, iLoadedFrames); - iEastFirst = shiftFirst(iEastFirst, iNumFrames, iFrameStart, iLoadedFrames); - iSouthFirst = shiftFirst(iSouthFirst, iNumFrames, iFrameStart, iLoadedFrames); - iWestFirst = shiftFirst(iWestFirst, iNumFrames, iFrameStart, iLoadedFrames); - - AnimationStartFrames oFrames; - oFrames.iNorth = -1; - oFrames.iEast = -1; - oFrames.iSouth = -1; - oFrames.iWest = -1; + uint32_t iNorthFirst = input.read_uint32(); + uint32_t iEastFirst = input.read_uint32(); + uint32_t iSouthFirst = input.read_uint32(); + uint32_t iWestFirst = input.read_uint32(); + + iNorthFirst = shift_first(iNorthFirst, iNumFrames, iFrameStart, iLoadedFrames); + iEastFirst = shift_first(iEastFirst, iNumFrames, iFrameStart, iLoadedFrames); + iSouthFirst = shift_first(iSouthFirst, iNumFrames, iFrameStart, iLoadedFrames); + iWestFirst = shift_first(iWestFirst, iNumFrames, iFrameStart, iLoadedFrames); + + animation_start_frames oFrames; + oFrames.north = -1; + oFrames.east = -1; + oFrames.south = -1; + oFrames.west = -1; if (iNorthFirst != 0xFFFFFFFFu) { - fixNextFrame(iNorthFirst, iNumFrames); - oFrames.iNorth = static_cast(m_vFirstFrames.size()); - m_vFirstFrames.push_back(iNorthFirst); + fix_next_frame(iNorthFirst, iNumFrames); + oFrames.north = static_cast(first_frames.size()); + first_frames.push_back(iNorthFirst); } if (iEastFirst != 0xFFFFFFFFu) { - fixNextFrame(iEastFirst, iNumFrames); - oFrames.iEast = static_cast(m_vFirstFrames.size()); - m_vFirstFrames.push_back(iEastFirst); + fix_next_frame(iEastFirst, iNumFrames); + oFrames.east = static_cast(first_frames.size()); + first_frames.push_back(iEastFirst); } if (iSouthFirst != 0xFFFFFFFFu) { - fixNextFrame(iSouthFirst, iNumFrames); - oFrames.iSouth = static_cast(m_vFirstFrames.size()); - m_vFirstFrames.push_back(iSouthFirst); + fix_next_frame(iSouthFirst, iNumFrames); + oFrames.south = static_cast(first_frames.size()); + first_frames.push_back(iSouthFirst); } if (iWestFirst != 0xFFFFFFFFu) { - fixNextFrame(iWestFirst, iNumFrames); - oFrames.iWest = static_cast(m_vFirstFrames.size()); - m_vFirstFrames.push_back(iWestFirst); + fix_next_frame(iWestFirst, iNumFrames); + oFrames.west = static_cast(first_frames.size()); + first_frames.push_back(iWestFirst); } - NamedAnimationPair p(oKey, oFrames); - m_oNamedAnimations.insert(p); + named_animation_pair p(oKey, oFrames); + named_animations.insert(p); continue; } @@ -584,34 +584,34 @@ if (iLoadedFrames >= iFrameCount) return false; - if (!input.Available(2+2)) + if (!input.are_bytes_available(2+2)) return false; - int iSound = input.Uint16(); - size_t iNumElements = input.Uint16(); + int iSound = input.read_uint16(); + size_t iNumElements = input.read_uint16(); - size_t iElm = loadElements(input, pSheet, iNumElements, + size_t iElm = load_elements(input, pSheet, iNumElements, iLoadedElements, iElementStart, iElementCount); if (iElm == SIZE_MAX) return false; - size_t iListElm = makeListElements(iElm, iNumElements, + size_t iListElm = make_list_elements(iElm, iNumElements, iLoadedListElements, iListStart, iListCount); if (iListElm == SIZE_MAX) return false; - frame_t oFrame; - oFrame.iListIndex = iListElm; - oFrame.iNextFrame = iFrameStart + iLoadedFrames + 1; // Point to next frame (changed later). - oFrame.iSound = iSound; - oFrame.iFlags = 0; // Set later. - oFrame.iMarkerX = 0; - oFrame.iMarkerY = 0; - oFrame.iSecondaryMarkerX = 0; - oFrame.iSecondaryMarkerY = 0; + frame oFrame; + oFrame.list_index = iListElm; + oFrame.next_frame = iFrameStart + iLoadedFrames + 1; // Point to next frame (changed later). + oFrame.sound = iSound; + oFrame.flags = 0; // Set later. + oFrame.marker_x = 0; + oFrame.marker_y = 0; + oFrame.secondary_marker_x = 0; + oFrame.secondary_marker_y = 0; - setBoundingBox(oFrame); + set_bounding_box(oFrame); - m_vFrames.push_back(oFrame); + frames.push_back(oFrame); iLoadedFrames++; continue; } @@ -622,11 +622,11 @@ if (iLoadedSprites >= iSpriteCount) return false; - if (!input.Available(2+2+4)) + if (!input.are_bytes_available(2+2+4)) return false; - int iWidth = input.Uint16(); - int iHeight = input.Uint16(); - uint32_t iSize = input.Uint32(); + int iWidth = input.read_uint16(); + int iHeight = input.read_uint16(); + uint32_t iSize = input.read_uint32(); if (iSize > INT_MAX) // Check it is safe to use as 'int' return false; @@ -635,14 +635,14 @@ if (pData == nullptr) { return false; } - if (!input.Available(iSize)) { + if (!input.are_bytes_available(iSize)) { delete[] pData; return false; } for (uint32_t i = 0; i < iSize; i++) - pData[i] = input.Uint8(); + pData[i] = input.read_uint8(); - if (!pSheet->setSpriteData(iLoadedSprites, pData, true, iSize, + if (!pSheet->set_sprite_data(iLoadedSprites, pData, true, iSize, iWidth, iHeight)) return false; @@ -663,179 +663,179 @@ assert(iLoadedSprites == iSpriteCount); // Fix the next pointer of the last frame in case it points to non-existing frames. - frame_t &oFrame = m_vFrames[iFrameStart + iFrameCount - 1]; - if (iFrameCount > 0 && oFrame.iNextFrame >= iFrameStart + iFrameCount) - oFrame.iNextFrame = iFrameStart; // Useless, but maybe less crashy. - - m_iAnimationCount = m_vFirstFrames.size(); - m_iFrameCount += iFrameCount; - m_iElementListCount += iListCount; - m_iElementCount += iElementCount; - assert(m_vFrames.size() == m_iFrameCount); - assert(m_vElementList.size() == m_iElementListCount); - assert(m_vElements.size() == m_iElementCount); + frame &oFrame = frames[iFrameStart + iFrameCount - 1]; + if (iFrameCount > 0 && oFrame.next_frame >= iFrameStart + iFrameCount) + oFrame.next_frame = iFrameStart; // Useless, but maybe less crashy. + + animation_count = first_frames.size(); + frame_count += iFrameCount; + element_list_count += iListCount; + element_count += iElementCount; + assert(frames.size() == frame_count); + assert(element_list.size() == element_list_count); + assert(elements.size() == element_count); return true; } -const AnimationStartFrames &THAnimationManager::getNamedAnimations(const std::string &sName, int iTilesize) const +const animation_start_frames &animation_manager::get_named_animations(const std::string &sName, int iTilesize) const { - static const AnimationStartFrames oNoneAnimations = {-1, -1, -1, -1}; + static const animation_start_frames oNoneAnimations = {-1, -1, -1, -1}; - AnimationKey oKey; - oKey.sName = sName; - oKey.iTilesize = iTilesize; + animation_key oKey; + oKey.name = sName; + oKey.tile_size = iTilesize; - NamedAnimationsMap::const_iterator iter = m_oNamedAnimations.find(oKey); - if (iter == m_oNamedAnimations.end()) + named_animations_map::const_iterator iter = named_animations.find(oKey); + if (iter == named_animations.end()) return oNoneAnimations; return (*iter).second; } -size_t THAnimationManager::getAnimationCount() const +size_t animation_manager::get_animation_count() const { - return m_iAnimationCount; + return animation_count; } -size_t THAnimationManager::getFrameCount() const +size_t animation_manager::get_frame_count() const { - return m_iFrameCount; + return frame_count; } -size_t THAnimationManager::getFirstFrame(size_t iAnimation) const +size_t animation_manager::get_first_frame(size_t iAnimation) const { - if(iAnimation < m_iAnimationCount) - return m_vFirstFrames[iAnimation]; + if(iAnimation < animation_count) + return first_frames[iAnimation]; else return 0; } -size_t THAnimationManager::getNextFrame(size_t iFrame) const +size_t animation_manager::get_next_frame(size_t iFrame) const { - if(iFrame < m_iFrameCount) - return m_vFrames[iFrame].iNextFrame; + if(iFrame < frame_count) + return frames[iFrame].next_frame; else return iFrame; } -void THAnimationManager::setAnimationAltPaletteMap(size_t iAnimation, const uint8_t* pMap, uint32_t iAlt32) +void animation_manager::set_animation_alt_palette_map(size_t iAnimation, const uint8_t* pMap, uint32_t iAlt32) { - if(iAnimation >= m_iAnimationCount) + if(iAnimation >= animation_count) return; - size_t iFrame = m_vFirstFrames[iAnimation]; + size_t iFrame = first_frames[iAnimation]; size_t iFirstFrame = iFrame; do { - size_t iListIndex = m_vFrames[iFrame].iListIndex; + size_t iListIndex = frames[iFrame].list_index; for(; ; ++iListIndex) { - uint16_t iElement = m_vElementList[iListIndex]; - if(iElement >= m_iElementCount) + uint16_t iElement = element_list[iListIndex]; + if(iElement >= element_count) break; - element_t& oElement = m_vElements[iElement]; - if (oElement.pSpriteSheet != nullptr) - oElement.pSpriteSheet->setSpriteAltPaletteMap(oElement.iSprite, pMap, iAlt32); + element& oElement = elements[iElement]; + if (oElement.element_sprite_sheet != nullptr) + oElement.element_sprite_sheet->set_sprite_alt_palette_map(oElement.sprite, pMap, iAlt32); } - iFrame = m_vFrames[iFrame].iNextFrame; + iFrame = frames[iFrame].next_frame; } while(iFrame != iFirstFrame); } -bool THAnimationManager::setFrameMarker(size_t iFrame, int iX, int iY) +bool animation_manager::set_frame_marker(size_t iFrame, int iX, int iY) { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return false; - m_vFrames[iFrame].iMarkerX = iX; - m_vFrames[iFrame].iMarkerY = iY; + frames[iFrame].marker_x = iX; + frames[iFrame].marker_y = iY; return true; } -bool THAnimationManager::setFrameSecondaryMarker(size_t iFrame, int iX, int iY) +bool animation_manager::set_frame_secondary_marker(size_t iFrame, int iX, int iY) { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return false; - m_vFrames[iFrame].iSecondaryMarkerX = iX; - m_vFrames[iFrame].iSecondaryMarkerY = iY; + frames[iFrame].secondary_marker_x = iX; + frames[iFrame].secondary_marker_y = iY; return true; } -bool THAnimationManager::getFrameMarker(size_t iFrame, int* pX, int* pY) +bool animation_manager::get_frame_marker(size_t iFrame, int* pX, int* pY) { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return false; - *pX = m_vFrames[iFrame].iMarkerX; - *pY = m_vFrames[iFrame].iMarkerY; + *pX = frames[iFrame].marker_x; + *pY = frames[iFrame].marker_y; return true; } -bool THAnimationManager::getFrameSecondaryMarker(size_t iFrame, int* pX, int* pY) +bool animation_manager::get_frame_secondary_marker(size_t iFrame, int* pX, int* pY) { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return false; - *pX = m_vFrames[iFrame].iSecondaryMarkerX; - *pY = m_vFrames[iFrame].iSecondaryMarkerY; + *pX = frames[iFrame].secondary_marker_x; + *pY = frames[iFrame].secondary_marker_y; return true; } -bool THAnimationManager::hitTest(size_t iFrame, const THLayers_t& oLayers, +bool animation_manager::hit_test(size_t iFrame, const ::layers& oLayers, int iX, int iY, uint32_t iFlags, int iTestX, int iTestY) const { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return false; - const frame_t& oFrame = m_vFrames[iFrame]; + const frame& oFrame = frames[iFrame]; iTestX -= iX; iTestY -= iY; - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) iTestX = -iTestX; - if(iTestX < oFrame.iBoundingLeft || iTestX > oFrame.iBoundingRight) + if(iTestX < oFrame.bounding_left || iTestX > oFrame.bounding_right) return false; - if(iFlags & THDF_FlipVertical) + if(iFlags & thdf_flip_vertical) { - if(-iTestY < oFrame.iBoundingTop || -iTestY > oFrame.iBoundingBottom) + if(-iTestY < oFrame.bounding_top || -iTestY > oFrame.bounding_bottom) return false; } else { - if(iTestY < oFrame.iBoundingTop || iTestY > oFrame.iBoundingBottom) + if(iTestY < oFrame.bounding_top || iTestY > oFrame.bounding_bottom) return false; } - if(iFlags & THDF_BoundBoxHitTest) + if(iFlags & thdf_bound_box_hit_test) return true; - size_t iListIndex = oFrame.iListIndex; + size_t iListIndex = oFrame.list_index; for(; ; ++iListIndex) { - uint16_t iElement = m_vElementList[iListIndex]; - if(iElement >= m_iElementCount) + uint16_t iElement = element_list[iListIndex]; + if(iElement >= element_count) break; - const element_t &oElement = m_vElements[iElement]; - if((oElement.iLayerId != 0 && oLayers.iLayerContents[oElement.iLayer] != oElement.iLayerId) - || oElement.pSpriteSheet == nullptr) + const element &oElement = elements[iElement]; + if((oElement.layer_id != 0 && oLayers.layer_contents[oElement.layer] != oElement.layer_id) + || oElement.element_sprite_sheet == nullptr) { continue; } - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) { unsigned int iWidth, iHeight; - oElement.pSpriteSheet->getSpriteSizeUnchecked(oElement.iSprite, &iWidth, &iHeight); - if(oElement.pSpriteSheet->hitTestSprite(oElement.iSprite, oElement.iX + iWidth - iTestX, - iTestY - oElement.iY, oElement.iFlags ^ THDF_FlipHorizontal)) + oElement.element_sprite_sheet->get_sprite_size_unchecked(oElement.sprite, &iWidth, &iHeight); + if(oElement.element_sprite_sheet->hit_test_sprite(oElement.sprite, oElement.x + iWidth - iTestX, + iTestY - oElement.y, oElement.flags ^ thdf_flip_horizontal)) { return true; } } else { - if(oElement.pSpriteSheet->hitTestSprite(oElement.iSprite, iTestX - oElement.iX, - iTestY - oElement.iY, oElement.iFlags)) + if(oElement.element_sprite_sheet->hit_test_sprite(oElement.sprite, iTestX - oElement.x, + iTestY - oElement.y, oElement.flags)) { return true; } @@ -845,27 +845,27 @@ return false; } -void THAnimationManager::drawFrame(THRenderTarget* pCanvas, size_t iFrame, - const THLayers_t& oLayers, +void animation_manager::draw_frame(render_target* pCanvas, size_t iFrame, + const ::layers& oLayers, int iX, int iY, uint32_t iFlags) const { - if(iFrame >= m_iFrameCount) + if(iFrame >= frame_count) return; - uint32_t iPassOnFlags = iFlags & THDF_AltPalette; + uint32_t iPassOnFlags = iFlags & thdf_alt_palette; - size_t iListIndex = m_vFrames[iFrame].iListIndex; + size_t iListIndex = frames[iFrame].list_index; for(; ; ++iListIndex) { - uint16_t iElement = m_vElementList[iListIndex]; - if(iElement >= m_iElementCount) + uint16_t iElement = element_list[iListIndex]; + if(iElement >= element_count) break; - const element_t &oElement = m_vElements[iElement]; - if (oElement.pSpriteSheet == nullptr) + const element &oElement = elements[iElement]; + if (oElement.element_sprite_sheet == nullptr) continue; - if(oElement.iLayerId != 0 && oLayers.iLayerContents[oElement.iLayer] != oElement.iLayerId) + if(oElement.layer_id != 0 && oLayers.layer_contents[oElement.layer] != oElement.layer_id) { // Some animations involving doctors (i.e. #72, #74, maybe others) // only provide versions for heads W1 and B1, not W2 and B2. The @@ -873,69 +873,69 @@ // the W1 layer as well as W2 if W2 is being used, and similarly // for B1 / B2. A better fix would be to go into each animation // which needs it, and duplicate the W1 / B1 layers to W2 / B2. - if(oElement.iLayer == 5 && oLayers.iLayerContents[5] - 4 == oElement.iLayerId) + if(oElement.layer == 5 && oLayers.layer_contents[5] - 4 == oElement.layer_id) /* don't skip */; else continue; } - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) { unsigned int iWidth, iHeight; - oElement.pSpriteSheet->getSpriteSizeUnchecked(oElement.iSprite, &iWidth, &iHeight); + oElement.element_sprite_sheet->get_sprite_size_unchecked(oElement.sprite, &iWidth, &iHeight); - oElement.pSpriteSheet->drawSprite(pCanvas, oElement.iSprite, iX - oElement.iX - iWidth, - iY + oElement.iY, iPassOnFlags | (oElement.iFlags ^ THDF_FlipHorizontal)); + oElement.element_sprite_sheet->draw_sprite(pCanvas, oElement.sprite, iX - oElement.x - iWidth, + iY + oElement.y, iPassOnFlags | (oElement.flags ^ thdf_flip_horizontal)); } else { - oElement.pSpriteSheet->drawSprite(pCanvas, oElement.iSprite, - iX + oElement.iX, iY + oElement.iY, iPassOnFlags | oElement.iFlags); + oElement.element_sprite_sheet->draw_sprite(pCanvas, oElement.sprite, + iX + oElement.x, iY + oElement.y, iPassOnFlags | oElement.flags); } } } -size_t THAnimationManager::getFrameSound(size_t iFrame) +size_t animation_manager::get_frame_sound(size_t iFrame) { - if(iFrame < m_iFrameCount) - return m_vFrames[iFrame].iSound; + if(iFrame < frame_count) + return frames[iFrame].sound; else return 0; } -void THAnimationManager::getFrameExtent(size_t iFrame, const THLayers_t& oLayers, - int* pMinX, int* pMaxX, - int* pMinY, int* pMaxY, - uint32_t iFlags) const +void animation_manager::get_frame_extent(size_t iFrame, const ::layers& oLayers, + int* pMinX, int* pMaxX, + int* pMinY, int* pMaxY, + uint32_t iFlags) const { int iMinX = INT_MAX; int iMaxX = INT_MIN; int iMinY = INT_MAX; int iMaxY = INT_MIN; - if(iFrame < m_iFrameCount) + if(iFrame < frame_count) { - size_t iListIndex = m_vFrames[iFrame].iListIndex; + size_t iListIndex = frames[iFrame].list_index; for(; ; ++iListIndex) { - uint16_t iElement = m_vElementList[iListIndex]; - if(iElement >= m_iElementCount) + uint16_t iElement = element_list[iListIndex]; + if(iElement >= element_count) break; - const element_t &oElement = m_vElements[iElement]; - if((oElement.iLayerId != 0 && oLayers.iLayerContents[oElement.iLayer] != oElement.iLayerId) - || oElement.pSpriteSheet == nullptr) + const element &oElement = elements[iElement]; + if((oElement.layer_id != 0 && oLayers.layer_contents[oElement.layer] != oElement.layer_id) + || oElement.element_sprite_sheet == nullptr) { continue; } - int iX = oElement.iX; - int iY = oElement.iY; + int iX = oElement.x; + int iY = oElement.y; unsigned int iWidth_, iHeight_; - oElement.pSpriteSheet->getSpriteSizeUnchecked(oElement.iSprite, &iWidth_, &iHeight_); + oElement.element_sprite_sheet->get_sprite_size_unchecked(oElement.sprite, &iWidth_, &iHeight_); int iWidth = static_cast(iWidth_); int iHeight = static_cast(iHeight_); - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) iX = -(iX + iWidth); if(iX < iMinX) iMinX = iX; @@ -957,107 +957,107 @@ *pMaxY = iMaxY; } -THChunkRenderer::THChunkRenderer(int width, int height, uint8_t *buffer) +chunk_renderer::chunk_renderer(int width, int height, uint8_t *buffer) { - m_data = buffer ? buffer : new uint8_t[width * height]; - m_ptr = m_data; - m_end = m_data + width * height; - m_x = 0; - m_y = 0; - m_width = width; - m_height = height; - m_skip_eol = false; + data = buffer ? buffer : new uint8_t[width * height]; + ptr = data; + end = data + width * height; + x = 0; + y = 0; + this->width = width; + this->height = height; + skip_eol = false; } -THChunkRenderer::~THChunkRenderer() +chunk_renderer::~chunk_renderer() { - delete[] m_data; + delete[] data; } -uint8_t* THChunkRenderer::takeData() +uint8_t* chunk_renderer::take_data() { - uint8_t *buffer = m_data; - m_data = 0; + uint8_t *buffer = data; + data = 0; return buffer; } -void THChunkRenderer::chunkFillToEndOfLine(uint8_t value) +void chunk_renderer::chunk_fill_to_end_of_line(uint8_t value) { - if(m_x != 0 || !m_skip_eol) + if(x != 0 || !skip_eol) { - chunkFill(m_width - m_x, value); + chunk_fill(width - x, value); } - m_skip_eol = false; + skip_eol = false; } -void THChunkRenderer::chunkFinish(uint8_t value) +void chunk_renderer::chunk_finish(uint8_t value) { - chunkFill(static_cast(m_end - m_ptr), value); + chunk_fill(static_cast(end - ptr), value); } -void THChunkRenderer::chunkFill(int npixels, uint8_t value) +void chunk_renderer::chunk_fill(int npixels, uint8_t value) { - _fixNpixels(npixels); + fix_n_pixels(npixels); if(npixels > 0) { - std::memset(m_ptr, value, npixels); - _incrementPosition(npixels); + std::memset(ptr, value, npixels); + increment_position(npixels); } } -void THChunkRenderer::chunkCopy(int npixels, const uint8_t* data) +void chunk_renderer::chunk_copy(int npixels, const uint8_t* in_data) { - _fixNpixels(npixels); + fix_n_pixels(npixels); if(npixels > 0) { - std::memcpy(m_ptr, data, npixels); - _incrementPosition(npixels); + std::memcpy(ptr, in_data, npixels); + increment_position(npixels); } } -inline void THChunkRenderer::_fixNpixels(int& npixels) const +void chunk_renderer::fix_n_pixels(int& npixels) const { - if(m_ptr + npixels > m_end) + if(ptr + npixels > end) { - npixels = static_cast(m_end - m_ptr); + npixels = static_cast(end - ptr); } } -inline void THChunkRenderer::_incrementPosition(int npixels) +void chunk_renderer::increment_position(int npixels) { - m_ptr += npixels; - m_x += npixels; - m_y += m_x / m_width; - m_x = m_x % m_width; - m_skip_eol = true; + ptr += npixels; + x += npixels; + y += x / width; + x = x % width; + skip_eol = true; } -void THChunkRenderer::decodeChunks(const uint8_t* data, int datalen, bool complex) +void chunk_renderer::decode_chunks(const uint8_t* data, int datalen, bool complex) { if(complex) { - while(!_isDone() && datalen > 0) + while(!is_done() && datalen > 0) { uint8_t b = *data; --datalen; ++data; if(b == 0) { - chunkFillToEndOfLine(0xFF); + chunk_fill_to_end_of_line(0xFF); } else if(b < 0x40) { int amt = b; if(datalen < amt) amt = datalen; - chunkCopy(amt, data); + chunk_copy(amt, data); data += amt; datalen -= amt; } else if((b & 0xC0) == 0x80) { - chunkFill(b - 0x80, 0xFF); + chunk_fill(b - 0x80, 0xFF); } else { @@ -1084,105 +1084,105 @@ --datalen; } } - chunkFill(amt, colour); + chunk_fill(amt, colour); } } } else { - while(!_isDone() && datalen > 0) + while(!is_done() && datalen > 0) { uint8_t b = *data; --datalen; ++data; if(b == 0) { - chunkFillToEndOfLine(0xFF); + chunk_fill_to_end_of_line(0xFF); } else if(b < 0x80) { int amt = b; if(datalen < amt) amt = datalen; - chunkCopy(amt, data); + chunk_copy(amt, data); data += amt; datalen -= amt; } else { - chunkFill(0x100 - b, 0xFF); + chunk_fill(0x100 - b, 0xFF); } } } - chunkFinish(0xFF); + chunk_finish(0xFF); } -#define AreFlagsSet(val, flags) (((val) & (flags)) == (flags)) +#define ARE_FLAGS_SET(val, flags) (((val) & (flags)) == (flags)) -void THAnimation::draw(THRenderTarget* pCanvas, int iDestX, int iDestY) +void animation::draw(render_target* pCanvas, int iDestX, int iDestY) { - if(AreFlagsSet(m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(flags, thdf_alpha_50 | thdf_alpha_75)) return; - iDestX += m_iX; - iDestY += m_iY; - if(m_iSoundToPlay) + iDestX += x_relative_to_tile; + iDestY += y_relative_to_tile; + if(sound_to_play) { - THSoundEffects *pSounds = THSoundEffects::getSingleton(); + sound_player *pSounds = sound_player::get_singleton(); if(pSounds) - pSounds->playSoundAt(m_iSoundToPlay, iDestX, iDestY); - m_iSoundToPlay = 0; + pSounds->play_at(sound_to_play, iDestX, iDestY); + sound_to_play = 0; } - if(m_pManager) + if(manager) { - if(m_iFlags & THDF_Crop) + if(flags & thdf_crop) { - THClipRect rcOld, rcNew; - pCanvas->getClipRect(&rcOld); + clip_rect rcOld, rcNew; + pCanvas->get_clip_rect(&rcOld); rcNew.y = rcOld.y; rcNew.h = rcOld.h; - rcNew.x = iDestX + (m_iCropColumn - 1) * 32; + rcNew.x = iDestX + (crop_column - 1) * 32; rcNew.w = 64; - IntersectTHClipRect(rcNew, rcOld); - pCanvas->setClipRect(&rcNew); - m_pManager->drawFrame(pCanvas, m_iFrame, m_oLayers, iDestX, iDestY, - m_iFlags); - pCanvas->setClipRect(&rcOld); + clip_rect_intersection(rcNew, rcOld); + pCanvas->set_clip_rect(&rcNew); + manager->draw_frame(pCanvas, frame_index, layers, iDestX, iDestY, + flags); + pCanvas->set_clip_rect(&rcOld); } else - m_pManager->drawFrame(pCanvas, m_iFrame, m_oLayers, iDestX, iDestY, - m_iFlags); + manager->draw_frame(pCanvas, frame_index, layers, iDestX, iDestY, + flags); } } -void THAnimation::drawChild(THRenderTarget* pCanvas, int iDestX, int iDestY) +void animation::draw_child(render_target* pCanvas, int iDestX, int iDestY) { - if(AreFlagsSet(m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(flags, thdf_alpha_50 | thdf_alpha_75)) return; - if(AreFlagsSet(m_pParent->m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(parent->flags, thdf_alpha_50 | thdf_alpha_75)) return; int iX = 0, iY = 0; - m_pParent->getMarker(&iX, &iY); - iX += m_iX + iDestX; - iY += m_iY + iDestY; - if(m_iSoundToPlay) + parent->get_marker(&iX, &iY); + iX += x_relative_to_tile + iDestX; + iY += y_relative_to_tile + iDestY; + if(sound_to_play) { - THSoundEffects *pSounds = THSoundEffects::getSingleton(); + sound_player *pSounds = sound_player::get_singleton(); if(pSounds) - pSounds->playSoundAt(m_iSoundToPlay, iX, iY); - m_iSoundToPlay = 0; + pSounds->play_at(sound_to_play, iX, iY); + sound_to_play = 0; } - if(m_pManager) - m_pManager->drawFrame(pCanvas, m_iFrame, m_oLayers, iX, iY, m_iFlags); + if(manager) + manager->draw_frame(pCanvas, frame_index, layers, iX, iY, flags); } -bool THAnimation::hitTestChild(int iDestX, int iDestY, int iTestX, int iTestY) +bool animation::hit_test_child(int iDestX, int iDestY, int iTestX, int iTestY) { // TODO return false; } -static void CalculateMorphRect(const THClipRect& rcOriginal, THClipRect& rcMorph, int iYLow, int iYHigh) +static void CalculateMorphRect(const clip_rect& rcOriginal, clip_rect& rcMorph, int iYLow, int iYHigh) { rcMorph = rcOriginal; if(rcMorph.y < iYLow) @@ -1196,102 +1196,102 @@ } } -void THAnimation::drawMorph(THRenderTarget* pCanvas, int iDestX, int iDestY) +void animation::draw_morph(render_target* pCanvas, int iDestX, int iDestY) { - if(AreFlagsSet(m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(flags, thdf_alpha_50 | thdf_alpha_75)) return; - if(!m_pManager) + if(!manager) return; - iDestX += m_iX; - iDestY += m_iY; - if(m_iSoundToPlay) + iDestX += x_relative_to_tile; + iDestY += y_relative_to_tile; + if(sound_to_play) { - THSoundEffects *pSounds = THSoundEffects::getSingleton(); + sound_player *pSounds = sound_player::get_singleton(); if(pSounds) - pSounds->playSoundAt(m_iSoundToPlay, iDestX, iDestY); - m_iSoundToPlay = 0; + pSounds->play_at(sound_to_play, iDestX, iDestY); + sound_to_play = 0; } - THClipRect oClipRect; - pCanvas->getClipRect(&oClipRect); - THClipRect oMorphRect; - CalculateMorphRect(oClipRect, oMorphRect, iDestY + m_pMorphTarget->m_iX, - iDestY + m_pMorphTarget->m_iY + 1); - pCanvas->setClipRect(&oMorphRect); - m_pManager->drawFrame(pCanvas, m_iFrame, m_oLayers, iDestX, iDestY, - m_iFlags); - CalculateMorphRect(oClipRect, oMorphRect, iDestY + m_pMorphTarget->m_iY, - iDestY + m_pMorphTarget->speed.x); - pCanvas->setClipRect(&oMorphRect); - m_pManager->drawFrame(pCanvas, m_pMorphTarget->m_iFrame, - m_pMorphTarget->m_oLayers, iDestX, - iDestY, m_pMorphTarget->m_iFlags); - pCanvas->setClipRect(&oClipRect); + clip_rect oClipRect; + pCanvas->get_clip_rect(&oClipRect); + clip_rect oMorphRect; + CalculateMorphRect(oClipRect, oMorphRect, iDestY + morph_target->x_relative_to_tile, + iDestY + morph_target->y_relative_to_tile + 1); + pCanvas->set_clip_rect(&oMorphRect); + manager->draw_frame(pCanvas, frame_index, layers, iDestX, iDestY, + flags); + CalculateMorphRect(oClipRect, oMorphRect, iDestY + morph_target->y_relative_to_tile, + iDestY + morph_target->speed.dx); + pCanvas->set_clip_rect(&oMorphRect); + manager->draw_frame(pCanvas, morph_target->frame_index, + morph_target->layers, iDestX, + iDestY, morph_target->flags); + pCanvas->set_clip_rect(&oClipRect); } -bool THAnimation::hitTest(int iDestX, int iDestY, int iTestX, int iTestY) +bool animation::hit_test(int iDestX, int iDestY, int iTestX, int iTestY) { - if(AreFlagsSet(m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(flags, thdf_alpha_50 | thdf_alpha_75)) return false; - if(m_pManager == nullptr) + if(manager == nullptr) return false; - return m_pManager->hitTest(m_iFrame, m_oLayers, m_iX + iDestX, - m_iY + iDestY, m_iFlags, iTestX, iTestY); + return manager->hit_test(frame_index, layers, x_relative_to_tile + iDestX, + y_relative_to_tile + iDestY, flags, iTestX, iTestY); } -bool THAnimation::hitTestMorph(int iDestX, int iDestY, int iTestX, int iTestY) +bool animation::hit_test_morph(int iDestX, int iDestY, int iTestX, int iTestY) { - if(AreFlagsSet(m_iFlags, THDF_Alpha50 | THDF_Alpha75)) + if(ARE_FLAGS_SET(flags, thdf_alpha_50 | thdf_alpha_75)) return false; - if(m_pManager == nullptr) + if(manager == nullptr) return false; - return m_pManager->hitTest(m_iFrame, m_oLayers, m_iX + iDestX, - m_iY + iDestY, m_iFlags, iTestX, iTestY) || m_pMorphTarget->hitTest( + return manager->hit_test(frame_index, layers, x_relative_to_tile + iDestX, + y_relative_to_tile + iDestY, flags, iTestX, iTestY) || morph_target->hit_test( iDestX, iDestY, iTestX, iTestY); } -#undef AreFlagsSet +#undef ARE_FLAGS_SET -static bool THAnimation_HitTestChild(THDrawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) +static bool THAnimation_hit_test_child(drawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) { - return reinterpret_cast(pSelf)->hitTestChild(iDestX, iDestY, iTestX, iTestY); + return reinterpret_cast(pSelf)->hit_test_child(iDestX, iDestY, iTestX, iTestY); } -static void THAnimation_DrawChild(THDrawable* pSelf, THRenderTarget* pCanvas, int iDestX, int iDestY) +static void THAnimation_draw_child(drawable* pSelf, render_target* pCanvas, int iDestX, int iDestY) { - reinterpret_cast(pSelf)->drawChild(pCanvas, iDestX, iDestY); + reinterpret_cast(pSelf)->draw_child(pCanvas, iDestX, iDestY); } -static bool THAnimation_HitTestMorph(THDrawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) +static bool THAnimation_hit_test_morph(drawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) { - return reinterpret_cast(pSelf)->hitTestMorph(iDestX, iDestY, iTestX, iTestY); + return reinterpret_cast(pSelf)->hit_test_morph(iDestX, iDestY, iTestX, iTestY); } -static void THAnimation_DrawMorph(THDrawable* pSelf, THRenderTarget* pCanvas, int iDestX, int iDestY) +static void THAnimation_draw_morph(drawable* pSelf, render_target* pCanvas, int iDestX, int iDestY) { - reinterpret_cast(pSelf)->drawMorph(pCanvas, iDestX, iDestY); + reinterpret_cast(pSelf)->draw_morph(pCanvas, iDestX, iDestY); } -static bool THAnimation_HitTest(THDrawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) +static bool THAnimation_hit_test(drawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) { - return reinterpret_cast(pSelf)->hitTest(iDestX, iDestY, iTestX, iTestY); + return reinterpret_cast(pSelf)->hit_test(iDestX, iDestY, iTestX, iTestY); } -static void THAnimation_Draw(THDrawable* pSelf, THRenderTarget* pCanvas, int iDestX, int iDestY) +static void THAnimation_draw(drawable* pSelf, render_target* pCanvas, int iDestX, int iDestY) { - reinterpret_cast(pSelf)->draw(pCanvas, iDestX, iDestY); + reinterpret_cast(pSelf)->draw(pCanvas, iDestX, iDestY); } -static bool THAnimation_isMultipleFrameAnimation(THDrawable* pSelf) +static bool THAnimation_is_multiple_frame_animation(drawable* pSelf) { - THAnimation *pAnimation = reinterpret_cast(pSelf); + animation *pAnimation = reinterpret_cast(pSelf); if(pAnimation) { - size_t firstFrame = pAnimation->getAnimationManager()->getFirstFrame(pAnimation->getAnimation()); - size_t nextFrame = pAnimation->getAnimationManager()->getNextFrame(firstFrame); + size_t firstFrame = pAnimation->get_animation_manager()->get_first_frame(pAnimation->get_animation()); + size_t nextFrame = pAnimation->get_animation_manager()->get_next_frame(firstFrame); return nextFrame != firstFrame; } else @@ -1299,87 +1299,87 @@ } -THAnimationBase::THAnimationBase() +animation_base::animation_base() { - m_iX = 0; - m_iY = 0; + x_relative_to_tile = 0; + y_relative_to_tile = 0; for(int i = 0; i < 13; ++i) - m_oLayers.iLayerContents[i] = 0; - m_iFlags = 0; + layers.layer_contents[i] = 0; + flags = 0; } -THAnimation::THAnimation(): - m_pManager(nullptr), - m_pMorphTarget(nullptr), - m_iAnimation(0), - m_iFrame(0), +animation::animation(): + manager(nullptr), + morph_target(nullptr), + animation_index(0), + frame_index(0), speed({0,0}), - m_iSoundToPlay(0), - m_iCropColumn(0) + sound_to_play(0), + crop_column(0) { - m_fnDraw = THAnimation_Draw; - m_fnHitTest = THAnimation_HitTest; - m_fnIsMultipleFrameAnimation = THAnimation_isMultipleFrameAnimation; + draw_fn = THAnimation_draw; + hit_test_fn = THAnimation_hit_test; + is_multiple_frame_animation_fn = THAnimation_is_multiple_frame_animation; } -void THAnimation::persist(LuaPersistWriter *pWriter) const +void animation::persist(lua_persist_writer *pWriter) const { - lua_State *L = pWriter->getStack(); + lua_State *L = pWriter->get_stack(); // Write the next chained thing lua_rawgeti(L, luaT_environindex, 2); - lua_pushlightuserdata(L, m_pNext); + lua_pushlightuserdata(L, next); lua_rawget(L, -2); - pWriter->fastWriteStackObject(-1); + pWriter->fast_write_stack_object(-1); lua_pop(L, 2); - // Write the THDrawable fields - pWriter->writeVUInt(m_iFlags); -#define IsUsingFunctionSet(d, ht) m_fnDraw == (THAnimation_ ## d) \ - && m_fnHitTest == (THAnimation_ ## ht) - - if(IsUsingFunctionSet(Draw, HitTest)) - pWriter->writeVUInt(1); - else if(IsUsingFunctionSet(DrawChild, HitTestChild)) - pWriter->writeVUInt(2); - else if(IsUsingFunctionSet(DrawMorph, HitTestMorph)) + // Write the drawable fields + pWriter->write_uint(flags); +#define IS_USING_FUNCTION_SET(d, ht) draw_fn == (THAnimation_ ## d) \ + && hit_test_fn == (THAnimation_ ## ht) + + if(IS_USING_FUNCTION_SET(draw, hit_test)) + pWriter->write_uint(1); + else if(IS_USING_FUNCTION_SET(draw_child, hit_test_child)) + pWriter->write_uint(2); + else if(IS_USING_FUNCTION_SET(draw_morph, hit_test_morph)) { // NB: Prior version of code used the number 3 here, and forgot // to persist the morph target. - pWriter->writeVUInt(4); + pWriter->write_uint(4); lua_rawgeti(L, luaT_environindex, 2); - lua_pushlightuserdata(L, m_pMorphTarget); + lua_pushlightuserdata(L, morph_target); lua_rawget(L, -2); - pWriter->writeStackObject(-1); + pWriter->write_stack_object(-1); lua_pop(L, 2); } else - pWriter->writeVUInt(0); + pWriter->write_uint(0); -#undef IsUsingFunctionSet +#undef IS_USING_FUNCTION_SET // Write the simple fields - pWriter->writeVUInt(m_iAnimation); - pWriter->writeVUInt(m_iFrame); - pWriter->writeVInt(m_iX); - pWriter->writeVInt(m_iY); - pWriter->writeVInt((int)m_iSoundToPlay); // Not a VUInt, for compatibility - pWriter->writeVInt(0); // For compatibility - if(m_iFlags & THDF_Crop) - pWriter->writeVInt(m_iCropColumn); + pWriter->write_uint(animation_index); + pWriter->write_uint(frame_index); + pWriter->write_int(x_relative_to_tile); + pWriter->write_int(y_relative_to_tile); + pWriter->write_int((int)sound_to_play); // Not a uint, for compatibility + pWriter->write_int(0); // For compatibility + if(flags & thdf_crop) + pWriter->write_int(crop_column); // Write the unioned fields - if(m_fnDraw != THAnimation_DrawChild) + if(draw_fn != THAnimation_draw_child) { - pWriter->writeVInt(speed.x); - pWriter->writeVInt(speed.y); + pWriter->write_int(speed.dx); + pWriter->write_int(speed.dy); } else { lua_rawgeti(L, luaT_environindex, 2); - lua_pushlightuserdata(L, m_pParent); + lua_pushlightuserdata(L, parent); lua_rawget(L, -2); - pWriter->writeStackObject(-1); + pWriter->write_stack_object(-1); lua_pop(L, 2); } @@ -1387,32 +1387,32 @@ int iNumLayers = 13; for( ; iNumLayers >= 1; --iNumLayers) { - if(m_oLayers.iLayerContents[iNumLayers - 1] != 0) + if(layers.layer_contents[iNumLayers - 1] != 0) break; } - pWriter->writeVUInt(iNumLayers); - pWriter->writeByteStream(m_oLayers.iLayerContents, iNumLayers); + pWriter->write_uint(iNumLayers); + pWriter->write_byte_stream(layers.layer_contents, iNumLayers); } -void THAnimation::depersist(LuaPersistReader *pReader) +void animation::depersist(lua_persist_reader *pReader) { - lua_State *L = pReader->getStack(); + lua_State *L = pReader->get_stack(); do { // Read the chain - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) break; - m_pNext = reinterpret_cast(lua_touserdata(L, -1)); - if(m_pNext) - m_pNext->m_pPrev = this; + next = reinterpret_cast(lua_touserdata(L, -1)); + if(next) + next->prev = this; lua_pop(L, 1); - // Read THDrawable fields - if(!pReader->readVUInt(m_iFlags)) + // Read drawable fields + if(!pReader->read_uint(flags)) break; int iFunctionSet; - if(!pReader->readVUInt(iFunctionSet)) + if(!pReader->read_uint(iFunctionSet)) break; switch(iFunctionSet) { @@ -1421,212 +1421,212 @@ // missing, so settle for a graphical bug rather than a segfault // by reverting to the normal function set. case 1: - m_fnDraw = THAnimation_Draw; - m_fnHitTest = THAnimation_HitTest; + draw_fn = THAnimation_draw; + hit_test_fn = THAnimation_hit_test; break; case 2: - m_fnDraw = THAnimation_DrawChild; - m_fnHitTest = THAnimation_HitTestChild; + draw_fn = THAnimation_draw_child; + hit_test_fn = THAnimation_hit_test_child; break; case 4: - m_fnDraw = THAnimation_DrawMorph; - m_fnHitTest = THAnimation_HitTestMorph; - pReader->readStackObject(); - m_pMorphTarget = reinterpret_cast(lua_touserdata(L, -1)); + draw_fn = THAnimation_draw_morph; + hit_test_fn = THAnimation_hit_test_morph; + pReader->read_stack_object(); + morph_target = reinterpret_cast(lua_touserdata(L, -1)); lua_pop(L, 1); break; default: - pReader->setError(lua_pushfstring(L, "Unknown animation function set #%i", iFunctionSet)); + pReader->set_error(lua_pushfstring(L, "Unknown animation function set #%i", iFunctionSet)); return; } // Read the simple fields - if(!pReader->readVUInt(m_iAnimation)) + if(!pReader->read_uint(animation_index)) break; - if(!pReader->readVUInt(m_iFrame)) + if(!pReader->read_uint(frame_index)) break; - if(!pReader->readVInt(m_iX)) + if(!pReader->read_int(x_relative_to_tile)) break; - if(!pReader->readVInt(m_iY)) + if(!pReader->read_int(y_relative_to_tile)) break; int iDummy; - if(!pReader->readVInt(iDummy)) + if(!pReader->read_int(iDummy)) break; if(iDummy >= 0) - m_iSoundToPlay = (unsigned int)iDummy; - if(!pReader->readVInt(iDummy)) + sound_to_play = (unsigned int)iDummy; + if(!pReader->read_int(iDummy)) break; - if(m_iFlags & THDF_Crop) + if(flags & thdf_crop) { - if(!pReader->readVInt(m_iCropColumn)) + if(!pReader->read_int(crop_column)) break; } else - m_iCropColumn = 0; + crop_column = 0; // Read the unioned fields - if(m_fnDraw != THAnimation_DrawChild) + if(draw_fn != THAnimation_draw_child) { - if(!pReader->readVInt(speed.x)) + if(!pReader->read_int(speed.dx)) break; - if(!pReader->readVInt(speed.y)) + if(!pReader->read_int(speed.dy)) break; } else { - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) break; - m_pParent = (THAnimation*)lua_touserdata(L, -1); + parent = (animation*)lua_touserdata(L, -1); lua_pop(L, 1); } // Read the layers - std::memset(m_oLayers.iLayerContents, 0, sizeof(m_oLayers.iLayerContents)); + std::memset(layers.layer_contents, 0, sizeof(layers.layer_contents)); int iNumLayers; - if(!pReader->readVUInt(iNumLayers)) + if(!pReader->read_uint(iNumLayers)) break; if(iNumLayers > 13) { - if(!pReader->readByteStream(m_oLayers.iLayerContents, 13)) + if(!pReader->read_byte_stream(layers.layer_contents, 13)) break; - if(!pReader->readByteStream(nullptr, iNumLayers - 13)) + if(!pReader->read_byte_stream(nullptr, iNumLayers - 13)) break; } else { - if(!pReader->readByteStream(m_oLayers.iLayerContents, iNumLayers)) + if(!pReader->read_byte_stream(layers.layer_contents, iNumLayers)) break; } // Fix the m_pAnimator field luaT_getenvfield(L, 2, "animator"); - m_pManager = (THAnimationManager*)lua_touserdata(L, -1); + manager = (animation_manager*)lua_touserdata(L, -1); lua_pop(L, 1); return; } while(false); - pReader->setError("Cannot depersist THAnimation instance"); + pReader->set_error("Cannot depersist animation instance"); } -void THAnimation::tick() +void animation::tick() { - m_iFrame = m_pManager->getNextFrame(m_iFrame); - if(m_fnDraw != THAnimation_DrawChild) + frame_index = manager->get_next_frame(frame_index); + if(draw_fn != THAnimation_draw_child) { - m_iX += speed.x; - m_iY += speed.y; + x_relative_to_tile += speed.dx; + y_relative_to_tile += speed.dy; } - if(m_pMorphTarget) + if(morph_target) { - m_pMorphTarget->m_iY += m_pMorphTarget->speed.y; - if(m_pMorphTarget->m_iY < m_pMorphTarget->m_iX) - m_pMorphTarget->m_iY = m_pMorphTarget->m_iX; + morph_target->y_relative_to_tile += morph_target->speed.dy; + if(morph_target->y_relative_to_tile < morph_target->x_relative_to_tile) + morph_target->y_relative_to_tile = morph_target->x_relative_to_tile; } //Female flying to heaven sound fix: - if(m_iFrame == 6987) - m_iSoundToPlay = 123; + if(frame_index == 6987) + sound_to_play = 123; else - m_iSoundToPlay = m_pManager->getFrameSound(m_iFrame); + sound_to_play = manager->get_frame_sound(frame_index); } -void THAnimationBase::removeFromTile() +void animation_base::remove_from_tile() { - THLinkList::removeFromList(); + link_list::remove_from_list(); } -void THAnimationBase::attachToTile(THMapNode *pMapNode, int layer) +void animation_base::attach_to_tile(map_tile *pMapNode, int layer) { - removeFromTile(); - THLinkList *pList; - if(m_iFlags & THDF_EarlyList) + remove_from_tile(); + link_list *pList; + if(flags & thdf_early_list) pList = &pMapNode->oEarlyEntities; else pList = pMapNode; - this->setDrawingLayer(layer); + this->set_drawing_layer(layer); -#define GetFlags(x) (reinterpret_cast(x)->m_iFlags) - while(pList->m_pNext && pList->m_pNext->getDrawingLayer() < layer) +#define GetFlags(x) (reinterpret_cast(x)->m_iFlags) + while(pList->next && pList->next->get_drawing_layer() < layer) { - pList = pList->m_pNext; + pList = pList->next; } #undef GetFlags - m_pPrev = pList; - if(pList->m_pNext != nullptr) + prev = pList; + if(pList->next != nullptr) { - pList->m_pNext->m_pPrev = this; - this->m_pNext = pList->m_pNext; + pList->next->prev = this; + this->next = pList->next; } else { - m_pNext = nullptr; + next = nullptr; } - pList->m_pNext = this; + pList->next = this; } -void THAnimation::setParent(THAnimation *pParent) +void animation::set_parent(animation *pParent) { - removeFromTile(); + remove_from_tile(); if(pParent == nullptr) { - m_fnDraw = THAnimation_Draw; - m_fnHitTest = THAnimation_HitTest; + draw_fn = THAnimation_draw; + hit_test_fn = THAnimation_hit_test; speed = { 0, 0 }; } else { - m_fnDraw = THAnimation_DrawChild; - m_fnHitTest = THAnimation_HitTestChild; - m_pParent = pParent; - m_pNext = m_pParent->m_pNext; - if(m_pNext) - m_pNext->m_pPrev = this; - m_pPrev = m_pParent; - m_pParent->m_pNext = this; + draw_fn = THAnimation_draw_child; + hit_test_fn = THAnimation_hit_test_child; + parent = pParent; + next = parent->next; + if(next) + next->prev = this; + prev = parent; + parent->next = this; } } -void THAnimation::setAnimation(THAnimationManager* pManager, size_t iAnimation) +void animation::set_animation(animation_manager* pManager, size_t iAnimation) { - m_pManager = pManager; - m_iAnimation = iAnimation; - m_iFrame = pManager->getFirstFrame(iAnimation); - if(m_pMorphTarget) + manager = pManager; + animation_index = iAnimation; + frame_index = pManager->get_first_frame(iAnimation); + if(morph_target) { - m_pMorphTarget = nullptr; - m_fnDraw = THAnimation_Draw; - m_fnHitTest = THAnimation_HitTest; + morph_target = nullptr; + draw_fn = THAnimation_draw; + hit_test_fn = THAnimation_hit_test; } } -bool THAnimation::getMarker(int* pX, int* pY) +bool animation::get_marker(int* pX, int* pY) { - if(!m_pManager || !m_pManager->getFrameMarker(m_iFrame, pX, pY)) + if(!manager || !manager->get_frame_marker(frame_index, pX, pY)) return false; - if(m_iFlags & THDF_FlipHorizontal) + if(flags & thdf_flip_horizontal) *pX = -*pX; - *pX += m_iX; - *pY += m_iY + 16; + *pX += x_relative_to_tile; + *pY += y_relative_to_tile + 16; return true; } -bool THAnimation::getSecondaryMarker(int* pX, int* pY) +bool animation::get_secondary_marker(int* pX, int* pY) { - if(!m_pManager || !m_pManager->getFrameSecondaryMarker(m_iFrame, pX, pY)) + if(!manager || !manager->get_frame_secondary_marker(frame_index, pX, pY)) return false; - if(m_iFlags & THDF_FlipHorizontal) + if(flags & thdf_flip_horizontal) *pX = -*pX; - *pX += m_iX; - *pY += m_iY + 16; + *pX += x_relative_to_tile; + *pY += y_relative_to_tile + 16; return true; } -static int GetAnimationDurationAndExtent(THAnimationManager *pManager, +static int GetAnimationDurationAndExtent(animation_manager *pManager, size_t iFrame, - const THLayers_t& oLayers, + const ::layers& oLayers, int* pMinY, int* pMaxY, uint32_t iFlags) { @@ -1638,12 +1638,12 @@ { int iFrameMinY; int iFrameMaxY; - pManager->getFrameExtent(iCurFrame, oLayers, nullptr, nullptr, &iFrameMinY, &iFrameMaxY, iFlags); + pManager->get_frame_extent(iCurFrame, oLayers, nullptr, nullptr, &iFrameMinY, &iFrameMaxY, iFlags); if(iFrameMinY < iMinY) iMinY = iFrameMinY; if(iFrameMaxY > iMaxY) iMaxY = iFrameMaxY; - iCurFrame = pManager->getNextFrame(iCurFrame); + iCurFrame = pManager->get_next_frame(iCurFrame); ++iDuration; } while(iCurFrame != iFrame); if(pMinY) @@ -1653,11 +1653,11 @@ return iDuration; } -void THAnimation::setMorphTarget(THAnimation *pMorphTarget, unsigned int iDurationFactor) +void animation::set_morph_target(animation *pMorphTarget, unsigned int iDurationFactor) { - m_pMorphTarget = pMorphTarget; - m_fnDraw = THAnimation_DrawMorph; - m_fnHitTest = THAnimation_HitTestMorph; + morph_target = pMorphTarget; + draw_fn = THAnimation_draw_morph; + hit_test_fn = THAnimation_hit_test_morph; /* Morphing is the process by which two animations are combined to give a single animation of one animation turning into another. At the moment, @@ -1668,10 +1668,10 @@ are cured at the pharmacy cabinet. The process of morphing requires four state variables, which are stored in the morph target animation: - * The y value top limit - m_pMorphTarget->m_iX - * The y value threshold - m_pMorphTarget->m_iY - * The y value bottom limit - m_pMorphTarget->m_iSpeedX - * The y value increment per frame - m_pMorphTarget->m_iSpeedY + * The y value top limit - morph_target->x + * The y value threshold - morph_target->y + * The y value bottom limit - morph_target->speed.dx + * The y value increment per frame - morph_target->speed.dy This obviously means that the morph target should not be ticked or rendered as it's position and speed contain other values. */ @@ -1680,241 +1680,241 @@ int iMorphMinY, iMorphMaxY; #define GADEA GetAnimationDurationAndExtent - int iOriginalDuration = GADEA(m_pManager, m_iFrame, m_oLayers, &iOrigMinY, - &iOrigMaxY, m_iFlags); - int iMorphDuration = GADEA(m_pMorphTarget->m_pManager, - m_pMorphTarget->m_iFrame, - m_pMorphTarget->m_oLayers, &iMorphMinY, - &iMorphMaxY, m_pMorphTarget->m_iFlags); + int iOriginalDuration = GADEA(manager, frame_index, layers, &iOrigMinY, + &iOrigMaxY, flags); + int iMorphDuration = GADEA(morph_target->manager, + morph_target->frame_index, + morph_target->layers, &iMorphMinY, + &iMorphMaxY, morph_target->flags); if(iMorphDuration > iOriginalDuration) iMorphDuration = iOriginalDuration; #undef GADEA iMorphDuration *= iDurationFactor; if(iOrigMinY < iMorphMinY) - m_pMorphTarget->m_iX = iOrigMinY; + morph_target->x_relative_to_tile = iOrigMinY; else - m_pMorphTarget->m_iX = iMorphMinY; + morph_target->x_relative_to_tile = iMorphMinY; if(iOrigMaxY > iMorphMaxY) - m_pMorphTarget->speed.x = iOrigMaxY; + morph_target->speed.dx = iOrigMaxY; else - m_pMorphTarget->speed.x = iMorphMaxY; + morph_target->speed.dx = iMorphMaxY; - int iDist = m_pMorphTarget->m_iX - m_pMorphTarget->speed.x; - m_pMorphTarget->speed.y = (iDist - iMorphDuration + 1) / iMorphDuration; - m_pMorphTarget->m_iY = m_pMorphTarget->speed.x; + int iDist = morph_target->x_relative_to_tile - morph_target->speed.dx; + morph_target->speed.dy = (iDist - iMorphDuration + 1) / iMorphDuration; + morph_target->y_relative_to_tile = morph_target->speed.dx; } -void THAnimation::setFrame(size_t iFrame) +void animation::set_frame(size_t iFrame) { - m_iFrame = iFrame; + frame_index = iFrame; } -void THAnimationBase::setLayer(int iLayer, int iId) +void animation_base::set_layer(int iLayer, int iId) { if(0 <= iLayer && iLayer <= 12) { - m_oLayers.iLayerContents[iLayer] = static_cast(iId); + layers.layer_contents[iLayer] = static_cast(iId); } } -static bool THSpriteRenderList_HitTest(THDrawable* pSelf, int iDestX, +static bool THSpriteRenderList_hit_test(drawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY) { - return reinterpret_cast(pSelf)-> - hitTest(iDestX, iDestY, iTestX, iTestY); + return reinterpret_cast(pSelf)-> + hit_test(iDestX, iDestY, iTestX, iTestY); } -static void THSpriteRenderList_Draw(THDrawable* pSelf, THRenderTarget* pCanvas, +static void THSpriteRenderList_draw(drawable* pSelf, render_target* pCanvas, int iDestX, int iDestY) { - reinterpret_cast(pSelf)-> + reinterpret_cast(pSelf)-> draw(pCanvas, iDestX, iDestY); } -static bool THSpriteRenderList_isMultipleFrameAnimation(THDrawable* pSelf) +static bool THSpriteRenderList_is_multiple_frame_animation(drawable* pSelf) { return false; } -THSpriteRenderList::THSpriteRenderList() +sprite_render_list::sprite_render_list() { - m_fnDraw = THSpriteRenderList_Draw; - m_fnHitTest = THSpriteRenderList_HitTest; - m_fnIsMultipleFrameAnimation = THSpriteRenderList_isMultipleFrameAnimation; - m_iBufferSize = 0; - m_iNumSprites = 0; - m_pSpriteSheet = nullptr; - m_pSprites = nullptr; - m_iSpeedX = 0; - m_iSpeedY = 0; - m_iLifetime = -1; + draw_fn = THSpriteRenderList_draw; + hit_test_fn = THSpriteRenderList_hit_test; + is_multiple_frame_animation_fn = THSpriteRenderList_is_multiple_frame_animation; + buffer_size = 0; + sprite_count = 0; + sheet = nullptr; + sprites = nullptr; + dx_per_tick = 0; + dy_per_tick = 0; + lifetime = -1; } -THSpriteRenderList::~THSpriteRenderList() +sprite_render_list::~sprite_render_list() { - delete[] m_pSprites; + delete[] sprites; } -void THSpriteRenderList::tick() +void sprite_render_list::tick() { - m_iX += m_iSpeedX; - m_iY += m_iSpeedY; - if(m_iLifetime > 0) - --m_iLifetime; + x_relative_to_tile += dx_per_tick; + y_relative_to_tile += dy_per_tick; + if(lifetime > 0) + --lifetime; } -void THSpriteRenderList::draw(THRenderTarget* pCanvas, int iDestX, int iDestY) +void sprite_render_list::draw(render_target* pCanvas, int iDestX, int iDestY) { - if(!m_pSpriteSheet) + if(!sheet) return; - iDestX += m_iX; - iDestY += m_iY; - for(_sprite_t *pSprite = m_pSprites, *pLast = m_pSprites + m_iNumSprites; + iDestX += x_relative_to_tile; + iDestY += y_relative_to_tile; + for(sprite *pSprite = sprites, *pLast = sprites + sprite_count; pSprite != pLast; ++pSprite) { - m_pSpriteSheet->drawSprite(pCanvas, pSprite->iSprite, - iDestX + pSprite->iX, iDestY + pSprite->iY, m_iFlags); + sheet->draw_sprite(pCanvas, pSprite->index, + iDestX + pSprite->x, iDestY + pSprite->y, flags); } } -bool THSpriteRenderList::hitTest(int iDestX, int iDestY, int iTestX, int iTestY) +bool sprite_render_list::hit_test(int iDestX, int iDestY, int iTestX, int iTestY) { // TODO return false; } -void THSpriteRenderList::setLifetime(int iLifetime) +void sprite_render_list::set_lifetime(int iLifetime) { if(iLifetime < 0) iLifetime = -1; - m_iLifetime = iLifetime; + lifetime = iLifetime; } -void THSpriteRenderList::appendSprite(size_t iSprite, int iX, int iY) +void sprite_render_list::append_sprite(size_t iSprite, int iX, int iY) { - if(m_iBufferSize == m_iNumSprites) + if(buffer_size == sprite_count) { - int iNewSize = m_iBufferSize * 2; + int iNewSize = buffer_size * 2; if(iNewSize == 0) iNewSize = 4; - _sprite_t* pNewSprites = new _sprite_t[iNewSize]; + sprite* pNewSprites = new sprite[iNewSize]; #ifdef _MSC_VER #pragma warning(disable: 4996) #endif - std::copy(m_pSprites, m_pSprites + m_iNumSprites, pNewSprites); + std::copy(sprites, sprites + sprite_count, pNewSprites); #ifdef _MSC_VER #pragma warning(default: 4996) #endif - delete[] m_pSprites; - m_pSprites = pNewSprites; - m_iBufferSize = iNewSize; - } - m_pSprites[m_iNumSprites].iSprite = iSprite; - m_pSprites[m_iNumSprites].iX = iX; - m_pSprites[m_iNumSprites].iY = iY; - ++m_iNumSprites; -} - -void THSpriteRenderList::persist(LuaPersistWriter *pWriter) const -{ - lua_State *L = pWriter->getStack(); - - pWriter->writeVUInt(m_iNumSprites); - pWriter->writeVUInt(m_iFlags); - pWriter->writeVInt(m_iX); - pWriter->writeVInt(m_iY); - pWriter->writeVInt(m_iSpeedX); - pWriter->writeVInt(m_iSpeedY); - pWriter->writeVInt(m_iLifetime); - for(_sprite_t *pSprite = m_pSprites, *pLast = m_pSprites + m_iNumSprites; + delete[] sprites; + sprites = pNewSprites; + buffer_size = iNewSize; + } + sprites[sprite_count].index = iSprite; + sprites[sprite_count].x = iX; + sprites[sprite_count].y = iY; + ++sprite_count; +} + +void sprite_render_list::persist(lua_persist_writer *pWriter) const +{ + lua_State *L = pWriter->get_stack(); + + pWriter->write_uint(sprite_count); + pWriter->write_uint(flags); + pWriter->write_int(x_relative_to_tile); + pWriter->write_int(y_relative_to_tile); + pWriter->write_int(dx_per_tick); + pWriter->write_int(dy_per_tick); + pWriter->write_int(lifetime); + for(sprite *pSprite = sprites, *pLast = sprites + sprite_count; pSprite != pLast; ++pSprite) { - pWriter->writeVUInt(pSprite->iSprite); - pWriter->writeVInt(pSprite->iX); - pWriter->writeVInt(pSprite->iY); + pWriter->write_uint(pSprite->index); + pWriter->write_int(pSprite->x); + pWriter->write_int(pSprite->y); } // Write the layers int iNumLayers = 13; for( ; iNumLayers >= 1; --iNumLayers) { - if(m_oLayers.iLayerContents[iNumLayers - 1] != 0) + if(layers.layer_contents[iNumLayers - 1] != 0) break; } - pWriter->writeVUInt(iNumLayers); - pWriter->writeByteStream(m_oLayers.iLayerContents, iNumLayers); + pWriter->write_uint(iNumLayers); + pWriter->write_byte_stream(layers.layer_contents, iNumLayers); // Write the next chained thing lua_rawgeti(L, luaT_environindex, 2); - lua_pushlightuserdata(L, m_pNext); + lua_pushlightuserdata(L, next); lua_rawget(L, -2); - pWriter->fastWriteStackObject(-1); + pWriter->fast_write_stack_object(-1); lua_pop(L, 2); } -void THSpriteRenderList::depersist(LuaPersistReader *pReader) +void sprite_render_list::depersist(lua_persist_reader *pReader) { - lua_State *L = pReader->getStack(); + lua_State *L = pReader->get_stack(); - if(!pReader->readVUInt(m_iNumSprites)) + if(!pReader->read_uint(sprite_count)) return; - m_iBufferSize = m_iNumSprites; - delete[] m_pSprites; - m_pSprites = new _sprite_t[m_iBufferSize]; + buffer_size = sprite_count; + delete[] sprites; + sprites = new sprite[buffer_size]; - if(!pReader->readVUInt(m_iFlags)) + if(!pReader->read_uint(flags)) return; - if(!pReader->readVInt(m_iX)) + if(!pReader->read_int(x_relative_to_tile)) return; - if(!pReader->readVInt(m_iY)) + if(!pReader->read_int(y_relative_to_tile)) return; - if(!pReader->readVInt(m_iSpeedX)) + if(!pReader->read_int(dx_per_tick)) return; - if(!pReader->readVInt(m_iSpeedY)) + if(!pReader->read_int(dy_per_tick)) return; - if(!pReader->readVInt(m_iLifetime)) + if(!pReader->read_int(lifetime)) return; - for(_sprite_t *pSprite = m_pSprites, *pLast = m_pSprites + m_iNumSprites; + for(sprite *pSprite = sprites, *pLast = sprites + sprite_count; pSprite != pLast; ++pSprite) { - if(!pReader->readVUInt(pSprite->iSprite)) + if(!pReader->read_uint(pSprite->index)) return; - if(!pReader->readVInt(pSprite->iX)) + if(!pReader->read_int(pSprite->x)) return; - if(!pReader->readVInt(pSprite->iY)) + if(!pReader->read_int(pSprite->y)) return; } // Read the layers - std::memset(m_oLayers.iLayerContents, 0, sizeof(m_oLayers.iLayerContents)); + std::memset(layers.layer_contents, 0, sizeof(layers.layer_contents)); int iNumLayers; - if(!pReader->readVUInt(iNumLayers)) + if(!pReader->read_uint(iNumLayers)) return; if(iNumLayers > 13) { - if(!pReader->readByteStream(m_oLayers.iLayerContents, 13)) + if(!pReader->read_byte_stream(layers.layer_contents, 13)) return; - if(!pReader->readByteStream(nullptr, iNumLayers - 13)) + if(!pReader->read_byte_stream(nullptr, iNumLayers - 13)) return; } else { - if(!pReader->readByteStream(m_oLayers.iLayerContents, iNumLayers)) + if(!pReader->read_byte_stream(layers.layer_contents, iNumLayers)) return; } // Read the chain - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return; - m_pNext = reinterpret_cast(lua_touserdata(L, -1)); - if(m_pNext) - m_pNext->m_pPrev = this; + next = reinterpret_cast(lua_touserdata(L, -1)); + if(next) + next->prev = this; lua_pop(L, 1); - // Fix the m_pSpriteSheet field + // Fix the sheet field luaT_getenvfield(L, 2, "sheet"); - m_pSpriteSheet = (THSpriteSheet*)lua_touserdata(L, -1); + sheet = (sprite_sheet*)lua_touserdata(L, -1); lua_pop(L, 1); } diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx_font.cpp corsix-th-0.62/CorsixTH/Src/th_gfx_font.cpp --- corsix-th-0.61/CorsixTH/Src/th_gfx_font.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx_font.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -1,8 +1,7 @@ /* Copyright (c) 2010 Peter "Corsix" Cawley -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do @@ -31,7 +30,7 @@ #include #include -static unsigned int utf8next(const char*& sString) +static unsigned int next_utf8_codepoint(const char*& sString) { unsigned int iCode = *reinterpret_cast(sString++); unsigned int iContinuation; @@ -82,12 +81,12 @@ // Since these functions are only used when we use freetype2, this silences // warnings about defined and not used. -static unsigned int utf8decode(const char* sString) +static unsigned int decode_utf8(const char* sString) { - return utf8next(sString); + return next_utf8_codepoint(sString); } -static const char* utf8prev(const char* sString) +static const char* previous_utf8_codepoint(const char* sString) { do { @@ -97,25 +96,25 @@ } #endif -THBitmapFont::THBitmapFont() +bitmap_font::bitmap_font() { - m_pSpriteSheet = nullptr; - m_iCharSep = 0; - m_iLineSep = 0; + sheet = nullptr; + letter_spacing = 0; + line_spacing = 0; } -void THBitmapFont::setSpriteSheet(THSpriteSheet* pSpriteSheet) +void bitmap_font::set_sprite_sheet(sprite_sheet* pSpriteSheet) { - m_pSpriteSheet = pSpriteSheet; + sheet = pSpriteSheet; } -void THBitmapFont::setSeparation(int iCharSep, int iLineSep) +void bitmap_font::set_separation(int iCharSep, int iLineSep) { - m_iCharSep = iCharSep; - m_iLineSep = iLineSep; + letter_spacing = iCharSep; + line_spacing = iLineSep; } -static const uint16_t g_aUnicodeToCP437[0x60] = { +static const uint16_t unicode_to_cp437_table[0x60] = { 0xFF, 0xAD, 0x9B, 0x9C, 0x3F, 0x9D, 0x3F, 0x3F, 0x3F, 0x3F, 0xA6, 0xAE, 0xAA, 0x3F, 0x3F, 0x3F, 0xF8, 0xF1, 0xFD, 0x3F, 0x3F, 0x3F, 0x3F, 0xFA, 0x3F, 0x3F, 0xA7, 0xAF, 0xAC, 0xAB, 0x3F, 0xA8, 0x3F, 0x3F, 0x3F, 0x3F, @@ -126,14 +125,14 @@ 0x93, 0x3F, 0x94, 0xF6, 0x3F, 0x97, 0xA3, 0x96, 0x81, 0x3F, 0x3F, 0x98 }; -static unsigned int unicodeToCodepage437(unsigned int iCodePoint) +static unsigned int unicode_to_codepage_437(unsigned int iCodePoint) { if(iCodePoint < 0x80) return iCodePoint; if(iCodePoint < 0xA0) return '?'; if(iCodePoint < 0x100) - return g_aUnicodeToCP437[iCodePoint - 0xA0]; + return unicode_to_cp437_table[iCodePoint - 0xA0]; switch(iCodePoint) { case 0x0192: return 0x9F; @@ -168,54 +167,54 @@ return 0x3F; } -THFontDrawArea THBitmapFont::getTextSize(const char* sMessage, size_t iMessageLength, - int iMaxWidth) const +text_layout bitmap_font::get_text_dimensions(const char* sMessage, size_t iMessageLength, + int iMaxWidth) const { - return drawTextWrapped(nullptr, sMessage, iMessageLength, 0, 0, iMaxWidth, INT_MAX, 0); + return draw_text_wrapped(nullptr, sMessage, iMessageLength, 0, 0, iMaxWidth, INT_MAX, 0); } -void THBitmapFont::drawText(THRenderTarget* pCanvas, const char* sMessage, size_t iMessageLength, int iX, int iY) const +void bitmap_font::draw_text(render_target* pCanvas, const char* sMessage, size_t iMessageLength, int iX, int iY) const { - pCanvas->startNonOverlapping(); - if(iMessageLength != 0 && m_pSpriteSheet != nullptr) + pCanvas->start_nonoverlapping_draws(); + if(iMessageLength != 0 && sheet != nullptr) { const unsigned int iFirstASCII = 31; - unsigned int iLastASCII = static_cast(m_pSpriteSheet->getSpriteCount()) + iFirstASCII; + unsigned int iLastASCII = static_cast(sheet->get_sprite_count()) + iFirstASCII; const char* sMessageEnd = sMessage + iMessageLength; while(sMessage != sMessageEnd) { - unsigned int iChar = unicodeToCodepage437(utf8next(sMessage)); + unsigned int iChar = unicode_to_codepage_437(next_utf8_codepoint(sMessage)); if(iFirstASCII <= iChar && iChar <= iLastASCII) { iChar -= iFirstASCII; unsigned int iWidth, iHeight; - m_pSpriteSheet->drawSprite(pCanvas, iChar, iX, iY, 0); - m_pSpriteSheet->getSpriteSizeUnchecked(iChar, &iWidth, &iHeight); - iX += iWidth + m_iCharSep; + sheet->draw_sprite(pCanvas, iChar, iX, iY, 0); + sheet->get_sprite_size_unchecked(iChar, &iWidth, &iHeight); + iX += iWidth + letter_spacing; } } } - pCanvas->finishNonOverlapping(); + pCanvas->finish_nonoverlapping_draws(); } -THFontDrawArea THBitmapFont::drawTextWrapped(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY, int iWidth, - int iMaxRows, int iSkipRows, eTHAlign eAlign) const +text_layout bitmap_font::draw_text_wrapped(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY, int iWidth, + int iMaxRows, int iSkipRows, text_alignment eAlign) const { - THFontDrawArea oDrawArea = {}; + text_layout oDrawArea = {}; int iSkippedRows = 0; - if(iMessageLength != 0 && m_pSpriteSheet != nullptr) + if(iMessageLength != 0 && sheet != nullptr) { const unsigned int iFirstASCII = 31; - unsigned int iLastASCII = static_cast(m_pSpriteSheet->getSpriteCount()) + iFirstASCII; + unsigned int iLastASCII = static_cast(sheet->get_sprite_count()) + iFirstASCII; const char* sMessageEnd = sMessage + iMessageLength; - while(sMessage != sMessageEnd && oDrawArea.iNumRows < iMaxRows) + while(sMessage != sMessageEnd && oDrawArea.row_count < iMaxRows) { const char* sBreakPosition = sMessageEnd; const char* sLastGoodBreakPosition = sBreakPosition; - int iMsgWidth = -m_iCharSep; + int iMsgWidth = -letter_spacing; int iMsgBreakWidth = iMsgWidth; unsigned int iTallest = 0; const char* s; @@ -225,8 +224,8 @@ for(s = sMessage; s != sMessageEnd; ) { const char* sOld = s; - unsigned int iChar = unicodeToCodepage437(utf8next(s)); - iNextChar = unicodeToCodepage437(static_cast(*s)); + unsigned int iChar = unicode_to_codepage_437(next_utf8_codepoint(s)); + iNextChar = unicode_to_codepage_437(static_cast(*s)); if((iChar == '\n' && iNextChar == '\n') || (iChar == '/' && iNextChar == '/')) { foundNewLine = true; @@ -237,9 +236,9 @@ unsigned int iCharWidth = 0, iCharHeight = 0; if(iFirstASCII <= iChar && iChar <= iLastASCII) { - m_pSpriteSheet->getSpriteSizeUnchecked(iChar - iFirstASCII, &iCharWidth, &iCharHeight); + sheet->get_sprite_size_unchecked(iChar - iFirstASCII, &iCharWidth, &iCharHeight); } - iMsgWidth += m_iCharSep + iCharWidth; + iMsgWidth += letter_spacing + iCharWidth; if(iChar == ' ') { sLastGoodBreakPosition = sOld; @@ -257,8 +256,8 @@ if(s == sMessageEnd) iMsgBreakWidth = iMsgWidth; - if(iMsgBreakWidth > oDrawArea.iWidth) - oDrawArea.iWidth = iMsgBreakWidth; + if(iMsgBreakWidth > oDrawArea.width) + oDrawArea.width = iMsgBreakWidth; if(iSkippedRows >= iSkipRows) { @@ -267,14 +266,14 @@ int iXOffset = 0; if(iMsgBreakWidth < iWidth) iXOffset = (iWidth - iMsgBreakWidth) * static_cast(eAlign) / 2; - drawText(pCanvas, sMessage, sBreakPosition - sMessage, iX + iXOffset, iY); + draw_text(pCanvas, sMessage, sBreakPosition - sMessage, iX + iXOffset, iY); } - iY += static_cast(iTallest) + m_iLineSep; - oDrawArea.iEndX = iMsgWidth; - oDrawArea.iNumRows++; + iY += static_cast(iTallest) + line_spacing; + oDrawArea.end_x = iMsgWidth; + oDrawArea.row_count++; if (foundNewLine) { - iY += static_cast(iTallest) + m_iLineSep; - oDrawArea.iNumRows++; + iY += static_cast(iTallest) + line_spacing; + oDrawArea.row_count++; } } else @@ -284,8 +283,8 @@ { if(iSkippedRows == iSkipRows) { - iY += static_cast(iTallest) + m_iLineSep; - oDrawArea.iNumRows++; + iY += static_cast(iTallest) + line_spacing; + oDrawArea.row_count++; } iSkippedRows++; } @@ -293,116 +292,116 @@ sMessage = sBreakPosition; if(sMessage != sMessageEnd) { - utf8next(sMessage); + next_utf8_codepoint(sMessage); if(foundNewLine) { - utf8next(sMessage); + next_utf8_codepoint(sMessage); } } foundNewLine = 0; } } - oDrawArea.iEndX = iX + oDrawArea.iEndX; - oDrawArea.iEndY = iY; + oDrawArea.end_x = iX + oDrawArea.end_x; + oDrawArea.end_y = iY; return oDrawArea; } #ifdef CORSIX_TH_USE_FREETYPE2 -FT_Library THFreeTypeFont::ms_pFreeType = nullptr; -int THFreeTypeFont::ms_iFreeTypeInitCount = 0; +FT_Library freetype_font::freetype_library = nullptr; +int freetype_font::freetype_init_count = 0; -THFreeTypeFont::THFreeTypeFont() +freetype_font::freetype_font() { - m_pFace = nullptr; - m_bDoneFreeTypeInit = false; - for(cached_text_t* pEntry = m_aCache; - pEntry != m_aCache + (1 << ms_CacheSizeLog2); ++pEntry) + font_face = nullptr; + is_done_freetype_init = false; + for(cached_text* pEntry = cache; + pEntry != cache + (1 << cache_size_log2); ++pEntry) { - pEntry->sMessage = nullptr; - pEntry->iMessageLength = 0; - pEntry->iMessageBufferLength = 0; - pEntry->eAlign = Align_Left; - pEntry->iWidth = 0; - pEntry->iHeight = 0; - pEntry->iWidestLine = 0; - pEntry->iLastX = 0; - pEntry->pData = nullptr; - pEntry->bIsValid = false; - pEntry->pTexture = nullptr; + pEntry->message = nullptr; + pEntry->message_length = 0; + pEntry->message_buffer_length = 0; + pEntry->alignment = text_alignment::left; + pEntry->width = 0; + pEntry->height = 0; + pEntry->widest_line_width = 0; + pEntry->last_x = 0; + pEntry->data = nullptr; + pEntry->is_valid = false; + pEntry->texture = nullptr; } } -THFreeTypeFont::~THFreeTypeFont() +freetype_font::~freetype_font() { - for(cached_text_t* pEntry = m_aCache; - pEntry != m_aCache + (1 << ms_CacheSizeLog2); ++pEntry) + for(cached_text* pEntry = cache; + pEntry != cache + (1 << cache_size_log2); ++pEntry) { - _freeTexture(pEntry); + free_texture(pEntry); } - if(m_pFace != nullptr) - FT_Done_Face(m_pFace); - if(m_bDoneFreeTypeInit) + if(font_face != nullptr) + FT_Done_Face(font_face); + if(is_done_freetype_init) { - if(--ms_iFreeTypeInitCount == 0) + if(--freetype_init_count == 0) { - FT_Done_FreeType(ms_pFreeType); - ms_pFreeType = nullptr; + FT_Done_FreeType(freetype_library); + freetype_library = nullptr; } } } -const char* THFreeTypeFont::getCopyrightNotice() +const char* freetype_font::get_copyright_notice() { return "Portions of this software are copyright \xC2\xA9 2010 " \ "The FreeType Project (www.freetype.org). All rights reserved."; } -FT_Error THFreeTypeFont::initialise() +FT_Error freetype_font::initialise() { - if(m_bDoneFreeTypeInit) + if(is_done_freetype_init) return FT_Err_Ok; - if(ms_iFreeTypeInitCount == 0) + if(freetype_init_count == 0) { - int iError = FT_Init_FreeType(&ms_pFreeType); + int iError = FT_Init_FreeType(&freetype_library); if(iError != FT_Err_Ok) return iError; } - ++ms_iFreeTypeInitCount; - m_bDoneFreeTypeInit = true; + ++freetype_init_count; + is_done_freetype_init = true; return FT_Err_Ok; } -void THFreeTypeFont::clearCache() +void freetype_font::clear_cache() { - for(cached_text_t* pEntry = m_aCache; - pEntry != m_aCache + (1 << ms_CacheSizeLog2); ++pEntry) + for(cached_text* pEntry = cache; + pEntry != cache + (1 << cache_size_log2); ++pEntry) { - pEntry->bIsValid = false; - _freeTexture(pEntry); + pEntry->is_valid = false; + free_texture(pEntry); } } -FT_Error THFreeTypeFont::setFace(const uint8_t* pData, size_t iLength) +FT_Error freetype_font::set_face(const uint8_t* pData, size_t iLength) { int iError; - if(ms_pFreeType == nullptr) + if(freetype_library == nullptr) { iError = initialise(); if(iError != FT_Err_Ok) return iError; } - if(m_pFace) + if(font_face) { - iError = FT_Done_Face(m_pFace); + iError = FT_Done_Face(font_face); if(iError != FT_Err_Ok) return iError; - m_pFace = nullptr; + font_face = nullptr; } - iError = FT_New_Memory_Face(ms_pFreeType, pData, static_cast(iLength), 0, &m_pFace); + iError = FT_New_Memory_Face(freetype_library, pData, static_cast(iLength), 0, &font_face); return iError; } -FT_Error THFreeTypeFont::matchBitmapFont(THSpriteSheet* pBitmapFontSpriteSheet) +FT_Error freetype_font::match_bitmap_font(sprite_sheet* pBitmapFontSpriteSheet) { if(pBitmapFontSpriteSheet == nullptr) return FT_Err_Invalid_Argument; @@ -414,23 +413,23 @@ { unsigned int iWidth, iHeight; unsigned int iSprite = *sCharToTry - 31; - if(pBitmapFontSpriteSheet->getSpriteSize(iSprite, &iWidth, &iHeight) - && pBitmapFontSpriteSheet->getSpriteAverageColour(iSprite, &m_oColour) + if(pBitmapFontSpriteSheet->get_sprite_size(iSprite, &iWidth, &iHeight) + && pBitmapFontSpriteSheet->get_sprite_average_colour(iSprite, &colour) && iWidth > 1 && iHeight > 1) { - return setPixelSize(iWidth, iHeight); + return set_ideal_character_size(iWidth, iHeight); } } // Take the average size of all characters, and the colour of one of them. unsigned int iWidthSum = 0, iHeightSum = 0, iAverageNum = 0; - for(unsigned int i = 0; i < pBitmapFontSpriteSheet->getSpriteCount(); ++i) + for(unsigned int i = 0; i < pBitmapFontSpriteSheet->get_sprite_count(); ++i) { unsigned int iWidth, iHeight; - pBitmapFontSpriteSheet->getSpriteSizeUnchecked(i, &iWidth, &iHeight); + pBitmapFontSpriteSheet->get_sprite_size_unchecked(i, &iWidth, &iHeight); if(iWidth <= 1 || iHeight <= 1) continue; - if(!pBitmapFontSpriteSheet->getSpriteAverageColour(i, &m_oColour)) + if(!pBitmapFontSpriteSheet->get_sprite_average_colour(i, &colour)) continue; iWidthSum += iWidth; iHeightSum += iHeight; @@ -439,26 +438,26 @@ if(iAverageNum == 0) return FT_Err_Divide_By_Zero; - return setPixelSize((iWidthSum + iAverageNum / 2) / iAverageNum, + return set_ideal_character_size((iWidthSum + iAverageNum / 2) / iAverageNum, (iHeightSum + iAverageNum / 2) / iAverageNum); } -FT_Error THFreeTypeFont::setPixelSize(int iWidth, int iHeight) +FT_Error freetype_font::set_ideal_character_size(int iWidth, int iHeight) { - if(m_pFace == nullptr) + if(font_face == nullptr) return FT_Err_Invalid_Face_Handle; - if(_isMonochrome() || iHeight <= 14 || iWidth <= 9) + if(is_monochrome() || iHeight <= 14 || iWidth <= 9) { // Look for a bitmap strike of a similar size int iBestBitmapScore = 50; FT_Int iBestBitmapIndex = -1; - for(FT_Int i = 0; i < m_pFace->num_fixed_sizes; ++i) + for(FT_Int i = 0; i < font_face->num_fixed_sizes; ++i) { - if(m_pFace->available_sizes[i].height > iHeight) + if(font_face->available_sizes[i].height > iHeight) continue; - int iDeltaH = iHeight - m_pFace->available_sizes[i].height; - int iDeltaW = m_pFace->available_sizes[i].width - iWidth; + int iDeltaH = iHeight - font_face->available_sizes[i].height; + int iDeltaW = font_face->available_sizes[i].width - iWidth; int iScore = iDeltaH * iDeltaH * 3 + iDeltaW * iDeltaW; if(iScore < iBestBitmapScore) { @@ -469,7 +468,7 @@ // Select the bitmap strike, if there was one if(iBestBitmapIndex != -1) - return FT_Select_Size(m_pFace, iBestBitmapIndex); + return FT_Select_Size(font_face, iBestBitmapIndex); } // Go with the original size request if there was no bitmap strike, unless @@ -485,79 +484,79 @@ iHeight = iHeight * 9 / iWidth; iWidth = 9; } - return FT_Set_Pixel_Sizes(m_pFace, iWidth, iHeight); + return FT_Set_Pixel_Sizes(font_face, iWidth, iHeight); } -THFontDrawArea THFreeTypeFont::getTextSize(const char* sMessage, size_t iMessageLength, int iMaxWidth) const +text_layout freetype_font::get_text_dimensions(const char* sMessage, size_t iMessageLength, int iMaxWidth) const { - return drawTextWrapped(nullptr, sMessage, iMessageLength, 0, 0, iMaxWidth, INT_MAX, 0); + return draw_text_wrapped(nullptr, sMessage, iMessageLength, 0, 0, iMaxWidth, INT_MAX, 0); } -void THFreeTypeFont::drawText(THRenderTarget* pCanvas, const char* sMessage, +void freetype_font::draw_text(render_target* pCanvas, const char* sMessage, size_t iMessageLength, int iX, int iY) const { - drawTextWrapped(pCanvas, sMessage, iMessageLength, iX, iY, INT_MAX); + draw_text_wrapped(pCanvas, sMessage, iMessageLength, iX, iY, INT_MAX); } -struct codepoint_glyph_t +struct codepoint_glyph { - FT_Glyph_Metrics oMetrics; - FT_Glyph pGlyph; - FT_UInt iGlyphIndex; + FT_Glyph_Metrics metrics; + FT_Glyph glyph; + FT_UInt index; }; -THFontDrawArea THFreeTypeFont::drawTextWrapped(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY, - int iWidth, int iMaxRows, int iSkipRows, eTHAlign eAlign) const +text_layout freetype_font::draw_text_wrapped(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY, + int iWidth, int iMaxRows, int iSkipRows, text_alignment eAlign) const { - THFontDrawArea oDrawArea = {}; + text_layout oDrawArea = {}; int iNumRows = 0; int iHandledRows = 0; // Calculate an index into the cache to use for this piece of text. size_t iHash = iMessageLength - + (static_cast(iMaxRows) << (ms_CacheSizeLog2 / 8)) - + (static_cast(iSkipRows) << (ms_CacheSizeLog2 / 4)) - + (static_cast(iWidth) << (ms_CacheSizeLog2 / 2)) - + (static_cast(eAlign) << ms_CacheSizeLog2); + + (static_cast(iMaxRows) << (cache_size_log2 / 8)) + + (static_cast(iSkipRows) << (cache_size_log2 / 4)) + + (static_cast(iWidth) << (cache_size_log2 / 2)) + + (static_cast(eAlign) << cache_size_log2); for(size_t i = 0; i < iMessageLength; ++i) iHash ^= (iHash << 5) + (iHash >> 2) + static_cast(sMessage[i]); - iHash &= (1 << ms_CacheSizeLog2) - 1; + iHash &= (1 << cache_size_log2) - 1; - cached_text_t* pEntry = m_aCache + iHash; - if(pEntry->iMessageLength != iMessageLength || pEntry->iWidth > iWidth - || (iWidth != INT_MAX && pEntry->iWidth < iWidth) - || pEntry->eAlign != eAlign || !pEntry->bIsValid - || std::memcmp(pEntry->sMessage, sMessage, iMessageLength) != 0) + cached_text* pEntry = cache + iHash; + if(pEntry->message_length != iMessageLength || pEntry->width > iWidth + || (iWidth != INT_MAX && pEntry->width < iWidth) + || pEntry->alignment != eAlign || !pEntry->is_valid + || std::memcmp(pEntry->message, sMessage, iMessageLength) != 0) { // Cache entry does not match the message being drawn, so discard the // cache entry. - _freeTexture(pEntry); - delete[] pEntry->pData; - pEntry->pData = nullptr; - pEntry->bIsValid = false; + free_texture(pEntry); + delete[] pEntry->data; + pEntry->data = nullptr; + pEntry->is_valid = false; // Set the entry metadata to that of the new message. - if(iMessageLength > pEntry->iMessageBufferLength) + if(iMessageLength > pEntry->message_buffer_length) { - delete[] pEntry->sMessage; - pEntry->sMessage = new char[iMessageLength]; - pEntry->iMessageBufferLength = iMessageLength; - } - std::memcpy(pEntry->sMessage, sMessage, iMessageLength); - pEntry->iMessageLength = iMessageLength; - pEntry->iWidth = iWidth; - pEntry->eAlign = eAlign; + delete[] pEntry->message; + pEntry->message = new char[iMessageLength]; + pEntry->message_buffer_length = iMessageLength; + } + std::memcpy(pEntry->message, sMessage, iMessageLength); + pEntry->message_length = iMessageLength; + pEntry->width = iWidth; + pEntry->alignment = eAlign; // Split the message into lines, and determine the position within the // line for each character. std::vector > vLines; std::vector vCharPositions(iMessageLength); - std::map mapGlyphs; + std::map mapGlyphs; vLines.reserve(2); FT_Vector ftvPen = {0, 0}; - FT_Bool bUseKerning = FT_HAS_KERNING(m_pFace); + FT_Bool bUseKerning = FT_HAS_KERNING(font_face); FT_UInt iPreviousGlyphIndex = 0; const char* sMessageStart = sMessage; @@ -568,7 +567,7 @@ while(sMessage != sMessageEnd) { const char* sOldMessage = sMessage; - unsigned int iCode = utf8next(sMessage); + unsigned int iCode = next_utf8_codepoint(sMessage); unsigned int iNextCode = *reinterpret_cast(sMessage); bool bIsNewLine = (iCode == '\n' && iNextCode == '\n') || (iCode == '/' && iNextCode == '/'); // Just replace single line breaks with space. @@ -577,35 +576,35 @@ iCode = ' '; } - codepoint_glyph_t& oGlyph = mapGlyphs[iCode]; - if(oGlyph.pGlyph == nullptr) + codepoint_glyph& oGlyph = mapGlyphs[iCode]; + if(oGlyph.glyph == nullptr) { - oGlyph.iGlyphIndex = FT_Get_Char_Index(m_pFace, iCode); + oGlyph.index = FT_Get_Char_Index(font_face, iCode); /* FT_Error iError = */ - FT_Load_Glyph(m_pFace, oGlyph.iGlyphIndex, FT_LOAD_DEFAULT); + FT_Load_Glyph(font_face, oGlyph.index, FT_LOAD_DEFAULT); // TODO: iError != FT_Err_Ok /* iError = */ - FT_Get_Glyph(m_pFace->glyph, &oGlyph.pGlyph); + FT_Get_Glyph(font_face->glyph, &oGlyph.glyph); // TODO: iError != FT_Err_Ok - oGlyph.oMetrics = m_pFace->glyph->metrics; + oGlyph.metrics = font_face->glyph->metrics; } // Apply kerning - if(bUseKerning && iPreviousGlyphIndex && oGlyph.iGlyphIndex) + if(bUseKerning && iPreviousGlyphIndex && oGlyph.index) { FT_Vector ftvKerning; - FT_Get_Kerning(m_pFace, iPreviousGlyphIndex, - oGlyph.iGlyphIndex, FT_KERNING_DEFAULT, &ftvKerning); + FT_Get_Kerning(font_face, iPreviousGlyphIndex, + oGlyph.index, FT_KERNING_DEFAULT, &ftvKerning); ftvPen.x += ftvKerning.x; ftvPen.y += ftvKerning.y; } // Make an automatic line break if one is needed. - if((ftvPen.x + oGlyph.oMetrics.horiBearingX + - oGlyph.oMetrics.width + 63) / 64 >= iWidth || bIsNewLine) + if((ftvPen.x + oGlyph.metrics.horiBearingX + + oGlyph.metrics.width + 63) / 64 >= iWidth || bIsNewLine) { if(bIsNewLine) { @@ -626,11 +625,11 @@ { vLines.push_back(std::make_pair(sLineBreakPosition, sLineBreakPosition)); } - utf8next(sLineBreakPosition); + next_utf8_codepoint(sLineBreakPosition); iHandledRows++; } sMessage = sLineBreakPosition; - utf8next(sMessage); + next_utf8_codepoint(sMessage); sLineStart = sMessage; } else @@ -640,7 +639,7 @@ } if(bIsNewLine) { - utf8next(sMessage); + next_utf8_codepoint(sMessage); sLineStart = sLineBreakPosition = sMessage; } else @@ -662,8 +661,8 @@ vCharPositions[sOldMessage - sMessageStart] = ftvPen; } - iPreviousGlyphIndex = oGlyph.iGlyphIndex; - ftvPen.x += oGlyph.oMetrics.horiAdvance; + iPreviousGlyphIndex = oGlyph.index; + ftvPen.x += oGlyph.metrics.horiAdvance; } if(sLineStart != sMessageEnd) vLines.push_back(std::make_pair(sLineStart, sMessageEnd)); @@ -675,9 +674,9 @@ FT_Pos iPriorLinesHeight = 0; FT_Pos iLineWidth = 0, iAlignDelta = 0, iWidestLine = 0; const FT_Pos iLineSpacing = 2 << 6; - codepoint_glyph_t& oGlyph = mapGlyphs['l']; - FT_Pos iBearingY = oGlyph.oMetrics.horiBearingY; - FT_Pos iNormalLineHeight = oGlyph.oMetrics.height - iBearingY; + codepoint_glyph& oGlyph = mapGlyphs['l']; + FT_Pos iBearingY = oGlyph.metrics.horiBearingY; + FT_Pos iNormalLineHeight = oGlyph.metrics.height - iBearingY; iBearingY = ((iBearingY + 63) >> 6) << 6; // Pixel-align iNormalLineHeight += iBearingY; iNormalLineHeight += iLineSpacing; @@ -686,11 +685,11 @@ itr = vLines.begin(), itrEnd = vLines.end(); itr != itrEnd && iNumRows < iMaxRows; ++itr) { // Calculate the X change resulting from alignment. - const char* sLastChar = utf8prev(itr->second); - codepoint_glyph_t& oLastGlyph = mapGlyphs[utf8decode(sLastChar)]; + const char* sLastChar = previous_utf8_codepoint(itr->second); + codepoint_glyph& oLastGlyph = mapGlyphs[decode_utf8(sLastChar)]; iLineWidth = vCharPositions[sLastChar - sMessage].x - + oLastGlyph.oMetrics.horiBearingX - + oLastGlyph.oMetrics.width; + + oLastGlyph.metrics.horiBearingX + + oLastGlyph.metrics.width; if((iLineWidth >> 6) < iWidth) { iAlignDelta = ((iWidth * 64 - iLineWidth) * @@ -704,9 +703,9 @@ FT_Pos iBaselinePos = 0; for(const char* s = itr->first; s != itr->second; ) { - codepoint_glyph_t& oGlyph = mapGlyphs[utf8next(s)]; - FT_Pos iBearingY = oGlyph.oMetrics.horiBearingY; - FT_Pos iCoBearingY = oGlyph.oMetrics.height - iBearingY; + codepoint_glyph& oGlyph = mapGlyphs[next_utf8_codepoint(s)]; + FT_Pos iBearingY = oGlyph.metrics.horiBearingY; + FT_Pos iCoBearingY = oGlyph.metrics.height - iBearingY; if(iBearingY > iBaselinePos) iBaselinePos = iBearingY; if(iCoBearingY > iLineHeight) @@ -720,7 +719,7 @@ iNormalLineHeight = std::max(iNormalLineHeight, iLineHeight); // Apply the character position changes. - for(const char* s = itr->first; s != itr->second; utf8next(s)) + for(const char* s = itr->first; s != itr->second; next_utf8_codepoint(s)) { FT_Vector& ftvPos = vCharPositions[s - sMessage]; ftvPos.x += iAlignDelta; @@ -739,26 +738,26 @@ } if(iPriorLinesHeight > 0) iPriorLinesHeight -= iLineSpacing; - pEntry->iHeight = static_cast(1 + (iPriorLinesHeight >> 6)); - pEntry->iWidestLine = static_cast(1 + (iWidestLine >> 6)); - pEntry->iNumRows = iNumRows; + pEntry->height = static_cast(1 + (iPriorLinesHeight >> 6)); + pEntry->widest_line_width = static_cast(1 + (iWidestLine >> 6)); + pEntry->row_count = iNumRows; if(iWidth == INT_MAX) - pEntry->iWidth = pEntry->iWidestLine; - pEntry->iLastX = 1 + (static_cast(iLineWidth + iAlignDelta) >> 6); + pEntry->width = pEntry->widest_line_width; + pEntry->last_x = 1 + (static_cast(iLineWidth + iAlignDelta) >> 6); // Get a bitmap for each glyph. - bool bIsMonochrome = _isMonochrome(); + bool bIsMonochrome = is_monochrome(); FT_Render_Mode eRenderMode = bIsMonochrome ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL; - for(std::map::iterator itr = + for(std::map::iterator itr = mapGlyphs.begin(), itrEnd = mapGlyphs.end(); itr != itrEnd; ++itr) { - FT_Glyph_To_Bitmap(&itr->second.pGlyph, eRenderMode, nullptr, 1); + FT_Glyph_To_Bitmap(&itr->second.glyph, eRenderMode, nullptr, 1); } // Prepare a canvas for rendering. - pEntry->pData = new uint8_t[pEntry->iWidth * pEntry->iHeight]; - std::memset(pEntry->pData, 0, pEntry->iWidth * pEntry->iHeight); + pEntry->data = new uint8_t[pEntry->width * pEntry->height]; + std::memset(pEntry->data, 0, pEntry->width * pEntry->height); int iDrawnLines = 0; // Render each character to the canvas. @@ -770,13 +769,13 @@ for(const char* s = itr->first; s != itr->second; ) { FT_Vector& ftvPos = vCharPositions[s - sMessage]; - unsigned int iCode = utf8next(s); + unsigned int iCode = next_utf8_codepoint(s); if(iCode == '\n') { iCode = ' '; } FT_BitmapGlyph pGlyph = reinterpret_cast( - mapGlyphs[iCode].pGlyph); + mapGlyphs[iCode].glyph); FT_Pos x = pGlyph->left + (ftvPos.x >> 6); FT_Pos y = (ftvPos.y >> 6) - pGlyph->top; // We may have asked for grayscale but been given monochrome, @@ -784,35 +783,35 @@ switch(pGlyph->bitmap.pixel_mode) { case FT_PIXEL_MODE_GRAY: - _renderGray(pEntry, &pGlyph->bitmap, x, y); + render_gray(pEntry, &pGlyph->bitmap, x, y); break; case FT_PIXEL_MODE_MONO: - _renderMono(pEntry, &pGlyph->bitmap, x, y); + render_mono(pEntry, &pGlyph->bitmap, x, y); break; } } } // Free all glyphs. - for(std::map::const_iterator itr = + for(std::map::const_iterator itr = mapGlyphs.begin(), itrEnd = mapGlyphs.end(); itr != itrEnd; ++itr) { - FT_Done_Glyph(itr->second.pGlyph); + FT_Done_Glyph(itr->second.glyph); } - pEntry->bIsValid = true; + pEntry->is_valid = true; } if (pCanvas != nullptr) { - if (pEntry->pTexture == nullptr) - _makeTexture(pCanvas, pEntry); - _drawTexture(pCanvas, pEntry, iX, iY); - } - oDrawArea.iWidth = pEntry->iWidestLine; - oDrawArea.iEndX = iX + pEntry->iLastX; - oDrawArea.iEndY = iY + pEntry->iHeight; - oDrawArea.iNumRows = pEntry->iNumRows; + if (pEntry->texture == nullptr) + make_texture(pCanvas, pEntry); + draw_texture(pCanvas, pEntry, iX, iY); + } + oDrawArea.width = pEntry->widest_line_width; + oDrawArea.end_x = iX + pEntry->last_x; + oDrawArea.end_y = iY + pEntry->height; + oDrawArea.row_count = pEntry->row_count; return oDrawArea; } @@ -821,17 +820,17 @@ // at which point the following line can be removed. // #define TRUST_RENDER_COORDS -void THFreeTypeFont::_renderMono(cached_text_t *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const +void freetype_font::render_mono(cached_text *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const { - uint8_t* pOutRow = pCacheEntry->pData + y * pCacheEntry->iWidth + x; + uint8_t* pOutRow = pCacheEntry->data + y * pCacheEntry->width + x; uint8_t* pInRow = pBitmap->buffer; - for(int iY = 0; iY < pBitmap->rows; ++iY, pOutRow += pCacheEntry->iWidth, + for(int iY = 0; iY < pBitmap->rows; ++iY, pOutRow += pCacheEntry->width, pInRow += pBitmap->pitch) { #ifndef TRUST_RENDER_COORDS if(y + iY < 0) continue; - if(y + iY >= pCacheEntry->iHeight) + if(y + iY >= pCacheEntry->height) break; #endif uint8_t *pIn = pInRow, *pOut = pOutRow; @@ -841,7 +840,7 @@ #ifndef TRUST_RENDER_COORDS if(x + iX < 0) continue; - if(x + iX >= pCacheEntry->iWidth) + if(x + iX >= pCacheEntry->width) break; #endif if(*pIn & iMask) @@ -856,17 +855,17 @@ } } -void THFreeTypeFont::_renderGray(cached_text_t *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const +void freetype_font::render_gray(cached_text *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const { - uint8_t* pOutRow = pCacheEntry->pData + y * pCacheEntry->iWidth + x; + uint8_t* pOutRow = pCacheEntry->data + y * pCacheEntry->width + x; uint8_t* pInRow = pBitmap->buffer; - for(int iY = 0; iY < pBitmap->rows; ++iY, pOutRow += pCacheEntry->iWidth, + for(int iY = 0; iY < pBitmap->rows; ++iY, pOutRow += pCacheEntry->width, pInRow += pBitmap->pitch) { #ifndef TRUST_RENDER_COORDS if(y + iY < 0) continue; - if(y + iY >= pCacheEntry->iHeight) + if(y + iY >= pCacheEntry->height) break; #endif uint8_t *pIn = pInRow, *pOut = pOutRow; @@ -875,7 +874,7 @@ #ifndef TRUST_RENDER_COORDS if(x + iX < 0) continue; - if(x + iX >= pCacheEntry->iWidth) + if(x + iX >= pCacheEntry->width) break; #endif unsigned int iIn = *pIn; diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx_font.h corsix-th-0.62/CorsixTH/Src/th_gfx_font.h --- corsix-th-0.61/CorsixTH/Src/th_gfx_font.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx_font.h 2018-07-21 11:13:17.000000000 +0000 @@ -28,39 +28,38 @@ #include FT_FREETYPE_H #endif -enum eTHAlign -{ - Align_Left = 0, - Align_Center = 1, - Align_Right = 2, +enum class text_alignment { + left = 0, + center = 1, + right = 2, }; /** Structure for the bounds of a text string that is rendered to the screen. */ -struct THFontDrawArea +struct text_layout { //! Number of rows the rendered text spans - int iNumRows; + int row_count; //! Left X-coordinate for the start of the text - int iStartX; + int start_x; //! Right X-coordinate for the right part of the last letter rendered - int iEndX; + int end_x; //! Top Y-coordinate for the start of the text - int iStartY; + int start_y; //! Bottom Y-coordinate for the end of the text - int iEndY; + int end_y; //! Width of the widest line in the text - int iWidth; + int width; }; -class THFont +class font { public: - virtual ~THFont() = default; + virtual ~font() = default; //! Get the size of drawn text. /*! @@ -73,8 +72,8 @@ @param iMaxWidth The maximum length, in pixels, that the text may occupy. Default is INT_MAX. */ - virtual THFontDrawArea getTextSize(const char* sMessage, size_t iMessageLength, - int iMaxWidth = INT_MAX) const = 0; + virtual text_layout get_text_dimensions(const char* sMessage, size_t iMessageLength, + int iMaxWidth = INT_MAX) const = 0; //! Draw a single line of text /*! @@ -88,8 +87,8 @@ @param iY The Y coordinate of the top-left corner of the bounding rectangle for the drawn text. */ - virtual void drawText(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY) const = 0; + virtual void draw_text(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY) const = 0; //! Draw a single line of text, splitting it at word boundaries /*! @@ -109,16 +108,16 @@ @param eAlign How to align each line of text if the width of the line of text is smaller than iWidth. */ - virtual THFontDrawArea drawTextWrapped(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY, - int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, - eTHAlign eAlign = Align_Left) const = 0; + virtual text_layout draw_text_wrapped(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY, + int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, + text_alignment eAlign = text_alignment::left) const = 0; }; -class THBitmapFont final : public THFont +class bitmap_font final : public font { public: - THBitmapFont(); + bitmap_font(); //! Set the character glyph sprite sheet /*! @@ -126,32 +125,32 @@ index 1, and other ASCII characters following on in simple order (i.e. '!' (ASCII 0x21) at index 2, 'A' (ASCII 0x41) at index 34, etc.) */ - void setSpriteSheet(THSpriteSheet* pSpriteSheet); + void set_sprite_sheet(sprite_sheet* pSpriteSheet); - THSpriteSheet* getSpriteSheet() {return m_pSpriteSheet;} + sprite_sheet* get_sprite_sheet() {return sheet;} //! Set the separation between characters and between lines /*! Generally, the sprite sheet glyphs will already include separation, and thus no extra separation is required (set iCharSep and iLineSep to 0). */ - void setSeparation(int iCharSep, int iLineSep); + void set_separation(int iCharSep, int iLineSep); - THFontDrawArea getTextSize(const char* sMessage, size_t iMessageLength, - int iMaxWidth = INT_MAX) const override; + text_layout get_text_dimensions(const char* sMessage, size_t iMessageLength, + int iMaxWidth = INT_MAX) const override; - void drawText(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY) const override; + void draw_text(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY) const override; - THFontDrawArea drawTextWrapped(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY, - int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, - eTHAlign eAlign = Align_Left) const override; + text_layout draw_text_wrapped(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY, + int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, + text_alignment eAlign = text_alignment::left) const override; private: - THSpriteSheet* m_pSpriteSheet; - int m_iCharSep; - int m_iLineSep; + sprite_sheet* sheet; + int letter_spacing; + int line_spacing; }; #ifdef CORSIX_TH_USE_FREETYPE2 @@ -168,11 +167,11 @@ THRawBitmap class, but with an alpha channel, and a single colour rather than a palette). */ -class THFreeTypeFont final : public THFont +class freetype_font final : public font { public: - THFreeTypeFont(); - ~THFreeTypeFont(); + freetype_font(); + ~freetype_font(); //! Get the copyright notice which should be displayed for FreeType2. /*! @@ -180,7 +179,7 @@ function needs to be displayed at some point. @return A null-terminated UTF-8 encoded string. */ - static const char* getCopyrightNotice(); + static const char* get_copyright_notice(); //! Initialise the FreeType2 library. /*! @@ -189,7 +188,7 @@ FT_Error initialise(); //! Remove all cached strings, as our graphics context has changed - void clearCache(); + void clear_cache(); //! Set the font face to be used. /*! @@ -198,7 +197,7 @@ of the THFreeTypeFont objcect. @param iLength The size, in bytes, of the font file at pData. */ - FT_Error setFace(const uint8_t* pData, size_t iLength); + FT_Error set_face(const uint8_t* pData, size_t iLength); //! Set the font size and colour to match that of a bitmap font. /*! @@ -207,7 +206,7 @@ @param pBitmapFontSpriteSheet The sprite sheet of the bitmap font. */ - FT_Error matchBitmapFont(THSpriteSheet* pBitmapFontSpriteSheet); + FT_Error match_bitmap_font(sprite_sheet* pBitmapFontSpriteSheet); //! Set the ideal character size using pixel values. /*! @@ -215,72 +214,72 @@ would result in a much nicer rendered font. This must be called after setFace(). */ - FT_Error setPixelSize(int iWidth, int iHeight); + FT_Error set_ideal_character_size(int iWidth, int iHeight); - THFontDrawArea getTextSize(const char* sMessage, size_t iMessageLength, - int iMaxWidth = INT_MAX) const override; + text_layout get_text_dimensions(const char* sMessage, size_t iMessageLength, + int iMaxWidth = INT_MAX) const override; - void drawText(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY) const override; + void draw_text(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY) const override; - THFontDrawArea drawTextWrapped(THRenderTarget* pCanvas, const char* sMessage, - size_t iMessageLength, int iX, int iY, - int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, - eTHAlign eAlign = Align_Left) const override; + text_layout draw_text_wrapped(render_target* pCanvas, const char* sMessage, + size_t iMessageLength, int iX, int iY, + int iWidth, int iMaxRows = INT_MAX, int iSkipRows = 0, + text_alignment eAlign = text_alignment::left) const override; private: - struct cached_text_t + struct cached_text { //! The text being converted to pixels - char* sMessage; + char* message; //! Raw pixel data in row major 8-bit greyscale - uint8_t* pData; + uint8_t* data; //! Generated texture ready to be rendered - SDL_Texture* pTexture; + SDL_Texture* texture; //! The length of sMessage - size_t iMessageLength; + size_t message_length; //! The size of the buffer allocated to store sMessage - size_t iMessageBufferLength; + size_t message_buffer_length; //! Width of the image to draw - int iWidth; + int width; //! Height of the image to draw - int iHeight; + int height; //! The width of the longest line of text in in the textbox in pixels - int iWidestLine; + int widest_line_width; //! X Coordinate trailing the last character in canvas coordinates - int iLastX; + int last_x; //! Number of rows required - int iNumRows; + int row_count; //! Alignment of the message in the box - eTHAlign eAlign; + text_alignment alignment; - //! True when the pData reflects the sMessage given the size constraints - bool bIsValid; + //! True when the data reflects the message given the size constraints + bool is_valid; }; //! Render a FreeType2 monochrome bitmap to a cache canvas. - void _renderMono(cached_text_t *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const; + void render_mono(cached_text *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const; //! Render a FreeType2 grayscale bitmap to a cache canvas. - void _renderGray(cached_text_t *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const; + void render_gray(cached_text *pCacheEntry, FT_Bitmap* pBitmap, FT_Pos x, FT_Pos y) const; - static FT_Library ms_pFreeType; - static int ms_iFreeTypeInitCount; - static const int ms_CacheSizeLog2 = 7; - FT_Face m_pFace; - THColour m_oColour; - bool m_bDoneFreeTypeInit; - mutable cached_text_t m_aCache[1 << ms_CacheSizeLog2]; + static FT_Library freetype_library; + static int freetype_init_count; + static const int cache_size_log2 = 7; + FT_Face font_face; + argb_colour colour; + bool is_done_freetype_init; + mutable cached_text cache[1 << cache_size_log2]; // The following five methods are implemented by the rendering engine. @@ -290,7 +289,7 @@ 8-bit grayscale rendering should be used (though in the latter case, 1-bit rendering might still get used). */ - bool _isMonochrome() const; + bool is_monochrome() const; //! Convert a cache canvas containing rendered text into a texture. /*! @@ -301,7 +300,7 @@ an object which can be used by the rendering engine, and store the result in the pTexture or iTexture field. */ - void _makeTexture(THRenderTarget *pEventualCanvas, cached_text_t* pCacheEntry) const; + void make_texture(render_target *pEventualCanvas, cached_text* pCacheEntry) const; //! Free a previously-made texture of a cache entry. /*! @@ -310,7 +309,7 @@ @param pCacheEntry A cache entry previously passed to _makeTexture(). */ - void _freeTexture(cached_text_t* pCacheEntry) const; + void free_texture(cached_text* pCacheEntry) const; //! Render a previously-made texture of a cache entry. /*! @@ -321,7 +320,7 @@ @param iX The X position at which to draw the texture on the canvas. @param iY The Y position at which to draw the texture on the canvas. */ - void _drawTexture(THRenderTarget* pCanvas, cached_text_t* pCacheEntry, + void draw_texture(render_target* pCanvas, cached_text* pCacheEntry, int iX, int iY) const; }; #endif // CORSIX_TH_USE_FREETYPE2 diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx.h corsix-th-0.62/CorsixTH/Src/th_gfx.h --- corsix-th-0.61/CorsixTH/Src/th_gfx.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx.h 2018-07-21 11:13:17.000000000 +0000 @@ -24,15 +24,14 @@ #define CORSIX_TH_TH_GFX_H_ #include "th.h" -class LuaPersistReader; -class LuaPersistWriter; +class lua_persist_reader; +class lua_persist_writer; -enum THScaledItems -{ - THSI_None = 0, - THSI_SpriteSheets = 1 << 0, - THSI_Bitmaps = 1 << 1, - THSI_All = 3, +enum class scaled_items { + none, + sprite_sheets, + bitmaps, + all }; #include "th_gfx_sdl.h" @@ -41,68 +40,61 @@ #include #include -void IntersectTHClipRect(THClipRect& rcClip,const THClipRect& rcIntersect); +void clip_rect_intersection(clip_rect& rcClip, const clip_rect& rcIntersect); //! Bitflags for drawing operations -enum THDrawFlags +enum draw_flags : uint32_t { /** Sprite drawing flags **/ /* Where possible, designed to be the same values used by TH data files */ //! Draw with the left becoming the right and vice versa - THDF_FlipHorizontal = 1 << 0, + thdf_flip_horizontal = 1 << 0, //! Draw with the top becoming the bottom and vice versa - THDF_FlipVertical = 1 << 1, + thdf_flip_vertical = 1 << 1, //! Draw with 50% transparency - THDF_Alpha50 = 1 << 2, + thdf_alpha_50 = 1 << 2, //! Draw with 75% transparency - THDF_Alpha75 = 1 << 3, + thdf_alpha_75 = 1 << 3, //! Draw using a remapped palette - THDF_AltPalette = 1 << 4, + thdf_alt_palette = 1 << 4, /** How to draw alternative palette in 32bpp. */ /* A 3 bit field (bits 5,6,7), currently 2 bits used. */ //! Lowest bit of the field. - THDF_Alt32_Start = 5, + thdf_alt32_start = 5, //! Mask for the 32bpp alternative drawing values. - THDF_Alt32_Mask = 0x7 << THDF_Alt32_Start, + thdf_alt32_mask = 0x7 << thdf_alt32_start, //! Draw the sprite with the normal palette (fallback option). - THDF_Alt32_Plain = 0 << THDF_Alt32_Start, + thdf_alt32_plain = 0 << thdf_alt32_start, //! Draw the sprite in grey scale. - THDF_Alt32_GreyScale = 1 << THDF_Alt32_Start, + thdf_alt32_grey_scale = 1 << thdf_alt32_start, //! Draw the sprite with red and blue colours swapped. - THDF_Alt32_BlueRedSwap = 2 << THDF_Alt32_Start, + thdf_alt32_blue_red_swap = 2 << thdf_alt32_start, /** Object attached to tile flags **/ /* (should be set prior to attaching to a tile) */ //! Attach to the early sprite list (right-to-left pass) - THDF_EarlyList = 1 << 10, + thdf_early_list = 1 << 10, //! Keep this sprite at the bottom of the attached list - THDF_ListBottom = 1 << 11, + thdf_list_bottom = 1 << 11, //! Hit-test using bounding-box precision rather than pixel-perfect - THDF_BoundBoxHitTest= 1 << 12, + thdf_bound_box_hit_test = 1 << 12, //! Apply a cropping operation prior to drawing - THDF_Crop = 1 << 13, -}; - -//! Bitflags for animation frames -enum THFrameFlags -{ - //! First frame of an animation - THFF_AnimationStart = 1 << 0, + thdf_crop = 1 << 13, }; /** Helper structure with parameters to create a #THRenderTarget. */ -struct THRenderTargetCreationParams +struct render_target_creation_params { - int iWidth; ///< Expected width of the render target. - int iHeight; ///< Expected height of the render target. - int iBPP; ///< Expected colour depth of the render target. - bool bFullscreen; ///< Run full-screen. - bool bPresentImmediate; ///< Whether to present immediately to the user (else wait for Vsync). + int width; ///< Expected width of the render target. + int height; ///< Expected height of the render target. + int bpp; ///< Expected colour depth of the render target. + bool fullscreen; ///< Run full-screen. + bool present_immediate; ///< Whether to present immediately to the user (else wait for Vsync). }; /*! @@ -110,35 +102,36 @@ Note that "object" is used as a generic term, not in specific reference to game objects (though they are the most common thing in drawing lists). */ -struct THDrawable : public THLinkList +// TODO: Replace this struct with something cleaner +struct drawable : public link_list { //! Draw the object at a specific point on a render target /*! Can also "draw" the object to the speakers, i.e. play sounds. */ - void (*m_fnDraw)(THDrawable* pSelf, THRenderTarget* pCanvas, int iDestX, int iDestY); + void (*draw_fn)(drawable* pSelf, render_target* pCanvas, int iDestX, int iDestY); //! Perform a hit test against the object /*! Should return true if when the object is drawn at (iDestX, iDestY) on a canvas, the point (iTestX, iTestY) is within / on the object. */ - bool (*m_fnHitTest)(THDrawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY); + bool (*hit_test_fn)(drawable* pSelf, int iDestX, int iDestY, int iTestX, int iTestY); - //! Drawing flags (zero or more list flags from #THDrawFlags). - uint32_t m_iFlags; + //! Drawing flags (zero or more list flags from #draw_flags). + uint32_t flags; /** Returns true if instance is a multiple frame animation. Should be overloaded in derived class. */ - bool (*m_fnIsMultipleFrameAnimation)(THDrawable *pSelf); + bool (*is_multiple_frame_animation_fn)(drawable *pSelf); }; /*! Utility class for decoding Theme Hospital "chunked" graphics files. - Generally used internally by THSpriteSheet. + Generally used internally by sprite_sheet. */ -class THChunkRenderer +class chunk_renderer { public: //! Initialise a renderer for a specific size result @@ -150,10 +143,11 @@ Ownership of this pointer is assumed by the class - call takeData() to take ownership back again. */ - THChunkRenderer(int width, int height, uint8_t *buffer = nullptr); + chunk_renderer(int width, int height, uint8_t *buffer = nullptr); - ~THChunkRenderer(); + ~chunk_renderer(); + // TODO: Should be function, not method of chunk_renderer //! Convert a stream of chunks into a raw bitmap /*! @param pData Stream data. @@ -164,7 +158,7 @@ Use getData() or takeData() to obtain the resulting bitmap. */ - void decodeChunks(const uint8_t* pData, int iDataLen, bool bComplex); + void decode_chunks(const uint8_t* pData, int iDataLen, bool bComplex); //! Get the result buffer, and take ownership of it /*! @@ -172,46 +166,46 @@ the class will not have any buffer, and thus cannot be used for anything. */ - uint8_t* takeData(); + uint8_t* take_data(); //! Get the result buffer - inline const uint8_t* getData() const {return m_data;} + inline const uint8_t* get_data() const {return data;} //! Perform a "copy" chunk (normally called by decodeChunks) - void chunkCopy(int npixels, const uint8_t* data); + void chunk_copy(int npixels, const uint8_t* in_data); //! Perform a "fill" chunk (normally called by decodeChunks) - void chunkFill(int npixels, uint8_t value); + void chunk_fill(int npixels, uint8_t value); //! Perform a "fill to end of line" chunk (normally called by decodeChunks) - void chunkFillToEndOfLine(uint8_t value); + void chunk_fill_to_end_of_line(uint8_t value); //! Perform a "fill to end of file" chunk (normally called by decodeChunks) - void chunkFinish(uint8_t value); + void chunk_finish(uint8_t value); private: - inline bool _isDone() {return m_ptr == m_end;} - inline void _fixNpixels(int& npixels) const; - inline void _incrementPosition(int npixels); + inline bool is_done() {return ptr == end;} + inline void fix_n_pixels(int& npixels) const; + inline void increment_position(int npixels); - uint8_t *m_data, *m_ptr, *m_end; - int m_x, m_y, m_width, m_height; - bool m_skip_eol; + uint8_t *data, *ptr, *end; + int x, y, width, height; + bool skip_eol; }; -//! Layer information (see THAnimationManager::drawFrame) -struct THLayers_t +//! Layer information (see animation_manager::draw_frame) +struct layers { - uint8_t iLayerContents[13]; + uint8_t layer_contents[13]; }; -class Input; +class memory_reader; /** Key value for finding an animation. */ -struct AnimationKey +struct animation_key { - std::string sName; ///< Name of the animations. - int iTilesize; ///< Size of a tile. + std::string name; ///< Name of the animations. + int tile_size; ///< Size of a tile. }; //! Less-than operator for map-sorting. @@ -220,29 +214,29 @@ @param oL Second key value. @return Whether \a oK should be before \a oL. */ -inline bool operator<(const AnimationKey &oK, const AnimationKey &oL) +inline bool operator<(const animation_key &oK, const animation_key &oL) { - if (oK.iTilesize != oL.iTilesize) return oK.iTilesize < oL.iTilesize; - return oK.sName < oL.sName; + if (oK.tile_size != oL.tile_size) return oK.tile_size < oL.tile_size; + return oK.name < oL.name; } /** * Start frames of an animation, in each view direction. * A negative number indicates there is no animation in that direction. */ -struct AnimationStartFrames +struct animation_start_frames { - long iNorth; ///< Animation start frame for the 'north' view. - long iEast; ///< Animation start frame for the 'east' view. - long iSouth; ///< Animation start frame for the 'south' view. - long iWest; ///< Animation start frame for the 'west' view. + long north; ///< Animation start frame for the 'north' view. + long east; ///< Animation start frame for the 'east' view. + long south; ///< Animation start frame for the 'south' view. + long west; ///< Animation start frame for the 'west' view. }; /** Map holding the custom animations. */ -typedef std::map NamedAnimationsMap; +typedef std::map named_animations_map; /** Insertion data structure. */ -typedef std::pair NamedAnimationPair; +typedef std::pair named_animation_pair; //! Theme Hospital sprite animation manager /*! @@ -250,17 +244,17 @@ files, and uses them to draw animation frames and provide information about the animations. */ -class THAnimationManager +class animation_manager { public: - THAnimationManager(); - ~THAnimationManager(); + animation_manager(); + ~animation_manager(); - void setSpriteSheet(THSpriteSheet* pSpriteSheet); + void set_sprite_sheet(sprite_sheet* pSpriteSheet); //! Load original animations. /*! - setSpriteSheet() must be called before calling this. + set_sprite_sheet() must be called before calling this. @param pStartData Animation first frame indices (e.g. VSTART-1.ANI) @param iStartDataLength Length of \a pStartData. @param pFrameData Frame details (e.g. VFRA-1.ANI) @@ -271,16 +265,16 @@ @param iElementDataLength Length of \a pElementData @return Loading was successful. */ - bool loadFromTHFile(const uint8_t* pStartData, size_t iStartDataLength, - const uint8_t* pFrameData, size_t iFrameDataLength, - const uint8_t* pListData, size_t iListDataLength, - const uint8_t* pElementData, size_t iElementDataLength); + bool load_from_th_file(const uint8_t* pStartData, size_t iStartDataLength, + const uint8_t* pFrameData, size_t iFrameDataLength, + const uint8_t* pListData, size_t iListDataLength, + const uint8_t* pElementData, size_t iElementDataLength); //! Set the video target. /*! @param pCanvas Video surface to use. */ - void setCanvas(THRenderTarget *pCanvas); + void set_canvas(render_target *pCanvas); //! Load free animations. /*! @@ -288,34 +282,34 @@ @param iDataLength Length of the loaded data. @return Loading was successful. */ - bool loadCustomAnimations(const uint8_t* pData, size_t iDataLength); + bool load_custom_animations(const uint8_t* pData, size_t iDataLength); //! Get the total numer of animations - size_t getAnimationCount() const; + size_t get_animation_count() const; //! Get the total number of animation frames - size_t getFrameCount() const; + size_t get_frame_count() const; //! Get the index of the first frame of an animation - size_t getFirstFrame(size_t iAnimation) const; + size_t get_first_frame(size_t iAnimation) const; //! Get the index of the frame after a given frame /*! - To draw an animation frame by frame, call getFirstFrame() to get the - index of the first frame, and then keep on calling getNextFrame() using - the most recent return value from getNextFrame() or getFirstFrame(). + To draw an animation frame by frame, call get_first_frame() to get the + index of the first frame, and then keep on calling get_next_frame() using + the most recent return value from get_next_frame() or get_first_frame(). */ - size_t getNextFrame(size_t iFrame) const; + size_t get_next_frame(size_t iFrame) const; //! Set the palette remap data for an animation /*! This sets the palette remap data for every single sprite used by the given animation. If the animation (or any of its sprites) are drawn - using the THDF_AltPalette flag, then palette indices will be mapped to + using the thdf_alt_palette flag, then palette indices will be mapped to new palette indices by the 256 byte array pMap. This is typically used to draw things in different colours or in greyscale. */ - void setAnimationAltPaletteMap(size_t iAnimation, const uint8_t* pMap, uint32_t iAlt32); + void set_animation_alt_palette_map(size_t iAnimation, const uint8_t* pMap, uint32_t iAlt32); //! Draw an animation frame /*! @@ -335,22 +329,22 @@ @param iY The screen position to use as the animation Y origin. @param iFlags Zero or more THDrawFlags flags. */ - void drawFrame(THRenderTarget* pCanvas, size_t iFrame, - const THLayers_t& oLayers, - int iX, int iY, uint32_t iFlags) const; - - void getFrameExtent(size_t iFrame, const THLayers_t& oLayers, - int* pMinX, int* pMaxX, int* pMinY, int* pMaxY, - uint32_t iFlags) const; - size_t getFrameSound(size_t iFrame); - - bool hitTest(size_t iFrame, const THLayers_t& oLayers, - int iX, int iY, uint32_t iFlags, int iTestX, int iTestY) const; - - bool setFrameMarker(size_t iFrame, int iX, int iY); - bool setFrameSecondaryMarker(size_t iFrame, int iX, int iY); - bool getFrameMarker(size_t iFrame, int* pX, int* pY); - bool getFrameSecondaryMarker(size_t iFrame, int* pX, int* pY); + void draw_frame(render_target* pCanvas, size_t iFrame, + const ::layers& oLayers, + int iX, int iY, uint32_t iFlags) const; + + void get_frame_extent(size_t iFrame, const ::layers& oLayers, + int* pMinX, int* pMaxX, int* pMinY, int* pMaxY, + uint32_t iFlags) const; + size_t get_frame_sound(size_t iFrame); + + bool hit_test(size_t iFrame, const ::layers& oLayers, + int iX, int iY, uint32_t iFlags, int iTestX, int iTestY) const; + + bool set_frame_marker(size_t iFrame, int iX, int iY); + bool set_frame_secondary_marker(size_t iFrame, int iX, int iY); + bool get_frame_marker(size_t iFrame, int* pX, int* pY); + bool get_frame_secondary_marker(size_t iFrame, int* pX, int* pY); //! Retrieve a custom animation by name and tile size. /*! @@ -358,22 +352,24 @@ @param iTilesize Tile size of the animation. @return A set starting frames for the queried animation. */ - const AnimationStartFrames &getNamedAnimations(const std::string &sName, int iTilesize) const; + const animation_start_frames &get_named_animations(const std::string &sName, int iTilesize) const; private: #if CORSIX_TH_USE_PACK_PRAGMAS #pragma pack(push) #pragma pack(1) #endif - struct th_anim_t + // Animation information structure reinterpreted from Theme Hospital data. + struct th_animation_properties { - uint16_t frame; + uint16_t first_frame; // It could be that frame is a uint32_t rather than a uint16_t, which // would resolve the following unknown (which seems to always be zero). uint16_t unknown; } CORSIX_TH_PACKED_FLAGS; - struct th_frame_t + // Frame information structure reinterpreted from Theme Hospital data. + struct th_frame_properties { uint32_t list_index; // These fields have something to do with width and height, but it's @@ -382,18 +378,19 @@ uint8_t height; // If non-zero, index into sound.dat filetable. uint8_t sound; - // Combination of zero or more THFrameFlags values + // Combination of zero or more fame_flags values uint8_t flags; uint16_t next; } CORSIX_TH_PACKED_FLAGS; - struct th_element_t + // Structure reinterpreted from Theme Hospital data. + struct th_element_properties { uint16_t table_position; uint8_t offx; uint8_t offy; // High nibble: The layer which the element belongs to [0, 12] - // Low nibble: Zero or more THDrawFlags flags + // Low nibble: Zero or more draw_flags uint8_t flags; // The layer option / layer id uint8_t layerid; @@ -402,63 +399,63 @@ #pragma pack(pop) #endif - struct frame_t + struct frame { - size_t iListIndex; ///< First entry in #m_vElementList (pointing to an element) for this frame. - size_t iNextFrame; ///< Number of the next frame. - unsigned int iSound; ///< Sound to play, if non-zero. - unsigned int iFlags; ///< Flags of the frame. Bit 0=start of animation. + size_t list_index; ///< First entry in #element_list (pointing to an element) for this frame. + size_t next_frame; ///< Number of the next frame. + unsigned int sound; ///< Sound to play, if non-zero. + unsigned int flags; ///< Flags of the frame. Bit 0=start of animation. // Bounding rectangle is with all layers / options enabled - used as a // quick test prior to a full pixel perfect test. - int iBoundingLeft; ///< Left edge of the bounding rectangle of this frame. - int iBoundingRight; ///< Right edge of the bounding rectangle of this frame. - int iBoundingTop; ///< Top edge of the bounding rectangle of this frame. - int iBoundingBottom; ///< Bottom edge of the bounding rectangle of this frame. + int bounding_left; ///< Left edge of the bounding rectangle of this frame. + int bounding_right; ///< Right edge of the bounding rectangle of this frame. + int bounding_top; ///< Top edge of the bounding rectangle of this frame. + int bounding_bottom; ///< Bottom edge of the bounding rectangle of this frame. // Markers are used to know where humanoids are on an frame. The // positions are pixels offsets from the centre of the frame's base // tile to the centre of the humanoid's feet. - int iMarkerX; ///< X position of the first center of a humanoids feet. - int iMarkerY; ///< Y position of the first center of a humanoids feet. - int iSecondaryMarkerX; ///< X position of the second center of a humanoids feet. - int iSecondaryMarkerY; ///< Y position of the second center of a humanoids feet. + int marker_x; ///< X position of the first center of a humanoids feet. + int marker_y; ///< Y position of the first center of a humanoids feet. + int secondary_marker_x; ///< X position of the second center of a humanoids feet. + int secondary_marker_y; ///< Y position of the second center of a humanoids feet. }; - struct element_t + struct element { - size_t iSprite; ///< Sprite number of the sprite sheet to display. - uint32_t iFlags; ///< Flags of the sprite. - ///< bit 0=flip vertically, bit 1=flip horizontally, - ///< bit 2=draw 50% alpha, bit 3=draw 75% alpha. - int iX; ///< X offset of the sprite. - int iY; ///< Y offset of the sprite. - uint8_t iLayer; ///< Layer class (0..12). - uint8_t iLayerId; ///< Value of the layer class to match. + size_t sprite; ///< Sprite number of the sprite sheet to display. + uint32_t flags; ///< Flags of the sprite. + ///< bit 0=flip vertically, bit 1=flip horizontally, + ///< bit 2=draw 50% alpha, bit 3=draw 75% alpha. + int x; ///< X offset of the sprite. + int y; ///< Y offset of the sprite. + uint8_t layer; ///< Layer class (0..12). + uint8_t layer_id; ///< Value of the layer class to match. - THSpriteSheet *pSpriteSheet; ///< Sprite sheet to use for this element. + sprite_sheet *element_sprite_sheet; ///< Sprite sheet to use for this element. }; - std::vector m_vFirstFrames; ///< First frame number of an animation. - std::vector m_vFrames; ///< The loaded frames. - std::vector m_vElementList; ///< List of elements for a frame. - std::vector m_vElements; ///< Sprite Elements. - std::vector m_vCustomSheets; ///< Sprite sheets with custom graphics. - NamedAnimationsMap m_oNamedAnimations; ///< Collected named animations. - - THSpriteSheet* m_pSpriteSheet; ///< Sprite sheet to use. - THRenderTarget *m_pCanvas; ///< Video surface to use. - - size_t m_iAnimationCount; ///< Number of animations. - size_t m_iFrameCount; ///< Number of frames. - size_t m_iElementListCount; ///< Number of list elements. - size_t m_iElementCount; ///< Number of sprite elements. + std::vector first_frames; ///< First frame number of an animation. + std::vector frames; ///< The loaded frames. + std::vector element_list; ///< List of elements for a frame. + std::vector elements; ///< Sprite Elements. + std::vector custom_sheets; ///< Sprite sheets with custom graphics. + named_animations_map named_animations; ///< Collected named animations. + + sprite_sheet* sheet; ///< Sprite sheet to use. + render_target *canvas; ///< Video surface to use. + + size_t animation_count; ///< Number of animations. + size_t frame_count; ///< Number of frames. + size_t element_list_count; ///< Number of list elements. + size_t element_count; ///< Number of sprite elements. //! Compute the bounding box of the frame. /*! @param oFrame Frame to inspect/set. */ - void setBoundingBox(frame_t &oFrame); + void set_bounding_box(frame &oFrame); //! Load sprite elements from the input. /*! @@ -468,153 +465,153 @@ @param [inout] iLoadedElements Number of loaded elements so far. @param iElementStart Offset of the first element. @param iElementCount Number of elements to load. - @return Index of the first loaded element in #m_vElements. Negative value means failure. + @return Index of the first loaded element in #elements. Negative value means failure. */ - size_t loadElements(Input &input, THSpriteSheet *pSpriteSheet, - size_t iNumElements, size_t &iLoadedElements, - size_t iElementStart, size_t iElementCount); + size_t load_elements(memory_reader &input, sprite_sheet *pSpriteSheet, + size_t iNumElements, size_t &iLoadedElements, + size_t iElementStart, size_t iElementCount); //! Construct a list element for every element, and a 0xFFFF at the end. /*! - @param iFirstElement Index of the first element in #m_vElements. + @param iFirstElement Index of the first element in #elements. @param iNumElements Number of elements to add. @param [inout] iLoadedListElements Number of created list elements so far. @param iListStart Offset of the first created list element. @param iListCount Expected number of list elements to create. @return Index of the list elements, or a negative value to indicate failure. */ - size_t makeListElements(size_t iFirstElement, size_t iNumElements, - size_t &iLoadedListElements, - size_t iListStart, size_t iListCount); + size_t make_list_elements(size_t iFirstElement, size_t iNumElements, + size_t &iLoadedListElements, + size_t iListStart, size_t iListCount); //! Fix the flags of the first frame, and set the next frame of the last frame back to the first frame. /*! @param iFirst First frame of the animation, or 0xFFFFFFFFu. @param iLength Number of frames in the animation. */ - void fixNextFrame(uint32_t iFirst, size_t iLength); + void fix_next_frame(uint32_t iFirst, size_t iLength); }; -struct THMapNode; -class THAnimationBase : public THDrawable +struct map_tile; +class animation_base : public drawable { public: - THAnimationBase(); + animation_base(); - void removeFromTile(); - void attachToTile(THMapNode *pMapNode, int layer); + void remove_from_tile(); + void attach_to_tile(map_tile *pMapNode, int layer); - uint32_t getFlags() const {return m_iFlags;} - int getX() const {return m_iX;} - int getY() const {return m_iY;} - - void setFlags(uint32_t iFlags) {m_iFlags = iFlags;} - void setPosition(int iX, int iY) {m_iX = iX, m_iY = iY;} - void setLayer(int iLayer, int iId); - void setLayersFrom(const THAnimationBase *pSrc) {m_oLayers = pSrc->m_oLayers;} + uint32_t get_flags() const {return flags;} + int get_x() const {return x_relative_to_tile;} + int get_y() const {return y_relative_to_tile;} + + void set_flags(uint32_t iFlags) {flags = iFlags;} + void set_position(int iX, int iY) {x_relative_to_tile = iX, y_relative_to_tile = iY;} + void set_layer(int iLayer, int iId); + void set_layers_from(const animation_base *pSrc) {layers = pSrc->layers;} // bool isMultipleFrameAnimation() { return false;} protected: //! X position on tile (not tile x-index) - int m_iX; + int x_relative_to_tile; //! Y position on tile (not tile y-index) - int m_iY; + int y_relative_to_tile; - THLayers_t m_oLayers; + ::layers layers; }; -class THAnimation : public THAnimationBase +class animation : public animation_base { public: - THAnimation(); + animation(); - void setParent(THAnimation *pParent); + void set_parent(animation *pParent); void tick(); - void draw(THRenderTarget* pCanvas, int iDestX, int iDestY); - bool hitTest(int iDestX, int iDestY, int iTestX, int iTestY); - void drawMorph(THRenderTarget* pCanvas, int iDestX, int iDestY); - bool hitTestMorph(int iDestX, int iDestY, int iTestX, int iTestY); - void drawChild(THRenderTarget* pCanvas, int iDestX, int iDestY); - bool hitTestChild(int iDestX, int iDestY, int iTestX, int iTestY); - - THLinkList* getPrevious() {return m_pPrev;} - size_t getAnimation() const {return m_iAnimation;} - bool getMarker(int* pX, int* pY); - bool getSecondaryMarker(int* pX, int* pY); - size_t getFrame() const {return m_iFrame;} - int getCropColumn() const {return m_iCropColumn;} - - void setAnimation(THAnimationManager* pManager, size_t iAnimation); - void setMorphTarget(THAnimation *pMorphTarget, unsigned int iDurationFactor = 1); - void setFrame(size_t iFrame); + void draw(render_target* pCanvas, int iDestX, int iDestY); + bool hit_test(int iDestX, int iDestY, int iTestX, int iTestY); + void draw_morph(render_target* pCanvas, int iDestX, int iDestY); + bool hit_test_morph(int iDestX, int iDestY, int iTestX, int iTestY); + void draw_child(render_target* pCanvas, int iDestX, int iDestY); + bool hit_test_child(int iDestX, int iDestY, int iTestX, int iTestY); + + link_list* get_previous() {return prev;} + size_t get_animation() const {return animation_index;} + bool get_marker(int* pX, int* pY); + bool get_secondary_marker(int* pX, int* pY); + size_t get_frame() const {return frame_index;} + int get_crop_column() const {return crop_column;} + + void set_animation(animation_manager* pManager, size_t iAnimation); + void set_morph_target(animation *pMorphTarget, unsigned int iDurationFactor = 1); + void set_frame(size_t iFrame); - void setSpeed(int iX, int iY) {speed.x = iX, speed.y = iY;} - void setCropColumn(int iColumn) {m_iCropColumn = iColumn;} + void set_speed(int iX, int iY) {speed.dx = iX, speed.dy = iY;} + void set_crop_column(int iColumn) {crop_column = iColumn;} - void persist(LuaPersistWriter *pWriter) const; - void depersist(LuaPersistReader *pReader); + void persist(lua_persist_writer *pWriter) const; + void depersist(lua_persist_reader *pReader); - THAnimationManager* getAnimationManager(){ return m_pManager;} + animation_manager* get_animation_manager(){ return manager;} private: - THAnimationManager *m_pManager; - THAnimation* m_pMorphTarget; - size_t m_iAnimation; ///< Animation number. - size_t m_iFrame; ///< Frame number. + animation_manager *manager; + animation* morph_target; + size_t animation_index; ///< Animation number. + size_t frame_index; ///< Frame number. union { struct { - //! Amount to change m_iX per tick - int x; - //! Amount to change m_iY per tick - int y; + //! Amount to change x per tick + int dx; + //! Amount to change y per tick + int dy; } speed; //! Some animations are tied to the marker of another animation and //! hence have a parent rather than a speed. - THAnimation* m_pParent; + animation* parent; }; - size_t m_iSoundToPlay; - int m_iCropColumn; + size_t sound_to_play; + int crop_column; }; -class THSpriteRenderList : public THAnimationBase +class sprite_render_list : public animation_base { public: - THSpriteRenderList(); - ~THSpriteRenderList(); + sprite_render_list(); + ~sprite_render_list(); void tick(); - void draw(THRenderTarget* pCanvas, int iDestX, int iDestY); - bool hitTest(int iDestX, int iDestY, int iTestX, int iTestY); + void draw(render_target* pCanvas, int iDestX, int iDestY); + bool hit_test(int iDestX, int iDestY, int iTestX, int iTestY); - void setSheet(THSpriteSheet* pSheet) {m_pSpriteSheet = pSheet;} - void setSpeed(int iX, int iY) {m_iSpeedX = iX, m_iSpeedY = iY;} - void setLifetime(int iLifetime); - void appendSprite(size_t iSprite, int iX, int iY); - bool isDead() const {return m_iLifetime == 0;} + void set_sheet(sprite_sheet* pSheet) {sheet = pSheet;} + void set_speed(int iX, int iY) {dx_per_tick = iX, dy_per_tick = iY;} + void set_lifetime(int iLifetime); + void append_sprite(size_t iSprite, int iX, int iY); + bool is_dead() const {return lifetime == 0;} - void persist(LuaPersistWriter *pWriter) const; - void depersist(LuaPersistReader *pReader); + void persist(lua_persist_writer *pWriter) const; + void depersist(lua_persist_reader *pReader); private: - struct _sprite_t + struct sprite { - size_t iSprite; - int iX; - int iY; + size_t index; + int x; + int y; }; - THSpriteSheet* m_pSpriteSheet; - _sprite_t* m_pSprites; - int m_iNumSprites; - int m_iBufferSize; - - //! Amount to change m_iX per tick - int m_iSpeedX; - //! Amount to change m_iY per tick - int m_iSpeedY; + sprite_sheet* sheet; + sprite* sprites; + int sprite_count; + int buffer_size; + + //! Amount to change x per tick + int dx_per_tick; + //! Amount to change y per tick + int dy_per_tick; //! Number of ticks until reports as dead (-1 = never dies) - int m_iLifetime; + int lifetime; }; #endif // CORSIX_TH_TH_GFX_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx_sdl.cpp corsix-th-0.62/CorsixTH/Src/th_gfx_sdl.cpp --- corsix-th-0.61/CorsixTH/Src/th_gfx_sdl.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx_sdl.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -33,10 +33,10 @@ #include #include -FullColourRenderer::FullColourRenderer(int iWidth, int iHeight) : m_iWidth(iWidth), m_iHeight(iHeight) +full_colour_renderer::full_colour_renderer(int iWidth, int iHeight) : width(iWidth), height(iHeight) { - m_iX = 0; - m_iY = 0; + x = 0; + y = 0; } //! Convert a colour to an equivalent grey scale level. @@ -56,7 +56,7 @@ // 0.0722 * 65536 = 4731.6992 -> 4732 // 13933 + 46871 + 4732 = 65536 = 2**16 uint8_t iGrey = static_cast((13933 * iR + 46871 * iG + 4732 * iB) >> 16); - return THPalette::packARGB(iOpacity, iGrey, iGrey, iGrey); + return palette::pack_argb(iOpacity, iGrey, iGrey, iGrey); } //! Convert a colour by swapping red and blue channel. @@ -78,17 +78,17 @@ int iNewBlue = iR * 1063 / 361; if (iNewBlue > 255) iNewBlue = 255; - return THPalette::packARGB(iOpacity, iNewRed, iG, static_cast(iNewBlue)); + return palette::pack_argb(iOpacity, iNewRed, iG, static_cast(iNewBlue)); } -bool FullColourRenderer::decodeImage(const uint8_t* pImg, const THPalette *pPalette, uint32_t iSpriteFlags) +bool full_colour_renderer::decode_image(const uint8_t* pImg, const palette *pPalette, uint32_t iSpriteFlags) { - if (m_iWidth <= 0 || m_iHeight <= 0) + if (width <= 0 || height <= 0) return false; - iSpriteFlags &= THDF_Alt32_Mask; + iSpriteFlags &= thdf_alt32_mask; - const uint32_t* pColours = pPalette->getARGBData(); + const uint32_t* pColours = pPalette->get_argb_data(); for (;;) { uint8_t iType = *pImg++; size_t iLength = iType & 63; @@ -98,13 +98,13 @@ while (iLength > 0) { uint32_t iColour; - if (iSpriteFlags == THDF_Alt32_BlueRedSwap) + if (iSpriteFlags == thdf_alt32_blue_red_swap) iColour = makeSwapRedBlue(0xFF, pImg[0], pImg[1], pImg[2]); - else if (iSpriteFlags == THDF_Alt32_GreyScale) + else if (iSpriteFlags == thdf_alt32_grey_scale) iColour = makeGreyScale(0xFF, pImg[0], pImg[1], pImg[2]); else - iColour = THPalette::packARGB(0xFF, pImg[0], pImg[1], pImg[2]); - _pushPixel(iColour); + iColour = palette::pack_argb(0xFF, pImg[0], pImg[1], pImg[2]); + push_pixel(iColour); pImg += 3; iLength--; } @@ -116,13 +116,13 @@ while (iLength > 0) { uint32_t iColour; - if (iSpriteFlags == THDF_Alt32_BlueRedSwap) + if (iSpriteFlags == thdf_alt32_blue_red_swap) iColour = makeSwapRedBlue(0xFF, pImg[0], pImg[1], pImg[2]); - else if (iSpriteFlags == THDF_Alt32_GreyScale) + else if (iSpriteFlags == thdf_alt32_grey_scale) iColour = makeGreyScale(iOpacity, pImg[0], pImg[1], pImg[2]); else - iColour = THPalette::packARGB(iOpacity, pImg[0], pImg[1], pImg[2]); - _pushPixel(iColour); + iColour = palette::pack_argb(iOpacity, pImg[0], pImg[1], pImg[2]); + push_pixel(iColour); pImg += 3; iLength--; } @@ -131,10 +131,10 @@ case 2: // Fixed fully transparent pixels { - static const uint32_t iTransparent = THPalette::packARGB(0, 0, 0, 0); + static const uint32_t iTransparent = palette::pack_argb(0, 0, 0, 0); while (iLength > 0) { - _pushPixel(iTransparent); + push_pixel(iTransparent); iLength--; } break; @@ -150,7 +150,7 @@ // Note that the iOpacity is ignored here. while (iLength > 0) { - _pushPixel(pColours[*pImg++]); + push_pixel(pColours[*pImg++]); iLength--; } } @@ -163,8 +163,8 @@ // For now just draw black pixels, so it won't go unnoticed. while (iLength > 0) { - uint32_t iColour = THPalette::packARGB(0xFF, 0, 0, 0); - _pushPixel(iColour); + uint32_t iColour = palette::pack_argb(0xFF, 0, 0, 0); + push_pixel(iColour); iLength--; } } @@ -172,182 +172,182 @@ } } - if (m_iY >= m_iHeight) + if (y >= height) break; } - return m_iX == 0; + return x == 0; } -FullColourStoring::FullColourStoring(uint32_t *pDest, int iWidth, int iHeight) : FullColourRenderer(iWidth, iHeight) +full_colour_storing::full_colour_storing(uint32_t *pDest, int iWidth, int iHeight) : full_colour_renderer(iWidth, iHeight) { - m_pDest = pDest; + destination = pDest; } -void FullColourStoring::storeARGB(uint32_t pixel) +void full_colour_storing::store_argb(uint32_t pixel) { - *m_pDest++ = pixel; + *destination++ = pixel; } -WxStoring::WxStoring(uint8_t* pRGBData, uint8_t* pAData, int iWidth, int iHeight) : FullColourRenderer(iWidth, iHeight) +wx_storing::wx_storing(uint8_t* pRGBData, uint8_t* pAData, int iWidth, int iHeight) : full_colour_renderer(iWidth, iHeight) { - m_pRGBData = pRGBData; - m_pAData = pAData; + rgb_data = pRGBData; + alpha_data = pAData; } -void WxStoring::storeARGB(uint32_t pixel) +void wx_storing::store_argb(uint32_t pixel) { - m_pRGBData[0] = THPalette::getR(pixel); - m_pRGBData[1] = THPalette::getG(pixel); - m_pRGBData[2] = THPalette::getB(pixel); - m_pRGBData += 3; + rgb_data[0] = palette::get_red(pixel); + rgb_data[1] = palette::get_green(pixel); + rgb_data[2] = palette::get_blue(pixel); + rgb_data += 3; - *m_pAData++ = THPalette::getA(pixel); + *alpha_data++ = palette::get_alpha(pixel); } -THRenderTarget::THRenderTarget() +render_target::render_target() { - m_pWindow = nullptr; - m_pRenderer = nullptr; - m_pFormat = nullptr; - m_pCursor = nullptr; - m_pZoomTexture = nullptr; - m_bShouldScaleBitmaps = false; - m_bBlueFilterActive = false; - m_bApplyOpenGlClipFix = false; - m_iWidth = -1; - m_iHeight = -1; + window = nullptr; + renderer = nullptr; + pixel_format = nullptr; + game_cursor = nullptr; + zoom_texture = nullptr; + scale_bitmaps = false; + blue_filter_active = false; + apply_opengl_clip_fix = false; + width = -1; + height = -1; } -THRenderTarget::~THRenderTarget() +render_target::~render_target() { destroy(); } -bool THRenderTarget::create(const THRenderTargetCreationParams* pParams) +bool render_target::create(const render_target_creation_params* pParams) { - if (m_pRenderer != nullptr) + if (renderer != nullptr) return false; SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - m_pFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888); - m_pWindow = SDL_CreateWindow("CorsixTH", + pixel_format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888); + window = SDL_CreateWindow("CorsixTH", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - pParams->iWidth, pParams->iHeight, + pParams->width, pParams->height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - if (!m_pWindow) + if (!window) { return false; } - Uint32 iRendererFlags = (pParams->bPresentImmediate ? 0 : SDL_RENDERER_PRESENTVSYNC); - m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, iRendererFlags); + Uint32 iRendererFlags = (pParams->present_immediate ? 0 : SDL_RENDERER_PRESENTVSYNC); + renderer = SDL_CreateRenderer(window, -1, iRendererFlags); SDL_RendererInfo info; - SDL_GetRendererInfo(m_pRenderer, &info); - m_bSupportsTargetTextures = (info.flags & SDL_RENDERER_TARGETTEXTURE) != 0; + SDL_GetRendererInfo(renderer, &info); + supports_target_textures = (info.flags & SDL_RENDERER_TARGETTEXTURE) != 0; SDL_version sdlVersion; SDL_GetVersion(&sdlVersion); - m_bApplyOpenGlClipFix = std::strncmp(info.name, "opengl", 6) == 0 && sdlVersion.major == 2 && sdlVersion.minor == 0 && sdlVersion.patch < 4; + apply_opengl_clip_fix = std::strncmp(info.name, "opengl", 6) == 0 && sdlVersion.major == 2 && sdlVersion.minor == 0 && sdlVersion.patch < 4; return update(pParams); } -bool THRenderTarget::update(const THRenderTargetCreationParams* pParams) +bool render_target::update(const render_target_creation_params* pParams) { - if (m_pWindow == nullptr) + if (window == nullptr) { return false; } - bool bUpdateSize = (m_iWidth != pParams->iWidth) || (m_iHeight != pParams->iHeight); - m_iWidth = pParams->iWidth; - m_iHeight = pParams->iHeight; + bool bUpdateSize = (width != pParams->width) || (height != pParams->height); + width = pParams->width; + height = pParams->height; - bool bIsFullscreen = ((SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP); - if (bIsFullscreen != pParams->bFullscreen) + bool bIsFullscreen = ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP); + if (bIsFullscreen != pParams->fullscreen) { - SDL_SetWindowFullscreen(m_pWindow, (pParams->bFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); + SDL_SetWindowFullscreen(window, (pParams->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); } - if (bUpdateSize || bIsFullscreen != pParams->bFullscreen) + if (bUpdateSize || bIsFullscreen != pParams->fullscreen) { - SDL_SetWindowSize(m_pWindow, m_iWidth, m_iHeight); + SDL_SetWindowSize(window, width, height); } if (bUpdateSize) { - SDL_RenderSetLogicalSize(m_pRenderer, m_iWidth, m_iHeight); + SDL_RenderSetLogicalSize(renderer, width, height); } return true; } -void THRenderTarget::destroy() +void render_target::destroy() { - if (m_pFormat) + if (pixel_format) { - SDL_FreeFormat(m_pFormat); - m_pFormat = nullptr; + SDL_FreeFormat(pixel_format); + pixel_format = nullptr; } - if (m_pZoomTexture) + if (zoom_texture) { - SDL_DestroyTexture(m_pZoomTexture); - m_pZoomTexture = nullptr; + SDL_DestroyTexture(zoom_texture); + zoom_texture = nullptr; } - if (m_pRenderer) + if (renderer) { - SDL_DestroyRenderer(m_pRenderer); - m_pRenderer = nullptr; + SDL_DestroyRenderer(renderer); + renderer = nullptr; } - if (m_pWindow) + if (window) { - SDL_DestroyWindow(m_pWindow); - m_pWindow = nullptr; + SDL_DestroyWindow(window); + window = nullptr; } } -bool THRenderTarget::setScaleFactor(double fScale, THScaledItems eWhatToScale) +bool render_target::set_scale_factor(double fScale, scaled_items eWhatToScale) { - _flushZoomBuffer(); - m_bShouldScaleBitmaps = false; + flush_zoom_buffer(); + scale_bitmaps = false; if(fScale <= 0.000) { return false; } - else if(eWhatToScale == THSI_All && m_bSupportsTargetTextures) + else if(eWhatToScale == scaled_items::all && supports_target_textures) { - //Draw everything from now until the next scale to m_pZoomTexture + //Draw everything from now until the next scale to zoom_texture //with the appropriate virtual size, which will be copied scaled to //fit the window. - int virtWidth = static_cast(m_iWidth / fScale); - int virtHeight = static_cast(m_iHeight / fScale); + int virtWidth = static_cast(width / fScale); + int virtHeight = static_cast(height / fScale); - m_pZoomTexture = SDL_CreateTexture(m_pRenderer, - SDL_PIXELFORMAT_ABGR8888, - SDL_TEXTUREACCESS_TARGET, - virtWidth, - virtHeight - ); + zoom_texture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_ABGR8888, + SDL_TEXTUREACCESS_TARGET, + virtWidth, + virtHeight + ); - SDL_RenderSetLogicalSize(m_pRenderer, virtWidth, virtHeight); - if(SDL_SetRenderTarget(m_pRenderer, m_pZoomTexture) != 0) + SDL_RenderSetLogicalSize(renderer, virtWidth, virtHeight); + if(SDL_SetRenderTarget(renderer, zoom_texture) != 0) { std::cout << "Warning: Could not render to zoom texture - " << SDL_GetError() << std::endl; - SDL_RenderSetLogicalSize(m_pRenderer, m_iWidth, m_iHeight); - SDL_DestroyTexture(m_pZoomTexture); - m_pZoomTexture = nullptr; + SDL_RenderSetLogicalSize(renderer, width, height); + SDL_DestroyTexture(zoom_texture); + zoom_texture = nullptr; return false; } // Clear the new texture to transparent/black. - SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, SDL_ALPHA_TRANSPARENT); - SDL_RenderClear(m_pRenderer); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_TRANSPARENT); + SDL_RenderClear(renderer); return true; } @@ -355,10 +355,10 @@ { return true; } - else if(eWhatToScale == THSI_Bitmaps) + else if(eWhatToScale == scaled_items::bitmaps) { - m_bShouldScaleBitmaps = true; - m_fBitmapScaleFactor = fScale; + scale_bitmaps = true; + bitmap_scale_factor = fScale; return true; } @@ -368,112 +368,112 @@ } } -void THRenderTarget::setCaption(const char* sCaption) +void render_target::set_caption(const char* sCaption) { - SDL_SetWindowTitle(m_pWindow, sCaption); + SDL_SetWindowTitle(window, sCaption); } -const char *THRenderTarget::getRendererDetails() const +const char *render_target::get_renderer_details() const { SDL_RendererInfo info = {}; - SDL_GetRendererInfo(m_pRenderer, &info); + SDL_GetRendererInfo(renderer, &info); return info.name; } -const char* THRenderTarget::getLastError() +const char* render_target::get_last_error() { return SDL_GetError(); } -bool THRenderTarget::startFrame() +bool render_target::start_frame() { - fillBlack(); + fill_black(); return true; } -bool THRenderTarget::endFrame() +bool render_target::end_frame() { - _flushZoomBuffer(); + flush_zoom_buffer(); // End the frame by adding the cursor and possibly a filter. - if(m_pCursor) + if(game_cursor) { - m_pCursor->draw(this, m_iCursorX, m_iCursorY); + game_cursor->draw(this, cursor_x, cursor_y); } - if(m_bBlueFilterActive) + if(blue_filter_active) { - SDL_SetRenderDrawBlendMode(m_pRenderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(m_pRenderer, 51, 51, 255, 128); // r=0.2, g=0.2, b=1, a=0.5 . - SDL_RenderFillRect(m_pRenderer, nullptr); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, 51, 51, 255, 128); // r=0.2, g=0.2, b=1, a=0.5 . + SDL_RenderFillRect(renderer, nullptr); } - SDL_RenderPresent(m_pRenderer); + SDL_RenderPresent(renderer); return true; } -bool THRenderTarget::fillBlack() +bool render_target::fill_black() { - SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderClear(m_pRenderer); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + SDL_RenderClear(renderer); return true; } -void THRenderTarget::setBlueFilterActive(bool bActivate) +void render_target::set_blue_filter_active(bool bActivate) { - m_bBlueFilterActive = bActivate; + blue_filter_active = bActivate; } // Actiate and Deactivate SDL function to capture mouse to window -void THRenderTarget::setWindowGrab(bool bActivate) +void render_target::set_window_grab(bool bActivate) { - SDL_SetWindowGrab(m_pWindow, bActivate ? SDL_TRUE : SDL_FALSE); + SDL_SetWindowGrab(window, bActivate ? SDL_TRUE : SDL_FALSE); } -uint32_t THRenderTarget::mapColour(uint8_t iR, uint8_t iG, uint8_t iB) +uint32_t render_target::map_colour(uint8_t iR, uint8_t iG, uint8_t iB) { - return THPalette::packARGB(0xFF, iR, iG, iB); + return palette::pack_argb(0xFF, iR, iG, iB); } -bool THRenderTarget::fillRect(uint32_t iColour, int iX, int iY, int iW, int iH) +bool render_target::fill_rect(uint32_t iColour, int iX, int iY, int iW, int iH) { SDL_Rect rcDest = { iX, iY, iW, iH }; Uint8 r, g, b, a; - SDL_GetRGBA(iColour, m_pFormat, &r, &g, &b, &a); + SDL_GetRGBA(iColour, pixel_format, &r, &g, &b, &a); - SDL_SetRenderDrawBlendMode(m_pRenderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(m_pRenderer, r, g, b, a); - SDL_RenderFillRect(m_pRenderer, &rcDest); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, r, g, b, a); + SDL_RenderFillRect(renderer, &rcDest); return true; } -void THRenderTarget::getClipRect(THClipRect* pRect) const +void render_target::get_clip_rect(clip_rect* pRect) const { - SDL_RenderGetClipRect(m_pRenderer, reinterpret_cast(pRect)); + SDL_RenderGetClipRect(renderer, reinterpret_cast(pRect)); // SDL returns empty rect when clipping is disabled -> return full rect for CTH if (SDL_RectEmpty(pRect)) { pRect->x = pRect->y = 0; - pRect->w = m_iWidth; - pRect->h = m_iHeight; + pRect->w = width; + pRect->h = height; } - if(m_bApplyOpenGlClipFix) + if(apply_opengl_clip_fix) { int renderWidth, renderHeight; - SDL_RenderGetLogicalSize(m_pRenderer, &renderWidth, &renderHeight); + SDL_RenderGetLogicalSize(renderer, &renderWidth, &renderHeight); pRect->y = renderHeight - pRect->y - pRect->h; } } -void THRenderTarget::setClipRect(const THClipRect* pRect) +void render_target::set_clip_rect(const clip_rect* pRect) { // Full clip rect for CTH means clipping disabled - if (pRect == nullptr || (pRect->w == m_iWidth && pRect->h == m_iHeight)) + if (pRect == nullptr || (pRect->w == width && pRect->h == height)) { - SDL_RenderSetClipRect(m_pRenderer, nullptr); + SDL_RenderSetClipRect(renderer, nullptr); return; } @@ -492,55 +492,55 @@ SDLRect = rcBogus; } - if(m_bApplyOpenGlClipFix) + if(apply_opengl_clip_fix) { int renderWidth, renderHeight; - SDL_RenderGetLogicalSize(m_pRenderer, &renderWidth, &renderHeight); + SDL_RenderGetLogicalSize(renderer, &renderWidth, &renderHeight); SDLRect.y = renderHeight - SDLRect.y - SDLRect.h; } - SDL_RenderSetClipRect(m_pRenderer, &SDLRect); + SDL_RenderSetClipRect(renderer, &SDLRect); } -int THRenderTarget::getWidth() const +int render_target::get_width() const { int w; - SDL_RenderGetLogicalSize(m_pRenderer, &w, nullptr); + SDL_RenderGetLogicalSize(renderer, &w, nullptr); return w; } -int THRenderTarget::getHeight() const +int render_target::get_height() const { int h; - SDL_RenderGetLogicalSize(m_pRenderer, nullptr, &h); + SDL_RenderGetLogicalSize(renderer, nullptr, &h); return h; } -void THRenderTarget::startNonOverlapping() +void render_target::start_nonoverlapping_draws() { // SDL has no optimisations for drawing lots of non-overlapping sprites } -void THRenderTarget::finishNonOverlapping() +void render_target::finish_nonoverlapping_draws() { // SDL has no optimisations for drawing lots of non-overlapping sprites } -void THRenderTarget::setCursor(THCursor* pCursor) +void render_target::set_cursor(cursor* pCursor) { - m_pCursor = pCursor; + game_cursor = pCursor; } -void THRenderTarget::setCursorPosition(int iX, int iY) +void render_target::set_cursor_position(int iX, int iY) { - m_iCursorX = iX; - m_iCursorY = iY; + cursor_x = iX; + cursor_y = iY; } -bool THRenderTarget::takeScreenshot(const char* sFile) +bool render_target::take_screenshot(const char* sFile) { int width = 0, height = 0; - if (SDL_GetRendererOutputSize(m_pRenderer, &width, &height) == -1) + if (SDL_GetRendererOutputSize(renderer, &width, &height) == -1) return false; // Create a window-sized surface, RGB format (0 Rmask means RGB.) @@ -553,7 +553,7 @@ { // Ask the renderer to (slowly) fill the surface with renderer // output data. - readStatus = SDL_RenderReadPixels(m_pRenderer, + readStatus = SDL_RenderReadPixels(renderer, nullptr, pRgbSurface->format->format, pRgbSurface->pixels, @@ -570,25 +570,25 @@ } -bool THRenderTarget::shouldScaleBitmaps(double* pFactor) +bool render_target::should_scale_bitmaps(double* pFactor) { - if(!m_bShouldScaleBitmaps) + if(!scale_bitmaps) return false; if(pFactor) - *pFactor = m_fBitmapScaleFactor; + *pFactor = bitmap_scale_factor; return true; } -void THRenderTarget::_flushZoomBuffer() +void render_target::flush_zoom_buffer() { - if(m_pZoomTexture == nullptr) { return; } + if(zoom_texture == nullptr) { return; } - SDL_SetRenderTarget(m_pRenderer, nullptr); - SDL_RenderSetLogicalSize(m_pRenderer, m_iWidth, m_iHeight); - SDL_SetTextureBlendMode(m_pZoomTexture, SDL_BLENDMODE_BLEND); - SDL_RenderCopy(m_pRenderer, m_pZoomTexture, nullptr, nullptr); - SDL_DestroyTexture(m_pZoomTexture); - m_pZoomTexture = nullptr; + SDL_SetRenderTarget(renderer, nullptr); + SDL_RenderSetLogicalSize(renderer, width, height); + SDL_SetTextureBlendMode(zoom_texture, SDL_BLENDMODE_BLEND); + SDL_RenderCopy(renderer, zoom_texture, nullptr, nullptr); + SDL_DestroyTexture(zoom_texture); + zoom_texture = nullptr; } //! Convert legacy 8bpp sprite data to recoloured 32bpp data, using special recolour table 0xFF. @@ -624,28 +624,28 @@ return pData; } -SDL_Texture* THRenderTarget::createPalettizedTexture( +SDL_Texture* render_target::create_palettized_texture( int iWidth, int iHeight, const uint8_t* pPixels, - const THPalette* pPalette, uint32_t iSpriteFlags) const + const palette* pPalette, uint32_t iSpriteFlags) const { uint32_t *pARGBPixels = new (std::nothrow) uint32_t[iWidth * iHeight]; if(pARGBPixels == nullptr) return 0; - FullColourStoring oRenderer(pARGBPixels, iWidth, iHeight); - bool bOk = oRenderer.decodeImage(pPixels, pPalette, iSpriteFlags); + full_colour_storing oRenderer(pARGBPixels, iWidth, iHeight); + bool bOk = oRenderer.decode_image(pPixels, pPalette, iSpriteFlags); if (!bOk) return 0; - SDL_Texture *pTexture = createTexture(iWidth, iHeight, pARGBPixels); + SDL_Texture *pTexture = create_texture(iWidth, iHeight, pARGBPixels); delete [] pARGBPixels; return pTexture; } -SDL_Texture* THRenderTarget::createTexture(int iWidth, int iHeight, +SDL_Texture* render_target::create_texture(int iWidth, int iHeight, const uint32_t* pPixels) const { - SDL_Texture *pTexture = SDL_CreateTexture(m_pRenderer, m_pFormat->format, SDL_TEXTUREACCESS_STATIC, iWidth, iHeight); + SDL_Texture *pTexture = SDL_CreateTexture(renderer, pixel_format->format, SDL_TEXTUREACCESS_STATIC, iWidth, iHeight); SDL_UpdateTexture(pTexture, nullptr, pPixels, static_cast(sizeof(*pPixels) * iWidth)); SDL_SetTextureBlendMode(pTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureColorMod(pTexture, 0xFF, 0xFF, 0xFF); @@ -654,59 +654,59 @@ return pTexture; } -void THRenderTarget::draw(SDL_Texture *pTexture, const SDL_Rect *prcSrcRect, const SDL_Rect *prcDstRect, int iFlags) +void render_target::draw(SDL_Texture *pTexture, const SDL_Rect *prcSrcRect, const SDL_Rect *prcDstRect, int iFlags) { SDL_SetTextureAlphaMod(pTexture, 0xFF); - if (iFlags & THDF_Alpha50) + if (iFlags & thdf_alpha_50) { SDL_SetTextureAlphaMod(pTexture, 0x80); } - else if (iFlags & THDF_Alpha75) + else if (iFlags & thdf_alpha_75) { SDL_SetTextureAlphaMod(pTexture, 0x40); } int iSDLFlip = SDL_FLIP_NONE; - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) iSDLFlip |= SDL_FLIP_HORIZONTAL; - if (iFlags & THDF_FlipVertical) + if (iFlags & thdf_flip_vertical) iSDLFlip |= SDL_FLIP_VERTICAL; if (iSDLFlip != 0) { - SDL_RenderCopyEx(m_pRenderer, pTexture, prcSrcRect, prcDstRect, 0, nullptr, (SDL_RendererFlip)iSDLFlip); + SDL_RenderCopyEx(renderer, pTexture, prcSrcRect, prcDstRect, 0, nullptr, (SDL_RendererFlip)iSDLFlip); } else { - SDL_RenderCopy(m_pRenderer, pTexture, prcSrcRect, prcDstRect); + SDL_RenderCopy(renderer, pTexture, prcSrcRect, prcDstRect); } } -void THRenderTarget::drawLine(THLine *pLine, int iX, int iY) +void render_target::draw_line(line *pLine, int iX, int iY) { - SDL_SetRenderDrawColor(m_pRenderer, pLine->m_iR, pLine->m_iG, pLine->m_iB, pLine->m_iA); + SDL_SetRenderDrawColor(renderer, pLine->red, pLine->green, pLine->blue, pLine->alpha); double lastX, lastY; - lastX = pLine->m_pFirstOp->m_fX; - lastY = pLine->m_pFirstOp->m_fY; + lastX = pLine->first_operation->x; + lastY = pLine->first_operation->y; - THLine::THLineOperation* op = (THLine::THLineOperation*)(pLine->m_pFirstOp->m_pNext); + line::line_operation* op = (line::line_operation*)(pLine->first_operation->next); while (op) { - if (op->type == THLine::THLOP_LINE) { - SDL_RenderDrawLine(m_pRenderer, static_cast(lastX + iX), + if (op->type == line::line_operation_type::line) { + SDL_RenderDrawLine(renderer, static_cast(lastX + iX), static_cast(lastY + iY), - static_cast(op->m_fX + iX), - static_cast(op->m_fY + iY)); + static_cast(op->x + iX), + static_cast(op->y + iY)); } - lastX = op->m_fX; - lastY = op->m_fY; + lastX = op->x; + lastY = op->y; - op = (THLine::THLineOperation*)(op->m_pNext); + op = (line::line_operation*)(op->next); } } -THPalette::THPalette() +palette::palette() { - m_iNumColours = 0; + colour_count = 0; } static const uint8_t gs_iTHColourLUT[0x40] = { @@ -721,90 +721,92 @@ 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF, }; -bool THPalette::loadFromTHFile(const uint8_t* pData, size_t iDataLength) +bool palette::load_from_th_file(const uint8_t* pData, size_t iDataLength) { if(iDataLength != 256 * 3) return false; - m_iNumColours = static_cast(iDataLength / 3); - for(int i = 0; i < m_iNumColours; ++i, pData += 3) + colour_count = static_cast(iDataLength / 3); + for(int i = 0; i < colour_count; ++i, pData += 3) { uint8_t iR = gs_iTHColourLUT[pData[0] & 0x3F]; uint8_t iG = gs_iTHColourLUT[pData[1] & 0x3F]; uint8_t iB = gs_iTHColourLUT[pData[2] & 0x3F]; - uint32_t iColour = packARGB(0xFF, iR, iG, iB); + uint32_t iColour = pack_argb(0xFF, iR, iG, iB); // Remap magenta to transparent - if(iColour == packARGB(0xFF, 0xFF, 0x00, 0xFF)) - iColour = packARGB(0x00, 0x00, 0x00, 0x00); - m_aColoursARGB[i] = iColour; + if(iColour == pack_argb(0xFF, 0xFF, 0x00, 0xFF)) + iColour = pack_argb(0x00, 0x00, 0x00, 0x00); + colour_index_to_argb_map[i] = iColour; } return true; } -bool THPalette::setEntry(int iEntry, uint8_t iR, uint8_t iG, uint8_t iB) +bool palette::set_entry(int iEntry, uint8_t iR, uint8_t iG, uint8_t iB) { - if(iEntry < 0 || iEntry >= m_iNumColours) + if(iEntry < 0 || iEntry >= colour_count) return false; - uint32_t iColour = packARGB(0xFF, iR, iG, iB); + uint32_t iColour = pack_argb(0xFF, iR, iG, iB); // Remap magenta to transparent - if(iColour == packARGB(0xFF, 0xFF, 0x00, 0xFF)) - iColour = packARGB(0x00, 0x00, 0x00, 0x00); - m_aColoursARGB[iEntry] = iColour; + if(iColour == pack_argb(0xFF, 0xFF, 0x00, 0xFF)) + iColour = pack_argb(0x00, 0x00, 0x00, 0x00); + colour_index_to_argb_map[iEntry] = iColour; return true; } -int THPalette::getColourCount() const +int palette::get_colour_count() const { - return m_iNumColours; + return colour_count; } -const uint32_t* THPalette::getARGBData() const +const uint32_t* palette::get_argb_data() const { - return m_aColoursARGB; + return colour_index_to_argb_map; } -THRawBitmap::THRawBitmap() +raw_bitmap::raw_bitmap() { - m_pTexture = nullptr; - m_pPalette = nullptr; - m_pTarget = nullptr; - m_iWidth = 0; - m_iHeight = 0; + texture = nullptr; + bitmap_palette = nullptr; + target = nullptr; + width = 0; + height = 0; } -THRawBitmap::~THRawBitmap() +raw_bitmap::~raw_bitmap() { - if (m_pTexture) + if (texture) { - SDL_DestroyTexture(m_pTexture); + SDL_DestroyTexture(texture); } } -void THRawBitmap::setPalette(const THPalette* pPalette) +void raw_bitmap::set_palette(const palette* pPalette) { - m_pPalette = pPalette; + bitmap_palette = pPalette; } -bool THRawBitmap::loadFromTHFile(const uint8_t* pPixelData, +bool raw_bitmap::load_from_th_file(const uint8_t* pPixelData, size_t iPixelDataLength, int iWidth, - THRenderTarget *pEventualCanvas) + render_target *pEventualCanvas) { if(pEventualCanvas == nullptr) return false; - pPixelData = convertLegacySprite(pPixelData, iPixelDataLength); - if (pPixelData == nullptr) + uint8_t* converted_sprite = convertLegacySprite(pPixelData, iPixelDataLength); + if (converted_sprite == nullptr) return false; int iHeight = static_cast(iPixelDataLength) / iWidth; - m_pTexture = pEventualCanvas->createPalettizedTexture(iWidth, iHeight, pPixelData, m_pPalette, THDF_Alt32_Plain); - if(!m_pTexture) + texture = pEventualCanvas->create_palettized_texture(iWidth, iHeight, converted_sprite, bitmap_palette, thdf_alt32_plain); + delete[] converted_sprite; + + if(!texture) return false; - m_iWidth = iWidth; - m_iHeight = iHeight; - m_pTarget = pEventualCanvas; + width = iWidth; + height = iHeight; + target = pEventualCanvas; return true; } @@ -876,19 +878,19 @@ return iDataLength == 0; } -void THRawBitmap::draw(THRenderTarget* pCanvas, int iX, int iY) +void raw_bitmap::draw(render_target* pCanvas, int iX, int iY) { - draw(pCanvas, iX, iY, 0, 0, m_iWidth, m_iHeight); + draw(pCanvas, iX, iY, 0, 0, width, height); } -void THRawBitmap::draw(THRenderTarget* pCanvas, int iX, int iY, - int iSrcX, int iSrcY, int iWidth, int iHeight) +void raw_bitmap::draw(render_target* pCanvas, int iX, int iY, + int iSrcX, int iSrcY, int iWidth, int iHeight) { double fScaleFactor; - if (m_pTexture == nullptr) + if (texture == nullptr) return; - if(!pCanvas->shouldScaleBitmaps(&fScaleFactor)) + if(!pCanvas->should_scale_bitmaps(&fScaleFactor)) { fScaleFactor = 1; } @@ -899,136 +901,136 @@ static_cast(iWidth * fScaleFactor), static_cast(iHeight * fScaleFactor) }; - pCanvas->draw(m_pTexture, &rcSrc, &rcDest, 0); + pCanvas->draw(texture, &rcSrc, &rcDest, 0); } -THSpriteSheet::THSpriteSheet() +sprite_sheet::sprite_sheet() { - m_pSprites = nullptr; - m_pPalette = nullptr; - m_pTarget = nullptr; - m_iSpriteCount = 0; + sprites = nullptr; + palette = nullptr; + target = nullptr; + sprite_count = 0; } -THSpriteSheet::~THSpriteSheet() +sprite_sheet::~sprite_sheet() { _freeSprites(); } -void THSpriteSheet::_freeSingleSprite(size_t iNumber) +void sprite_sheet::_freeSingleSprite(size_t iNumber) { - if (iNumber >= m_iSpriteCount) + if (iNumber >= sprite_count) return; - if (m_pSprites[iNumber].pTexture != nullptr) + if (sprites[iNumber].texture != nullptr) { - SDL_DestroyTexture(m_pSprites[iNumber].pTexture); - m_pSprites[iNumber].pTexture = nullptr; + SDL_DestroyTexture(sprites[iNumber].texture); + sprites[iNumber].texture = nullptr; } - if (m_pSprites[iNumber].pAltTexture != nullptr) + if (sprites[iNumber].alt_texture != nullptr) { - SDL_DestroyTexture(m_pSprites[iNumber].pAltTexture); - m_pSprites[iNumber].pAltTexture = nullptr; + SDL_DestroyTexture(sprites[iNumber].alt_texture); + sprites[iNumber].alt_texture = nullptr; } - if(m_pSprites[iNumber].pData != nullptr) + if(sprites[iNumber].data != nullptr) { - delete[] m_pSprites[iNumber].pData; - m_pSprites[iNumber].pData = nullptr; + delete[] sprites[iNumber].data; + sprites[iNumber].data = nullptr; } } -void THSpriteSheet::_freeSprites() +void sprite_sheet::_freeSprites() { - for(size_t i = 0; i < m_iSpriteCount; ++i) + for(size_t i = 0; i < sprite_count; ++i) _freeSingleSprite(i); - delete[] m_pSprites; - m_pSprites = nullptr; - m_iSpriteCount = 0; + delete[] sprites; + sprites = nullptr; + sprite_count = 0; } -void THSpriteSheet::setPalette(const THPalette* pPalette) +void sprite_sheet::set_palette(const ::palette* pPalette) { - m_pPalette = pPalette; + palette = pPalette; } -bool THSpriteSheet::setSpriteCount(size_t iCount, THRenderTarget* pCanvas) +bool sprite_sheet::set_sprite_count(size_t iCount, render_target* pCanvas) { _freeSprites(); if(pCanvas == nullptr) return false; - m_pTarget = pCanvas; + target = pCanvas; - m_iSpriteCount = iCount; - m_pSprites = new (std::nothrow) sprite_t[m_iSpriteCount]; - if(m_pSprites == nullptr) + sprite_count = iCount; + sprites = new (std::nothrow) sprite[sprite_count]; + if(sprites == nullptr) { - m_iSpriteCount = 0; + sprite_count = 0; return false; } - for (size_t i = 0; i < m_iSpriteCount; i++) + for (size_t i = 0; i < sprite_count; i++) { - sprite_t &spr = m_pSprites[i]; - spr.pTexture = nullptr; - spr.pAltTexture = nullptr; - spr.pData = nullptr; - spr.pAltPaletteMap = nullptr; - spr.iSpriteFlags = THDF_Alt32_Plain; - spr.iWidth = 0; - spr.iHeight = 0; + sprite &spr = sprites[i]; + spr.texture = nullptr; + spr.alt_texture = nullptr; + spr.data = nullptr; + spr.alt_palette_map = nullptr; + spr.sprite_flags = thdf_alt32_plain; + spr.width = 0; + spr.height = 0; } return true; } -bool THSpriteSheet::loadFromTHFile(const uint8_t* pTableData, size_t iTableDataLength, - const uint8_t* pChunkData, size_t iChunkDataLength, - bool bComplexChunks, THRenderTarget* pCanvas) +bool sprite_sheet::load_from_th_file(const uint8_t* pTableData, size_t iTableDataLength, + const uint8_t* pChunkData, size_t iChunkDataLength, + bool bComplexChunks, render_target* pCanvas) { _freeSprites(); if(pCanvas == nullptr) return false; - size_t iCount = iTableDataLength / sizeof(th_sprite_t); - if (!setSpriteCount(iCount, pCanvas)) + size_t iCount = iTableDataLength / sizeof(th_sprite_properties); + if (!set_sprite_count(iCount, pCanvas)) return false; - for(size_t i = 0; i < m_iSpriteCount; ++i) + for(size_t i = 0; i < sprite_count; ++i) { - sprite_t *pSprite = m_pSprites + i; - const th_sprite_t *pTHSprite = reinterpret_cast(pTableData) + i; + sprite *pSprite = sprites + i; + const th_sprite_properties *pTHSprite = reinterpret_cast(pTableData) + i; - pSprite->pTexture = nullptr; - pSprite->pAltTexture = nullptr; - pSprite->pData = nullptr; - pSprite->pAltPaletteMap = nullptr; - pSprite->iWidth = pTHSprite->width; - pSprite->iHeight = pTHSprite->height; + pSprite->texture = nullptr; + pSprite->alt_texture = nullptr; + pSprite->data = nullptr; + pSprite->alt_palette_map = nullptr; + pSprite->width = pTHSprite->width; + pSprite->height = pTHSprite->height; - if(pSprite->iWidth == 0 || pSprite->iHeight == 0) + if(pSprite->width == 0 || pSprite->height == 0) continue; { - uint8_t *pData = new uint8_t[pSprite->iWidth * pSprite->iHeight]; - THChunkRenderer oRenderer(pSprite->iWidth, pSprite->iHeight, pData); + uint8_t *pData = new uint8_t[pSprite->width * pSprite->height]; + chunk_renderer oRenderer(pSprite->width, pSprite->height, pData); int iDataLen = static_cast(iChunkDataLength) - static_cast(pTHSprite->position); if(iDataLen < 0) iDataLen = 0; - oRenderer.decodeChunks(pChunkData + pTHSprite->position, iDataLen, bComplexChunks); - pData = oRenderer.takeData(); - pSprite->pData = convertLegacySprite(pData, pSprite->iWidth * pSprite->iHeight); + oRenderer.decode_chunks(pChunkData + pTHSprite->position, iDataLen, bComplexChunks); + pData = oRenderer.take_data(); + pSprite->data = convertLegacySprite(pData, pSprite->width * pSprite->height); delete[] pData; } } return true; } -bool THSpriteSheet::setSpriteData(size_t iSprite, const uint8_t *pData, bool bTakeData, - size_t iDataLength, int iWidth, int iHeight) +bool sprite_sheet::set_sprite_data(size_t iSprite, const uint8_t *pData, bool bTakeData, + size_t iDataLength, int iWidth, int iHeight) { - if (iSprite >= m_iSpriteCount) + if (iSprite >= sprite_count) return false; if (!testSprite(pData, iDataLength, iWidth, iHeight)) @@ -1038,10 +1040,10 @@ } _freeSingleSprite(iSprite); - sprite_t *pSprite = m_pSprites + iSprite; + sprite *pSprite = sprites + iSprite; if (bTakeData) { - pSprite->pData = pData; + pSprite->data = pData; } else { @@ -1050,71 +1052,71 @@ return false; std::memcpy(pNewData, pData, iDataLength); - pSprite->pData = pNewData; + pSprite->data = pNewData; } - pSprite->iWidth = iWidth; - pSprite->iHeight = iHeight; + pSprite->width = iWidth; + pSprite->height = iHeight; return true; } -void THSpriteSheet::setSpriteAltPaletteMap(size_t iSprite, const uint8_t* pMap, uint32_t iAlt32) +void sprite_sheet::set_sprite_alt_palette_map(size_t iSprite, const uint8_t* pMap, uint32_t iAlt32) { - if(iSprite >= m_iSpriteCount) + if(iSprite >= sprite_count) return; - sprite_t *pSprite = m_pSprites + iSprite; - if(pSprite->pAltPaletteMap != pMap) + sprite *pSprite = sprites + iSprite; + if(pSprite->alt_palette_map != pMap) { - pSprite->pAltPaletteMap = pMap; - pSprite->iSpriteFlags = iAlt32; - if(pSprite->pAltTexture) + pSprite->alt_palette_map = pMap; + pSprite->sprite_flags = iAlt32; + if(pSprite->alt_texture) { - SDL_DestroyTexture(pSprite->pAltTexture); - pSprite->pAltTexture = nullptr; + SDL_DestroyTexture(pSprite->alt_texture); + pSprite->alt_texture = nullptr; } } } -size_t THSpriteSheet::getSpriteCount() const +size_t sprite_sheet::get_sprite_count() const { - return m_iSpriteCount; + return sprite_count; } -bool THSpriteSheet::getSpriteSize(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const +bool sprite_sheet::get_sprite_size(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const { - if(iSprite >= m_iSpriteCount) + if(iSprite >= sprite_count) return false; if(pWidth != nullptr) - *pWidth = m_pSprites[iSprite].iWidth; + *pWidth = sprites[iSprite].width; if(pHeight != nullptr) - *pHeight = m_pSprites[iSprite].iHeight; + *pHeight = sprites[iSprite].height; return true; } -void THSpriteSheet::getSpriteSizeUnchecked(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const +void sprite_sheet::get_sprite_size_unchecked(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const { - *pWidth = m_pSprites[iSprite].iWidth; - *pHeight = m_pSprites[iSprite].iHeight; + *pWidth = sprites[iSprite].width; + *pHeight = sprites[iSprite].height; } -bool THSpriteSheet::getSpriteAverageColour(size_t iSprite, THColour* pColour) const +bool sprite_sheet::get_sprite_average_colour(size_t iSprite, argb_colour* pColour) const { - if(iSprite >= m_iSpriteCount) + if(iSprite >= sprite_count) return false; - const sprite_t *pSprite = m_pSprites + iSprite; + const sprite *pSprite = sprites + iSprite; int iCountTotal = 0; int iUsageCounts[256] = {0}; - for(long i = 0; i < pSprite->iWidth * pSprite->iHeight; ++i) + for(long i = 0; i < pSprite->width * pSprite->height; ++i) { - uint8_t cPalIndex = pSprite->pData[i]; - uint32_t iColour = m_pPalette->getARGBData()[cPalIndex]; + uint8_t cPalIndex = pSprite->data[i]; + uint32_t iColour = palette->get_argb_data()[cPalIndex]; if((iColour >> 24) == 0) continue; // Grant higher score to pixels with high or low intensity (helps avoid grey fonts) - int iR = THPalette::getR(iColour); - int iG = THPalette::getG(iColour); - int iB = THPalette::getB(iColour); + int iR = palette::get_red(iColour); + int iG = palette::get_green(iColour); + int iB = palette::get_blue(iColour); uint8_t cIntensity = static_cast((iR + iG + iB) / 3); int iScore = 1 + std::max(0, 3 - ((255 - cIntensity) / 32)) + std::max(0, 3 - (cIntensity / 32)); iUsageCounts[cPalIndex] += iScore; @@ -1128,31 +1130,31 @@ if(iUsageCounts[i] > iUsageCounts[iHighestCountIndex]) iHighestCountIndex = i; } - *pColour = m_pPalette->getARGBData()[iHighestCountIndex]; + *pColour = palette->get_argb_data()[iHighestCountIndex]; return true; } -void THSpriteSheet::drawSprite(THRenderTarget* pCanvas, size_t iSprite, int iX, int iY, uint32_t iFlags) +void sprite_sheet::draw_sprite(render_target* pCanvas, size_t iSprite, int iX, int iY, uint32_t iFlags) { - if(iSprite >= m_iSpriteCount || pCanvas == nullptr || pCanvas != m_pTarget) + if(iSprite >= sprite_count || pCanvas == nullptr || pCanvas != target) return; - sprite_t &sprite = m_pSprites[iSprite]; + sprite &sprite = sprites[iSprite]; // Find or create the texture - SDL_Texture *pTexture = sprite.pTexture; + SDL_Texture *pTexture = sprite.texture; if(!pTexture) { - if(sprite.pData == nullptr) + if(sprite.data == nullptr) return; - uint32_t iSprFlags = (sprite.iSpriteFlags & ~THDF_Alt32_Mask) | THDF_Alt32_Plain; - pTexture = m_pTarget->createPalettizedTexture(sprite.iWidth, sprite.iHeight, - sprite.pData, m_pPalette, iSprFlags); - sprite.pTexture = pTexture; + uint32_t iSprFlags = (sprite.sprite_flags & ~thdf_alt32_mask) | thdf_alt32_plain; + pTexture = target->create_palettized_texture(sprite.width, sprite.height, + sprite.data, palette, iSprFlags); + sprite.texture = pTexture; } - if(iFlags & THDF_AltPalette) + if(iFlags & thdf_alt_palette) { - pTexture = sprite.pAltTexture; + pTexture = sprite.alt_texture; if(!pTexture) { pTexture = _makeAltBitmap(&sprite); @@ -1161,51 +1163,51 @@ } } - SDL_Rect rcSrc = { 0, 0, sprite.iWidth, sprite.iHeight }; - SDL_Rect rcDest = { iX, iY, sprite.iWidth, sprite.iHeight }; + SDL_Rect rcSrc = { 0, 0, sprite.width, sprite.height }; + SDL_Rect rcDest = { iX, iY, sprite.width, sprite.height }; pCanvas->draw(pTexture, &rcSrc, &rcDest, iFlags); } -void THSpriteSheet::wxDrawSprite(size_t iSprite, uint8_t* pRGBData, uint8_t* pAData) +void sprite_sheet::wx_draw_sprite(size_t iSprite, uint8_t* pRGBData, uint8_t* pAData) { - if(iSprite >= m_iSpriteCount || pRGBData == nullptr || pAData == nullptr) + if(iSprite >= sprite_count || pRGBData == nullptr || pAData == nullptr) return; - sprite_t *pSprite = m_pSprites + iSprite; + sprite *pSprite = sprites + iSprite; - WxStoring oRenderer(pRGBData, pAData, pSprite->iWidth, pSprite->iHeight); - oRenderer.decodeImage(pSprite->pData, m_pPalette, pSprite->iSpriteFlags); + wx_storing oRenderer(pRGBData, pAData, pSprite->width, pSprite->height); + oRenderer.decode_image(pSprite->data, palette, pSprite->sprite_flags); } -SDL_Texture* THSpriteSheet::_makeAltBitmap(sprite_t *pSprite) +SDL_Texture* sprite_sheet::_makeAltBitmap(sprite *pSprite) { - const uint32_t *pPalette = m_pPalette->getARGBData(); + const uint32_t *pPalette = palette->get_argb_data(); - if (!pSprite->pAltPaletteMap) // Use normal palette. + if (!pSprite->alt_palette_map) // Use normal palette. { - uint32_t iSprFlags = (pSprite->iSpriteFlags & ~THDF_Alt32_Mask) | THDF_Alt32_Plain; - pSprite->pAltTexture = m_pTarget->createPalettizedTexture(pSprite->iWidth, pSprite->iHeight, - pSprite->pData, m_pPalette, iSprFlags); + uint32_t iSprFlags = (pSprite->sprite_flags & ~thdf_alt32_mask) | thdf_alt32_plain; + pSprite->alt_texture = target->create_palettized_texture(pSprite->width, pSprite->height, + pSprite->data, palette, iSprFlags); } else if (!pPalette) // Draw alternative palette, but no palette set (ie 32bpp image). { - pSprite->pAltTexture = m_pTarget->createPalettizedTexture(pSprite->iWidth, pSprite->iHeight, - pSprite->pData, m_pPalette, pSprite->iSpriteFlags); + pSprite->alt_texture = target->create_palettized_texture(pSprite->width, pSprite->height, + pSprite->data, palette, pSprite->sprite_flags); } else // Paletted image, build recolour palette. { - THPalette oPalette; + ::palette oPalette; for (int iColour = 0; iColour < 255; iColour++) { - oPalette.setARGB(iColour, pPalette[pSprite->pAltPaletteMap[iColour]]); + oPalette.set_argb(iColour, pPalette[pSprite->alt_palette_map[iColour]]); } - oPalette.setARGB(255, pPalette[255]); // Colour 0xFF doesn't get remapped. + oPalette.set_argb(255, pPalette[255]); // Colour 0xFF doesn't get remapped. - pSprite->pAltTexture = m_pTarget->createPalettizedTexture(pSprite->iWidth, pSprite->iHeight, - pSprite->pData, &oPalette, pSprite->iSpriteFlags); + pSprite->alt_texture = target->create_palettized_texture(pSprite->width, pSprite->height, + pSprite->data, &oPalette, pSprite->sprite_flags); } - return pSprite->pAltTexture; + return pSprite->alt_texture; } /** @@ -1217,12 +1219,12 @@ * @param iPixelNumber Number of the pixel to retrieve. */ static uint32_t get32BppPixel(const uint8_t* pImg, int iWidth, int iHeight, - const THPalette *pPalette, size_t iPixelNumber) + const ::palette *pPalette, size_t iPixelNumber) { if (iWidth <= 0 || iHeight <= 0 || iPixelNumber < 0 || iPixelNumber >= static_cast(iWidth) * iHeight) { - return THPalette::packARGB(0, 0, 0,0); + return palette::pack_argb(0, 0, 0,0); } for (;;) { @@ -1241,7 +1243,7 @@ while (iLength > 0) { if (iPixelNumber == 0) - return THPalette::packARGB(0xFF, pImg[0], pImg[1], pImg[2]); + return palette::pack_argb(0xFF, pImg[0], pImg[1], pImg[2]); iPixelNumber--; pImg += 3; @@ -1262,7 +1264,7 @@ while (iLength > 0) { if (iPixelNumber == 0) - return THPalette::packARGB(iOpacity, pImg[0], pImg[1], pImg[2]); + return palette::pack_argb(iOpacity, pImg[0], pImg[1], pImg[2]); iPixelNumber--; pImg += 3; @@ -1279,7 +1281,7 @@ break; } - return THPalette::packARGB(0, 0, 0, 0); + return palette::pack_argb(0, 0, 0, 0); } case 3: // Recolour layer @@ -1297,7 +1299,7 @@ { // Legacy sprite data. Use the palette to recolour the layer. // Note that the iOpacity is ignored here. - const uint32_t* pColours = pPalette->getARGBData(); + const uint32_t* pColours = pPalette->get_argb_data(); return pColours[pImg[iPixelNumber]]; } else @@ -1307,47 +1309,47 @@ // opacity comes from the byte after the iTable byte. // // For now just draw black pixels, so it won't go unnoticed. - return THPalette::packARGB(0xFF, 0, 0, 0); + return palette::pack_argb(0xFF, 0, 0, 0); } } } } } -bool THSpriteSheet::hitTestSprite(size_t iSprite, int iX, int iY, uint32_t iFlags) const +bool sprite_sheet::hit_test_sprite(size_t iSprite, int iX, int iY, uint32_t iFlags) const { - if(iX < 0 || iY < 0 || iSprite >= m_iSpriteCount) + if(iX < 0 || iY < 0 || iSprite >= sprite_count) return false; - sprite_t &sprite = m_pSprites[iSprite]; - int iWidth = sprite.iWidth; - int iHeight = sprite.iHeight; + sprite &sprite = sprites[iSprite]; + int iWidth = sprite.width; + int iHeight = sprite.height; if(iX >= iWidth || iY >= iHeight) return false; - if(iFlags & THDF_FlipHorizontal) + if(iFlags & thdf_flip_horizontal) iX = iWidth - iX - 1; - if(iFlags & THDF_FlipVertical) + if(iFlags & thdf_flip_vertical) iY = iHeight - iY - 1; - uint32_t iCol = get32BppPixel(sprite.pData, iWidth, iHeight, m_pPalette, iY * iWidth + iX); - return THPalette::getA(iCol) != 0; + uint32_t iCol = get32BppPixel(sprite.data, iWidth, iHeight, palette, iY * iWidth + iX); + return palette::get_alpha(iCol) != 0; } -THCursor::THCursor() +cursor::cursor() { - m_pBitmap = nullptr; - m_iHotspotX = 0; - m_iHotspotY = 0; - m_pCursorHidden = nullptr; + bitmap = nullptr; + hotspot_x = 0; + hotspot_y = 0; + hidden_cursor = nullptr; } -THCursor::~THCursor() +cursor::~cursor() { - SDL_FreeSurface(m_pBitmap); - SDL_FreeCursor(m_pCursorHidden); + SDL_FreeSurface(bitmap); + SDL_FreeCursor(hidden_cursor); } -bool THCursor::createFromSprite(THSpriteSheet* pSheet, size_t iSprite, +bool cursor::create_from_sprite(sprite_sheet* pSheet, size_t iSprite, int iHotspotX, int iHotspotY) { #if 0 @@ -1367,7 +1369,7 @@ #endif } -void THCursor::use(THRenderTarget* pTarget) +void cursor::use(render_target* pTarget) { #if 0 //SDL_ShowCursor(0) is buggy in fullscreen until 1.3 (they say) @@ -1379,7 +1381,7 @@ #endif } -bool THCursor::setPosition(THRenderTarget* pTarget, int iX, int iY) +bool cursor::set_position(render_target* pTarget, int iX, int iY) { #if 0 pTarget->setCursorPosition(iX, iY); @@ -1389,7 +1391,7 @@ #endif } -void THCursor::draw(THRenderTarget* pCanvas, int iX, int iY) +void cursor::draw(render_target* pCanvas, int iX, int iY) { #if 0 SDL_Rect rcDest; @@ -1399,162 +1401,162 @@ #endif } -THLine::THLine() +line::line() { initialize(); } -THLine::~THLine() +line::~line() { - THLineOperation* op = m_pFirstOp; + line_operation* op = first_operation; while (op) { - THLineOperation* next = (THLineOperation*)(op->m_pNext); + line_operation* next = (line_operation*)(op->next); delete(op); op = next; } } -void THLine::initialize() +void line::initialize() { - m_fWidth = 1; - m_iR = 0; - m_iG = 0; - m_iB = 0; - m_iA = 255; + width = 1; + red = 0; + green = 0; + blue = 0; + alpha = 255; // We start at 0,0 - m_pFirstOp = new THLineOperation(THLOP_MOVE, 0, 0); - m_pCurrentOp = m_pFirstOp; + first_operation = new line_operation(line_operation_type::move, 0, 0); + current_operation = first_operation; } -void THLine::moveTo(double fX, double fY) +void line::move_to(double fX, double fY) { - THLineOperation* previous = m_pCurrentOp; - m_pCurrentOp = new THLineOperation(THLOP_MOVE, fX, fY); - previous->m_pNext = m_pCurrentOp; + line_operation* previous = current_operation; + current_operation = new line_operation(line_operation_type::move, fX, fY); + previous->next = current_operation; } -void THLine::lineTo(double fX, double fY) +void line::line_to(double fX, double fY) { - THLineOperation* previous = m_pCurrentOp; - m_pCurrentOp = new THLineOperation(THLOP_LINE, fX, fY); - previous->m_pNext = m_pCurrentOp; + line_operation* previous = current_operation; + current_operation = new line_operation(line_operation_type::line, fX, fY); + previous->next = current_operation; } -void THLine::setWidth(double pLineWidth) +void line::set_width(double pLineWidth) { - m_fWidth = pLineWidth; + width = pLineWidth; } -void THLine::setColour(uint8_t iR, uint8_t iG, uint8_t iB, uint8_t iA) +void line::set_colour(uint8_t iR, uint8_t iG, uint8_t iB, uint8_t iA) { - m_iR = iR; - m_iG = iG; - m_iB = iB; - m_iA = iA; + red = iR; + green = iG; + blue = iB; + alpha = iA; } -void THLine::draw(THRenderTarget* pCanvas, int iX, int iY) +void line::draw(render_target* pCanvas, int iX, int iY) { - pCanvas->drawLine(this, iX, iY); + pCanvas->draw_line(this, iX, iY); } -void THLine::persist(LuaPersistWriter *pWriter) const +void line::persist(lua_persist_writer *pWriter) const { - pWriter->writeVUInt((uint32_t)m_iR); - pWriter->writeVUInt((uint32_t)m_iG); - pWriter->writeVUInt((uint32_t)m_iB); - pWriter->writeVUInt((uint32_t)m_iA); - pWriter->writeVFloat(m_fWidth); + pWriter->write_uint((uint32_t)red); + pWriter->write_uint((uint32_t)green); + pWriter->write_uint((uint32_t)blue); + pWriter->write_uint((uint32_t)alpha); + pWriter->write_float(width); - THLineOperation* op = (THLineOperation*)(m_pFirstOp->m_pNext); + line_operation* op = (line_operation*)(first_operation->next); uint32_t numOps = 0; for (; op; numOps++) { - op = (THLineOperation*)(op->m_pNext); + op = (line_operation*)(op->next); } - pWriter->writeVUInt(numOps); + pWriter->write_uint(numOps); - op = (THLineOperation*)(m_pFirstOp->m_pNext); + op = (line_operation*)(first_operation->next); while (op) { - pWriter->writeVUInt((uint32_t)op->type); - pWriter->writeVFloat(op->m_fX); - pWriter->writeVFloat(op->m_fY); + pWriter->write_uint((uint32_t)op->type); + pWriter->write_float(op->x); + pWriter->write_float(op->y); - op = (THLineOperation*)(op->m_pNext); + op = (line_operation*)(op->next); } } -void THLine::depersist(LuaPersistReader *pReader) +void line::depersist(lua_persist_reader *pReader) { initialize(); - pReader->readVUInt(m_iR); - pReader->readVUInt(m_iG); - pReader->readVUInt(m_iB); - pReader->readVUInt(m_iA); - pReader->readVFloat(m_fWidth); + pReader->read_uint(red); + pReader->read_uint(green); + pReader->read_uint(blue); + pReader->read_uint(alpha); + pReader->read_float(width); uint32_t numOps = 0; - pReader->readVUInt(numOps); + pReader->read_uint(numOps); for (uint32_t i = 0; i < numOps; i++) { - THLineOpType type; + line_operation_type type; double fX, fY; - pReader->readVUInt((uint32_t&)type); - pReader->readVFloat(fX); - pReader->readVFloat(fY); - - if (type == THLOP_MOVE) { - moveTo(fX, fY); - } else if (type == THLOP_LINE) { - lineTo(fX, fY); + pReader->read_uint((uint32_t&)type); + pReader->read_float(fX); + pReader->read_float(fY); + + if (type == line_operation_type::move) { + move_to(fX, fY); + } else if (type == line_operation_type::line) { + line_to(fX, fY); } } } #ifdef CORSIX_TH_USE_FREETYPE2 -bool THFreeTypeFont::_isMonochrome() const +bool freetype_font::is_monochrome() const { return true; } -void THFreeTypeFont::_freeTexture(cached_text_t* pCacheEntry) const +void freetype_font::free_texture(cached_text* pCacheEntry) const { - if(pCacheEntry->pTexture != nullptr) + if(pCacheEntry->texture != nullptr) { - SDL_DestroyTexture(pCacheEntry->pTexture); - pCacheEntry->pTexture = nullptr; + SDL_DestroyTexture(pCacheEntry->texture); + pCacheEntry->texture = nullptr; } } -void THFreeTypeFont::_makeTexture(THRenderTarget *pEventualCanvas, cached_text_t* pCacheEntry) const +void freetype_font::make_texture(render_target *pEventualCanvas, cached_text* pCacheEntry) const { - uint32_t* pPixels = new uint32_t[pCacheEntry->iWidth * pCacheEntry->iHeight]; - std::memset(pPixels, 0, pCacheEntry->iWidth * pCacheEntry->iHeight * sizeof(uint32_t)); - uint8_t* pInRow = pCacheEntry->pData; + uint32_t* pPixels = new uint32_t[pCacheEntry->width * pCacheEntry->height]; + std::memset(pPixels, 0, pCacheEntry->width * pCacheEntry->height * sizeof(uint32_t)); + uint8_t* pInRow = pCacheEntry->data; uint32_t* pOutRow = pPixels; - uint32_t iColBase = m_oColour & 0xFFFFFF; - for(int iY = 0; iY < pCacheEntry->iHeight; ++iY, pOutRow += pCacheEntry->iWidth, - pInRow += pCacheEntry->iWidth) + uint32_t iColBase = colour & 0xFFFFFF; + for(int iY = 0; iY < pCacheEntry->height; ++iY, pOutRow += pCacheEntry->width, + pInRow += pCacheEntry->width) { - for(int iX = 0; iX < pCacheEntry->iWidth; ++iX) + for(int iX = 0; iX < pCacheEntry->width; ++iX) { pOutRow[iX] = (static_cast(pInRow[iX]) << 24) | iColBase; } } - pCacheEntry->pTexture = pEventualCanvas->createTexture(pCacheEntry->iWidth, pCacheEntry->iHeight, pPixels); + pCacheEntry->texture = pEventualCanvas->create_texture(pCacheEntry->width, pCacheEntry->height, pPixels); delete[] pPixels; } -void THFreeTypeFont::_drawTexture(THRenderTarget* pCanvas, cached_text_t* pCacheEntry, int iX, int iY) const +void freetype_font::draw_texture(render_target* pCanvas, cached_text* pCacheEntry, int iX, int iY) const { - if(pCacheEntry->pTexture == nullptr) + if(pCacheEntry->texture == nullptr) return; - SDL_Rect rcDest = { iX, iY, pCacheEntry->iWidth, pCacheEntry->iHeight }; - pCanvas->draw(pCacheEntry->pTexture, nullptr, &rcDest, 0); + SDL_Rect rcDest = { iX, iY, pCacheEntry->width, pCacheEntry->height }; + pCanvas->draw(pCacheEntry->texture, nullptr, &rcDest, 0); } #endif // CORSIX_TH_USE_FREETYPE2 diff -Nru corsix-th-0.61/CorsixTH/Src/th_gfx_sdl.h corsix-th-0.62/CorsixTH/Src/th_gfx_sdl.h --- corsix-th-0.61/CorsixTH/Src/th_gfx_sdl.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_gfx_sdl.h 2018-07-21 11:13:17.000000000 +0000 @@ -27,18 +27,17 @@ #include #include "persist_lua.h" -class THCursor; -struct THClipRect : public SDL_Rect -{ - typedef Sint16 xy_t; - typedef Uint16 wh_t; +class cursor; +struct clip_rect : public SDL_Rect { + typedef Sint16 x_y_type; + typedef Uint16 w_h_type; }; -struct THRenderTargetCreationParams; +struct render_target_creation_params; /*! Utility class for decoding 32bpp images. */ -class FullColourRenderer +class full_colour_renderer { public: //! Initialize the renderer for a specific render. @@ -46,8 +45,8 @@ @param iWidth Pixel width of the resulting image @param iHeight Pixel height of the resulting image */ - FullColourRenderer(int iWidth, int iHeight); - virtual ~FullColourRenderer() = default; + full_colour_renderer(int iWidth, int iHeight); + virtual ~full_colour_renderer() = default; //! Decode a 32bpp image, and push it to the storage backend. /*! @@ -56,133 +55,133 @@ @param iSpriteFlags Flags how to render the sprite. @return Decoding was successful. */ - bool decodeImage(const uint8_t* pImg, const THPalette *pPalette, uint32_t iSpriteFlags); + bool decode_image(const uint8_t* pImg, const ::palette *pPalette, uint32_t iSpriteFlags); private: - //! Store a decoded pixel. Use m_iX and m_iY if necessary. + //! Store a decoded pixel. Use x and y if necessary. /*! @param pixel Pixel to store. */ - virtual void storeARGB(uint32_t pixel) = 0; + virtual void store_argb(uint32_t pixel) = 0; - const int m_iWidth; - const int m_iHeight; - int m_iX; - int m_iY; + const int width; + const int height; + int x; + int y; //! Push a pixel to the storage. /*! @param iValue Pixel value to store. */ - inline void _pushPixel(uint32_t iValue) + inline void push_pixel(uint32_t iValue) { - if (m_iY < m_iHeight) + if (y < height) { - storeARGB(iValue); - m_iX++; - if (m_iX >= m_iWidth) + store_argb(iValue); + x++; + if (x >= width) { - m_iX = 0; - m_iY++; + x = 0; + y++; } } else { - m_iX = 1; // Will return 'failed'. + x = 1; // Will return 'failed'. } } }; -class FullColourStoring : public FullColourRenderer +class full_colour_storing : public full_colour_renderer { public: - FullColourStoring(uint32_t *pDest, int iWidth, int iHeight); + full_colour_storing(uint32_t *pDest, int iWidth, int iHeight); private: - void storeARGB(uint32_t pixel) override; + void store_argb(uint32_t pixel) override; //! Pointer to the storage (not owned by this class). - uint32_t *m_pDest; + uint32_t *destination; }; -class WxStoring : public FullColourRenderer +class wx_storing : public full_colour_renderer { public: - WxStoring(uint8_t* pRGBData, uint8_t* pAData, int iWidth, int iHeight); + wx_storing(uint8_t* pRGBData, uint8_t* pAData, int iWidth, int iHeight); private: - void storeARGB(uint32_t pixel) override; + void store_argb(uint32_t pixel) override; //! Pointer to the RGB storage (not owned by this class). - uint8_t *m_pRGBData; + uint8_t *rgb_data; //! Pointer to the Alpha channel storage (not owned by this class). - uint8_t *m_pAData; + uint8_t *alpha_data; }; -class THRenderTarget +class render_target { public: // External API - THRenderTarget(); - ~THRenderTarget(); + render_target(); + ~render_target(); //! Initialise the render target - bool create(const THRenderTargetCreationParams* pParams); + bool create(const render_target_creation_params* pParams); //! Update the parameters for the render target - bool update(const THRenderTargetCreationParams* pParams); + bool update(const render_target_creation_params* pParams); //! Shut down the render target void destroy(); //! Get the reason for the last operation failing - const char* getLastError(); + const char* get_last_error(); //! Begin rendering a new frame - bool startFrame(); + bool start_frame(); //! Finish rendering the current frame and present it - bool endFrame(); + bool end_frame(); //! Paint the entire render target black - bool fillBlack(); + bool fill_black(); //! Sets a blue filter on the current surface. // Used to add the blue effect when the game is paused. - void setBlueFilterActive(bool bActivate); + void set_blue_filter_active(bool bActivate); //! Encode an RGB triplet for fillRect() - uint32_t mapColour(uint8_t iR, uint8_t iG, uint8_t iB); + uint32_t map_colour(uint8_t iR, uint8_t iG, uint8_t iB); //! Fill a rectangle of the render target with a solid colour - bool fillRect(uint32_t iColour, int iX, int iY, int iW, int iH); + bool fill_rect(uint32_t iColour, int iX, int iY, int iW, int iH); //! Get the current clip rectangle - void getClipRect(THClipRect* pRect) const; + void get_clip_rect(clip_rect* pRect) const; //! Get the width of the render target (in pixels) - int getWidth() const; + int get_width() const; //! Get the height of the render target (in pixels) - int getHeight() const; + int get_height() const; //! Set the new clip rectangle - void setClipRect(const THClipRect* pRect); + void set_clip_rect(const clip_rect* pRect); //! Enable optimisations for non-overlapping draws - void startNonOverlapping(); + void start_nonoverlapping_draws(); //! Disable optimisations for non-overlapping draws - void finishNonOverlapping(); + void finish_nonoverlapping_draws(); //! Set the cursor to be used - void setCursor(THCursor* pCursor); + void set_cursor(cursor* pCursor); //! Update the cursor position (if the cursor is being simulated) - void setCursorPosition(int iX, int iY); + void set_cursor_position(int iX, int iY); //! Take a screenshot and save it as a bitmap - bool takeScreenshot(const char* sFile); + bool take_screenshot(const char* sFile); //! Set the amount by which future draw operations are scaled. /*! @@ -190,23 +189,23 @@ @param eWhatToScale Th kind of items to scale. @return Whether the scale could be set. */ - bool setScaleFactor(double fScale, THScaledItems eWhatToScale); + bool set_scale_factor(double fScale, scaled_items eWhatToScale); //! Set the window caption - void setCaption(const char* sCaption); + void set_caption(const char* sCaption); //! Toggle mouse capture on the window. - void setWindowGrab(bool bActivate); + void set_window_grab(bool bActivate); //! Get any user-displayable information to describe the renderer path used - const char *getRendererDetails() const; + const char *get_renderer_details() const; // If you add any extra methods here which are called from outside the // rendering engine, then be sure to at least add dummy implementations // to the other rendering engines. public: // Internal (this rendering engine only) API - SDL_Renderer *getRenderer() const { return m_pRenderer; } + SDL_Renderer *get_renderer() const { return renderer; } //! Should bitmaps be scaled? /*! @@ -214,45 +213,45 @@ for scaling (can be \c nullptr if not interested in the value). @return Whether bitmaps should be scaled. */ - bool shouldScaleBitmaps(double* pFactor); + bool should_scale_bitmaps(double* pFactor); - SDL_Texture* createPalettizedTexture(int iWidth, int iHeight, const uint8_t* pPixels, - const THPalette* pPalette, uint32_t iSpriteFlags) const; - SDL_Texture* createTexture(int iWidth, int iHeight, const uint32_t* pPixels) const; + SDL_Texture* create_palettized_texture(int iWidth, int iHeight, const uint8_t* pPixels, + const ::palette* pPalette, uint32_t iSpriteFlags) const; + SDL_Texture* create_texture(int iWidth, int iHeight, const uint32_t* pPixels) const; void draw(SDL_Texture *pTexture, const SDL_Rect *prcSrcRect, const SDL_Rect *prcDstRect, int iFlags); - void drawLine(THLine *pLine, int iX, int iY); + void draw_line(line *pLine, int iX, int iY); private: - SDL_Window *m_pWindow; - SDL_Renderer *m_pRenderer; - SDL_Texture *m_pZoomTexture; - SDL_PixelFormat *m_pFormat; - bool m_bBlueFilterActive; - THCursor* m_pCursor; - double m_fBitmapScaleFactor; ///< Bitmap scale factor. - int m_iWidth; - int m_iHeight; - int m_iCursorX; - int m_iCursorY; - bool m_bShouldScaleBitmaps; ///< Whether bitmaps should be scaled. - bool m_bSupportsTargetTextures; + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *zoom_texture; + SDL_PixelFormat *pixel_format; + bool blue_filter_active; + cursor* game_cursor; + double bitmap_scale_factor; ///< Bitmap scale factor. + int width; + int height; + int cursor_x; + int cursor_y; + bool scale_bitmaps; ///< Whether bitmaps should be scaled. + bool supports_target_textures; // In SDL2 < 2.0.4 there is an issue with the y coordinates used for // ClipRects in opengl and opengles. // see: https://bugzilla.libsdl.org/show_bug.cgi?id=2700 - bool m_bApplyOpenGlClipFix; + bool apply_opengl_clip_fix; - void _flushZoomBuffer(); + void flush_zoom_buffer(); }; -//! 32bpp ARGB colour. See #THPalette::packARGB -typedef uint32_t THColour; +//! 32bpp ARGB colour. See #palette::pack_argb +typedef uint32_t argb_colour; //! 8bpp palette class. -class THPalette +class palette { public: // External API - THPalette(); + palette(); //! Load palette from the supplied data. /*! @@ -261,7 +260,7 @@ @param iDataLength Size of the data. @return Whether loading of the palette succeeded. */ - bool loadFromTHFile(const uint8_t* pData, size_t iDataLength); + bool load_from_th_file(const uint8_t* pData, size_t iDataLength); //! Set an entry of the palette. /*! @@ -272,7 +271,7 @@ @param iB Amount of blue in the new entry. @return Setting the entry succeeded. */ - bool setEntry(int iEntry, uint8_t iR, uint8_t iG, uint8_t iB); + bool set_entry(int iEntry, uint8_t iR, uint8_t iG, uint8_t iB); public: // Internal (this rendering engine only) API @@ -284,12 +283,12 @@ @param iB Amount of blue (0-255). @return 32bpp value representing the provided colour values. */ - inline static THColour packARGB(uint8_t iA, uint8_t iR, uint8_t iG, uint8_t iB) + inline static argb_colour pack_argb(uint8_t iA, uint8_t iR, uint8_t iG, uint8_t iB) { - return (static_cast(iR) << 0) | - (static_cast(iG) << 8) | - (static_cast(iB) << 16) | - (static_cast(iA) << 24) ; + return (static_cast(iR) << 0) | + (static_cast(iG) << 8) | + (static_cast(iB) << 16) | + (static_cast(iA) << 24) ; } //! Get the red component of a colour. @@ -297,7 +296,7 @@ @param iColour Colour to examine. @return The red component intensity of the colour. */ - inline static uint8_t getR(THColour iColour) + inline static uint8_t get_red(argb_colour iColour) { return static_cast((iColour >> 0) & 0xFF); } @@ -307,7 +306,7 @@ @param iColour Colour to examine. @return The green component intensity of the colour. */ - inline static uint8_t getG(THColour iColour) + inline static uint8_t get_green(argb_colour iColour) { return static_cast((iColour >> 8) & 0xFF); } @@ -317,7 +316,7 @@ @param iColour Colour to examine. @return The blue component intensity of the colour. */ - inline static uint8_t getB(THColour iColour) + inline static uint8_t get_blue(argb_colour iColour) { return static_cast((iColour >> 16) & 0xFF); } @@ -327,7 +326,7 @@ @param iColour Colour to examine. @return The opacity of the colour. */ - inline static uint8_t getA(THColour iColour) + inline static uint8_t get_alpha(argb_colour iColour) { return static_cast((iColour >> 24) & 0xFF); } @@ -336,44 +335,44 @@ /*! @return The number of colours in the palette. */ - int getColourCount() const; + int get_colour_count() const; //! Get the internal palette data for fast (read-only) access. /*! @return Table with all 256 colours of the palette. */ - const THColour* getARGBData() const; + const argb_colour* get_argb_data() const; //! Set an entry of the palette. /*! @param iEntry Entry to modify. @param iVal Palette value to set. */ - inline void setARGB(int iEntry, uint32_t iVal) + inline void set_argb(int iEntry, uint32_t iVal) { - m_aColoursARGB[iEntry] = iVal; + colour_index_to_argb_map[iEntry] = iVal; } private: //! 32bpp palette colours associated with the 8bpp colour index. - uint32_t m_aColoursARGB[256]; + uint32_t colour_index_to_argb_map[256]; //! Number of colours in the palette. - int m_iNumColours; + int colour_count; }; //! Stored image. -class THRawBitmap +class raw_bitmap { public: - THRawBitmap(); - ~THRawBitmap(); + raw_bitmap(); + ~raw_bitmap(); //! Set the palette of the image. /*! @param pPalette Palette to set for this image. */ - void setPalette(const THPalette* pPalette); + void set_palette(const ::palette* pPalette); //! Load the image from the supplied pixel data. /*! @@ -384,8 +383,8 @@ @param pEventualCanvas Canvas to render the image to (eventually). @return Loading was a success. */ - bool loadFromTHFile(const uint8_t* pPixelData, size_t iPixelDataLength, - int iWidth, THRenderTarget *pEventualCanvas); + bool load_from_th_file(const uint8_t* pPixelData, size_t iPixelDataLength, + int iWidth, render_target *pEventualCanvas); //! Draw the image at a given position at the given canvas. /*! @@ -393,7 +392,7 @@ @param iX Destination x position. @param iY Destination y position. */ - void draw(THRenderTarget* pCanvas, int iX, int iY); + void draw(render_target* pCanvas, int iX, int iY); //! Draw part of the image at a given position at the given canvas. /*! @@ -405,42 +404,42 @@ @param iWidth Width of the part to display. @param iHeight Height of the part to display. */ - void draw(THRenderTarget* pCanvas, int iX, int iY, int iSrcX, int iSrcY, + void draw(render_target* pCanvas, int iX, int iY, int iSrcX, int iSrcY, int iWidth, int iHeight); private: //! Image stored in SDL format for quick rendering. - SDL_Texture *m_pTexture; + SDL_Texture *texture; //! Palette of the image. - const THPalette* m_pPalette; + const ::palette* bitmap_palette; //! Target canvas. - THRenderTarget* m_pTarget; + render_target* target; //! Width of the stored image. - int m_iWidth; + int width; //! Height of the stored image. - int m_iHeight; + int height; }; //! Sheet of sprites. -class THSpriteSheet +class sprite_sheet { public: // External API - THSpriteSheet(); - ~THSpriteSheet(); + sprite_sheet(); + ~sprite_sheet(); //! Set the palette to use for the sprites in the sheet. /*! @param pPalette Palette to use for the sprites at the sheet. */ - void setPalette(const THPalette* pPalette); + void set_palette(const ::palette* pPalette); //! Load the sprites from the supplied data (using the palette supplied earlier). /*! - @param pTableData Start of table data with TH sprite information (see th_sprite_t). + @param pTableData Start of table data with TH sprite information (see th_sprite_properties). @param iTableDataLength Length of the table data. @param pChunkData Start of image data (chunks). @param iChunkDataLength Length of the chunk data. @@ -448,9 +447,9 @@ @param pEventualCanvas Canvas to draw at. @return Loading succeeded. */ - bool loadFromTHFile(const uint8_t* pTableData, size_t iTableDataLength, - const uint8_t* pChunkData, size_t iChunkDataLength, - bool bComplexChunks, THRenderTarget* pEventualCanvas); + bool load_from_th_file(const uint8_t* pTableData, size_t iTableDataLength, + const uint8_t* pChunkData, size_t iChunkDataLength, + bool bComplexChunks, render_target* pEventualCanvas); //! Set the data of a sprite. /*! @@ -462,8 +461,8 @@ @param iHeight Height of the sprite. @return Setting the sprite succeeded. */ - bool setSpriteData(size_t iSprite, const uint8_t *pData, bool bTakeData, - size_t iDataLength, int iWidth, int iHeight); + bool set_sprite_data(size_t iSprite, const uint8_t *pData, bool bTakeData, + size_t iDataLength, int iWidth, int iHeight); //! Supply a new mapped palette to a sprite. /*! @@ -471,13 +470,13 @@ @param pMap The palette map to apply. @param iAlt32 What to do for a 32bpp sprite (#THDF_Alt32_Mask bits). */ - void setSpriteAltPaletteMap(size_t iSprite, const uint8_t* pMap, uint32_t iAlt32); + void set_sprite_alt_palette_map(size_t iSprite, const uint8_t* pMap, uint32_t iAlt32); //! Get the number of sprites at the sheet. /*! @return The number of sprites available at the sheet. */ - size_t getSpriteCount() const; + size_t get_sprite_count() const; //! Set the number of sprites in the sheet. /*! @@ -485,7 +484,7 @@ @param pCanvas Canvas to draw at. @return Whether the number of sprites could be allocated. */ - bool setSpriteCount(size_t iCount, THRenderTarget* pCanvas); + bool set_sprite_count(size_t iCount, render_target* pCanvas); //! Get size of a sprite. /*! @@ -494,7 +493,7 @@ @param pHeight [out] If not nullptr, the sprite height is stored in the destination. @return Size could be provided for the sprite. */ - bool getSpriteSize(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const; + bool get_sprite_size(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const; //! Get size of a sprite, assuming all input is correctly supplied. /*! @@ -502,7 +501,7 @@ @param pWidth [out] The sprite width is stored in the destination. @param pHeight [out] The sprite height is stored in the destination. */ - void getSpriteSizeUnchecked(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const; + void get_sprite_size_unchecked(size_t iSprite, unsigned int* pWidth, unsigned int* pHeight) const; //! Get the best colour to represent the sprite. /*! @@ -510,7 +509,7 @@ @param pColour [out] Resulting colour. @return Best colour could be established. */ - bool getSpriteAverageColour(size_t iSprite, THColour* pColour) const; + bool get_sprite_average_colour(size_t iSprite, argb_colour* pColour) const; //! Draw a sprite onto the canvas. /*! @@ -520,7 +519,7 @@ @param iY Y position to draw the sprite. @param iFlags Flags to apply for drawing. */ - void drawSprite(THRenderTarget* pCanvas, size_t iSprite, int iX, int iY, uint32_t iFlags); + void draw_sprite(render_target* pCanvas, size_t iSprite, int iX, int iY, uint32_t iFlags); //! Test whether a sprite was hit. /*! @@ -530,7 +529,7 @@ @param iFlags Draw flags to apply to the sprite before testing. @return Whether the sprite covers the give point. */ - bool hitTestSprite(size_t iSprite, int iX, int iY, uint32_t iFlags) const; + bool hit_test_sprite(size_t iSprite, int iX, int iY, uint32_t iFlags) const; public: // Internal (this rendering engine only) API //! Draw a sprite into wxImage data arrays (for the Map Editor) @@ -539,16 +538,16 @@ @param pRGBData Output RGB data array. @param pAData Output Alpha channel array. */ - void wxDrawSprite(size_t iSprite, uint8_t* pRGBData, uint8_t* pAData); + void wx_draw_sprite(size_t iSprite, uint8_t* pRGBData, uint8_t* pAData); private: - friend class THCursor; + friend class cursor; #if CORSIX_TH_USE_PACK_PRAGMAS #pragma pack(push) #pragma pack(1) #endif //! Sprite structure in the table file. - struct th_sprite_t + struct th_sprite_properties { //! Position of the sprite in the chunk data file. uint32_t position; @@ -564,38 +563,38 @@ #endif //! Sprites of the sheet. - struct sprite_t + struct sprite { //! SDL structure containing the sprite with original palette. - SDL_Texture *pTexture; + SDL_Texture *texture; //! SDL structure containing the sprite with alternative palette. - SDL_Texture *pAltTexture; + SDL_Texture *alt_texture; //! Data of the sprite. - const uint8_t *pData; + const uint8_t *data; //! Alternative palette (if available). - const uint8_t *pAltPaletteMap; + const uint8_t *alt_palette_map; //! Flags how to render the sprite, contains #THDF_Alt32_Mask bits. - uint32_t iSpriteFlags; + uint32_t sprite_flags; //! Width of the sprite. - int iWidth; + int width; //! Height of the sprite. - int iHeight; - } *m_pSprites; + int height; + } *sprites; //! Original palette. - const THPalette* m_pPalette; + const ::palette* palette; //! Target to render to. - THRenderTarget* m_pTarget; + render_target* target; //! Number of sprites in the sprite sheet. - size_t m_iSpriteCount; + size_t sprite_count; //! Free memory of a single sprite. /*! @@ -611,72 +610,73 @@ @param pSprite Sprite to change. @return SDL texture containing the sprite. */ - SDL_Texture *_makeAltBitmap(sprite_t *pSprite); + SDL_Texture *_makeAltBitmap(sprite *pSprite); }; -class THCursor +class cursor { public: - THCursor(); - ~THCursor(); + cursor(); + ~cursor(); - bool createFromSprite(THSpriteSheet* pSheet, size_t iSprite, - int iHotspotX = 0, int iHotspotY = 0); + bool create_from_sprite(sprite_sheet* pSheet, size_t iSprite, + int iHotspotX = 0, int iHotspotY = 0); - void use(THRenderTarget* pTarget); + void use(render_target* pTarget); - static bool setPosition(THRenderTarget* pTarget, int iX, int iY); + static bool set_position(render_target* pTarget, int iX, int iY); - void draw(THRenderTarget* pCanvas, int iX, int iY); + void draw(render_target* pCanvas, int iX, int iY); private: - SDL_Surface* m_pBitmap; - SDL_Cursor* m_pCursorHidden; - int m_iHotspotX; - int m_iHotspotY; + SDL_Surface* bitmap; + SDL_Cursor* hidden_cursor; + int hotspot_x; + int hotspot_y; }; -class THLine +class line { public: - THLine(); - ~THLine(); + line(); + ~line(); - void moveTo(double fX, double fY); + void move_to(double fX, double fY); - void lineTo(double fX, double fY); + void line_to(double fX, double fY); - void setWidth(double lineWidth); + void set_width(double lineWidth); - void draw(THRenderTarget* pCanvas, int iX, int iY); + void draw(render_target* pCanvas, int iX, int iY); - void setColour(uint8_t iR, uint8_t iG, uint8_t iB, uint8_t iA = 255); + void set_colour(uint8_t iR, uint8_t iG, uint8_t iB, uint8_t iA = 255); - void persist(LuaPersistWriter *pWriter) const; - void depersist(LuaPersistReader *pReader); + void persist(lua_persist_writer *pWriter) const; + void depersist(lua_persist_reader *pReader); private: - friend class THRenderTarget; + friend class render_target; void initialize(); - enum THLineOpType { - THLOP_MOVE, - THLOP_LINE + enum class line_operation_type { + move, + line }; - struct THLineOperation : public THLinkList + class line_operation : public link_list { - THLineOpType type; - double m_fX, m_fY; - THLineOperation(THLineOpType type, double m_fX, double m_fY) : type(type), m_fX(m_fX), m_fY(m_fY) { - m_pNext = nullptr; + public: + line_operation_type type; + double x, y; + line_operation(line_operation_type type, double x, double y) : type(type), x(x), y(y) { + next = nullptr; } }; - THLineOperation* m_pFirstOp; - THLineOperation* m_pCurrentOp; - double m_fWidth; - uint8_t m_iR, m_iG, m_iB, m_iA; + line_operation* first_operation; + line_operation* current_operation; + double width; + uint8_t red, green, blue, alpha; }; #endif // CORSIX_TH_TH_GFX_SDL_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/th.h corsix-th-0.62/CorsixTH/Src/th.h --- corsix-th-0.61/CorsixTH/Src/th.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th.h 2018-07-21 11:13:17.000000000 +0000 @@ -26,51 +26,55 @@ #include //! Generic linked list class (for inheriting from) -struct THLinkList +class link_list { - THLinkList() ; - ~THLinkList(); +public: + link_list() ; + ~link_list(); + + link_list* prev; + link_list* next; - THLinkList* m_pPrev; - THLinkList* m_pNext; + void remove_from_list(); - void removeFromList(); - int getDrawingLayer() {return m_drawingLayer;} - void setDrawingLayer(int layer) {m_drawingLayer = layer;} + // TODO: drawing layer doesn't belong in a generic link list. + int get_drawing_layer() {return drawing_layer;} + void set_drawing_layer(int layer) {drawing_layer = layer;} - int m_drawingLayer; +private: + int drawing_layer; }; //! \brief Theme Hospital localised string list //! //! Presents Theme Hospital strings by section and index. -class THStringList +class th_string_list { public: - //! Construct an instance of THStringList from the given data + //! Construct an instance of string_list from the given data //! from a Theme Hosptial string file. The format of the data is //! described at: //! https://github.com/alexandergitter/theme-hospital-spec/blob/master/format-specification.md#strings //! //! \param data A pointer to the raw data //! \param length The size of the data - THStringList(const uint8_t* data, size_t length); + th_string_list(const uint8_t* data, size_t length); // Delete default constructors and assignment operators. They // can be implemented properly later if they are needed but // for now they are unneeded so it is safer to remove them. - THStringList() = delete; - THStringList(const THStringList &) = delete; - THStringList(THStringList &&) = delete; - THStringList& operator= (const THStringList &) = delete; - THStringList&& operator= (THStringList &&) = delete; - ~THStringList(); + th_string_list() = delete; + th_string_list(const th_string_list &) = delete; + th_string_list(th_string_list &&) = delete; + th_string_list& operator= (const th_string_list &) = delete; + th_string_list&& operator= (th_string_list &&) = delete; + ~th_string_list(); //! Get the number of sections in the string list - size_t getSectionCount(); + size_t get_section_count(); //! Get the number of strings in a section of the string list - size_t getSectionSize(size_t section); + size_t get_section_size(size_t section); //! Get a string from the string list /*! @@ -78,7 +82,7 @@ @param index String index in range [0, getSectionSize(iSection) - 1] @return nullptr if the index is invalid, otherwise a UTF-8 encoded string. */ - const char* getString(size_t section, size_t index); + const char* get_string(size_t section, size_t index); private: //! Section information diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_anims.cpp corsix-th-0.62/CorsixTH/Src/th_lua_anims.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_anims.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_anims.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -26,21 +26,21 @@ /* this variable is used to determine the layer of the animation, it should be rewriten at some point so that the it is passed as an argument in the function l_anim_set_tile */ -static int lastLayer = 2; +static int last_layer = 2; static int l_anims_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_anims_set_spritesheet(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); - THSpriteSheet* pSheet = luaT_testuserdata(L, 2); + animation_manager* pAnims = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L, 2); lua_settop(L, 2); - pAnims->setSpriteSheet(pSheet); + pAnims->set_sprite_sheet(pSheet); luaT_setenvfield(L, 1, "sprites"); return 1; } @@ -51,25 +51,25 @@ */ static int l_anims_set_canvas(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + animation_manager* pAnims = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); lua_settop(L, 2); - pAnims->setCanvas(pCanvas); + pAnims->set_canvas(pCanvas); luaT_setenvfield(L, 1, "target"); return 1; } static int l_anims_load(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); size_t iStartDataLength, iFrameDataLength, iListDataLength, iElementDataLength; const uint8_t* pStartData = luaT_checkfile(L, 2, &iStartDataLength); const uint8_t* pFrameData = luaT_checkfile(L, 3, &iFrameDataLength); const uint8_t* pListData = luaT_checkfile(L, 4, &iListDataLength); const uint8_t* pElementData = luaT_checkfile(L, 5, &iElementDataLength); - if(pAnims->loadFromTHFile(pStartData, iStartDataLength, pFrameData, iFrameDataLength, + if(pAnims->load_from_th_file(pStartData, iStartDataLength, pFrameData, iFrameDataLength, pListData, iListDataLength, pElementData, iElementDataLength)) { lua_pushboolean(L, 1); @@ -88,11 +88,11 @@ */ static int l_anims_loadcustom(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); size_t iDataLength; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLength); - if (pAnims->loadCustomAnimations(pData, iDataLength)) + if (pAnims->load_custom_animations(pData, iDataLength)) { lua_pushboolean(L, 1); } @@ -111,40 +111,40 @@ */ static int l_anims_getanims(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); int iTileSize = static_cast(luaL_checkinteger(L, 2)); const char *pName = luaL_checkstring(L, 3); - const AnimationStartFrames &oFrames = pAnims->getNamedAnimations(pName, iTileSize); - if (oFrames.iNorth < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.iNorth)); } - if (oFrames.iEast < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.iEast)); } - if (oFrames.iSouth < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.iSouth)); } - if (oFrames.iWest < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.iWest)); } + const animation_start_frames &oFrames = pAnims->get_named_animations(pName, iTileSize); + if (oFrames.north < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.north)); } + if (oFrames.east < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.east)); } + if (oFrames.south < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.south)); } + if (oFrames.west < 0) { lua_pushnil(L); } else { lua_pushnumber(L, static_cast(oFrames.west)); } return 4; } static int l_anims_getfirst(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); int iAnim = static_cast(luaL_checkinteger(L, 2)); - lua_pushinteger(L, pAnims->getFirstFrame(iAnim)); + lua_pushinteger(L, pAnims->get_first_frame(iAnim)); return 1; } static int l_anims_getnext(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); int iFrame = static_cast(luaL_checkinteger(L, 2)); - lua_pushinteger(L, pAnims->getNextFrame(iFrame)); + lua_pushinteger(L, pAnims->get_next_frame(iFrame)); return 1; } static int l_anims_set_alt_pal(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); + animation_manager* pAnims = luaT_testuserdata(L); size_t iAnimation = luaL_checkinteger(L, 2); size_t iPalLen; const uint8_t *pPal = luaT_checkfile(L, 3, &iPalLen); @@ -154,7 +154,7 @@ } uint32_t iAlt32 = static_cast(luaL_checkinteger(L, 4)); - pAnims->setAnimationAltPaletteMap(iAnimation, pPal, iAlt32); + pAnims->set_animation_alt_palette_map(iAnimation, pPal, iAlt32); lua_getfenv(L, 1); lua_insert(L, 2); @@ -166,31 +166,31 @@ static int l_anims_set_marker(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); - lua_pushboolean(L, pAnims->setFrameMarker(luaL_checkinteger(L, 2), + animation_manager* pAnims = luaT_testuserdata(L); + lua_pushboolean(L, pAnims->set_frame_marker(luaL_checkinteger(L, 2), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))) ? 1 : 0); return 1; } static int l_anims_set_secondary_marker(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); - lua_pushboolean(L, pAnims->setFrameSecondaryMarker(luaL_checkinteger(L, 2), + animation_manager* pAnims = luaT_testuserdata(L); + lua_pushboolean(L, pAnims->set_frame_secondary_marker(luaL_checkinteger(L, 2), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))) ? 1 : 0); return 1; } static int l_anims_draw(lua_State *L) { - THAnimationManager* pAnims = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + animation_manager* pAnims = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); size_t iFrame = luaL_checkinteger(L, 3); - THLayers_t* pLayers = luaT_testuserdata(L, 4, luaT_upvalueindex(2)); + layers* pLayers = luaT_testuserdata(L, 4, luaT_upvalueindex(2)); int iX = static_cast(luaL_checkinteger(L, 5)); int iY = static_cast(luaL_checkinteger(L, 6)); int iFlags = static_cast(luaL_optinteger(L, 7, 0)); - pAnims->drawFrame(pCanvas, iFrame, *pLayers, iX, iY, iFlags); + pAnims->draw_frame(pCanvas, iFrame, *pLayers, iX, iY, iFlags); lua_settop(L, 1); return 1; @@ -222,13 +222,13 @@ // Fast __persist call pAnimation = (T*)lua_touserdata(L, -1); } - LuaPersistWriter* pWriter = (LuaPersistWriter*)lua_touserdata(L, 1); + lua_persist_writer* pWriter = (lua_persist_writer*)lua_touserdata(L, 1); pAnimation->persist(pWriter); lua_rawgeti(L, luaT_environindex, 1); lua_pushlightuserdata(L, pAnimation); lua_gettable(L, -2); - pWriter->writeStackObject(-1); + pWriter->write_stack_object(-1); lua_pop(L, 2); return 0; } @@ -241,7 +241,7 @@ // things work nicely, we initialise all the fields of a THAnimation as // soon as possible, thus preventing issues like an anim -> map -> anim // reference chain whereby l_anim_depersist is called after l_map_depersist - // (as anim references map in its environment table) causing the pPrev + // (as anim references map in its environment table) causing the prev // field to be set during map depersistence, then cleared to nullptr by the // constructor during l_anim_depersist. T* pAnimation = luaT_testuserdata(L); @@ -255,7 +255,7 @@ T* pAnimation = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader* pReader = (lua_persist_reader*)lua_touserdata(L, 1); lua_rawgeti(L, luaT_environindex, 2); lua_pushlightuserdata(L, pAnimation); @@ -265,7 +265,7 @@ pAnimation->depersist(pReader); lua_rawgeti(L, luaT_environindex, 1); lua_pushlightuserdata(L, pAnimation); - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return 0; lua_settable(L, -3); lua_pop(L, 1); @@ -286,48 +286,48 @@ static int l_anim_set_frame(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - pAnimation->setFrame(luaL_checkinteger(L, 2)); + animation* pAnimation = luaT_testuserdata(L); + pAnimation->set_frame(luaL_checkinteger(L, 2)); lua_settop(L, 1); return 1; } static int l_anim_get_frame(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - lua_pushinteger(L, pAnimation->getFrame()); + animation* pAnimation = luaT_testuserdata(L); + lua_pushinteger(L, pAnimation->get_frame()); return 1; } static int l_anim_set_crop(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - pAnimation->setCropColumn(static_cast(luaL_checkinteger(L, 2))); + animation* pAnimation = luaT_testuserdata(L); + pAnimation->set_crop_column(static_cast(luaL_checkinteger(L, 2))); lua_settop(L, 1); return 1; } static int l_anim_get_crop(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - lua_pushinteger(L, pAnimation->getCropColumn()); + animation* pAnimation = luaT_testuserdata(L); + lua_pushinteger(L, pAnimation->get_crop_column()); return 1; } static int l_anim_set_anim(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - THAnimationManager* pManager = luaT_testuserdata(L, 2); + animation* pAnimation = luaT_testuserdata(L); + animation_manager* pManager = luaT_testuserdata(L, 2); size_t iAnim = luaL_checkinteger(L, 3); - if(iAnim < 0 || iAnim >= pManager->getAnimationCount()) + if(iAnim < 0 || iAnim >= pManager->get_animation_count()) luaL_argerror(L, 3, "Animation index out of bounds"); if(lua_isnoneornil(L, 4)) - pAnimation->setFlags(0); + pAnimation->set_flags(0); else - pAnimation->setFlags(static_cast(luaL_checkinteger(L, 4))); + pAnimation->set_flags(static_cast(luaL_checkinteger(L, 4))); - pAnimation->setAnimation(pManager, iAnim); + pAnimation->set_animation(pManager, iAnim); lua_settop(L, 2); luaT_setenvfield(L, 1, "animator"); lua_pushnil(L); @@ -338,14 +338,14 @@ static int l_anim_set_morph(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - THAnimation* pMorphTarget = luaT_testuserdata(L, 2, luaT_environindex); + animation* pAnimation = luaT_testuserdata(L); + animation* pMorphTarget = luaT_testuserdata(L, 2, luaT_environindex); unsigned int iDurationFactor = 1; if(!lua_isnoneornil(L, 3) && luaL_checkinteger(L, 3) > 0) iDurationFactor = static_cast(luaL_checkinteger(L, 3)); - pAnimation->setMorphTarget(pMorphTarget, iDurationFactor); + pAnimation->set_morph_target(pMorphTarget, iDurationFactor); lua_settop(L, 2); luaT_setenvfield(L, 1, "morph_target"); @@ -354,14 +354,14 @@ static int l_anim_set_drawable_layer(lua_State *L) { - lastLayer = static_cast(luaL_checkinteger(L, 2)); + last_layer = static_cast(luaL_checkinteger(L, 2)); return 1; } static int l_anim_get_anim(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - lua_pushinteger(L, pAnimation->getAnimation()); + animation* pAnimation = luaT_testuserdata(L); + lua_pushinteger(L, pAnimation->get_animation()); return 1; } @@ -373,17 +373,17 @@ T* pAnimation = luaT_testuserdata(L); if(lua_isnoneornil(L, 2)) { - pAnimation->removeFromTile(); + pAnimation->remove_from_tile(); lua_pushnil(L); luaT_setenvfield(L, 1, "map"); lua_settop(L, 1); } else { - THMap* pMap = luaT_testuserdata(L, 2); - THMapNode* pNode = pMap->getNode(static_cast(luaL_checkinteger(L, 3) - 1), static_cast(luaL_checkinteger(L, 4) - 1)); + level_map* pMap = luaT_testuserdata(L, 2); + map_tile* pNode = pMap->get_tile(static_cast(luaL_checkinteger(L, 3) - 1), static_cast(luaL_checkinteger(L, 4) - 1)); if(pNode) - pAnimation->attachToTile(pNode, lastLayer); + pAnimation->attach_to_tile(pNode, last_layer); else { @@ -401,7 +401,7 @@ static int l_anim_get_tile(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); + animation* pAnimation = luaT_testuserdata(L); lua_settop(L, 1); lua_getfenv(L, 1); lua_getfield(L, 2, "map"); @@ -410,24 +410,24 @@ { return 0; } - THMap* pMap = (THMap*)lua_touserdata(L, 2); - const THLinkList* pListNode = pAnimation->getPrevious(); - while(pListNode->m_pPrev) + level_map* pMap = (level_map*)lua_touserdata(L, 2); + const link_list* pListNode = pAnimation->get_previous(); + while(pListNode->prev) { - pListNode = pListNode->m_pPrev; + pListNode = pListNode->prev; } - // Casting pListNode to a THMapNode* is slightly dubious, but it should - // work. If on the normal list, then pListNode will be a THMapNode*, and + // Casting pListNode to a map_tile* is slightly dubious, but it should + // work. If on the normal list, then pListNode will be a map_tile*, and // all is fine. However, if on the early list, pListNode will be pointing - // to a member of a THMapNode, so we're relying on pointer arithmetic - // being a subtract and integer divide by sizeof(THMapNode) to yield the - // correct map node. - const THMapNode *pRootNode = pMap->getNodeUnchecked(0, 0); + // to a member of a map_tile, so we're relying on pointer arithmetic + // being a subtract and integer divide by sizeof(map_tile) to yield the + // correct map_tile. + const map_tile *pRootNode = pMap->get_tile_unchecked(0, 0); uintptr_t iDiff = reinterpret_cast(pListNode) - reinterpret_cast(pRootNode); - int iIndex = (int)(iDiff / sizeof(THMapNode)); - int iY = iIndex / pMap->getWidth(); - int iX = iIndex - (iY * pMap->getWidth()); + int iIndex = (int)(iDiff / sizeof(map_tile)); + int iY = iIndex / pMap->get_width(); + int iX = iIndex - (iY * pMap->get_width()); lua_pushinteger(L, iX + 1); lua_pushinteger(L, iY + 1); return 3; // map, x, y @@ -435,9 +435,9 @@ static int l_anim_set_parent(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - THAnimation* pParent = luaT_testuserdata(L, 2, luaT_environindex, false); - pAnimation->setParent(pParent); + animation* pAnimation = luaT_testuserdata(L); + animation* pParent = luaT_testuserdata(L, 2, luaT_environindex, false); + pAnimation->set_parent(pParent); lua_settop(L, 1); return 1; } @@ -446,7 +446,7 @@ static int l_anim_set_flag(lua_State *L) { T* pAnimation = luaT_testuserdata(L); - pAnimation->setFlags(static_cast(luaL_checkinteger(L, 2))); + pAnimation->set_flags(static_cast(luaL_checkinteger(L, 2))); lua_settop(L, 1); return 1; @@ -459,11 +459,11 @@ uint32_t iFlags = static_cast(luaL_checkinteger(L, 2)); if(lua_isnone(L, 3) || lua_toboolean(L, 3)) { - pAnimation->setFlags(pAnimation->getFlags() | iFlags); + pAnimation->set_flags(pAnimation->get_flags() | iFlags); } else { - pAnimation->setFlags(pAnimation->getFlags() & ~iFlags); + pAnimation->set_flags(pAnimation->get_flags() & ~iFlags); } lua_settop(L, 1); return 1; @@ -473,7 +473,7 @@ static int l_anim_make_visible(lua_State *L) { T* pAnimation = luaT_testuserdata(L); - pAnimation->setFlags(pAnimation->getFlags() & ~static_cast(THDF_Alpha50 | THDF_Alpha75)); + pAnimation->set_flags(pAnimation->get_flags() & ~static_cast(thdf_alpha_50 | thdf_alpha_75)); lua_settop(L, 1); return 1; @@ -483,7 +483,7 @@ static int l_anim_make_invisible(lua_State *L) { T* pAnimation = luaT_testuserdata(L); - pAnimation->setFlags(pAnimation->getFlags() | static_cast(THDF_Alpha50 | THDF_Alpha75)); + pAnimation->set_flags(pAnimation->get_flags() | static_cast(thdf_alpha_50 | thdf_alpha_75)); lua_settop(L, 1); return 1; @@ -493,7 +493,7 @@ static int l_anim_get_flag(lua_State *L) { T* pAnimation = luaT_testuserdata(L); - lua_pushinteger(L, pAnimation->getFlags()); + lua_pushinteger(L, pAnimation->get_flags()); return 1; } @@ -503,7 +503,7 @@ { T* pAnimation = luaT_testuserdata(L); - pAnimation->setPosition(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))); + pAnimation->set_position(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))); lua_settop(L, 1); return 1; @@ -511,10 +511,10 @@ static int l_anim_get_position(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); + animation* pAnimation = luaT_testuserdata(L); - lua_pushinteger(L, pAnimation->getX()); - lua_pushinteger(L, pAnimation->getY()); + lua_pushinteger(L, pAnimation->get_x()); + lua_pushinteger(L, pAnimation->get_y()); return 2; } @@ -524,7 +524,7 @@ { T* pAnimation = luaT_testuserdata(L); - pAnimation->setSpeed(static_cast(luaL_optinteger(L, 2, 0)), static_cast(luaL_optinteger(L, 3, 0))); + pAnimation->set_speed(static_cast(luaL_optinteger(L, 2, 0)), static_cast(luaL_optinteger(L, 3, 0))); lua_settop(L, 1); return 1; @@ -535,7 +535,7 @@ { T* pAnimation = luaT_testuserdata(L); - pAnimation->setLayer(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_optinteger(L, 3, 0))); + pAnimation->set_layer(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_optinteger(L, 3, 0))); lua_settop(L, 1); return 1; @@ -543,10 +543,10 @@ static int l_anim_set_layers_from(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); - const THAnimation* pAnimationSrc = luaT_testuserdata(L, 2, luaT_environindex); + animation* pAnimation = luaT_testuserdata(L); + const animation* pAnimationSrc = luaT_testuserdata(L, 2, luaT_environindex); - pAnimation->setLayersFrom(pAnimationSrc); + pAnimation->set_layers_from(pAnimationSrc); lua_settop(L, 1); return 1; @@ -554,7 +554,7 @@ static int l_anim_set_tag(lua_State *L) { - luaT_testuserdata(L); + luaT_testuserdata(L); lua_settop(L, 2); luaT_setenvfield(L, 1, "tag"); return 1; @@ -562,7 +562,7 @@ static int l_anim_get_tag(lua_State *L) { - luaT_testuserdata(L); + luaT_testuserdata(L); lua_settop(L, 1); lua_getfenv(L, 1); lua_getfield(L, 2, "tag"); @@ -571,10 +571,10 @@ static int l_anim_get_marker(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); + animation* pAnimation = luaT_testuserdata(L); int iX = 0; int iY = 0; - pAnimation->getMarker(&iX, &iY); + pAnimation->get_marker(&iX, &iY); lua_pushinteger(L, iX); lua_pushinteger(L, iY); return 2; @@ -582,10 +582,10 @@ static int l_anim_get_secondary_marker(lua_State *L) { - THAnimation* pAnimation = luaT_testuserdata(L); + animation* pAnimation = luaT_testuserdata(L); int iX = 0; int iY = 0; - pAnimation->getSecondaryMarker(&iX, &iY); + pAnimation->get_secondary_marker(&iX, &iY); lua_pushinteger(L, iX); lua_pushinteger(L, iY); return 2; @@ -604,7 +604,7 @@ static int l_anim_draw(lua_State *L) { T* pAnimation = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + render_target* pCanvas = luaT_testuserdata(L, 2); pAnimation->draw(pCanvas, static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))); lua_settop(L, 1); return 1; @@ -612,9 +612,9 @@ static int l_srl_set_sheet(lua_State *L) { - THSpriteRenderList *pSrl = luaT_testuserdata(L); - THSpriteSheet *pSheet = luaT_testuserdata(L, 2); - pSrl->setSheet(pSheet); + sprite_render_list *pSrl = luaT_testuserdata(L); + sprite_sheet *pSheet = luaT_testuserdata(L, 2); + pSrl->set_sheet(pSheet); lua_settop(L, 2); luaT_setenvfield(L, 1, "sheet"); @@ -623,8 +623,8 @@ static int l_srl_append(lua_State *L) { - THSpriteRenderList *pSrl = luaT_testuserdata(L); - pSrl->appendSprite(luaL_checkinteger(L, 2), + sprite_render_list *pSrl = luaT_testuserdata(L); + pSrl->append_sprite(luaL_checkinteger(L, 2), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))); lua_settop(L, 1); return 1; @@ -632,36 +632,36 @@ static int l_srl_set_lifetime(lua_State *L) { - THSpriteRenderList *pSrl = luaT_testuserdata(L); - pSrl->setLifetime(static_cast(luaL_checkinteger(L, 2))); + sprite_render_list *pSrl = luaT_testuserdata(L); + pSrl->set_lifetime(static_cast(luaL_checkinteger(L, 2))); lua_settop(L, 1); return 1; } static int l_srl_is_dead(lua_State *L) { - THSpriteRenderList *pSrl = luaT_testuserdata(L); - lua_pushboolean(L, pSrl->isDead() ? 1 : 0); + sprite_render_list *pSrl = luaT_testuserdata(L); + lua_pushboolean(L, pSrl->is_dead() ? 1 : 0); return 1; } -void THLuaRegisterAnims(const THLuaRegisterState_t *pState) +void lua_register_anims(const lua_register_state *pState) { // Anims - luaT_class(THAnimationManager, l_anims_new, "anims", MT_Anims); + luaT_class(animation_manager, l_anims_new, "anims", lua_metatable::anims); luaT_setfunction(l_anims_load, "load"); luaT_setfunction(l_anims_loadcustom, "loadCustom"); - luaT_setfunction(l_anims_set_spritesheet, "setSheet", MT_Sheet); - luaT_setfunction(l_anims_set_canvas, "setCanvas", MT_Surface); + luaT_setfunction(l_anims_set_spritesheet, "setSheet", lua_metatable::sheet); + luaT_setfunction(l_anims_set_canvas, "setCanvas", lua_metatable::surface); luaT_setfunction(l_anims_getanims, "getAnimations"); luaT_setfunction(l_anims_getfirst, "getFirstFrame"); luaT_setfunction(l_anims_getnext, "getNextFrame"); luaT_setfunction(l_anims_set_alt_pal, "setAnimationGhostPalette"); luaT_setfunction(l_anims_set_marker, "setFrameMarker"); luaT_setfunction(l_anims_set_secondary_marker, "setFrameSecondaryMarker"); - luaT_setfunction(l_anims_draw, "draw", MT_Surface, MT_Layers); - luaT_setconstant("Alt32_GreyScale", THDF_Alt32_GreyScale); - luaT_setconstant("Alt32_BlueRedSwap", THDF_Alt32_BlueRedSwap); + luaT_setfunction(l_anims_draw, "draw", lua_metatable::surface, lua_metatable::layers); + luaT_setconstant("Alt32_GreyScale", thdf_alt32_grey_scale); + luaT_setconstant("Alt32_BlueRedSwap", thdf_alt32_blue_red_swap); luaT_endclass(); // Weak table at AnimMetatable[1] for light UD -> object lookup @@ -671,7 +671,7 @@ lua_pushliteral(pState->L, "v"); lua_setfield(pState->L, -2, "__mode"); lua_setmetatable(pState->L, -2); - lua_rawseti(pState->L, pState->aiMetatables[MT_Anim], 1); + lua_rawseti(pState->L, pState->metatables[static_cast(lua_metatable::anim)], 1); // Weak table at AnimMetatable[2] for light UD -> full UD lookup // For persisting Map @@ -680,68 +680,68 @@ lua_pushliteral(pState->L, "v"); lua_setfield(pState->L, -2, "__mode"); lua_setmetatable(pState->L, -2); - lua_rawseti(pState->L, pState->aiMetatables[MT_Anim], 2); + lua_rawseti(pState->L, pState->metatables[static_cast(lua_metatable::anim)], 2); // Anim - luaT_class(THAnimation, l_anim_new, "animation", MT_Anim); - luaT_setmetamethod(l_anim_persist, "persist"); - luaT_setmetamethod(l_anim_pre_depersist, "pre_depersist"); - luaT_setmetamethod(l_anim_depersist, "depersist"); - luaT_setfunction(l_anim_set_anim, "setAnimation", MT_Anims); + luaT_class(animation, l_anim_new, "animation", lua_metatable::anim); + luaT_setmetamethod(l_anim_persist, "persist"); + luaT_setmetamethod(l_anim_pre_depersist, "pre_depersist"); + luaT_setmetamethod(l_anim_depersist, "depersist"); + luaT_setfunction(l_anim_set_anim, "setAnimation", lua_metatable::anims); luaT_setfunction(l_anim_set_crop, "setCrop"); luaT_setfunction(l_anim_get_crop, "getCrop"); luaT_setfunction(l_anim_set_morph, "setMorph"); luaT_setfunction(l_anim_set_frame, "setFrame"); luaT_setfunction(l_anim_get_frame, "getFrame"); luaT_setfunction(l_anim_get_anim, "getAnimation"); - luaT_setfunction(l_anim_set_tile, "setTile", MT_Map); + luaT_setfunction(l_anim_set_tile, "setTile", lua_metatable::map); luaT_setfunction(l_anim_get_tile, "getTile"); luaT_setfunction(l_anim_set_parent, "setParent"); - luaT_setfunction(l_anim_set_flag, "setFlag"); - luaT_setfunction(l_anim_set_flag_partial, "setPartialFlag"); - luaT_setfunction(l_anim_get_flag, "getFlag"); - luaT_setfunction(l_anim_make_visible, "makeVisible"); - luaT_setfunction(l_anim_make_invisible, "makeInvisible"); + luaT_setfunction(l_anim_set_flag, "setFlag"); + luaT_setfunction(l_anim_set_flag_partial, "setPartialFlag"); + luaT_setfunction(l_anim_get_flag, "getFlag"); + luaT_setfunction(l_anim_make_visible, "makeVisible"); + luaT_setfunction(l_anim_make_invisible, "makeInvisible"); luaT_setfunction(l_anim_set_tag, "setTag"); luaT_setfunction(l_anim_get_tag, "getTag"); - luaT_setfunction(l_anim_set_position, "setPosition"); + luaT_setfunction(l_anim_set_position, "setPosition"); luaT_setfunction(l_anim_get_position, "getPosition"); - luaT_setfunction(l_anim_set_speed, "setSpeed"); - luaT_setfunction(l_anim_set_layer, "setLayer"); + luaT_setfunction(l_anim_set_speed, "setSpeed"); + luaT_setfunction(l_anim_set_layer, "setLayer"); luaT_setfunction(l_anim_set_layers_from, "setLayersFrom"); luaT_setfunction(l_anim_set_hitresult, "setHitTestResult"); luaT_setfunction(l_anim_get_marker, "getMarker"); luaT_setfunction(l_anim_get_secondary_marker, "getSecondaryMarker"); - luaT_setfunction(l_anim_tick, "tick"); - luaT_setfunction(l_anim_draw, "draw", MT_Surface); + luaT_setfunction(l_anim_tick, "tick"); + luaT_setfunction(l_anim_draw, "draw", lua_metatable::surface); luaT_setfunction(l_anim_set_drawable_layer, "setDrawingLayer"); luaT_endclass(); // Duplicate AnimMetatable[1,2] to SpriteListMetatable[1,2] - lua_rawgeti(pState->L, pState->aiMetatables[MT_Anim], 1); - lua_rawseti(pState->L, pState->aiMetatables[MT_SpriteList], 1); - lua_rawgeti(pState->L, pState->aiMetatables[MT_Anim], 2); - lua_rawseti(pState->L, pState->aiMetatables[MT_SpriteList], 2); + lua_rawgeti(pState->L, pState->metatables[static_cast(lua_metatable::anim)], 1); + lua_rawseti(pState->L, pState->metatables[static_cast(lua_metatable::sprite_list)], 1); + lua_rawgeti(pState->L, pState->metatables[static_cast(lua_metatable::anim)], 2); + lua_rawseti(pState->L, pState->metatables[static_cast(lua_metatable::sprite_list)], 2); // SpriteList - luaT_class(THSpriteRenderList, l_anim_new, "spriteList", MT_SpriteList); - luaT_setmetamethod(l_anim_persist, "persist"); - luaT_setmetamethod(l_anim_pre_depersist, "pre_depersist"); - luaT_setmetamethod(l_anim_depersist, "depersist"); - luaT_setfunction(l_srl_set_sheet, "setSheet", MT_Sheet); + luaT_class(sprite_render_list, l_anim_new, "spriteList", lua_metatable::sprite_list); + luaT_setmetamethod(l_anim_persist, "persist"); + luaT_setmetamethod(l_anim_pre_depersist, "pre_depersist"); + luaT_setmetamethod(l_anim_depersist, "depersist"); + luaT_setfunction(l_srl_set_sheet, "setSheet", lua_metatable::sheet); luaT_setfunction(l_srl_append, "append"); luaT_setfunction(l_srl_set_lifetime, "setLifetime"); luaT_setfunction(l_srl_is_dead, "isDead"); - luaT_setfunction(l_anim_set_tile, "setTile", MT_Map); - luaT_setfunction(l_anim_set_flag, "setFlag"); - luaT_setfunction(l_anim_set_flag_partial, "setPartialFlag"); - luaT_setfunction(l_anim_get_flag, "getFlag"); - luaT_setfunction(l_anim_make_visible, "makeVisible"); - luaT_setfunction(l_anim_make_invisible, "makeInvisible"); - luaT_setfunction(l_anim_set_position, "setPosition"); - luaT_setfunction(l_anim_set_speed, "setSpeed"); - luaT_setfunction(l_anim_set_layer, "setLayer"); - luaT_setfunction(l_anim_tick, "tick"); - luaT_setfunction(l_anim_draw, "draw", MT_Surface); + luaT_setfunction(l_anim_set_tile, "setTile", lua_metatable::map); + luaT_setfunction(l_anim_set_flag, "setFlag"); + luaT_setfunction(l_anim_set_flag_partial, "setPartialFlag"); + luaT_setfunction(l_anim_get_flag, "getFlag"); + luaT_setfunction(l_anim_make_visible, "makeVisible"); + luaT_setfunction(l_anim_make_invisible, "makeInvisible"); + luaT_setfunction(l_anim_set_position, "setPosition"); + luaT_setfunction(l_anim_set_speed, "setSpeed"); + luaT_setfunction(l_anim_set_layer, "setLayer"); + luaT_setfunction(l_anim_tick, "tick"); + luaT_setfunction(l_anim_draw, "draw", lua_metatable::surface); luaT_endclass(); } diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua.cpp corsix-th-0.62/CorsixTH/Src/th_lua.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -27,14 +27,14 @@ #include #include -void THLuaRegisterAnims(const THLuaRegisterState_t *pState); -void THLuaRegisterGfx(const THLuaRegisterState_t *pState); -void THLuaRegisterMap(const THLuaRegisterState_t *pState); -void THLuaRegisterSound(const THLuaRegisterState_t *pState); -void THLuaRegisterMovie(const THLuaRegisterState_t *pState); -void THLuaRegisterStrings(const THLuaRegisterState_t *pState); -void THLuaRegisterUI(const THLuaRegisterState_t *pState); -void THLuaRegisterLfsExt(const THLuaRegisterState_t *pState); +void lua_register_anims(const lua_register_state *pState); +void lua_register_gfx(const lua_register_state *pState); +void lua_register_map(const lua_register_state *pState); +void lua_register_sound(const lua_register_state *pState); +void lua_register_movie(const lua_register_state *pState); +void lua_register_strings(const lua_register_state *pState); +void lua_register_ui(const lua_register_state *pState); +void lua_register_lfs_ext(const lua_register_state *pState); //! Set a field on the environment table of an object void luaT_setenvfield(lua_State *L, int index, const char *k) @@ -175,16 +175,16 @@ try { - THStringList oStrings(pData, iDataLength); + th_string_list oStrings(pData, iDataLength); lua_settop(L, 0); - lua_createtable(L, static_cast(oStrings.getSectionCount()), 0); - for(size_t iSec = 0; iSec < oStrings.getSectionCount(); ++iSec) + lua_createtable(L, static_cast(oStrings.get_section_count()), 0); + for(size_t iSec = 0; iSec < oStrings.get_section_count(); ++iSec) { - size_t iCount = oStrings.getSectionSize(iSec); + size_t iCount = oStrings.get_section_size(iSec); lua_createtable(L, static_cast(iCount), 0); for(size_t iStr = 0; iStr < iCount; ++iStr) { - lua_pushstring(L, oStrings.getString(iSec, iStr)); + lua_pushstring(L, oStrings.get_string(iSec, iStr)); lua_rawseti(L, 2, static_cast(iStr + 1)); } lua_rawseti(L, 1, static_cast(iSec + 1)); @@ -244,59 +244,44 @@ return 1; } -void luaT_setclosure(const THLuaRegisterState_t *pState, lua_CFunction fn, - eTHLuaMetatable eMetatable1, ...) -{ - int iUpCount = 0; - va_list args; - for(va_start(args, eMetatable1); - eMetatable1 != MT_Count; - eMetatable1 = static_cast(va_arg(args, int))) - { - if(eMetatable1 == MT_DummyString) - lua_pushstring(pState->L, va_arg(args, char*)); - else - lua_pushvalue(pState->L, pState->aiMetatables[eMetatable1]); - ++iUpCount; - } - va_end(args); - luaT_pushcclosure(pState->L, fn, iUpCount); +void luaT_setclosure(const lua_register_state *pState, lua_CFunction fn, size_t iUps) { + luaT_pushcclosure(pState->L, fn, iUps); } int luaopen_th(lua_State *L) { lua_settop(L, 0); - lua_checkstack(L, 16 + static_cast(MT_Count)); + lua_checkstack(L, 16 + static_cast(lua_metatable::count)); - THLuaRegisterState_t oState; - const THLuaRegisterState_t *pState = &oState; + lua_register_state oState; + const lua_register_state *pState = &oState; oState.L = L; - for(int i = 0; i < static_cast(MT_Count); ++i) + for(int i = 0; i < static_cast(lua_metatable::count); ++i) { lua_createtable(L, 0, 5); - oState.aiMetatables[i] = lua_gettop(L); + oState.metatables[i] = lua_gettop(L); } lua_createtable(L, 0, lua_gettop(L)); - oState.iMainTable = lua_gettop(L); - oState.iTop = lua_gettop(L); + oState.main_table = lua_gettop(L); + oState.top = lua_gettop(L); // Misc. functions - lua_settop(L, oState.iTop); + lua_settop(L, oState.top); luaT_setfunction(l_load_strings, "LoadStrings"); luaT_setfunction(l_get_compile_options, "GetCompileOptions"); - luaT_setfunction(Bootstrap_lua_resources, "GetBuiltinFont"); + luaT_setfunction(bootstrap_lua_resources, "GetBuiltinFont"); // Classes - THLuaRegisterMap(pState); - THLuaRegisterGfx(pState); - THLuaRegisterAnims(pState); - THLuaRegisterSound(pState); - THLuaRegisterMovie(pState); - THLuaRegisterStrings(pState); - THLuaRegisterUI(pState); - THLuaRegisterLfsExt(pState); + lua_register_map(pState); + lua_register_gfx(pState); + lua_register_anims(pState); + lua_register_sound(pState); + lua_register_movie(pState); + lua_register_strings(pState); + lua_register_ui(pState); + lua_register_lfs_ext(pState); - lua_settop(L, oState.iMainTable); + lua_settop(L, oState.main_table); return 1; } diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_gfx.cpp corsix-th-0.62/CorsixTH/Src/th_lua_gfx.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_gfx.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_gfx.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -27,17 +27,17 @@ static int l_palette_new(lua_State *L) { - luaT_stdnew(L); + luaT_stdnew(L); return 1; } static int l_palette_load(lua_State *L) { - THPalette* pPalette = luaT_testuserdata(L); + palette* pPalette = luaT_testuserdata(L); size_t iDataLen; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen); - if(pPalette->loadFromTHFile(pData, iDataLen)) + if(pPalette->load_from_th_file(pData, iDataLen)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -46,8 +46,8 @@ static int l_palette_set_entry(lua_State *L) { - THPalette* pPalette = luaT_testuserdata(L); - lua_pushboolean(L, pPalette->setEntry(static_cast(luaL_checkinteger(L, 2)), + palette* pPalette = luaT_testuserdata(L); + lua_pushboolean(L, pPalette->set_entry(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5))) @@ -57,30 +57,30 @@ static int l_rawbitmap_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_rawbitmap_set_pal(lua_State *L) { - THRawBitmap* pBitmap = luaT_testuserdata(L); - THPalette* pPalette = luaT_testuserdata(L, 2); + raw_bitmap* pBitmap = luaT_testuserdata(L); + palette* pPalette = luaT_testuserdata(L, 2); lua_settop(L, 2); - pBitmap->setPalette(pPalette); + pBitmap->set_palette(pPalette); luaT_setenvfield(L, 1, "palette"); return 1; } static int l_rawbitmap_load(lua_State *L) { - THRawBitmap* pBitmap = luaT_testuserdata(L); + raw_bitmap* pBitmap = luaT_testuserdata(L); size_t iDataLen; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen); int iWidth = static_cast(luaL_checkinteger(L, 3)); - THRenderTarget* pSurface = luaT_testuserdata(L, 4, luaT_upvalueindex(1), false); + render_target* pSurface = luaT_testuserdata(L, 4, luaT_upvalueindex(1), false); - if(pBitmap->loadFromTHFile(pData, iDataLen, iWidth, pSurface)) + if(pBitmap->load_from_th_file(pData, iDataLen, iWidth, pSurface)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -90,8 +90,8 @@ static int l_rawbitmap_draw(lua_State *L) { - THRawBitmap* pBitmap = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + raw_bitmap* pBitmap = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); if(lua_gettop(L) >= 8) { @@ -108,31 +108,31 @@ static int l_spritesheet_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_spritesheet_set_pal(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); - THPalette* pPalette = luaT_testuserdata(L, 2); + sprite_sheet* pSheet = luaT_testuserdata(L); + palette* pPalette = luaT_testuserdata(L, 2); lua_settop(L, 2); - pSheet->setPalette(pPalette); + pSheet->set_palette(pPalette); luaT_setenvfield(L, 1, "palette"); return 1; } static int l_spritesheet_load(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L); size_t iDataLenTable, iDataLenChunk; const uint8_t* pDataTable = luaT_checkfile(L, 2, &iDataLenTable); const uint8_t* pDataChunk = luaT_checkfile(L, 3, &iDataLenChunk); bool bComplex = lua_toboolean(L, 4) != 0; - THRenderTarget* pSurface = luaT_testuserdata(L, 5, luaT_upvalueindex(1), false); + render_target* pSurface = luaT_testuserdata(L, 5, luaT_upvalueindex(1), false); - if(pSheet->loadFromTHFile(pDataTable, iDataLenTable, pDataChunk, iDataLenChunk, bComplex, pSurface)) + if(pSheet->load_from_th_file(pDataTable, iDataLenTable, pDataChunk, iDataLenChunk, bComplex, pSurface)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -142,21 +142,21 @@ static int l_spritesheet_count(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L); - lua_pushinteger(L, pSheet->getSpriteCount()); + lua_pushinteger(L, pSheet->get_sprite_count()); return 1; } static int l_spritesheet_size(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L); size_t iSprite = luaL_checkinteger(L, 2); // No array adjustment - if(iSprite < 0 || iSprite >= pSheet->getSpriteCount()) + if(iSprite < 0 || iSprite >= pSheet->get_sprite_count()) return luaL_argerror(L, 2, "Sprite index out of bounds"); unsigned int iWidth, iHeight; - pSheet->getSpriteSizeUnchecked(iSprite, &iWidth, &iHeight); + pSheet->get_sprite_size_unchecked(iSprite, &iWidth, &iHeight); lua_pushinteger(L, iWidth); lua_pushinteger(L, iHeight); @@ -165,11 +165,11 @@ static int l_spritesheet_draw(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + sprite_sheet* pSheet = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); int iSprite = static_cast(luaL_checkinteger(L, 3)); // No array adjustment - pSheet->drawSprite(pCanvas, iSprite, static_cast(luaL_optinteger(L, 4, 0)), static_cast(luaL_optinteger(L, 5, 0)), static_cast(luaL_optinteger(L, 6, 0))); + pSheet->draw_sprite(pCanvas, iSprite, static_cast(luaL_optinteger(L, 4, 0)), static_cast(luaL_optinteger(L, 5, 0)), static_cast(luaL_optinteger(L, 6, 0))); lua_settop(L, 1); return 1; @@ -177,20 +177,20 @@ static int l_spritesheet_hittest(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L); size_t iSprite = luaL_checkinteger(L, 2); int iX = static_cast(luaL_checkinteger(L, 3)); int iY = static_cast(luaL_checkinteger(L, 4)); uint32_t iFlags = static_cast(luaL_optinteger(L, 5, 0)); - return pSheet->hitTestSprite(iSprite, iX, iY, iFlags); + return pSheet->hit_test_sprite(iSprite, iX, iY, iFlags); } static int l_spritesheet_isvisible(lua_State *L) { - THSpriteSheet* pSheet = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L); size_t iSprite = luaL_checkinteger(L, 2); - THColour oDummy; - lua_pushboolean(L, pSheet->getSpriteAverageColour(iSprite, &oDummy) ? 1:0); + argb_colour oDummy; + lua_pushboolean(L, pSheet->get_sprite_average_colour(iSprite, &oDummy) ? 1:0); return 1; } @@ -201,33 +201,33 @@ static int l_bitmap_font_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_bitmap_font_set_spritesheet(lua_State *L) { - THBitmapFont* pFont = luaT_testuserdata(L); - THSpriteSheet* pSheet = luaT_testuserdata(L, 2); + bitmap_font* pFont = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L, 2); lua_settop(L, 2); - pFont->setSpriteSheet(pSheet); + pFont->set_sprite_sheet(pSheet); luaT_setenvfield(L, 1, "sprites"); return 1; } static int l_bitmap_font_get_spritesheet(lua_State *L) { - luaT_testuserdata(L); + luaT_testuserdata(L); luaT_getenvfield(L, 1, "sprites"); return 1; } static int l_bitmap_font_set_sep(lua_State *L) { - THBitmapFont* pFont = luaT_testuserdata(L); + bitmap_font* pFont = luaT_testuserdata(L); - pFont->setSeparation(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_optinteger(L, 3, 0))); + pFont->set_separation(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_optinteger(L, 3, 0))); lua_settop(L, 1); return 1; @@ -255,7 +255,7 @@ static int l_freetype_font_new(lua_State *L) { - THFreeTypeFont *pFont = luaT_stdnew(L, luaT_environindex, + freetype_font *pFont = luaT_stdnew(L, luaT_environindex, true); l_freetype_throw_error_code(L, pFont->initialise()); return 1; @@ -263,37 +263,37 @@ static int l_freetype_font_set_spritesheet(lua_State *L) { - THFreeTypeFont* pFont = luaT_testuserdata(L); - THSpriteSheet* pSheet = luaT_testuserdata(L, 2); + freetype_font* pFont = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L, 2); lua_settop(L, 2); - l_freetype_throw_error_code(L, pFont->matchBitmapFont(pSheet)); + l_freetype_throw_error_code(L, pFont->match_bitmap_font(pSheet)); lua_settop(L, 1); return 1; } static int l_freetype_font_get_copyright(lua_State *L) { - lua_pushstring(L, THFreeTypeFont::getCopyrightNotice()); + lua_pushstring(L, freetype_font::get_copyright_notice()); return 1; } static int l_freetype_font_set_face(lua_State *L) { - THFreeTypeFont* pFont = luaT_testuserdata(L); + freetype_font* pFont = luaT_testuserdata(L); size_t iLength; const uint8_t* pData = luaT_checkfile(L, 2, &iLength); lua_settop(L, 2); - l_freetype_throw_error_code(L, pFont->setFace(pData, iLength)); + l_freetype_throw_error_code(L, pFont->set_face(pData, iLength)); luaT_setenvfield(L, 1, "face"); return 1; } static int l_freetype_font_clear_cache(lua_State *L) { - THFreeTypeFont* pFont = luaT_testuserdata(L); - pFont->clearCache(); + freetype_font* pFont = luaT_testuserdata(L); + pFont->clear_cache(); return 0; } @@ -301,7 +301,7 @@ static int l_font_get_size(lua_State *L) { - THFont* pFont = luaT_testuserdata(L); + font* pFont = luaT_testuserdata(L); size_t iMsgLen; const char* sMsg = luaT_checkstring(L, 2, &iMsgLen); @@ -309,95 +309,96 @@ if(!lua_isnoneornil(L, 3)) iMaxWidth = static_cast(luaL_checkinteger(L, 3)); - THFontDrawArea oDrawArea = pFont->getTextSize(sMsg, iMsgLen, iMaxWidth); + text_layout oDrawArea = pFont->get_text_dimensions(sMsg, iMsgLen, iMaxWidth); - lua_pushinteger(L, oDrawArea.iEndX); - lua_pushinteger(L, oDrawArea.iEndY); - lua_pushinteger(L, oDrawArea.iNumRows); + lua_pushinteger(L, oDrawArea.end_x); + lua_pushinteger(L, oDrawArea.end_y); + lua_pushinteger(L, oDrawArea.row_count); return 3; } static int l_font_draw(lua_State *L) { - THFont* pFont = luaT_testuserdata(L); - THRenderTarget* pCanvas = nullptr; + font* pFont = luaT_testuserdata(L); + render_target* pCanvas = nullptr; if(!lua_isnoneornil(L, 2)) { - pCanvas = luaT_testuserdata(L, 2); + pCanvas = luaT_testuserdata(L, 2); } size_t iMsgLen; const char* sMsg = luaT_checkstring(L, 3, &iMsgLen); int iX = static_cast(luaL_checkinteger(L, 4)); int iY = static_cast(luaL_checkinteger(L, 5)); - eTHAlign eAlign = Align_Center; - if(!lua_isnoneornil(L, 8)) - { + + text_alignment eAlign = text_alignment::center; + if(!lua_isnoneornil(L, 8)) { const char* sAlign = luaL_checkstring(L, 8); - if(std::strcmp(sAlign, "right") == 0) - eAlign = Align_Right; - else if(std::strcmp(sAlign, "left") == 0) - eAlign = Align_Left; - else if(std::strcmp(sAlign, "center") == 0 - || std::strcmp(sAlign, "centre") == 0 - || std::strcmp(sAlign, "middle") == 0) - { - eAlign = Align_Center; - } - else + if(std::strcmp(sAlign, "right") == 0) { + eAlign = text_alignment::right; + } else if(std::strcmp(sAlign, "left") == 0) { + eAlign = text_alignment::left; + } else if(std::strcmp(sAlign, "center") == 0 || + std::strcmp(sAlign, "centre") == 0 || + std::strcmp(sAlign, "middle") == 0) { + eAlign = text_alignment::center; + } else { return luaL_error(L, "Invalid alignment: \"%s\"", sAlign); + } } - THFontDrawArea oDrawArea = pFont->getTextSize(sMsg, iMsgLen); + text_layout oDrawArea = pFont->get_text_dimensions(sMsg, iMsgLen); if(!lua_isnoneornil(L, 7)) { int iW = static_cast(luaL_checkinteger(L, 6)); int iH = static_cast(luaL_checkinteger(L, 7)); - if(iW > oDrawArea.iEndX && eAlign != Align_Left) - iX += (iW - oDrawArea.iEndX) / ((eAlign == Align_Center) ? 2 : 1); - if(iH > oDrawArea.iEndY) - iY += (iH - oDrawArea.iEndY) / 2; + if(iW > oDrawArea.end_x && eAlign != text_alignment::left) { + iX += (iW - oDrawArea.end_x) / ((eAlign == text_alignment::center) ? 2 : 1); + } + if(iH > oDrawArea.end_y) { + iY += (iH - oDrawArea.end_y) / 2; + } } if(pCanvas != nullptr) { - pFont->drawText(pCanvas, sMsg, iMsgLen, iX, iY); + pFont->draw_text(pCanvas, sMsg, iMsgLen, iX, iY); } - lua_pushinteger(L, iY + oDrawArea.iEndY); - lua_pushinteger(L, iX + oDrawArea.iEndX); + lua_pushinteger(L, iY + oDrawArea.end_y); + lua_pushinteger(L, iX + oDrawArea.end_x); return 2; } static int l_font_draw_wrapped(lua_State *L) { - THFont* pFont = luaT_testuserdata(L); - THRenderTarget* pCanvas = nullptr; + font* pFont = luaT_testuserdata(L); + render_target* pCanvas = nullptr; if(!lua_isnoneornil(L, 2)) { - pCanvas = luaT_testuserdata(L, 2); + pCanvas = luaT_testuserdata(L, 2); } size_t iMsgLen; const char* sMsg = luaT_checkstring(L, 3, &iMsgLen); int iX = static_cast(luaL_checkinteger(L, 4)); int iY = static_cast(luaL_checkinteger(L, 5)); int iW = static_cast(luaL_checkinteger(L, 6)); - eTHAlign eAlign = Align_Left; - if(!lua_isnoneornil(L, 7)) - { + + text_alignment eAlign = text_alignment::left; + if(!lua_isnoneornil(L, 7)) { const char* sAlign = luaL_checkstring(L, 7); - if(std::strcmp(sAlign, "right") == 0) - eAlign = Align_Right; - else if(std::strcmp(sAlign, "left") == 0) - eAlign = Align_Left; - else if(std::strcmp(sAlign, "center") == 0 - || std::strcmp(sAlign, "centre") == 0 - || std::strcmp(sAlign, "middle") == 0) - { - eAlign = Align_Center; - } - else + if(std::strcmp(sAlign, "right") == 0) { + eAlign = text_alignment::right; + } else if(std::strcmp(sAlign, "left") == 0) { + eAlign = text_alignment::left; + } else if(std::strcmp(sAlign, "center") == 0 || + std::strcmp(sAlign, "centre") == 0 || + std::strcmp(sAlign, "middle") == 0) { + eAlign = text_alignment::center; + } else { return luaL_error(L, "Invalid alignment: \"%s\"", sAlign); + } } + int iMaxRows = INT_MAX; if(!lua_isnoneornil(L, 8)) { @@ -410,59 +411,59 @@ iSkipRows = static_cast(luaL_checkinteger(L, 9)); } - THFontDrawArea oDrawArea = pFont->drawTextWrapped(pCanvas, sMsg, iMsgLen, iX, iY, + text_layout oDrawArea = pFont->draw_text_wrapped(pCanvas, sMsg, iMsgLen, iX, iY, iW, iMaxRows, iSkipRows, eAlign); - lua_pushinteger(L, oDrawArea.iEndY); - lua_pushinteger(L, oDrawArea.iEndX); - lua_pushinteger(L, oDrawArea.iNumRows); + lua_pushinteger(L, oDrawArea.end_y); + lua_pushinteger(L, oDrawArea.end_x); + lua_pushinteger(L, oDrawArea.row_count); return 3; } static int l_font_draw_tooltip(lua_State *L) { - THFont* pFont = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + font* pFont = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); size_t iMsgLen; const char* sMsg = luaT_checkstring(L, 3, &iMsgLen); int iX = static_cast(luaL_checkinteger(L, 4)); int iY = static_cast(luaL_checkinteger(L, 5)); - int iScreenWidth = pCanvas->getWidth(); + int iScreenWidth = pCanvas->get_width(); int iW = 200; // (for now) hardcoded width of tooltips - uint32_t iBlack = pCanvas->mapColour(0x00, 0x00, 0x00); - uint32_t iWhite = pCanvas->mapColour(0xFF, 0xFF, 0xFF); - THFontDrawArea oArea = pFont->drawTextWrapped(nullptr, sMsg, iMsgLen, iX + 2, iY + 1, iW - 4, INT_MAX, 0); - int iLastX = iX + oArea.iWidth + 3; - int iFirstY = iY - (oArea.iEndY - iY) - 1; + uint32_t iBlack = pCanvas->map_colour(0x00, 0x00, 0x00); + uint32_t iWhite = pCanvas->map_colour(0xFF, 0xFF, 0xFF); + text_layout oArea = pFont->draw_text_wrapped(nullptr, sMsg, iMsgLen, iX + 2, iY + 1, iW - 4, INT_MAX, 0); + int iLastX = iX + oArea.width + 3; + int iFirstY = iY - (oArea.end_y - iY) - 1; int iXOffset = iLastX > iScreenWidth ? iScreenWidth - iLastX : 0; int iYOffset = iFirstY < 0 ? -iFirstY : 0; - pCanvas->fillRect(iBlack, iX + iXOffset, iFirstY + iYOffset, oArea.iWidth + 3, oArea.iEndY - iY + 2); - pCanvas->fillRect(iWhite, iX + iXOffset + 1, iFirstY + 1 + iYOffset, oArea.iWidth + 1, oArea.iEndY - iY); + pCanvas->fill_rect(iBlack, iX + iXOffset, iFirstY + iYOffset, oArea.width + 3, oArea.end_y - iY + 2); + pCanvas->fill_rect(iWhite, iX + iXOffset + 1, iFirstY + 1 + iYOffset, oArea.width + 1, oArea.end_y - iY); - pFont->drawTextWrapped(pCanvas, sMsg, iMsgLen, iX + 2 + iXOffset, iFirstY + 1 + iYOffset, iW - 4); + pFont->draw_text_wrapped(pCanvas, sMsg, iMsgLen, iX + 2 + iXOffset, iFirstY + 1 + iYOffset, iW - 4); - lua_pushinteger(L, oArea.iEndY); + lua_pushinteger(L, oArea.end_y); return 1; } static int l_layers_new(lua_State *L) { - THLayers_t* pLayers = luaT_stdnew(L, luaT_environindex, false); + layers* pLayers = luaT_stdnew(L, luaT_environindex, false); for(int i = 0; i < 13; ++i) - pLayers->iLayerContents[i] = 0; + pLayers->layer_contents[i] = 0; return 1; } static int l_layers_get(lua_State *L) { - THLayers_t* pLayers = luaT_testuserdata(L); + layers* pLayers = luaT_testuserdata(L); lua_Integer iLayer = luaL_checkinteger(L, 2); if(0 <= iLayer && iLayer < 13) - lua_pushinteger(L, pLayers->iLayerContents[iLayer]); + lua_pushinteger(L, pLayers->layer_contents[iLayer]); else lua_pushnil(L); return 1; @@ -470,53 +471,53 @@ static int l_layers_set(lua_State *L) { - THLayers_t* pLayers = luaT_testuserdata(L); + layers* pLayers = luaT_testuserdata(L); lua_Integer iLayer = luaL_checkinteger(L, 2); uint8_t iValue = static_cast(luaL_checkinteger(L, 3)); if(0 <= iLayer && iLayer < 13) - pLayers->iLayerContents[iLayer] = iValue; + pLayers->layer_contents[iLayer] = iValue; return 0; } static int l_layers_persist(lua_State *L) { - THLayers_t* pLayers = luaT_testuserdata(L); + layers* pLayers = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistWriter* pWriter = (LuaPersistWriter*)lua_touserdata(L, 1); + lua_persist_writer* pWriter = (lua_persist_writer*)lua_touserdata(L, 1); int iNumLayers = 13; for( ; iNumLayers >= 1; --iNumLayers) { - if(pLayers->iLayerContents[iNumLayers - 1] != 0) + if(pLayers->layer_contents[iNumLayers - 1] != 0) break; } - pWriter->writeVUInt(iNumLayers); - pWriter->writeByteStream(pLayers->iLayerContents, iNumLayers); + pWriter->write_uint(iNumLayers); + pWriter->write_byte_stream(pLayers->layer_contents, iNumLayers); return 0; } static int l_layers_depersist(lua_State *L) { - THLayers_t* pLayers = luaT_testuserdata(L); + layers* pLayers = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader* pReader = (lua_persist_reader*)lua_touserdata(L, 1); - std::memset(pLayers->iLayerContents, 0, sizeof(pLayers->iLayerContents)); + std::memset(pLayers->layer_contents, 0, sizeof(pLayers->layer_contents)); int iNumLayers; - if(!pReader->readVUInt(iNumLayers)) + if(!pReader->read_uint(iNumLayers)) return 0; if(iNumLayers > 13) { - if(!pReader->readByteStream(pLayers->iLayerContents, 13)) + if(!pReader->read_byte_stream(pLayers->layer_contents, 13)) return 0; - if(!pReader->readByteStream(nullptr, iNumLayers - 13)) + if(!pReader->read_byte_stream(nullptr, iNumLayers - 13)) return 0; } else { - if(!pReader->readByteStream(pLayers->iLayerContents, iNumLayers)) + if(!pReader->read_byte_stream(pLayers->layer_contents, iNumLayers)) return 0; } return 0; @@ -524,15 +525,15 @@ static int l_cursor_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, false); + luaT_stdnew(L, luaT_environindex, false); return 1; } static int l_cursor_load(lua_State *L) { - THCursor* pCursor = luaT_testuserdata(L); - THSpriteSheet* pSheet = luaT_testuserdata(L, 2); - if(pCursor->createFromSprite(pSheet, static_cast(luaL_checkinteger(L, 3)), + cursor* pCursor = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L, 2); + if(pCursor->create_from_sprite(pSheet, static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_optinteger(L, 4, 0)), static_cast(luaL_optinteger(L, 5, 0)))) { lua_settop(L, 1); @@ -547,28 +548,28 @@ static int l_cursor_use(lua_State *L) { - THCursor* pCursor = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + cursor* pCursor = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); pCursor->use(pCanvas); return 0; } static int l_cursor_position(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L, 1, luaT_upvalueindex(1)); - lua_pushboolean(L, THCursor::setPosition(pCanvas, static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))) ? 1 : 0); + render_target* pCanvas = luaT_testuserdata(L, 1, luaT_upvalueindex(1)); + lua_pushboolean(L, cursor::set_position(pCanvas, static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))) ? 1 : 0); return 1; } /** Construct the helper structure for making a #THRenderTarget. */ -static THRenderTargetCreationParams l_surface_creation_params(lua_State *L, int iArgStart) +static render_target_creation_params l_surface_creation_params(lua_State *L, int iArgStart) { - THRenderTargetCreationParams oParams; - oParams.iWidth = static_cast(luaL_checkinteger(L, iArgStart)); - oParams.iHeight = static_cast(luaL_checkinteger(L, iArgStart + 1)); + render_target_creation_params oParams; + oParams.width = static_cast(luaL_checkinteger(L, iArgStart)); + oParams.height = static_cast(luaL_checkinteger(L, iArgStart + 1)); - oParams.bFullscreen = false; - oParams.bPresentImmediate = false; + oParams.fullscreen = false; + oParams.present_immediate = false; // Parse string arguments, looking for matching parameter names. for(int iArg = iArgStart + 2, iArgCount = lua_gettop(L); iArg <= iArgCount; ++iArg) @@ -577,8 +578,8 @@ if(sOption[0] == 0) continue; - if (std::strcmp(sOption, "fullscreen") == 0) oParams.bFullscreen = true; - if (std::strcmp(sOption, "present immediate") == 0) oParams.bPresentImmediate = true; + if (std::strcmp(sOption, "fullscreen") == 0) oParams.fullscreen = true; + if (std::strcmp(sOption, "present immediate") == 0) oParams.present_immediate = true; } return oParams; @@ -588,93 +589,93 @@ { lua_remove(L, 1); // Value inserted by __call - THRenderTargetCreationParams oParams = l_surface_creation_params(L, 1); - THRenderTarget* pCanvas = luaT_stdnew(L); + render_target_creation_params oParams = l_surface_creation_params(L, 1); + render_target* pCanvas = luaT_stdnew(L); if(pCanvas->create(&oParams)) return 1; lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_update(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - THRenderTargetCreationParams oParams = l_surface_creation_params(L, 2); + render_target* pCanvas = luaT_testuserdata(L); + render_target_creation_params oParams = l_surface_creation_params(L, 2); if(pCanvas->update(&oParams)) { lua_pushnil(L); return 1; } - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 1; } static int l_surface_destroy(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - pCanvas->endFrame(); + render_target* pCanvas = luaT_testuserdata(L); + pCanvas->end_frame(); pCanvas->destroy(); return 1; } static int l_surface_fill_black(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L); lua_settop(L, 1); - if(pCanvas->fillBlack()) + if(pCanvas->fill_black()) return 1; lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_start_frame(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L); lua_settop(L, 1); - if(pCanvas->startFrame()) + if(pCanvas->start_frame()) return 1; lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_end_frame(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L); lua_settop(L, 1); - if(pCanvas->endFrame()) + if(pCanvas->end_frame()) return 1; lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_nonoverlapping(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L); if(lua_isnone(L, 2) || lua_toboolean(L, 2) != 0) - pCanvas->startNonOverlapping(); + pCanvas->start_nonoverlapping_draws(); else - pCanvas->finishNonOverlapping(); + pCanvas->finish_nonoverlapping_draws(); lua_settop(L, 1); return 1; } static int l_surface_set_blue_filter_active(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - pCanvas->setBlueFilterActive((lua_isnoneornil(L, 2) != 0) ? false : (lua_toboolean(L, 2) != 0)); + render_target* pCanvas = luaT_testuserdata(L); + pCanvas->set_blue_filter_active((lua_isnoneornil(L, 2) != 0) ? false : (lua_toboolean(L, 2) != 0)); return 1; } static int l_surface_map(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - lua_pushnumber(L, (lua_Number)pCanvas->mapColour( + render_target* pCanvas = luaT_testuserdata(L); + lua_pushnumber(L, (lua_Number)pCanvas->map_colour( (Uint8)luaL_checkinteger(L, 2), (Uint8)luaL_checkinteger(L, 3), (Uint8)luaL_checkinteger(L, 4))); @@ -683,8 +684,8 @@ static int l_surface_rect(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - if(pCanvas->fillRect(static_cast(luaL_checkinteger(L, 2)), + render_target* pCanvas = luaT_testuserdata(L); + if(pCanvas->fill_rect(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5)), static_cast(luaL_checkinteger(L, 6)))) { @@ -692,29 +693,29 @@ return 1; } lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_screenshot(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L); const char *sFile = luaL_checkstring(L, 2); - if(pCanvas->takeScreenshot(sFile)) + if(pCanvas->take_screenshot(sFile)) { lua_settop(L, 1); return 1; } lua_pushnil(L); - lua_pushstring(L, pCanvas->getLastError()); + lua_pushstring(L, pCanvas->get_last_error()); return 2; } static int l_surface_get_clip(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - THClipRect rcClip; - pCanvas->getClipRect(&rcClip); + render_target* pCanvas = luaT_testuserdata(L); + clip_rect rcClip; + pCanvas->get_clip_rect(&rcClip); lua_pushinteger(L, rcClip.x); lua_pushinteger(L, rcClip.y); lua_pushinteger(L, rcClip.w); @@ -724,30 +725,30 @@ static int l_surface_set_clip(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - THClipRect rcClip; - rcClip.x = static_cast(luaL_checkinteger(L, 2)); - rcClip.y = static_cast(luaL_checkinteger(L, 3)); - rcClip.w = static_cast(luaL_checkinteger(L, 4)); - rcClip.h = static_cast(luaL_checkinteger(L, 5)); + render_target* pCanvas = luaT_testuserdata(L); + clip_rect rcClip; + rcClip.x = static_cast(luaL_checkinteger(L, 2)); + rcClip.y = static_cast(luaL_checkinteger(L, 3)); + rcClip.w = static_cast(luaL_checkinteger(L, 4)); + rcClip.h = static_cast(luaL_checkinteger(L, 5)); if(lua_toboolean(L, 6) != 0) { - THClipRect rcExistingClip; - pCanvas->getClipRect(&rcExistingClip); - IntersectTHClipRect(rcClip, rcExistingClip); + clip_rect rcExistingClip; + pCanvas->get_clip_rect(&rcExistingClip); + clip_rect_intersection(rcClip, rcExistingClip); } - pCanvas->setClipRect(&rcClip); + pCanvas->set_clip_rect(&rcClip); lua_settop(L, 1); return 1; } static int l_surface_scale(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - THScaledItems eToScale = THSI_None; + render_target* pCanvas = luaT_testuserdata(L); + scaled_items eToScale = scaled_items::none; if(lua_isnoneornil(L, 3)) { - eToScale = THSI_All; + eToScale = scaled_items::all; } else { @@ -755,20 +756,20 @@ const char* sOption = lua_tolstring(L, 3, &iLength); if(sOption && iLength >= 6 && std::memcmp(sOption, "bitmap", 6) == 0) { - eToScale = THSI_Bitmaps; + eToScale = scaled_items::bitmaps; } else luaL_error(L, "Expected \"bitmap\" as 2nd argument"); } - lua_pushboolean(L, pCanvas->setScaleFactor(static_cast( + lua_pushboolean(L, pCanvas->set_scale_factor(static_cast( luaL_checknumber(L, 2)), eToScale) ? 1 : 0); return 1; } static int l_surface_set_caption(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - pCanvas->setCaption(luaL_checkstring(L, 2)); + render_target* pCanvas = luaT_testuserdata(L); + pCanvas->set_caption(luaL_checkstring(L, 2)); lua_settop(L, 1); return 1; @@ -776,29 +777,29 @@ static int l_surface_get_renderer_details(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - lua_pushstring(L, pCanvas->getRendererDetails()); + render_target* pCanvas = luaT_testuserdata(L); + lua_pushstring(L, pCanvas->get_renderer_details()); return 1; } // Lua to THRenderTarget->setWindowGrab static int l_surface_set_capture_mouse(lua_State *L) { - THRenderTarget* pCanvas = luaT_testuserdata(L); - pCanvas->setWindowGrab((lua_isnoneornil(L, 2) != 0) ? false : (lua_toboolean(L, 2) != 0)); + render_target* pCanvas = luaT_testuserdata(L); + pCanvas->set_window_grab((lua_isnoneornil(L, 2) != 0) ? false : (lua_toboolean(L, 2) != 0)); return 0; } static int l_line_new(lua_State *L) { - luaT_stdnew(L); + luaT_stdnew(L); return 1; } static int l_move_to(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); - pLine->moveTo(luaL_optnumber(L, 2, 0), luaL_optnumber(L, 3, 0)); + line* pLine = luaT_testuserdata(L); + pLine->move_to(luaL_optnumber(L, 2, 0), luaL_optnumber(L, 3, 0)); lua_settop(L, 1); return 1; @@ -806,8 +807,8 @@ static int l_line_to(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); - pLine->lineTo(luaL_optnumber(L, 2, 0), luaL_optnumber(L, 3, 0)); + line* pLine = luaT_testuserdata(L); + pLine->line_to(luaL_optnumber(L, 2, 0), luaL_optnumber(L, 3, 0)); lua_settop(L, 1); return 1; @@ -815,8 +816,8 @@ static int l_set_width(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); - pLine->setWidth(luaL_optnumber(L, 2, 1)); + line* pLine = luaT_testuserdata(L); + pLine->set_width(luaL_optnumber(L, 2, 1)); lua_settop(L, 1); return 1; @@ -824,8 +825,8 @@ static int l_set_colour(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); - pLine->setColour(static_cast(luaL_optinteger(L, 2, 0)), + line* pLine = luaT_testuserdata(L); + pLine->set_colour(static_cast(luaL_optinteger(L, 2, 0)), static_cast(luaL_optinteger(L, 3, 0)), static_cast(luaL_optinteger(L, 4, 0)), static_cast(luaL_optinteger(L, 5, 255))); @@ -836,8 +837,8 @@ static int l_line_draw(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + line* pLine = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); pLine->draw(pCanvas, static_cast(luaL_optinteger(L, 3, 0)), static_cast(luaL_optinteger(L, 4, 0))); lua_settop(L, 1); @@ -846,72 +847,72 @@ static int l_line_persist(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); + line* pLine = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistWriter* pWriter = (LuaPersistWriter*)lua_touserdata(L, 1); + lua_persist_writer* pWriter = (lua_persist_writer*)lua_touserdata(L, 1); pLine->persist(pWriter); return 0; } static int l_line_depersist(lua_State *L) { - THLine* pLine = luaT_testuserdata(L); + line* pLine = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader* pReader = (lua_persist_reader*)lua_touserdata(L, 1); pLine->depersist(pReader); return 0; } -void THLuaRegisterGfx(const THLuaRegisterState_t *pState) +void lua_register_gfx(const lua_register_state *pState) { // Palette - luaT_class(THPalette, l_palette_new, "palette", MT_Palette); + luaT_class(palette, l_palette_new, "palette", lua_metatable::palette); luaT_setfunction(l_palette_load, "load"); luaT_setfunction(l_palette_set_entry, "setEntry"); luaT_endclass(); // Raw bitmap - luaT_class(THRawBitmap, l_rawbitmap_new, "bitmap", MT_Bitmap); - luaT_setfunction(l_rawbitmap_load, "load", MT_Surface); - luaT_setfunction(l_rawbitmap_set_pal, "setPalette", MT_Palette); - luaT_setfunction(l_rawbitmap_draw, "draw", MT_Surface); + luaT_class(raw_bitmap, l_rawbitmap_new, "bitmap", lua_metatable::bitmap); + luaT_setfunction(l_rawbitmap_load, "load", lua_metatable::surface); + luaT_setfunction(l_rawbitmap_set_pal, "setPalette", lua_metatable::palette); + luaT_setfunction(l_rawbitmap_draw, "draw", lua_metatable::surface); luaT_endclass(); // Sprite sheet - luaT_class(THSpriteSheet, l_spritesheet_new, "sheet", MT_Sheet); + luaT_class(sprite_sheet, l_spritesheet_new, "sheet", lua_metatable::sheet); luaT_setmetamethod(l_spritesheet_count, "len"); - luaT_setfunction(l_spritesheet_load, "load", MT_Surface); - luaT_setfunction(l_spritesheet_set_pal, "setPalette", MT_Palette); + luaT_setfunction(l_spritesheet_load, "load", lua_metatable::surface); + luaT_setfunction(l_spritesheet_set_pal, "setPalette", lua_metatable::palette); luaT_setfunction(l_spritesheet_size, "size"); - luaT_setfunction(l_spritesheet_draw, "draw", MT_Surface); + luaT_setfunction(l_spritesheet_draw, "draw", lua_metatable::surface); luaT_setfunction(l_spritesheet_hittest, "hitTest"); luaT_setfunction(l_spritesheet_isvisible, "isVisible"); luaT_endclass(); // Font // Also adapt the font proxy meta table (font_proxy_mt) in graphics.lua. - luaT_class(THFont, l_font_new, "font", MT_Font); + luaT_class(font, l_font_new, "font", lua_metatable::font); luaT_setfunction(l_font_get_size, "sizeOf"); - luaT_setfunction(l_font_draw, "draw", MT_Surface); - luaT_setfunction(l_font_draw_wrapped, "drawWrapped", MT_Surface); - luaT_setfunction(l_font_draw_tooltip, "drawTooltip", MT_Surface); + luaT_setfunction(l_font_draw, "draw", lua_metatable::surface); + luaT_setfunction(l_font_draw_wrapped, "drawWrapped", lua_metatable::surface); + luaT_setfunction(l_font_draw_tooltip, "drawTooltip", lua_metatable::surface); luaT_endclass(); // BitmapFont - luaT_class(THBitmapFont, l_bitmap_font_new, "bitmap_font", MT_BitmapFont); - luaT_superclass(MT_Font); - luaT_setfunction(l_bitmap_font_set_spritesheet, "setSheet", MT_Sheet); - luaT_setfunction(l_bitmap_font_get_spritesheet, "getSheet", MT_Sheet); + luaT_class(bitmap_font, l_bitmap_font_new, "bitmap_font", lua_metatable::bitmap_font); + luaT_superclass(lua_metatable::font); + luaT_setfunction(l_bitmap_font_set_spritesheet, "setSheet", lua_metatable::sheet); + luaT_setfunction(l_bitmap_font_get_spritesheet, "getSheet", lua_metatable::sheet); luaT_setfunction(l_bitmap_font_set_sep, "setSeparation"); luaT_endclass(); #ifdef CORSIX_TH_USE_FREETYPE2 // FreeTypeFont - luaT_class(THFreeTypeFont, l_freetype_font_new, "freetype_font", MT_FreeTypeFont); - luaT_superclass(MT_Font); - luaT_setfunction(l_freetype_font_set_spritesheet, "setSheet", MT_Sheet); + luaT_class(freetype_font, l_freetype_font_new, "freetype_font", lua_metatable::freetype_font); + luaT_superclass(lua_metatable::font); + luaT_setfunction(l_freetype_font_set_spritesheet, "setSheet", lua_metatable::sheet); luaT_setfunction(l_freetype_font_set_face, "setFace"); luaT_setfunction(l_freetype_font_get_copyright, "getCopyrightNotice"); luaT_setfunction(l_freetype_font_clear_cache, "clearCache"); @@ -919,7 +920,7 @@ #endif // Layers - luaT_class(THLayers_t, l_layers_new, "layers", MT_Layers); + luaT_class(layers, l_layers_new, "layers", lua_metatable::layers); luaT_setmetamethod(l_layers_get, "index"); luaT_setmetamethod(l_layers_set, "newindex"); luaT_setmetamethod(l_layers_persist, "persist"); @@ -927,14 +928,14 @@ luaT_endclass(); // Cursor - luaT_class(THCursor, l_cursor_new, "cursor", MT_Cursor); - luaT_setfunction(l_cursor_load, "load", MT_Sheet); - luaT_setfunction(l_cursor_use, "use", MT_Surface); - luaT_setfunction(l_cursor_position, "setPosition", MT_Surface); + luaT_class(cursor, l_cursor_new, "cursor", lua_metatable::cursor); + luaT_setfunction(l_cursor_load, "load", lua_metatable::sheet); + luaT_setfunction(l_cursor_use, "use", lua_metatable::surface); + luaT_setfunction(l_cursor_position, "setPosition", lua_metatable::surface); luaT_endclass(); // Surface - luaT_class(THRenderTarget, l_surface_new, "surface", MT_Surface); + luaT_class(render_target, l_surface_new, "surface", lua_metatable::surface); luaT_setfunction(l_surface_update, "update"); luaT_setfunction(l_surface_destroy, "destroy"); luaT_setfunction(l_surface_fill_black, "fillBlack"); @@ -954,12 +955,12 @@ luaT_endclass(); // Line - luaT_class(THLine, l_line_new, "line", MT_Line); + luaT_class(line, l_line_new, "line", lua_metatable::line); luaT_setfunction(l_move_to, "moveTo"); luaT_setfunction(l_line_to, "lineTo"); luaT_setfunction(l_set_width, "setWidth"); luaT_setfunction(l_set_colour, "setColour"); - luaT_setfunction(l_line_draw, "draw", MT_Surface); + luaT_setfunction(l_line_draw, "draw", lua_metatable::surface); luaT_setmetamethod(l_line_persist, "persist"); luaT_setmetamethod(l_line_depersist, "depersist"); luaT_endclass(); diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua.h corsix-th-0.62/CorsixTH/Src/th_lua.h --- corsix-th-0.61/CorsixTH/Src/th_lua.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua.h 2018-07-21 11:13:17.000000000 +0000 @@ -170,120 +170,120 @@ template struct luaT_classinfo {}; -class THRenderTarget; -template <> struct luaT_classinfo { +class render_target; +template <> struct luaT_classinfo { static inline const char* name() {return "Surface";} }; -class THMap; -template <> struct luaT_classinfo { +class level_map; +template <> struct luaT_classinfo { static inline const char* name() {return "Map";} }; -class THSpriteSheet; -template <> struct luaT_classinfo { +class sprite_sheet; +template <> struct luaT_classinfo { static inline const char* name() {return "SpriteSheet";} }; -class THAnimation; -template <> struct luaT_classinfo { +class animation; +template <> struct luaT_classinfo { static inline const char* name() {return "Animation";} }; -class THAnimationManager; -template <> struct luaT_classinfo { +class animation_manager; +template <> struct luaT_classinfo { static inline const char* name() {return "Animator";} }; -class THPalette; -template <> struct luaT_classinfo { +class palette; +template <> struct luaT_classinfo { static inline const char* name() {return "Palette";} }; -class THRawBitmap; -template <> struct luaT_classinfo { +class raw_bitmap; +template <> struct luaT_classinfo { static inline const char* name() {return "RawBitmap";} }; -class THFont; -template <> struct luaT_classinfo { +class font; +template <> struct luaT_classinfo { static inline const char* name() {return "Font";} }; -class THBitmapFont; -template <> struct luaT_classinfo { +class bitmap_font; +template <> struct luaT_classinfo { static inline const char* name() {return "BitmapFont";} }; #ifdef CORSIX_TH_USE_FREETYPE2 -class THFreeTypeFont; -template <> struct luaT_classinfo { +class freetype_font; +template <> struct luaT_classinfo { static inline const char* name() {return "FreeTypeFont";} }; #endif -struct THLayers_t; -template <> struct luaT_classinfo { +struct layers; +template <> struct luaT_classinfo { static inline const char* name() {return "Layers";} }; -class THPathfinder; -template <> struct luaT_classinfo { +class pathfinder; +template <> struct luaT_classinfo { static inline const char* name() {return "Pathfinder";} }; -class THCursor; -template <> struct luaT_classinfo { +class cursor; +template <> struct luaT_classinfo { static inline const char* name() {return "Cursor";} }; -class THLine; -template <> struct luaT_classinfo { +class line; +template <> struct luaT_classinfo { static inline const char* name() {return "Line";} }; -struct music_t; -template <> struct luaT_classinfo { +class music; +template <> struct luaT_classinfo { static inline const char* name() {return "Music";} }; -class THSoundArchive; -template <> struct luaT_classinfo { +class sound_archive; +template <> struct luaT_classinfo { static inline const char* name() {return "SoundArchive";} }; -class THSoundEffects; -template <> struct luaT_classinfo { +class sound_player; +template <> struct luaT_classinfo { static inline const char* name() {return "SoundEffects";} }; -class THMovie; -template <> struct luaT_classinfo { +class movie_player; +template <> struct luaT_classinfo { static inline const char* name() {return "Movie";} }; -struct THWindowBase_t; -template <> struct luaT_classinfo { +class abstract_window; +template <> struct luaT_classinfo { static inline const char* name() {return "WindowBase";} }; -class THSpriteRenderList; -template <> struct luaT_classinfo { +class sprite_render_list; +template <> struct luaT_classinfo { static inline const char* name() {return "SpriteRenderList";} }; -struct THStringProxy_t; -template <> struct luaT_classinfo { +class string_proxy; +template <> struct luaT_classinfo { static inline const char* name() {return "StringProxy";} }; -struct THLfsExt; -template <> struct luaT_classinfo { +class lfs_ext; +template <> struct luaT_classinfo { static inline const char* name() {return "LfsExt";} }; -class IsoFilesystem; -template <> struct luaT_classinfo { +class iso_filesystem; +template <> struct luaT_classinfo { static inline const char* name() {return "ISO Filesystem";} }; diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_internal.h corsix-th-0.62/CorsixTH/Src/th_lua_internal.h --- corsix-th-0.61/CorsixTH/Src/th_lua_internal.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_internal.h 2018-07-21 11:13:17.000000000 +0000 @@ -25,53 +25,63 @@ #include "config.h" #include "th_lua.h" -enum eTHLuaMetatable -{ - MT_Map, - MT_Palette, - MT_Sheet, - MT_Font, - MT_BitmapFont, +enum class lua_metatable { + map, + palette, + sheet, + font, + bitmap_font, #ifdef CORSIX_TH_USE_FREETYPE2 - MT_FreeTypeFont, + freetype_font, #endif - MT_Layers, - MT_Anims, - MT_Anim, - MT_Path, - MT_Surface, - MT_Bitmap, - MT_Cursor, - MT_LfsExt, - MT_SoundArc, - MT_SoundFx, - MT_Movie, - MT_String, - MT_WindowBase, - MT_SpriteList, - MT_StringProxy, - MT_Line, - - MT_Count, + layers, + anims, + anim, + pathfinder, + surface, + bitmap, + cursor, + lfs_ext, + sound_archive, + sound_fx, + movie, + string, + window_base, + sprite_list, + string_proxy, + line, - MT_DummyString, + count }; -struct THLuaRegisterState_t +struct lua_register_state { lua_State *L; - int aiMetatables[MT_Count]; - int iMainTable; - int iTop; + int metatables[static_cast(lua_metatable::count)]; + int main_table; + int top; }; -void luaT_setclosure(const THLuaRegisterState_t *pState, lua_CFunction fn, - eTHLuaMetatable eMetatable1, ...); +void luaT_setclosure(const lua_register_state *pState, lua_CFunction fn, size_t iUps); + +template +void luaT_setclosure(const lua_register_state *pState, lua_CFunction fn, size_t iUps, + lua_metatable eMetatable1, Args... args) { + lua_pushvalue(pState->L, pState->metatables[static_cast(eMetatable1)]); + luaT_setclosure(pState, fn, iUps + 1, args...); +} + +template +void luaT_setclosure(const lua_register_state *pState, lua_CFunction fn, size_t iUps, + const char* str, Args... args) { + lua_pushstring(pState->L, str); + luaT_setclosure(pState, fn, iUps + 1, args...); +} #define luaT_class(typnam, new_fn, name, mt) { \ const char * sCurrentClassName = name; \ - int iCurrentClassMT = pState->aiMetatables[mt]; \ - lua_settop(pState->L, pState->iTop); \ + int iCurrentClassMT = pState->metatables[static_cast(mt)]; \ + lua_settop(pState->L, pState->top); \ /* Make metatable the environment for registered functions */ \ lua_pushvalue(pState->L, iCurrentClassMT); \ lua_replace(pState->L, luaT_environindex); \ @@ -95,22 +105,22 @@ #define luaT_superclass(super_mt) \ /* Set __index on the methods metatable to the superclass methods */ \ lua_getmetatable(pState->L, -1); \ - lua_getfield(pState->L, pState->aiMetatables[super_mt], "__index"); \ + lua_getfield(pState->L, pState->metatables[static_cast(super_mt)], "__index"); \ lua_setfield(pState->L, -2, "__index"); \ lua_pop(pState->L, 1); \ /* Set metatable[1] to super_mt */ \ - lua_pushvalue(pState->L, pState->aiMetatables[super_mt]); \ + lua_pushvalue(pState->L, pState->metatables[static_cast(super_mt)]); \ lua_rawseti(pState->L, iCurrentClassMT, 1) #define luaT_endclass() \ - lua_setfield(pState->L, pState->iMainTable, sCurrentClassName); } + lua_setfield(pState->L, pState->main_table, sCurrentClassName); } #define luaT_setmetamethod(fn, name, ...) \ - luaT_setclosure(pState, fn, ## __VA_ARGS__, MT_Count); \ + luaT_setclosure(pState, fn, 0, ## __VA_ARGS__); \ lua_setfield(pState->L, iCurrentClassMT, "__" name) #define luaT_setfunction(fn, name, ...) \ - luaT_setclosure(pState, fn, ## __VA_ARGS__, MT_Count); \ + luaT_setclosure(pState, fn, 0, ## __VA_ARGS__); \ lua_setfield(pState->L, -2, name) /** diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_lfs_ext.cpp corsix-th-0.62/CorsixTH/Src/th_lua_lfs_ext.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_lfs_ext.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_lfs_ext.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -27,11 +27,11 @@ #include #endif -struct THLfsExt {}; +class lfs_ext {}; static int l_lfs_ext_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } @@ -96,9 +96,9 @@ } #endif -void THLuaRegisterLfsExt(const THLuaRegisterState_t *pState) +void lua_register_lfs_ext(const lua_register_state *pState) { - luaT_class(THLfsExt, l_lfs_ext_new, "lfsExt", MT_LfsExt); + luaT_class(lfs_ext, l_lfs_ext_new, "lfsExt", lua_metatable::lfs_ext); luaT_setfunction(l_volume_list, "volumes"); luaT_endclass(); } diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_map.cpp corsix-th-0.62/CorsixTH/Src/th_lua_map.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_map.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_map.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -31,45 +31,45 @@ static int l_map_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_map_set_sheet(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - THSpriteSheet* pSheet = luaT_testuserdata(L, 2); + level_map* pMap = luaT_testuserdata(L); + sprite_sheet* pSheet = luaT_testuserdata(L, 2); lua_settop(L, 2); - pMap->setBlockSheet(pSheet); + pMap->set_block_sheet(pSheet); luaT_setenvfield(L, 1, "sprites"); return 1; } static int l_map_persist(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - pMap->persist((LuaPersistWriter*)lua_touserdata(L, 1)); + pMap->persist((lua_persist_writer*)lua_touserdata(L, 1)); return 0; } static int l_map_depersist(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader* pReader = (lua_persist_reader*)lua_touserdata(L, 1); pMap->depersist(pReader); luaT_getenvfield(L, 2, "sprites"); - pMap->setBlockSheet((THSpriteSheet*)lua_touserdata(L, -1)); + pMap->set_block_sheet((sprite_sheet*)lua_touserdata(L, -1)); lua_pop(L, 1); return 0; } -static void l_map_load_obj_cb(void *pL, int iX, int iY, THObjectType eTHOB, uint8_t iFlags) +static void l_map_load_obj_cb(void *pL, int iX, int iY, object_type eTHOB, uint8_t iFlags) { lua_State *L = reinterpret_cast(pL); lua_createtable(L, 4, 0); @@ -88,12 +88,12 @@ static int l_map_load(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); size_t iDataLen; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen); lua_settop(L, 2); lua_newtable(L); - if(pMap->loadFromTHFile(pData, iDataLen, l_map_load_obj_cb, (void*)L)) + if(pMap->load_from_th_file(pData, iDataLen, l_map_load_obj_cb, (void*)L)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -103,8 +103,8 @@ static int l_map_loadblank(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - if(pMap->loadBlank()) + level_map* pMap = luaT_testuserdata(L); + if(pMap->load_blank()) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -114,20 +114,20 @@ static int l_map_save(lua_State *L) { - THMap *pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); std::string filename(luaL_checkstring(L, 2)); pMap->save(filename); return 0; } -static THAnimation* l_map_updateblueprint_getnextanim(lua_State *L, int& iIndex) +static animation* l_map_updateblueprint_getnextanim(lua_State *L, int& iIndex) { - THAnimation *pAnim; + animation *pAnim; lua_rawgeti(L, 11, iIndex); if(lua_type(L, -1) == LUA_TNIL) { lua_pop(L, 1); - pAnim = luaT_new(L, THAnimation); + pAnim = luaT_new(L, animation); lua_pushvalue(L, luaT_upvalueindex(2)); lua_setmetatable(L, -2); lua_createtable(L, 0, 2); @@ -140,7 +140,7 @@ } else { - pAnim = luaT_testuserdata(L, -1, luaT_upvalueindex(2)); + pAnim = luaT_testuserdata(L, -1, luaT_upvalueindex(2)); lua_pop(L, 1); } ++iIndex; @@ -157,61 +157,77 @@ static int l_map_settemperaturedisplay(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_Integer iTD = luaL_checkinteger(L, 2) - 1; - if (iTD >= THMT_Count) iTD = THMT_Red; - pMap->setTemperatureDisplay(static_cast(iTD)); + level_map* pMap = luaT_testuserdata(L); + lua_Integer iTD = luaL_checkinteger(L, 2); + + temperature_theme temperatureDisplay; + switch(iTD) { + case 1: + temperatureDisplay = temperature_theme::red; + break; + case 2: + temperatureDisplay = temperature_theme::multi_colour; + break; + case 3: + temperatureDisplay = temperature_theme::yellow_red; + break; + default: + return luaL_argerror(L, 2, "TemperatureDisplay index out of bounds"); + } + + pMap->set_temperature_display(temperatureDisplay); + return 1; } static int l_map_updatetemperature(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); uint16_t iAir = l_check_temp(L, 2); uint16_t iRadiator = l_check_temp(L, 3); - pMap->updateTemperatures(iAir, iRadiator); + pMap->update_temperatures(iAir, iRadiator); lua_settop(L, 1); return 1; } static int l_map_gettemperature(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2)) - 1; int iY = static_cast(luaL_checkinteger(L, 3)) - 1; - const THMapNode* pNode = pMap->getNode(iX, iY); - uint16_t iTemp = pMap->getNodeTemperature(pNode); + const map_tile* pNode = pMap->get_tile(iX, iY); + uint16_t iTemp = pMap->get_tile_temperature(pNode); lua_pushnumber(L, static_cast(iTemp) / static_cast(65535)); return 1; } /** - * Is the node position valid for a new room? + * Is the tile position valid for a new room? * @param entire_invalid Entire blueprint is invalid (eg wrong position or too small). - * @param pNode Node to examine. + * @param pNode Tile to examine. * @param pMap The world map. * @param player_id The player to check for. - * @return Whether the node position is valid for a new room. + * @return Whether the tile position is valid for a new room. */ static inline bool is_valid( - bool entire_invalid, const THMapNode *pNode, - const THMap *pMap, int player_id) + bool entire_invalid, const map_tile *pNode, + const level_map* pMap, int player_id) { return !entire_invalid && !pNode->flags.room && pNode->flags.buildable && - (player_id == 0 || pMap->getNodeOwner(pNode) == player_id); + (player_id == 0 || pMap->get_tile_owner(pNode) == player_id); } static int l_map_updateblueprint(lua_State *L) { // NB: This function can be implemented in Lua, but is implemented in C for // efficiency. - const unsigned short iFloorTileGood = 24 + (THDF_Alpha50 << 8); - const unsigned short iFloorTileGoodCenter = 37 + (THDF_Alpha50 << 8); - const unsigned short iFloorTileBad = 67 + (THDF_Alpha50 << 8); + const unsigned short iFloorTileGood = 24 + (thdf_alpha_50 << 8); + const unsigned short iFloorTileGoodCenter = 37 + (thdf_alpha_50 << 8); + const unsigned short iFloorTileBad = 67 + (thdf_alpha_50 << 8); const unsigned int iWallAnimTopCorner = 124; const unsigned int iWallAnim = 120; - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iOldX = static_cast(luaL_checkinteger(L, 2)) - 1; int iOldY = static_cast(luaL_checkinteger(L, 3)) - 1; int iOldW = static_cast(luaL_checkinteger(L, 4)); @@ -223,13 +239,13 @@ int player_id = static_cast(luaL_checkinteger(L, 10)); luaL_checktype(L, 11, LUA_TTABLE); // Animation list - THAnimationManager* pAnims = luaT_testuserdata(L, 12, luaT_upvalueindex(1)); + animation_manager* pAnims = luaT_testuserdata(L, 12, luaT_upvalueindex(1)); bool entire_invalid = lua_toboolean(L, 13) != 0; bool valid = !entire_invalid; - if(iOldX < 0 || iOldY < 0 || (iOldX + iOldW) > pMap->getWidth() || (iOldY + iOldH) > pMap->getHeight()) + if(iOldX < 0 || iOldY < 0 || (iOldX + iOldW) > pMap->get_width() || (iOldY + iOldH) > pMap->get_height()) luaL_argerror(L, 2, "Old rectangle is out of bounds"); - if(iNewX < 0 || iNewY < 0 || (iNewX + iNewW) >= pMap->getWidth() || (iNewY + iNewH) >= pMap->getHeight()) + if(iNewX < 0 || iNewY < 0 || (iNewX + iNewW) >= pMap->get_width() || (iNewY + iNewH) >= pMap->get_height()) luaL_argerror(L, 6, "New rectangle is out of bounds"); // Clear blueprint flag from previous selected floor tiles (copying it to the passable flag). @@ -237,7 +253,7 @@ { for(int iX = iOldX; iX < iOldX + iOldW; ++iX) { - THMapNode *pNode = pMap->getNodeUnchecked(iX, iY); + map_tile *pNode = pMap->get_tile_unchecked(iX, iY); pNode->iBlock[3] = 0; pNode->flags.passable |= pNode->flags.passable_if_not_for_blueprint; pNode->flags.passable_if_not_for_blueprint = false; @@ -249,7 +265,7 @@ { for(int iX = iNewX; iX < iNewX + iNewW; ++iX) { - THMapNode *pNode = pMap->getNodeUnchecked(iX, iY); + map_tile *pNode = pMap->get_tile_unchecked(iX, iY); if(is_valid(entire_invalid, pNode, pMap, player_id)) pNode->iBlock[3] = iFloorTileGood; else @@ -267,68 +283,68 @@ int iCenterX = iNewX + (iNewW - 2) / 2; int iCenterY = iNewY + (iNewH - 2) / 2; - THMapNode *pNode = pMap->getNodeUnchecked(iCenterX, iCenterY); + map_tile *pNode = pMap->get_tile_unchecked(iCenterX, iCenterY); if(pNode->iBlock[3] == iFloorTileGood) pNode->iBlock[3] = iFloorTileGoodCenter + 2; - pNode = pMap->getNodeUnchecked(iCenterX + 1, iCenterY); + pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY); if(pNode->iBlock[3] == iFloorTileGood) pNode->iBlock[3] = iFloorTileGoodCenter + 1; - pNode = pMap->getNodeUnchecked(iCenterX, iCenterY + 1); + pNode = pMap->get_tile_unchecked(iCenterX, iCenterY + 1); if(pNode->iBlock[3] == iFloorTileGood) pNode->iBlock[3] = iFloorTileGoodCenter + 0; - pNode = pMap->getNodeUnchecked(iCenterX + 1, iCenterY + 1); + pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY + 1); if(pNode->iBlock[3] == iFloorTileGood) pNode->iBlock[3] = iFloorTileGoodCenter + 3; } // Set wall animations int iNextAnim = 1; - THAnimation *pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - THMapNode *pNode = pMap->getNodeUnchecked(iNewX, iNewY); - pAnim->setAnimation(pAnims, iWallAnimTopCorner); - pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : THDF_AltPalette)); - pAnim->attachToTile(pNode, 0); + animation *pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); + map_tile *pNode = pMap->get_tile_unchecked(iNewX, iNewY); + pAnim->set_animation(pAnims, iWallAnimTopCorner); + pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette)); + pAnim->attach_to_tile(pNode, 0); for(int iX = iNewX; iX < iNewX + iNewW; ++iX) { if(iX != iNewX) { pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - pNode = pMap->getNodeUnchecked(iX, iNewY); - pAnim->setAnimation(pAnims, iWallAnim); - pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : THDF_AltPalette)); - pAnim->attachToTile(pNode, 0); - pAnim->setPosition(0, 0); + pNode = pMap->get_tile_unchecked(iX, iNewY); + pAnim->set_animation(pAnims, iWallAnim); + pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette)); + pAnim->attach_to_tile(pNode, 0); + pAnim->set_position(0, 0); } pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - pNode = pMap->getNodeUnchecked(iX, iNewY + iNewH - 1); - pAnim->setAnimation(pAnims, iWallAnim); - pAnim->setFlags(THDF_ListBottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : THDF_AltPalette)); - pNode = pMap->getNodeUnchecked(iX, iNewY + iNewH); - pAnim->attachToTile(pNode, 0); - pAnim->setPosition(0, -1); + pNode = pMap->get_tile_unchecked(iX, iNewY + iNewH - 1); + pAnim->set_animation(pAnims, iWallAnim); + pAnim->set_flags(thdf_list_bottom | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette)); + pNode = pMap->get_tile_unchecked(iX, iNewY + iNewH); + pAnim->attach_to_tile(pNode, 0); + pAnim->set_position(0, -1); } for(int iY = iNewY; iY < iNewY + iNewH; ++iY) { if(iY != iNewY) { pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - pNode = pMap->getNodeUnchecked(iNewX, iY); - pAnim->setAnimation(pAnims, iWallAnim); - pAnim->setFlags(THDF_ListBottom | THDF_FlipHorizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : THDF_AltPalette)); - pAnim->attachToTile(pNode, 0); - pAnim->setPosition(2, 0); + pNode = pMap->get_tile_unchecked(iNewX, iY); + pAnim->set_animation(pAnims, iWallAnim); + pAnim->set_flags(thdf_list_bottom | thdf_flip_horizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette)); + pAnim->attach_to_tile(pNode, 0); + pAnim->set_position(2, 0); } pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - pNode = pMap->getNodeUnchecked(iNewX + iNewW - 1, iY); - pAnim->setAnimation(pAnims, iWallAnim); - pAnim->setFlags(THDF_ListBottom | THDF_FlipHorizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : THDF_AltPalette)); - pNode = pMap->getNodeUnchecked(iNewX + iNewW, iY); - pAnim->attachToTile(pNode, 0); - pAnim->setPosition(2, -1); + pNode = pMap->get_tile_unchecked(iNewX + iNewW - 1, iY); + pAnim->set_animation(pAnims, iWallAnim); + pAnim->set_flags(thdf_list_bottom | thdf_flip_horizontal | (is_valid(entire_invalid, pNode, pMap, player_id) ? 0 : thdf_alt_palette)); + pNode = pMap->get_tile_unchecked(iNewX + iNewW, iY); + pAnim->attach_to_tile(pNode, 0); + pAnim->set_position(2, -1); } // Clear away extra animations @@ -338,7 +354,7 @@ for(int i = iNextAnim; i <= iAnimCount; ++i) { pAnim = l_map_updateblueprint_getnextanim(L, iNextAnim); - pAnim->removeFromTile(); + pAnim->remove_from_tile(); lua_pushnil(L); lua_rawseti(L, 11, i); } @@ -350,27 +366,27 @@ static int l_map_getsize(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_pushinteger(L, pMap->getWidth()); - lua_pushinteger(L, pMap->getHeight()); + level_map* pMap = luaT_testuserdata(L); + lua_pushinteger(L, pMap->get_width()); + lua_pushinteger(L, pMap->get_height()); return 2; } static int l_map_get_player_count(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_pushinteger(L, pMap->getPlayerCount()); + level_map* pMap = luaT_testuserdata(L); + lua_pushinteger(L, pMap->get_player_count()); return 1; } static int l_map_set_player_count(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int count = static_cast(luaL_checkinteger(L, 2)); try { - pMap->setPlayerCount(count); + pMap->set_player_count(count); } catch (std::out_of_range) { @@ -381,10 +397,10 @@ static int l_map_get_player_camera(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX, iY; int iPlayer = static_cast(luaL_optinteger(L, 2, 1)); - bool bGood = pMap->getPlayerCameraTile(iPlayer - 1, &iX, &iY); + bool bGood = pMap->get_player_camera_tile(iPlayer - 1, &iX, &iY); if(!bGood) return luaL_error(L, "Player index out of range: %d", iPlayer); lua_pushinteger(L, iX + 1); @@ -394,7 +410,7 @@ static int l_map_set_player_camera(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); int iY = static_cast(luaL_checkinteger(L, 3) - 1); int iPlayer = static_cast(luaL_optinteger(L, 4, 1)); @@ -402,16 +418,16 @@ if (iPlayer < 1 || iPlayer > player_max) return luaL_error(L, "Player index out of range: %i", iPlayer); - pMap->setPlayerCameraTile(iPlayer - 1, iX, iY); + pMap->set_player_camera_tile(iPlayer - 1, iX, iY); return 0; } static int l_map_get_player_heliport(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX, iY; int iPlayer = static_cast(luaL_optinteger(L, 2, 1)); - bool bGood = pMap->getPlayerHeliportTile(iPlayer - 1, &iX, &iY); + bool bGood = pMap->get_player_heliport_tile(iPlayer - 1, &iX, &iY); if(!bGood) return luaL_error(L, "Player index out of range: %d", iPlayer); lua_pushinteger(L, iX + 1); @@ -421,7 +437,7 @@ static int l_map_set_player_heliport(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); int iY = static_cast(luaL_checkinteger(L, 3) - 1); int iPlayer = static_cast(luaL_optinteger(L, 4, 1)); @@ -429,16 +445,16 @@ if (iPlayer < 1 || iPlayer > player_max) return luaL_error(L, "Player index out of range: %i", iPlayer); - pMap->setPlayerHeliportTile(iPlayer - 1, iX, iY); + pMap->set_player_heliport_tile(iPlayer - 1, iX, iY); return 0; } static int l_map_getcell(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) { return luaL_argerror(L, 2, lua_pushfstring(L, "Map co-ordinates out " @@ -462,46 +478,46 @@ } } -/** Recognized node flags by Lua. */ -static const std::map lua_node_flag_map = { - {"passable", th_map_node_flags::key::passable_mask}, - {"hospital", th_map_node_flags::key::hospital_mask}, - {"buildable", th_map_node_flags::key::buildable_mask}, - {"room", th_map_node_flags::key::room_mask}, - {"doorWest", th_map_node_flags::key::door_west_mask}, - {"doorNorth", th_map_node_flags::key::door_north_mask}, - {"tallWest", th_map_node_flags::key::tall_west_mask}, - {"tallNorth", th_map_node_flags::key::tall_north_mask}, - {"travelNorth", th_map_node_flags::key::can_travel_n_mask}, - {"travelEast", th_map_node_flags::key::can_travel_e_mask}, - {"travelSouth", th_map_node_flags::key::can_travel_s_mask}, - {"travelWest", th_map_node_flags::key::can_travel_w_mask}, - {"doNotIdle", th_map_node_flags::key::do_not_idle_mask}, - {"buildableNorth", th_map_node_flags::key::buildable_n_mask}, - {"buildableEast", th_map_node_flags::key::buildable_e_mask}, - {"buildableSouth", th_map_node_flags::key::buildable_s_mask}, - {"buildableWest", th_map_node_flags::key::buildable_w_mask}, +/** Recognized tile flags by Lua. */ +static const std::map lua_tile_flag_map = { + {"passable", map_tile_flags::key::passable_mask}, + {"hospital", map_tile_flags::key::hospital_mask}, + {"buildable", map_tile_flags::key::buildable_mask}, + {"room", map_tile_flags::key::room_mask}, + {"doorWest", map_tile_flags::key::door_west_mask}, + {"doorNorth", map_tile_flags::key::door_north_mask}, + {"tallWest", map_tile_flags::key::tall_west_mask}, + {"tallNorth", map_tile_flags::key::tall_north_mask}, + {"travelNorth", map_tile_flags::key::can_travel_n_mask}, + {"travelEast", map_tile_flags::key::can_travel_e_mask}, + {"travelSouth", map_tile_flags::key::can_travel_s_mask}, + {"travelWest", map_tile_flags::key::can_travel_w_mask}, + {"doNotIdle", map_tile_flags::key::do_not_idle_mask}, + {"buildableNorth", map_tile_flags::key::buildable_n_mask}, + {"buildableEast", map_tile_flags::key::buildable_e_mask}, + {"buildableSouth", map_tile_flags::key::buildable_s_mask}, + {"buildableWest", map_tile_flags::key::buildable_w_mask}, }; /** - * Add the current value of the \a flag in the \a node to the output. + * Add the current value of the \a flag in the \a tile to the output. * @param L Lua context. - * @param node Node to inspect. - * @param flag Flag of the node to check (and report). + * @param tile Tile to inspect. + * @param flag Flag of the tile to check (and report). * @param name Name of the flag in Lua code. */ -static inline void add_cellflag(lua_State *L, const THMapNode *node, - th_map_node_flags::key flag, const std::string &name) +static inline void add_cellflag(lua_State *L, const map_tile *tile, + map_tile_flags::key flag, const std::string &name) { lua_pushlstring(L, name.c_str(), name.size()); - lua_pushboolean(L, node->flags[flag] ? 1 : 0); + lua_pushboolean(L, tile->flags[flag] ? 1 : 0); lua_settable(L, 4); } /** - * Add the current value of a node field to the output. + * Add the current value of a tile field to the output. * @param L Lua context. - * @param value Value of the node field to add. + * @param value Value of the tile field to add. * @param name Name of the field in Lua code. */ static inline void add_cellint(lua_State *L, int value, const std::string &name) @@ -518,10 +534,10 @@ */ static int l_map_getcellflags(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); if(lua_type(L, 4) != LUA_TTABLE) @@ -534,15 +550,15 @@ lua_settop(L, 4); } - // Fill Lua table with the flags and numbers of the node. - for (auto val : lua_node_flag_map) + // Fill Lua table with the flags and numbers of the tile. + for (auto val : lua_tile_flag_map) { add_cellflag(L, pNode, val.second, val.first); } add_cellint(L, pNode->iRoomId, "roomId"); add_cellint(L, pNode->iParcelId, "parcelId"); - add_cellint(L, pMap->getNodeOwner(pNode), "owner"); - add_cellint(L, static_cast(pNode->objects.empty() ? THObjectType::no_object : pNode->objects.front()), "thob"); + add_cellint(L, pMap->get_tile_owner(pNode), "owner"); + add_cellint(L, static_cast(pNode->objects.empty() ? object_type::no_object : pNode->objects.front()), "thob"); return 1; } @@ -552,10 +568,10 @@ of thobs in the object list. */ static int l_map_erase_thobs(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); pNode->objects.clear(); @@ -564,13 +580,13 @@ static int l_map_remove_cell_thob(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); - auto thob = static_cast(luaL_checkinteger(L, 4)); + auto thob = static_cast(luaL_checkinteger(L, 4)); for(auto iter = pNode->objects.begin(); iter != pNode->objects.end(); iter++) { if(*iter == thob) @@ -584,10 +600,10 @@ static int l_map_setcellflags(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); luaL_checktype(L, 4, LUA_TTABLE); @@ -601,8 +617,8 @@ { const char *field = lua_tostring(L, 5); - auto iter = lua_node_flag_map.find(field); - if(iter != lua_node_flag_map.end()) + auto iter = lua_tile_flag_map.find(field); + if(iter != lua_tile_flag_map.end()) { if (lua_toboolean(L, 6) == 0) pNode->flags[(*iter).second] = false; @@ -611,7 +627,7 @@ } else if (std::strcmp(field, "thob") == 0) { - auto thob = static_cast(lua_tointeger(L, 6)); + auto thob = static_cast(lua_tointeger(L, 6)); pNode->objects.push_back(thob); } else if(std::strcmp(field, "parcelId") == 0) @@ -634,18 +650,18 @@ static int l_map_setwallflags(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - pMap->setAllWallDrawFlags((uint8_t)luaL_checkinteger(L, 2)); + level_map* pMap = luaT_testuserdata(L); + pMap->set_all_wall_draw_flags((uint8_t)luaL_checkinteger(L, 2)); lua_settop(L, 1); return 1; } static int l_map_setcell(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX = static_cast(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast(luaL_checkinteger(L, 3) - 1); // the map does too. - THMapNode* pNode = pMap->getNode(iX, iY); + map_tile* pNode = pMap->get_tile(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); if(lua_gettop(L) >= 7) @@ -670,23 +686,23 @@ static int l_map_updateshadows(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - pMap->updateShadows(); + level_map* pMap = luaT_testuserdata(L); + pMap->update_shadows(); lua_settop(L, 1); return 1; } static int l_map_updatepathfinding(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - pMap->updatePathfinding(); + level_map* pMap = luaT_testuserdata(L); + pMap->update_pathfinding(); lua_settop(L, 1); return 1; } static int l_map_mark_room(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX_ = static_cast(luaL_checkinteger(L, 2) - 1); int iY_ = static_cast(luaL_checkinteger(L, 3) - 1); int iW = static_cast(luaL_checkinteger(L, 4)); @@ -694,14 +710,14 @@ uint16_t iTile = static_cast(luaL_checkinteger(L, 6)); uint16_t iRoomId = static_cast(luaL_optinteger(L, 7, 0)); - if(iX_ < 0 || iY_ < 0 || (iX_ + iW) > pMap->getWidth() || (iY_ + iH) > pMap->getHeight()) + if(iX_ < 0 || iY_ < 0 || (iX_ + iW) > pMap->get_width() || (iY_ + iH) > pMap->get_height()) luaL_argerror(L, 2, "Rectangle is out of bounds"); for(int iY = iY_; iY < iY_ + iH; ++iY) { for(int iX = iX_; iX < iX_ + iW; ++iX) { - THMapNode *pNode = pMap->getNodeUnchecked(iX, iY); + map_tile *pNode = pMap->get_tile_unchecked(iX, iY); pNode->iBlock[0] = iTile; pNode->iBlock[3] = 0; pNode->flags.room = true; @@ -711,36 +727,36 @@ } } - pMap->updatePathfinding(); - pMap->updateShadows(); + pMap->update_pathfinding(); + pMap->update_shadows(); lua_settop(L, 1); return 1; } static int l_map_unmark_room(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iX_ = static_cast(luaL_checkinteger(L, 2) - 1); int iY_ = static_cast(luaL_checkinteger(L, 3) - 1); int iW = static_cast(luaL_checkinteger(L, 4)); int iH = static_cast(luaL_checkinteger(L, 5)); - if(iX_ < 0 || iY_ < 0 || (iX_ + iW) > pMap->getWidth() || (iY_ + iH) > pMap->getHeight()) + if(iX_ < 0 || iY_ < 0 || (iX_ + iW) > pMap->get_width() || (iY_ + iH) > pMap->get_height()) luaL_argerror(L, 2, "Rectangle is out of bounds"); for(int iY = iY_; iY < iY_ + iH; ++iY) { for(int iX = iX_; iX < iX_ + iW; ++iX) { - THMapNode *pNode = pMap->getNodeUnchecked(iX, iY); - pNode->iBlock[0] = pMap->getOriginalNodeUnchecked(iX, iY)->iBlock[0]; + map_tile *pNode = pMap->get_tile_unchecked(iX, iY); + pNode->iBlock[0] = pMap->get_original_tile_unchecked(iX, iY)->iBlock[0]; pNode->flags.room = false; pNode->iRoomId = 0; } } - pMap->updatePathfinding(); - pMap->updateShadows(); + pMap->update_pathfinding(); + pMap->update_shadows(); lua_settop(L, 1); return 1; @@ -748,8 +764,8 @@ static int l_map_draw(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - THRenderTarget* pCanvas = luaT_testuserdata(L, 2); + level_map* pMap = luaT_testuserdata(L); + render_target* pCanvas = luaT_testuserdata(L, 2); pMap->draw(pCanvas, static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5)), static_cast(luaL_checkinteger(L, 6)), static_cast(luaL_optinteger(L, 7, 0)), static_cast(luaL_optinteger(L, 8, 0))); @@ -760,8 +776,8 @@ static int l_map_hittest(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - THDrawable* pObject = pMap->hitTest(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))); + level_map* pMap = luaT_testuserdata(L); + drawable* pObject = pMap->hit_test(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))); if(pObject == nullptr) return 0; lua_rawgeti(L, luaT_upvalueindex(1), 1); @@ -772,23 +788,23 @@ static int l_map_get_parcel_tilecount(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int iParcel = static_cast(luaL_checkinteger(L, 2)); - lua_Integer iCount = pMap->getParcelTileCount(iParcel); + lua_Integer iCount = pMap->get_parcel_tile_count(iParcel); lua_pushinteger(L, iCount); return 1; } static int l_map_get_parcel_count(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_pushinteger(L, pMap->getParcelCount()); + level_map* pMap = luaT_testuserdata(L); + lua_pushinteger(L, pMap->get_parcel_count()); return 1; } static int l_map_set_parcel_owner(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int parcelId = static_cast(luaL_checkinteger(L, 2)); int player = static_cast(luaL_checkinteger(L, 3)); if(lua_type(L, 4) != LUA_TTABLE) @@ -800,7 +816,7 @@ { lua_settop(L, 4); } - std::vector> vSplitTiles = pMap->setParcelOwner(parcelId, player); + std::vector> vSplitTiles = pMap->set_parcel_owner(parcelId, player); for (std::vector>::size_type i = 0; i != vSplitTiles.size(); i++) { lua_pushinteger(L, i + 1); @@ -818,15 +834,15 @@ static int l_map_get_parcel_owner(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_pushinteger(L, pMap->getParcelOwner(static_cast(luaL_checkinteger(L, 2)))); + level_map* pMap = luaT_testuserdata(L); + lua_pushinteger(L, pMap->get_parcel_owner(static_cast(luaL_checkinteger(L, 2)))); return 1; } static int l_map_is_parcel_purchasable(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); - lua_pushboolean(L, pMap->isParcelPurchasable(static_cast(luaL_checkinteger(L, 2)), + level_map* pMap = luaT_testuserdata(L); + lua_pushboolean(L, pMap->is_parcel_purchasable(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3))) ? 1 : 0); return 1; } @@ -834,7 +850,7 @@ /* Compute the fraction of corridor tiles with litter, of the parcels owned by the given player. */ static int l_map_get_litter_fraction(lua_State *L) { - THMap* pMap = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L); int owner = static_cast(luaL_checkinteger(L, 2)); if (owner == 0) { @@ -844,12 +860,12 @@ double tile_count = 0; double litter_count = 0; - for (int x = 0; x < pMap->getWidth(); x++) + for (int x = 0; x < pMap->get_width(); x++) { - for (int y = 0; y < pMap->getHeight(); y++) + for (int y = 0; y < pMap->get_height(); y++) { - const THMapNode* pNode = pMap->getNodeUnchecked(x, y); - if (pNode->iParcelId == 0 || owner != pMap->getParcelOwner(pNode->iParcelId) || + const map_tile* pNode = pMap->get_tile_unchecked(x, y); + if (pNode->iParcelId == 0 || owner != pMap->get_parcel_owner(pNode->iParcelId) || pNode->iRoomId != 0) { continue; @@ -858,7 +874,7 @@ tile_count++; for(auto iter = pNode->objects.begin(); iter != pNode->objects.end(); iter++) { - if(*iter == THObjectType::litter) + if(*iter == object_type::litter) { litter_count++; break; @@ -874,52 +890,52 @@ static int l_path_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_path_set_map(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); - THMap* pMap = luaT_testuserdata(L, 2); + pathfinder* pPathfinder = luaT_testuserdata(L); + level_map* pMap = luaT_testuserdata(L, 2); lua_settop(L, 2); - pPathfinder->setDefaultMap(pMap); + pPathfinder->set_default_map(pMap); luaT_setenvfield(L, 1, "map"); return 1; } static int l_path_persist(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); + pathfinder* pPathfinder = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - pPathfinder->persist((LuaPersistWriter*)lua_touserdata(L, 1)); + pPathfinder->persist((lua_persist_writer*)lua_touserdata(L, 1)); return 0; } static int l_path_depersist(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); + pathfinder* pPathfinder = luaT_testuserdata(L); lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader* pReader = (lua_persist_reader*)lua_touserdata(L, 1); pPathfinder->depersist(pReader); luaT_getenvfield(L, 2, "map"); - pPathfinder->setDefaultMap(reinterpret_cast(lua_touserdata(L, -1))); + pPathfinder->set_default_map(reinterpret_cast(lua_touserdata(L, -1))); return 0; } static int l_path_is_reachable_from_hospital(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); - if(pPathfinder->findPathToHospital(nullptr, static_cast(luaL_checkinteger(L, 2) - 1), + pathfinder* pPathfinder = luaT_testuserdata(L); + if(pPathfinder->find_path_to_hospital(nullptr, static_cast(luaL_checkinteger(L, 2) - 1), static_cast(luaL_checkinteger(L, 3) - 1))) { lua_pushboolean(L, 1); int iX, iY; - pPathfinder->getPathEnd(&iX, &iY); + pPathfinder->get_path_end(&iX, &iY); lua_pushinteger(L, iX + 1); lua_pushinteger(L, iY + 1); return 3; @@ -933,11 +949,11 @@ static int l_path_distance(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); - if(pPathfinder->findPath(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, static_cast(luaL_checkinteger(L, 3)) - 1, + pathfinder* pPathfinder = luaT_testuserdata(L); + if(pPathfinder->find_path(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, static_cast(luaL_checkinteger(L, 3)) - 1, static_cast(luaL_checkinteger(L, 4)) - 1, static_cast(luaL_checkinteger(L, 5)) - 1)) { - lua_pushinteger(L, pPathfinder->getPathLength()); + lua_pushinteger(L, pPathfinder->get_path_length()); } else { @@ -948,23 +964,23 @@ static int l_path_path(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); - pPathfinder->findPath(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, static_cast(luaL_checkinteger(L, 3)) - 1, + pathfinder* pPathfinder = luaT_testuserdata(L); + pPathfinder->find_path(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, static_cast(luaL_checkinteger(L, 3)) - 1, static_cast(luaL_checkinteger(L, 4)) - 1, static_cast(luaL_checkinteger(L, 5)) - 1); - pPathfinder->pushResult(L); + pPathfinder->push_result(L); return 2; } static int l_path_idle(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); - if(!pPathfinder->findIdleTile(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, + pathfinder* pPathfinder = luaT_testuserdata(L); + if(!pPathfinder->find_idle_tile(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, static_cast(luaL_checkinteger(L, 3)) - 1, static_cast(luaL_optinteger(L, 4, 0)))) { return 0; } int iX, iY; - pPathfinder->getPathEnd(&iX, &iY); + pPathfinder->get_path_end(&iX, &iY); lua_pushinteger(L, iX + 1); lua_pushinteger(L, iY + 1); return 2; @@ -972,20 +988,20 @@ static int l_path_visit(lua_State *L) { - THPathfinder* pPathfinder = luaT_testuserdata(L); + pathfinder* pPathfinder = luaT_testuserdata(L); luaL_checktype(L, 6, LUA_TFUNCTION); - lua_pushboolean(L, pPathfinder->visitObjects(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, - static_cast(luaL_checkinteger(L, 3)) - 1, static_cast(luaL_checkinteger(L, 4)), + lua_pushboolean(L, pPathfinder->visit_objects(nullptr, static_cast(luaL_checkinteger(L, 2)) - 1, + static_cast(luaL_checkinteger(L, 3)) - 1, static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5)), L, 6, luaL_checkinteger(L, 4) == 0 ? true : false) ? 1 : 0); return 1; } -void THLuaRegisterMap(const THLuaRegisterState_t *pState) +void lua_register_map(const lua_register_state *pState) { // Map - luaT_class(THMap, l_map_new, "map", MT_Map); - luaT_setmetamethod(l_map_persist, "persist", MT_Anim); - luaT_setmetamethod(l_map_depersist, "depersist", MT_Anim); + luaT_class(level_map, l_map_new, "map", lua_metatable::map); + luaT_setmetamethod(l_map_persist, "persist", lua_metatable::anim); + luaT_setmetamethod(l_map_depersist, "depersist", lua_metatable::anim); luaT_setfunction(l_map_load, "load"); luaT_setfunction(l_map_loadblank, "loadBlank"); luaT_setfunction(l_map_save, "save"); @@ -1004,14 +1020,14 @@ luaT_setfunction(l_map_setwallflags, "setWallDrawFlags"); luaT_setfunction(l_map_settemperaturedisplay, "setTemperatureDisplay"); luaT_setfunction(l_map_updatetemperature, "updateTemperatures"); - luaT_setfunction(l_map_updateblueprint, "updateRoomBlueprint", MT_Anims, MT_Anim); + luaT_setfunction(l_map_updateblueprint, "updateRoomBlueprint", lua_metatable::anims, lua_metatable::anim); luaT_setfunction(l_map_updateshadows, "updateShadows"); luaT_setfunction(l_map_updatepathfinding, "updatePathfinding"); luaT_setfunction(l_map_mark_room, "markRoom"); luaT_setfunction(l_map_unmark_room, "unmarkRoom"); - luaT_setfunction(l_map_set_sheet, "setSheet", MT_Sheet); - luaT_setfunction(l_map_draw, "draw", MT_Surface); - luaT_setfunction(l_map_hittest, "hitTestObjects", MT_Anim); + luaT_setfunction(l_map_set_sheet, "setSheet", lua_metatable::sheet); + luaT_setfunction(l_map_draw, "draw", lua_metatable::surface); + luaT_setfunction(l_map_hittest, "hitTestObjects", lua_metatable::anim); luaT_setfunction(l_map_get_parcel_tilecount, "getParcelTileCount"); luaT_setfunction(l_map_get_parcel_count, "getPlotCount"); luaT_setfunction(l_map_set_parcel_owner, "setPlotOwner"); @@ -1023,7 +1039,7 @@ luaT_endclass(); // Pathfinder - luaT_class(THPathfinder, l_path_new, "pathfinder", MT_Path); + luaT_class(pathfinder, l_path_new, "pathfinder", lua_metatable::pathfinder); luaT_setmetamethod(l_path_persist, "persist"); luaT_setmetamethod(l_path_depersist, "depersist"); luaT_setfunction(l_path_distance, "findDistance"); @@ -1031,6 +1047,6 @@ luaT_setfunction(l_path_path, "findPath"); luaT_setfunction(l_path_idle, "findIdleTile"); luaT_setfunction(l_path_visit, "findObject"); - luaT_setfunction(l_path_set_map, "setMap", MT_Map); + luaT_setfunction(l_path_set_map, "setMap", lua_metatable::map); luaT_endclass(); } diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_movie.cpp corsix-th-0.62/CorsixTH/Src/th_lua_movie.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_movie.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_movie.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -26,22 +26,22 @@ static int l_movie_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_movie_set_renderer(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - THRenderTarget *pRenderTarget = luaT_testuserdata(L, 2); - pMovie->setRenderer(pRenderTarget->getRenderer()); + movie_player *pMovie = luaT_testuserdata(L); + render_target *pRenderTarget = luaT_testuserdata(L, 2); + pMovie->set_renderer(pRenderTarget->get_renderer()); return 0; } static int l_movie_enabled(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - lua_pushboolean(L, pMovie->moviesEnabled()); + movie_player *pMovie = luaT_testuserdata(L); + lua_pushboolean(L, pMovie->movies_enabled()); return 1; } @@ -49,11 +49,11 @@ { bool loaded; const char* warning; - THMovie *pMovie = luaT_testuserdata(L); + movie_player *pMovie = luaT_testuserdata(L); const char* filepath = lua_tolstring(L, 2, nullptr); - pMovie->clearLastError(); + pMovie->clear_last_error(); loaded = pMovie->load(filepath); - warning = pMovie->getLastError(); + warning = pMovie->get_last_error(); lua_pushboolean(L, loaded); lua_pushstring(L, warning); return 2; @@ -61,7 +61,7 @@ static int l_movie_unload(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); + movie_player *pMovie = luaT_testuserdata(L); pMovie->unload(); return 0; } @@ -69,46 +69,46 @@ static int l_movie_play(lua_State *L) { const char* warning; - THMovie *pMovie = luaT_testuserdata(L); - pMovie->clearLastError(); + movie_player *pMovie = luaT_testuserdata(L); + pMovie->clear_last_error(); pMovie->play( static_cast(luaL_checkinteger(L, 2))); - warning = pMovie->getLastError(); + warning = pMovie->get_last_error(); lua_pushstring(L, warning); return 1; } static int l_movie_stop(lua_State *L) { - THMovie *pVideo = luaT_testuserdata(L); + movie_player *pVideo = luaT_testuserdata(L); pVideo->stop(); return 0; } static int l_movie_get_native_height(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - lua_pushinteger(L, pMovie->getNativeHeight()); + movie_player *pMovie = luaT_testuserdata(L); + lua_pushinteger(L, pMovie->get_native_height()); return 1; } static int l_movie_get_native_width(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - lua_pushinteger(L, pMovie->getNativeWidth()); + movie_player *pMovie = luaT_testuserdata(L); + lua_pushinteger(L, pMovie->get_native_width()); return 1; } static int l_movie_has_audio_track(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - lua_pushboolean(L, pMovie->hasAudioTrack()); + movie_player *pMovie = luaT_testuserdata(L); + lua_pushboolean(L, pMovie->has_audio_track()); return 1; } static int l_movie_refresh(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); + movie_player *pMovie = luaT_testuserdata(L); pMovie->refresh(SDL_Rect{ static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3)), @@ -119,22 +119,22 @@ static int l_movie_allocate_picture_buffer(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - pMovie->allocatePictureBuffer(); + movie_player *pMovie = luaT_testuserdata(L); + pMovie->allocate_picture_buffer(); return 0; } static int l_movie_deallocate_picture_buffer(lua_State *L) { - THMovie *pMovie = luaT_testuserdata(L); - pMovie->deallocatePictureBuffer(); + movie_player *pMovie = luaT_testuserdata(L); + pMovie->deallocate_picture_buffer(); return 0; } -void THLuaRegisterMovie(const THLuaRegisterState_t *pState) +void lua_register_movie(const lua_register_state *pState) { - luaT_class(THMovie, l_movie_new, "moviePlayer", MT_Movie); - luaT_setfunction(l_movie_set_renderer, "setRenderer", MT_Surface); + luaT_class(movie_player, l_movie_new, "moviePlayer", lua_metatable::movie); + luaT_setfunction(l_movie_set_renderer, "setRenderer", lua_metatable::surface); luaT_setfunction(l_movie_enabled, "getEnabled"); luaT_setfunction(l_movie_load, "load"); luaT_setfunction(l_movie_unload, "unload"); diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_sound.cpp corsix-th-0.62/CorsixTH/Src/th_lua_sound.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_sound.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_sound.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -28,23 +28,23 @@ #include #include -static int m_a_iPlayedSoundCallbackIDs[1000]; -static int m_iPlayedSoundCallbackIDsPointer = 0; -static std::map m_mapSoundTimers; +static int played_sound_callback_ids[1000]; +static int played_sound_callback_index = 0; +static std::map map_sound_timers; static int l_soundarc_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_soundarc_load(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); + sound_archive* pArchive = luaT_testuserdata(L); size_t iDataLen; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen); - if(pArchive->loadFromTHFile(pData, iDataLen)) + if(pArchive->load_from_th_file(pData, iDataLen)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); @@ -53,8 +53,8 @@ static int l_soundarc_count(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); - lua_pushnumber(L, (lua_Number)pArchive->getSoundCount()); + sound_archive* pArchive = luaT_testuserdata(L); + lua_pushnumber(L, (lua_Number)pArchive->get_number_of_sounds()); return 1; } @@ -78,18 +78,18 @@ return std::tolower(*s1) - std::tolower(*s2); } -static size_t l_soundarc_checkidx(lua_State *L, int iArg, THSoundArchive* pArchive) +static size_t l_soundarc_checkidx(lua_State *L, int iArg, sound_archive* pArchive) { if(lua_isnumber(L, iArg)) { size_t iIndex = (size_t)lua_tonumber(L, iArg); - if(iIndex >= pArchive->getSoundCount()) + if(iIndex >= pArchive->get_number_of_sounds()) { lua_pushnil(L); lua_pushfstring(L, "Sound index out of " "bounds (%f is not in range [0, %d])", lua_tonumber(L, iArg), - static_cast(pArchive->getSoundCount()) - 1); - return pArchive->getSoundCount(); + static_cast(pArchive->get_number_of_sounds()) - 1); + return pArchive->get_number_of_sounds(); } return iIndex; } @@ -104,10 +104,10 @@ return iIndex; } lua_pop(L, 2); - size_t iCount = pArchive->getSoundCount(); + size_t iCount = pArchive->get_number_of_sounds(); for(size_t i = 0; i < iCount; ++i) { - if(ignorecase_cmp(sName, pArchive->getSoundFilename(i)) == 0) + if(ignorecase_cmp(sName, pArchive->get_sound_name(i)) == 0) { lua_getfenv(L, 1); lua_pushvalue(L, iArg); @@ -121,37 +121,37 @@ lua_pushliteral(L, "File not found in sound archive: "); lua_pushvalue(L, iArg); lua_concat(L, 2); - return pArchive->getSoundCount(); + return pArchive->get_number_of_sounds(); } -static int l_soundarc_filename(lua_State *L) +static int l_soundarc_sound_name(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); + sound_archive* pArchive = luaT_testuserdata(L); size_t iIndex = l_soundarc_checkidx(L, 2, pArchive); - if(iIndex == pArchive->getSoundCount()) + if(iIndex == pArchive->get_number_of_sounds()) return 2; - lua_pushstring(L, pArchive->getSoundFilename(iIndex)); + lua_pushstring(L, pArchive->get_sound_name(iIndex)); return 1; } static int l_soundarc_duration(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); + sound_archive* pArchive = luaT_testuserdata(L); size_t iIndex = l_soundarc_checkidx(L, 2, pArchive); - if(iIndex == pArchive->getSoundCount()) + if(iIndex == pArchive->get_number_of_sounds()) return 2; - size_t iDuration = pArchive->getSoundDuration(iIndex); + size_t iDuration = pArchive->get_sound_duration(iIndex); lua_pushnumber(L, static_cast(iDuration) / static_cast(1000)); return 1; } -static int l_soundarc_filedata(lua_State *L) +static int l_soundarc_data(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); + sound_archive* pArchive = luaT_testuserdata(L); size_t iIndex = l_soundarc_checkidx(L, 2, pArchive); - if(iIndex == pArchive->getSoundCount()) + if(iIndex == pArchive->get_number_of_sounds()) return 2; - SDL_RWops *pRWops = pArchive->loadSound(iIndex); + SDL_RWops *pRWops = pArchive->load_sound(iIndex); if(!pRWops) return 0; size_t iLength = SDL_RWseek(pRWops, 0, SEEK_END); @@ -168,9 +168,9 @@ static int l_soundarc_sound_exists(lua_State *L) { - THSoundArchive* pArchive = luaT_testuserdata(L); + sound_archive* pArchive = luaT_testuserdata(L); size_t iIndex = l_soundarc_checkidx(L, 2, pArchive); - if(iIndex == pArchive->getSoundCount()) + if(iIndex == pArchive->get_number_of_sounds()) lua_pushboolean(L, 0); else lua_pushboolean(L, 1); @@ -179,15 +179,15 @@ static int l_soundfx_new(lua_State *L) { - luaT_stdnew(L, luaT_environindex, true); + luaT_stdnew(L, luaT_environindex, true); return 1; } static int l_soundfx_set_archive(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); - THSoundArchive *pArchive = luaT_testuserdata(L, 2); - pEffects->setSoundArchive(pArchive); + sound_player *pEffects = luaT_testuserdata(L); + sound_archive *pArchive = luaT_testuserdata(L, 2); + pEffects->populate_from(pArchive); lua_settop(L, 2); luaT_setenvfield(L, 1, "archive"); return 1; @@ -195,15 +195,15 @@ static int l_soundfx_set_sound_volume(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); - pEffects->setSoundEffectsVolume(luaL_checknumber(L, 2)); + sound_player *pEffects = luaT_testuserdata(L); + pEffects->set_sound_effect_volume(luaL_checknumber(L, 2)); return 1; } static int l_soundfx_set_sound_effects_on(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); - pEffects->setSoundEffectsOn(lua_toboolean(L, 2) != 0); + sound_player *pEffects = luaT_testuserdata(L); + pEffects->set_sound_effects_enabled(lua_toboolean(L, 2) != 0); return 1; } @@ -213,8 +213,8 @@ e.type = SDL_USEREVENT_SOUND_OVER; e.user.data1 = param; int iSoundID = *(static_cast(param)); - SDL_RemoveTimer(m_mapSoundTimers[iSoundID]); - m_mapSoundTimers.erase(iSoundID); + SDL_RemoveTimer(map_sound_timers[iSoundID]); + map_sound_timers.erase(iSoundID); SDL_PushEvent(&e); return interval; @@ -222,12 +222,12 @@ static int l_soundfx_play(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); + sound_player *pEffects = luaT_testuserdata(L); lua_settop(L, 7); lua_getfenv(L, 1); lua_pushliteral(L, "archive"); lua_rawget(L,8); - THSoundArchive *pArchive = (THSoundArchive*)lua_touserdata(L, 9); + sound_archive *pArchive = (sound_archive*)lua_touserdata(L, 9); if(pArchive == nullptr) { return 0; @@ -235,15 +235,15 @@ // l_soundarc_checkidx requires the archive at the bottom of the stack lua_replace(L, 1); size_t iIndex = l_soundarc_checkidx(L, 2, pArchive); - if(iIndex == pArchive->getSoundCount()) + if(iIndex == pArchive->get_number_of_sounds()) return 2; if(lua_isnil(L, 4)) { - pEffects->playSound(iIndex, luaL_checknumber(L, 3)); + pEffects->play(iIndex, luaL_checknumber(L, 3)); } else { - pEffects->playSoundAt(iIndex, luaL_checknumber(L, 3), static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5))); + pEffects->play_at(iIndex, luaL_checknumber(L, 3), static_cast(luaL_checkinteger(L, 4)), static_cast(luaL_checkinteger(L, 5))); } //SDL SOUND_OVER Callback Timer: //6: unusedPlayedCallbackID @@ -254,16 +254,16 @@ if(!lua_isnil(L, 7)) iPlayedCallbackDelay = static_cast(luaL_checknumber(L, 7)); - if(m_iPlayedSoundCallbackIDsPointer == sizeof(m_a_iPlayedSoundCallbackIDs)) - m_iPlayedSoundCallbackIDsPointer = 0; + if(played_sound_callback_index == sizeof(played_sound_callback_ids)) + played_sound_callback_index = 0; - m_a_iPlayedSoundCallbackIDs[m_iPlayedSoundCallbackIDsPointer] = static_cast(luaL_checkinteger(L, 6)); - size_t interval = pArchive->getSoundDuration(iIndex) + iPlayedCallbackDelay; + played_sound_callback_ids[played_sound_callback_index] = static_cast(luaL_checkinteger(L, 6)); + size_t interval = pArchive->get_sound_duration(iIndex) + iPlayedCallbackDelay; SDL_TimerID timersID = SDL_AddTimer(static_cast(interval), played_sound_callback, - &(m_a_iPlayedSoundCallbackIDs[m_iPlayedSoundCallbackIDsPointer])); - m_mapSoundTimers.insert(std::pair(m_a_iPlayedSoundCallbackIDs[m_iPlayedSoundCallbackIDsPointer], timersID)); - m_iPlayedSoundCallbackIDsPointer++; + &(played_sound_callback_ids[played_sound_callback_index])); + map_sound_timers.insert(std::pair(played_sound_callback_ids[played_sound_callback_index], timersID)); + played_sound_callback_index++; } lua_pushboolean(L, 1); @@ -272,42 +272,42 @@ static int l_soundfx_set_camera(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); - pEffects->setCamera(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))); + sound_player *pEffects = luaT_testuserdata(L); + pEffects->set_camera(static_cast(luaL_checkinteger(L, 2)), static_cast(luaL_checkinteger(L, 3)), static_cast(luaL_checkinteger(L, 4))); return 0; } static int l_soundfx_reserve_channel(lua_State *L) { int iChannel; - THSoundEffects *pEffects = luaT_testuserdata(L); - iChannel = pEffects->reserveChannel(); + sound_player *pEffects = luaT_testuserdata(L); + iChannel = pEffects->reserve_channel(); lua_pushinteger(L, iChannel); return 1; } static int l_soundfx_release_channel(lua_State *L) { - THSoundEffects *pEffects = luaT_testuserdata(L); - pEffects->releaseChannel(static_cast(luaL_checkinteger(L, 2))); + sound_player *pEffects = luaT_testuserdata(L); + pEffects->release_channel(static_cast(luaL_checkinteger(L, 2))); return 1; } -void THLuaRegisterSound(const THLuaRegisterState_t *pState) +void lua_register_sound(const lua_register_state *pState) { // Sound Archive - luaT_class(THSoundArchive, l_soundarc_new, "soundArchive", MT_SoundArc); + luaT_class(sound_archive, l_soundarc_new, "soundArchive", lua_metatable::sound_archive); luaT_setmetamethod(l_soundarc_count, "len"); luaT_setfunction(l_soundarc_load, "load"); - luaT_setfunction(l_soundarc_filename, "getFilename"); + luaT_setfunction(l_soundarc_sound_name, "getFilename"); // Bad name, doesn't represent a file luaT_setfunction(l_soundarc_duration, "getDuration"); - luaT_setfunction(l_soundarc_filedata, "getFileData"); + luaT_setfunction(l_soundarc_data, "getFileData"); // Bad name, doesn't represent a file luaT_setfunction(l_soundarc_sound_exists, "soundExists"); luaT_endclass(); // Sound Effects - luaT_class(THSoundEffects, l_soundfx_new, "soundEffects", MT_SoundFx); - luaT_setfunction(l_soundfx_set_archive, "setSoundArchive", MT_SoundArc); + luaT_class(sound_player, l_soundfx_new, "soundEffects", lua_metatable::sound_fx); + luaT_setfunction(l_soundfx_set_archive, "setSoundArchive", lua_metatable::sound_archive); luaT_setfunction(l_soundfx_play, "play"); luaT_setfunction(l_soundfx_set_sound_volume, "setSoundVolume"); luaT_setfunction(l_soundfx_set_sound_effects_on, "setSoundEffectsOn"); diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_strings.cpp corsix-th-0.62/CorsixTH/Src/th_lua_strings.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_strings.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_strings.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -51,22 +51,22 @@ environment. */ -struct THStringProxy_t {}; +class string_proxy {}; // We need 2 lightuserdata keys for naming the weak tables in the registry, // which we get by having 2 bytes of dummy global variables. -static uint8_t g_aStringDummyGlobals[2] = {0}; +static uint8_t weak_table_keys[2] = {0}; static inline void aux_push_weak_table(lua_State *L, int iIndex) { - lua_pushlightuserdata(L, &g_aStringDummyGlobals[iIndex]); + lua_pushlightuserdata(L, &weak_table_keys[iIndex]); lua_rawget(L, LUA_REGISTRYINDEX); } // Replace the value at the top of the stack with a userdata proxy static int l_str_new_aux(lua_State *L) { - luaT_stdnew(L); + luaT_stdnew(L); aux_push_weak_table(L, 0); lua_pushvalue(L, -2); lua_pushvalue(L, -4); @@ -444,12 +444,12 @@ { lua_settop(L, 2); lua_insert(L, 1); - LuaPersistWriter *pWriter = (LuaPersistWriter*)lua_touserdata(L, 1); + lua_persist_writer *pWriter = (lua_persist_writer*)lua_touserdata(L, 1); // Recreation instructions are stored in the environment, which is written // automatically. For compatibility, we write a simple boolean. lua_pushboolean(L, 1); - pWriter->writeStackObject(3); + pWriter->write_stack_object(3); lua_getfenv(L, 2); // If there were no instructions (i.e. for the root object) then write the @@ -460,7 +460,7 @@ aux_push_weak_table(L, 0); lua_pushvalue(L, 2); lua_rawget(L, 3); - pWriter->writeStackObject(4); + pWriter->write_stack_object(4); } return 0; } @@ -470,10 +470,10 @@ { lua_settop(L, 2); lua_insert(L, 1); - LuaPersistReader *pReader = (LuaPersistReader*)lua_touserdata(L, 1); + lua_persist_reader *pReader = (lua_persist_reader*)lua_touserdata(L, 1); // Read the instructions for re-creating the value - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return 0; if(lua_type(L, 3) == LUA_TBOOLEAN && lua_toboolean(L, 3) == 1) { @@ -504,7 +504,7 @@ if(lua_objlen(L, 3) == 0) { // No instructions provided, so read the value itself - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return 0; } else @@ -695,14 +695,14 @@ return 1; } -void THLuaRegisterStrings(const THLuaRegisterState_t *pState) +void lua_register_strings(const lua_register_state *pState) { lua_State *L = pState->L; // Create Value, and Cache weak tables for inside-out objects. for(int i = 0; i <= 1; ++i) { - lua_pushlightuserdata(L, &g_aStringDummyGlobals[i]); + lua_pushlightuserdata(L, &weak_table_keys[i]); lua_newtable(L); lua_createtable(L, 0, 1); lua_pushliteral(L, "__mode"); @@ -724,14 +724,14 @@ } // Give the Value weak table a friendly name for Lua code to use lua_pushliteral(L, "StringProxyValues"); - lua_pushlightuserdata(L, &g_aStringDummyGlobals[0]); + lua_pushlightuserdata(L, &weak_table_keys[0]); lua_rawget(L, LUA_REGISTRYINDEX); lua_rawset(L, LUA_REGISTRYINDEX); - luaT_class(THStringProxy_t, l_str_new, "stringProxy", MT_StringProxy); - // As we overwrite __index, move methods to MT_StringProxy[4] - lua_getfield(L, pState->aiMetatables[MT_StringProxy], "__index"); - lua_rawseti(L, pState->aiMetatables[MT_StringProxy], 4); + luaT_class(string_proxy, l_str_new, "stringProxy", lua_metatable::string_proxy); + // As we overwrite __index, move methods to lua_metatable::string_proxy[4] + lua_getfield(L, pState->metatables[static_cast(lua_metatable::string_proxy)], "__index"); + lua_rawseti(L, pState->metatables[static_cast(lua_metatable::string_proxy)], 4); luaT_setmetamethod(l_str_index, "index"); luaT_setmetamethod(l_str_newindex, "newindex"); luaT_setmetamethod(l_str_concat, "concat"); @@ -745,11 +745,11 @@ luaT_setmetamethod(l_str_ipairs, "ipairs"); luaT_setmetamethod(l_str_next, "next"); luaT_setmetamethod(l_str_inext, "inext"); - luaT_setfunction(l_str_func, "format" , MT_DummyString, "format"); - luaT_setfunction(l_str_func, "lower" , MT_DummyString, "lower"); - luaT_setfunction(l_str_func, "rep" , MT_DummyString, "rep"); - luaT_setfunction(l_str_func, "reverse", MT_DummyString, "reverse"); - luaT_setfunction(l_str_func, "upper" , MT_DummyString, "upper"); + luaT_setfunction(l_str_func, "format", "format"); + luaT_setfunction(l_str_func, "lower", "lower"); + luaT_setfunction(l_str_func, "rep", "rep"); + luaT_setfunction(l_str_func, "reverse", "reverse"); + luaT_setfunction(l_str_func, "upper", "upper"); luaT_setfunction(l_str_unwrap, "_unwrap"); luaT_setfunction(l_str_reload, "reload"); luaT_endclass(); diff -Nru corsix-th-0.61/CorsixTH/Src/th_lua_ui.cpp corsix-th-0.62/CorsixTH/Src/th_lua_ui.cpp --- corsix-th-0.61/CorsixTH/Src/th_lua_ui.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_lua_ui.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -25,9 +25,9 @@ #include "th_map.h" #include -struct THWindowBase_t {}; +class abstract_window {}; -static int l_window_base_new(lua_State *L) +static int l_abstract_window_new(lua_State *L) { return luaL_error(L, "windowBase can only be used a base class - " " do not create a windowBase directly."); @@ -41,22 +41,22 @@ static int l_town_map_draw(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - THMap *pMap = luaT_testuserdata(L, 2); - THRenderTarget *pCanvas = luaT_testuserdata(L, 3); + level_map* pMap = luaT_testuserdata(L, 2); + render_target *pCanvas = luaT_testuserdata(L, 3); int iCanvasXBase = static_cast(luaL_checkinteger(L, 4)); int iCanvasYBase = static_cast(luaL_checkinteger(L, 5)); bool bShowHeat = lua_toboolean(L, 6) != 0; - uint32_t iColourMyHosp = pCanvas->mapColour(0, 0, 70); - uint32_t iColourWall = pCanvas->mapColour(255, 255, 255); - uint32_t iColourDoor = pCanvas->mapColour(200, 200, 200); - uint32_t iColourPurchasable = pCanvas->mapColour(255, 0, 0); + uint32_t iColourMyHosp = pCanvas->map_colour(0, 0, 70); + uint32_t iColourWall = pCanvas->map_colour(255, 255, 255); + uint32_t iColourDoor = pCanvas->map_colour(200, 200, 200); + uint32_t iColourPurchasable = pCanvas->map_colour(255, 0, 0); - const THMapNode *pNode = pMap->getNodeUnchecked(0, 0); - const THMapNode *pOriginalNode = pMap->getOriginalNodeUnchecked(0, 0); + const map_tile *pNode = pMap->get_tile_unchecked(0, 0); + const map_tile *pOriginalNode = pMap->get_original_tile_unchecked(0, 0); int iCanvasY = iCanvasYBase + 3; - int iMapWidth = pMap->getWidth(); - for(int iY = 0; iY < pMap->getHeight(); ++iY, iCanvasY += 3) + int iMapWidth = pMap->get_width(); + for(int iY = 0; iY < pMap->get_height(); ++iY, iCanvasY += 3) { int iCanvasX = iCanvasXBase; for(int iX = 0; iX < iMapWidth; ++iX, ++pNode, ++pOriginalNode, iCanvasX += 3) @@ -67,14 +67,14 @@ if(!(pNode->flags.hospital)) { // TODO: Replace 1 with player number - if(pMap->isParcelPurchasable(pNode->iParcelId, 1)) + if(pMap->is_parcel_purchasable(pNode->iParcelId, 1)) iColour = iColourPurchasable; else goto dont_paint_tile; } else if(bShowHeat) { - uint16_t iTemp = pMap->getNodeTemperature(pNode); + uint16_t iTemp = pMap->get_tile_temperature(pNode); if(iTemp < 5200) // Less than 4 degrees iTemp = 0; else if(iTemp > 32767) // More than 25 degrees @@ -85,72 +85,68 @@ const uint16_t minOkTemp = 140; const uint16_t maxOkTemp = 180; - switch(pMap->getTemperatureDisplay()) + uint8_t iR = 0; + uint8_t iG = 0; + uint8_t iB = 0; + switch(pMap->get_temperature_display()) { - case THMT_MultiColour: - { - uint8_t iR = 0; - uint8_t iG = 0; - uint8_t iB = 70; - if(iTemp < minOkTemp) + case temperature_theme::multi_colour: + iB = 70; + if(iTemp < minOkTemp) { iB = range_scale(0, minOkTemp - 1, iTemp, 200, 60); - else if(iTemp < maxOkTemp) + } else if(iTemp < maxOkTemp) { iG = range_scale(minOkTemp, maxOkTemp - 1, iTemp, 140, 224); - else + } else { iR = range_scale(maxOkTemp, 255, iTemp, 224, 255); - iColour = pCanvas->mapColour(iR, iG, iB); - break; - } - case THMT_YellowRed: - if(iTemp < minOkTemp) // Below 11 degrees - { - uint8_t iR = range_scale(0, minOkTemp - 1, iTemp, 100, 213); - uint8_t iG = range_scale(0, minOkTemp - 1, iTemp, 80, 180); - iColour = pCanvas->mapColour(iR, iG, 0); } - else - { - uint8_t iR = range_scale(minOkTemp, 255, iTemp, 223, 235); - uint8_t iG = range_scale(minOkTemp, 255, iTemp, 184, 104); - uint8_t iB = range_scale(minOkTemp, 255, iTemp, 0, 53); - iColour = pCanvas->mapColour(iR, iG, iB); + break; + case temperature_theme::yellow_red: + if(iTemp < minOkTemp) { // Below 11 degrees + iR = range_scale(0, minOkTemp - 1, iTemp, 100, 213); + iG = range_scale(0, minOkTemp - 1, iTemp, 80, 180); + } else { + iR = range_scale(minOkTemp, 255, iTemp, 223, 235); + iG = range_scale(minOkTemp, 255, iTemp, 184, 104); + iB = range_scale(minOkTemp, 255, iTemp, 0, 53); } break; - default: - case THMT_Red: - iColour = pCanvas->mapColour(static_cast(iTemp), 0, 70); + case temperature_theme::red: + iR = static_cast(iTemp); + iB = 70; break; } + + iColour = pCanvas->map_colour(iR, iG, iB); } - pCanvas->fillRect(iColour, iCanvasX, iCanvasY, 3, 3); + pCanvas->fill_rect(iColour, iCanvasX, iCanvasY, 3, 3); } dont_paint_tile: #define IsWall(blk) ((82 <= ((blk) & 0xFF)) && (((blk) & 0xFF) <= 164)) -#define IsWallDrawn(n) pMap->getNodeOwner(pNode) != 0 ? \ +#define IsWallDrawn(n) pMap->get_tile_owner(pNode) != 0 ? \ IsWall(pNode->iBlock[n]) : IsWall(pOriginalNode->iBlock[n]) if(IsWallDrawn(1)) { - pCanvas->fillRect(iColourWall, iCanvasX, iCanvasY, 3, 1); + pCanvas->fill_rect(iColourWall, iCanvasX, iCanvasY, 3, 1); // Draw entrance door auto l = (pNode - 1)->objects; - if(!l.empty() && l.front() == THObjectType::entrance_right_door) { + if(!l.empty() && l.front() == object_type::entrance_right_door) { if (pNode->flags.hospital) { - pCanvas->fillRect(iColourDoor, iCanvasX-6, iCanvasY-2, 9, 3); + pCanvas->fill_rect(iColourDoor, iCanvasX-6, iCanvasY-2, 9, 3); } else { - pCanvas->fillRect(iColourDoor, iCanvasX-6, iCanvasY, 9, 3); + pCanvas->fill_rect(iColourDoor, iCanvasX-6, iCanvasY, 9, 3); } } } if(IsWallDrawn(2)) { - pCanvas->fillRect(iColourWall, iCanvasX, iCanvasY, 1, 3); + pCanvas->fill_rect(iColourWall, iCanvasX, iCanvasY, 1, 3); // Draw entrance door auto l = (pNode - iMapWidth)->objects; - if(!l.empty() && l.front() == THObjectType::entrance_right_door) { + if(!l.empty() && l.front() == object_type::entrance_right_door) { if (pNode->flags.hospital) { - pCanvas->fillRect(iColourDoor, iCanvasX-2, iCanvasY-6, 3, 9); + pCanvas->fill_rect(iColourDoor, iCanvasX-2, iCanvasY-6, 3, 9); } else { - pCanvas->fillRect(iColourDoor, iCanvasX, iCanvasY-6, 3, 9); + pCanvas->fill_rect(iColourDoor, iCanvasX, iCanvasY-6, 3, 9); } } } @@ -162,10 +158,10 @@ return 0; } -void THLuaRegisterUI(const THLuaRegisterState_t *pState) +void lua_register_ui(const lua_register_state *pState) { // WindowBase - luaT_class(THWindowBase_t, l_window_base_new, "windowHelpers", MT_WindowBase); - luaT_setfunction(l_town_map_draw, "townMapDraw", MT_Map, MT_Surface); + luaT_class(abstract_window, l_abstract_window_new, "windowHelpers", lua_metatable::window_base); + luaT_setfunction(l_town_map_draw, "townMapDraw", lua_metatable::map, lua_metatable::surface); luaT_endclass(); } diff -Nru corsix-th-0.61/CorsixTH/Src/th_map.cpp corsix-th-0.62/CorsixTH/Src/th_map.cpp --- corsix-th-0.61/CorsixTH/Src/th_map.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_map.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -34,164 +34,164 @@ #include #include -th_map_node_flags& th_map_node_flags::operator=(uint32_t raw) +map_tile_flags& map_tile_flags::operator=(uint32_t raw) { - passable = (raw & static_cast(th_map_node_flags::key::passable_mask)) != 0; - can_travel_n = (raw & static_cast(th_map_node_flags::key::can_travel_n_mask)) != 0; - can_travel_e = (raw & static_cast(th_map_node_flags::key::can_travel_e_mask)) != 0; - can_travel_s = (raw & static_cast(th_map_node_flags::key::can_travel_s_mask)) != 0; - can_travel_w = (raw & static_cast(th_map_node_flags::key::can_travel_w_mask)) != 0; - hospital = (raw & static_cast(th_map_node_flags::key::hospital_mask)) != 0; - buildable = (raw & static_cast(th_map_node_flags::key::buildable_mask)) != 0; - passable_if_not_for_blueprint = (raw & static_cast(th_map_node_flags::key::passable_if_not_for_blueprint_mask)) != 0; - room = (raw & static_cast(th_map_node_flags::key::room_mask)) != 0; - shadow_half = (raw & static_cast(th_map_node_flags::key::shadow_half_mask)) != 0; - shadow_full = (raw & static_cast(th_map_node_flags::key::shadow_full_mask)) != 0; - shadow_wall = (raw & static_cast(th_map_node_flags::key::shadow_wall_mask)) != 0; - door_north = (raw & static_cast(th_map_node_flags::key::door_north_mask)) != 0; - door_west = (raw & static_cast(th_map_node_flags::key::door_west_mask)) != 0; - do_not_idle = (raw & static_cast(th_map_node_flags::key::do_not_idle_mask)) != 0; - tall_north = (raw & static_cast(th_map_node_flags::key::tall_north_mask)) != 0; - tall_west = (raw & static_cast(th_map_node_flags::key::tall_west_mask)) != 0; - buildable_n = (raw & static_cast(th_map_node_flags::key::buildable_n_mask)) != 0; - buildable_e = (raw & static_cast(th_map_node_flags::key::buildable_e_mask)) != 0; - buildable_s = (raw & static_cast(th_map_node_flags::key::buildable_s_mask)) != 0; - buildable_w = (raw & static_cast(th_map_node_flags::key::buildable_w_mask)) != 0; + passable = (raw & static_cast(map_tile_flags::key::passable_mask)) != 0; + can_travel_n = (raw & static_cast(map_tile_flags::key::can_travel_n_mask)) != 0; + can_travel_e = (raw & static_cast(map_tile_flags::key::can_travel_e_mask)) != 0; + can_travel_s = (raw & static_cast(map_tile_flags::key::can_travel_s_mask)) != 0; + can_travel_w = (raw & static_cast(map_tile_flags::key::can_travel_w_mask)) != 0; + hospital = (raw & static_cast(map_tile_flags::key::hospital_mask)) != 0; + buildable = (raw & static_cast(map_tile_flags::key::buildable_mask)) != 0; + passable_if_not_for_blueprint = (raw & static_cast(map_tile_flags::key::passable_if_not_for_blueprint_mask)) != 0; + room = (raw & static_cast(map_tile_flags::key::room_mask)) != 0; + shadow_half = (raw & static_cast(map_tile_flags::key::shadow_half_mask)) != 0; + shadow_full = (raw & static_cast(map_tile_flags::key::shadow_full_mask)) != 0; + shadow_wall = (raw & static_cast(map_tile_flags::key::shadow_wall_mask)) != 0; + door_north = (raw & static_cast(map_tile_flags::key::door_north_mask)) != 0; + door_west = (raw & static_cast(map_tile_flags::key::door_west_mask)) != 0; + do_not_idle = (raw & static_cast(map_tile_flags::key::do_not_idle_mask)) != 0; + tall_north = (raw & static_cast(map_tile_flags::key::tall_north_mask)) != 0; + tall_west = (raw & static_cast(map_tile_flags::key::tall_west_mask)) != 0; + buildable_n = (raw & static_cast(map_tile_flags::key::buildable_n_mask)) != 0; + buildable_e = (raw & static_cast(map_tile_flags::key::buildable_e_mask)) != 0; + buildable_s = (raw & static_cast(map_tile_flags::key::buildable_s_mask)) != 0; + buildable_w = (raw & static_cast(map_tile_flags::key::buildable_w_mask)) != 0; return *this; } -bool& th_map_node_flags::operator[](th_map_node_flags::key key) +bool& map_tile_flags::operator[](map_tile_flags::key key) { switch(key) { - case th_map_node_flags::key::passable_mask: + case map_tile_flags::key::passable_mask: return passable; - case th_map_node_flags::key::can_travel_n_mask: + case map_tile_flags::key::can_travel_n_mask: return can_travel_n; - case th_map_node_flags::key::can_travel_e_mask: + case map_tile_flags::key::can_travel_e_mask: return can_travel_e; - case th_map_node_flags::key::can_travel_s_mask: + case map_tile_flags::key::can_travel_s_mask: return can_travel_s; - case th_map_node_flags::key::can_travel_w_mask: + case map_tile_flags::key::can_travel_w_mask: return can_travel_w; - case th_map_node_flags::key::hospital_mask: + case map_tile_flags::key::hospital_mask: return hospital; - case th_map_node_flags::key::buildable_mask: + case map_tile_flags::key::buildable_mask: return buildable; - case th_map_node_flags::key::passable_if_not_for_blueprint_mask: + case map_tile_flags::key::passable_if_not_for_blueprint_mask: return passable_if_not_for_blueprint; - case th_map_node_flags::key::room_mask: + case map_tile_flags::key::room_mask: return room; - case th_map_node_flags::key::shadow_half_mask: + case map_tile_flags::key::shadow_half_mask: return shadow_half; - case th_map_node_flags::key::shadow_full_mask: + case map_tile_flags::key::shadow_full_mask: return shadow_full; - case th_map_node_flags::key::shadow_wall_mask: + case map_tile_flags::key::shadow_wall_mask: return shadow_wall; - case th_map_node_flags::key::door_north_mask: + case map_tile_flags::key::door_north_mask: return door_north; - case th_map_node_flags::key::door_west_mask: + case map_tile_flags::key::door_west_mask: return door_west; - case th_map_node_flags::key::do_not_idle_mask: + case map_tile_flags::key::do_not_idle_mask: return do_not_idle; - case th_map_node_flags::key::tall_north_mask: + case map_tile_flags::key::tall_north_mask: return tall_north; - case th_map_node_flags::key::tall_west_mask: + case map_tile_flags::key::tall_west_mask: return tall_west; - case th_map_node_flags::key::buildable_n_mask: + case map_tile_flags::key::buildable_n_mask: return buildable_n; - case th_map_node_flags::key::buildable_e_mask: + case map_tile_flags::key::buildable_e_mask: return buildable_e; - case th_map_node_flags::key::buildable_s_mask: + case map_tile_flags::key::buildable_s_mask: return buildable_s; - case th_map_node_flags::key::buildable_w_mask: + case map_tile_flags::key::buildable_w_mask: return buildable_w; default: - throw std::out_of_range("map node flag is invalid"); + throw std::out_of_range("map tile flag is invalid"); } } -const bool& th_map_node_flags::operator[](th_map_node_flags::key key) const +const bool& map_tile_flags::operator[](map_tile_flags::key key) const { switch(key) { - case th_map_node_flags::key::passable_mask: + case map_tile_flags::key::passable_mask: return passable; - case th_map_node_flags::key::can_travel_n_mask: + case map_tile_flags::key::can_travel_n_mask: return can_travel_n; - case th_map_node_flags::key::can_travel_e_mask: + case map_tile_flags::key::can_travel_e_mask: return can_travel_e; - case th_map_node_flags::key::can_travel_s_mask: + case map_tile_flags::key::can_travel_s_mask: return can_travel_s; - case th_map_node_flags::key::can_travel_w_mask: + case map_tile_flags::key::can_travel_w_mask: return can_travel_w; - case th_map_node_flags::key::hospital_mask: + case map_tile_flags::key::hospital_mask: return hospital; - case th_map_node_flags::key::buildable_mask: + case map_tile_flags::key::buildable_mask: return buildable; - case th_map_node_flags::key::passable_if_not_for_blueprint_mask: + case map_tile_flags::key::passable_if_not_for_blueprint_mask: return passable_if_not_for_blueprint; - case th_map_node_flags::key::room_mask: + case map_tile_flags::key::room_mask: return room; - case th_map_node_flags::key::shadow_half_mask: + case map_tile_flags::key::shadow_half_mask: return shadow_half; - case th_map_node_flags::key::shadow_full_mask: + case map_tile_flags::key::shadow_full_mask: return shadow_full; - case th_map_node_flags::key::shadow_wall_mask: + case map_tile_flags::key::shadow_wall_mask: return shadow_wall; - case th_map_node_flags::key::door_north_mask: + case map_tile_flags::key::door_north_mask: return door_north; - case th_map_node_flags::key::door_west_mask: + case map_tile_flags::key::door_west_mask: return door_west; - case th_map_node_flags::key::do_not_idle_mask: + case map_tile_flags::key::do_not_idle_mask: return do_not_idle; - case th_map_node_flags::key::tall_north_mask: + case map_tile_flags::key::tall_north_mask: return tall_north; - case th_map_node_flags::key::tall_west_mask: + case map_tile_flags::key::tall_west_mask: return tall_west; - case th_map_node_flags::key::buildable_n_mask: + case map_tile_flags::key::buildable_n_mask: return buildable_n; - case th_map_node_flags::key::buildable_e_mask: + case map_tile_flags::key::buildable_e_mask: return buildable_e; - case th_map_node_flags::key::buildable_s_mask: + case map_tile_flags::key::buildable_s_mask: return buildable_s; - case th_map_node_flags::key::buildable_w_mask: + case map_tile_flags::key::buildable_w_mask: return buildable_w; default: - throw std::out_of_range("map node flag is invalid"); + throw std::out_of_range("map tile flag is invalid"); } } -th_map_node_flags::operator uint32_t() const +map_tile_flags::operator uint32_t() const { uint32_t raw = 0; - if(passable) { raw |= static_cast(th_map_node_flags::key::passable_mask); } - if(can_travel_n) { raw |= static_cast(th_map_node_flags::key::can_travel_n_mask); } - if(can_travel_e) { raw |= static_cast(th_map_node_flags::key::can_travel_e_mask); } - if(can_travel_s) { raw |= static_cast(th_map_node_flags::key::can_travel_s_mask); } - if(can_travel_w) { raw |= static_cast(th_map_node_flags::key::can_travel_w_mask); } - if(hospital) { raw |= static_cast(th_map_node_flags::key::hospital_mask); } - if(buildable) { raw |= static_cast(th_map_node_flags::key::buildable_mask); } - if(passable_if_not_for_blueprint) { raw |= static_cast(th_map_node_flags::key::passable_if_not_for_blueprint_mask); } - if(room) { raw |= static_cast(th_map_node_flags::key::room_mask); } - if(shadow_half) { raw |= static_cast(th_map_node_flags::key::shadow_half_mask); } - if(shadow_full) { raw |= static_cast(th_map_node_flags::key::shadow_full_mask); } - if(shadow_wall) { raw |= static_cast(th_map_node_flags::key::shadow_wall_mask); } - if(door_north) { raw |= static_cast(th_map_node_flags::key::door_north_mask); } - if(door_west) { raw |= static_cast(th_map_node_flags::key::door_west_mask); } - if(do_not_idle) { raw |= static_cast(th_map_node_flags::key::do_not_idle_mask); } - if(tall_north) { raw |= static_cast(th_map_node_flags::key::tall_north_mask); } - if(tall_west) { raw |= static_cast(th_map_node_flags::key::tall_west_mask); } - if(buildable_n) { raw |= static_cast(th_map_node_flags::key::buildable_n_mask); } - if(buildable_e) { raw |= static_cast(th_map_node_flags::key::buildable_e_mask); } - if(buildable_s) { raw |= static_cast(th_map_node_flags::key::buildable_s_mask); } - if(buildable_w) { raw |= static_cast(th_map_node_flags::key::buildable_w_mask); } + if(passable) { raw |= static_cast(map_tile_flags::key::passable_mask); } + if(can_travel_n) { raw |= static_cast(map_tile_flags::key::can_travel_n_mask); } + if(can_travel_e) { raw |= static_cast(map_tile_flags::key::can_travel_e_mask); } + if(can_travel_s) { raw |= static_cast(map_tile_flags::key::can_travel_s_mask); } + if(can_travel_w) { raw |= static_cast(map_tile_flags::key::can_travel_w_mask); } + if(hospital) { raw |= static_cast(map_tile_flags::key::hospital_mask); } + if(buildable) { raw |= static_cast(map_tile_flags::key::buildable_mask); } + if(passable_if_not_for_blueprint) { raw |= static_cast(map_tile_flags::key::passable_if_not_for_blueprint_mask); } + if(room) { raw |= static_cast(map_tile_flags::key::room_mask); } + if(shadow_half) { raw |= static_cast(map_tile_flags::key::shadow_half_mask); } + if(shadow_full) { raw |= static_cast(map_tile_flags::key::shadow_full_mask); } + if(shadow_wall) { raw |= static_cast(map_tile_flags::key::shadow_wall_mask); } + if(door_north) { raw |= static_cast(map_tile_flags::key::door_north_mask); } + if(door_west) { raw |= static_cast(map_tile_flags::key::door_west_mask); } + if(do_not_idle) { raw |= static_cast(map_tile_flags::key::do_not_idle_mask); } + if(tall_north) { raw |= static_cast(map_tile_flags::key::tall_north_mask); } + if(tall_west) { raw |= static_cast(map_tile_flags::key::tall_west_mask); } + if(buildable_n) { raw |= static_cast(map_tile_flags::key::buildable_n_mask); } + if(buildable_e) { raw |= static_cast(map_tile_flags::key::buildable_e_mask); } + if(buildable_s) { raw |= static_cast(map_tile_flags::key::buildable_s_mask); } + if(buildable_w) { raw |= static_cast(map_tile_flags::key::buildable_w_mask); } return raw; } -THMapNode::THMapNode() : +map_tile::map_tile() : iParcelId(0), iRoomId(0), objects() @@ -204,74 +204,74 @@ flags = {}; } -THMapNode::~THMapNode() +map_tile::~map_tile() { } -THMap::THMap() +level_map::level_map() { - m_iWidth = 0; - m_iHeight = 0; - m_iPlayerCount = 0; - m_iCurrentTemperatureIndex = 0; - m_eTempDisplay = THMT_Red; - m_iParcelCount = 0; - m_pCells = nullptr; - m_pOriginalCells = nullptr; - m_pBlocks = nullptr; - m_pOverlay = nullptr; - m_bOwnOverlay = false; - m_pPlotOwner = nullptr; - m_pParcelTileCounts = nullptr; - m_pParcelAdjacencyMatrix = nullptr; - m_pPurchasableMatrix = nullptr; + width = 0; + height = 0; + player_count = 0; + current_temperature_index = 0; + current_temperature_theme = temperature_theme::red; + parcel_count = 0; + cells = nullptr; + original_cells = nullptr; + blocks = nullptr; + overlay = nullptr; + owns_overlay = false; + plot_owner = nullptr; + parcel_tile_counts = nullptr; + parcel_adjacency_matrix = nullptr; + purchasable_matrix = nullptr; } -THMap::~THMap() +level_map::~level_map() { - setOverlay(nullptr, false); - delete[] m_pCells; - delete[] m_pOriginalCells; - delete[] m_pPlotOwner; - delete[] m_pParcelTileCounts; - delete[] m_pParcelAdjacencyMatrix; - delete[] m_pPurchasableMatrix; + set_overlay(nullptr, false); + delete[] cells; + delete[] original_cells; + delete[] plot_owner; + delete[] parcel_tile_counts; + delete[] parcel_adjacency_matrix; + delete[] purchasable_matrix; } -void THMap::setOverlay(THMapOverlay *pOverlay, bool bTakeOwnership) +void level_map::set_overlay(map_overlay *pOverlay, bool bTakeOwnership) { - if(m_pOverlay && m_bOwnOverlay) - delete m_pOverlay; - m_pOverlay = pOverlay; - m_bOwnOverlay = bTakeOwnership; + if(overlay && owns_overlay) + delete overlay; + overlay = pOverlay; + owns_overlay = bTakeOwnership; } -bool THMap::setSize(int iWidth, int iHeight) +bool level_map::set_size(int iWidth, int iHeight) { if(iWidth <= 0 || iHeight <= 0) return false; - delete[] m_pCells; - delete[] m_pOriginalCells; - delete[] m_pParcelAdjacencyMatrix; - delete[] m_pPurchasableMatrix; - m_iWidth = iWidth; - m_iHeight = iHeight; - m_pCells = nullptr; - m_pCells = new (std::nothrow) THMapNode[iWidth * iHeight]; - m_pOriginalCells = nullptr; - m_pOriginalCells = new (std::nothrow) THMapNode[iWidth * iHeight]; - m_pParcelAdjacencyMatrix = nullptr; - m_pPurchasableMatrix = nullptr; - - if(m_pCells == nullptr || m_pOriginalCells == nullptr) - { - delete[] m_pCells; - delete[] m_pOriginalCells; - m_pOriginalCells = nullptr; - m_pCells = nullptr; - m_iWidth = 0; - m_iHeight = 0; + delete[] cells; + delete[] original_cells; + delete[] parcel_adjacency_matrix; + delete[] purchasable_matrix; + width = iWidth; + height = iHeight; + cells = nullptr; + cells = new (std::nothrow) map_tile[iWidth * iHeight]; + original_cells = nullptr; + original_cells = new (std::nothrow) map_tile[iWidth * iHeight]; + parcel_adjacency_matrix = nullptr; + purchasable_matrix = nullptr; + + if(cells == nullptr || original_cells == nullptr) + { + delete[] cells; + delete[] original_cells; + original_cells = nullptr; + cells = nullptr; + width = 0; + height = 0; return false; } @@ -305,36 +305,36 @@ 0x00, 0x00, 0x00, 0x00 }; -void THMap::_readTileIndex(const uint8_t* pData, int& iX, int &iY) const +void level_map::read_tile_index(const uint8_t* pData, int& iX, int &iY) const { unsigned int iIndex = static_cast(pData[1]); iIndex = iIndex * 0x100 + static_cast(pData[0]); - iX = iIndex % m_iWidth; - iY = iIndex / m_iWidth; + iX = iIndex % width; + iY = iIndex / width; } -void THMap::_writeTileIndex(uint8_t* pData, int iX, int iY) const +void level_map::write_tile_index(uint8_t* pData, int iX, int iY) const { - uint16_t iIndex = static_cast(iY * m_iWidth + iX); + uint16_t iIndex = static_cast(iY * width + iX); pData[0] = static_cast(iIndex & 0xFF); pData[1] = static_cast(iIndex >> 8); } -bool THMap::loadBlank() +bool level_map::load_blank() { - if(!setSize(128, 128)) + if(!set_size(128, 128)) return false; - m_iPlayerCount = 1; - m_aiInitialCameraX[0] = m_aiInitialCameraY[0] = 63; - m_aiHeliportX[0] = m_aiHeliportY[0] = 0; - m_iParcelCount = 1; - delete[] m_pPlotOwner; - delete[] m_pParcelTileCounts; - m_pPlotOwner = nullptr; - m_pParcelTileCounts = nullptr; - THMapNode *pNode = m_pCells; - THMapNode *pOriginalNode = m_pOriginalCells; + player_count = 1; + initial_camera_x[0] = initial_camera_y[0] = 63; + heliport_x[0] = heliport_y[0] = 0; + parcel_count = 1; + delete[] plot_owner; + delete[] parcel_tile_counts; + plot_owner = nullptr; + parcel_tile_counts = nullptr; + map_tile *pNode = cells; + map_tile *pOriginalNode = original_cells; for(int iY = 0; iY < 128; ++iY) { for(int iX = 0; iX < 128; ++iX, ++pNode, ++pOriginalNode) @@ -342,37 +342,37 @@ pNode->iBlock[0] = static_cast(2 + (iX % 2)); } } - m_pPlotOwner = new int[1]; - m_pPlotOwner[0] = 0; - m_pParcelTileCounts = new int[1]; - m_pParcelTileCounts[0] = 128 * 128; + plot_owner = new int[1]; + plot_owner[0] = 0; + parcel_tile_counts = new int[1]; + parcel_tile_counts[0] = 128 * 128; return true; } -bool THMap::loadFromTHFile(const uint8_t* pData, size_t iDataLength, - THMapLoadObjectCallback_t fnObjectCallback, +bool level_map::load_from_th_file(const uint8_t* pData, size_t iDataLength, + map_load_object_callback_fn fnObjectCallback, void* pCallbackToken) { - if(iDataLength < 163948 || !setSize(128, 128)) + if(iDataLength < 163948 || !set_size(128, 128)) return false; - m_iPlayerCount = pData[0]; - for(int i = 0; i < m_iPlayerCount; ++i) + player_count = pData[0]; + for(int i = 0; i < player_count; ++i) { - _readTileIndex(pData + 163876 + (i % 4) * 2, - m_aiInitialCameraX[i], m_aiInitialCameraY[i]); - _readTileIndex(pData + 163884 + (i % 4) * 2, - m_aiHeliportX[i], m_aiHeliportY[i]); - } - m_iParcelCount = 0; - delete[] m_pPlotOwner; - delete[] m_pParcelTileCounts; - m_pPlotOwner = nullptr; - m_pParcelTileCounts = nullptr; + read_tile_index(pData + 163876 + (i % 4) * 2, + initial_camera_x[i], initial_camera_y[i]); + read_tile_index(pData + 163884 + (i % 4) * 2, + heliport_x[i], heliport_y[i]); + } + parcel_count = 0; + delete[] plot_owner; + delete[] parcel_tile_counts; + plot_owner = nullptr; + parcel_tile_counts = nullptr; - THMapNode *pNode = m_pCells; - THMapNode *pOriginalNode = m_pOriginalCells; + map_tile *pNode = cells; + map_tile *pOriginalNode = original_cells; const uint16_t *pParcel = reinterpret_cast(pData + 131106); pData += 34; @@ -432,8 +432,8 @@ pNode->iRoomId = 0; pNode->iParcelId = *pParcel; - if(*pParcel >= m_iParcelCount) - m_iParcelCount = *pParcel + 1; + if(*pParcel >= parcel_count) + parcel_count = *pParcel + 1; if(!(pData[5] & 1)) { @@ -469,33 +469,33 @@ if(pData[1] != 0 && fnObjectCallback != nullptr) { - fnObjectCallback(pCallbackToken, iX, iY, (THObjectType)pData[1], pData[0]); + fnObjectCallback(pCallbackToken, iX, iY, (object_type)pData[1], pData[0]); } } } - m_pPlotOwner = new int[m_iParcelCount]; - m_pPlotOwner[0] = 0; - for(int i = 1; i < m_iParcelCount; ++i) - m_pPlotOwner[i] = 1; + plot_owner = new int[parcel_count]; + plot_owner[0] = 0; + for(int i = 1; i < parcel_count; ++i) + plot_owner[i] = 1; - updateShadows(); + update_shadows(); - m_pParcelTileCounts = new int[m_iParcelCount]; - m_pParcelTileCounts[0] = 0; - for(int i = 1; i < m_iParcelCount; ++i) - m_pParcelTileCounts[i] = _getParcelTileCount(i); + parcel_tile_counts = new int[parcel_count]; + parcel_tile_counts[0] = 0; + for(int i = 1; i < parcel_count; ++i) + parcel_tile_counts[i] = count_parcel_tiles(i); return true; } -void THMap::save(std::string filename) +void level_map::save(std::string filename) { uint8_t aBuffer[256] = {0}; int iBufferNext = 0; std::ofstream os(filename, std::ios_base::trunc | std::ios_base::binary); // Header - aBuffer[0] = static_cast(m_iPlayerCount); + aBuffer[0] = static_cast(player_count); // TODO: Determine correct contents for the next 33 bytes os.write(reinterpret_cast(aBuffer), 34); @@ -506,12 +506,12 @@ } aReverseBlockLUT[0] = 0; - for(THMapNode *pNode = m_pCells, *pLimitNode = pNode + m_iWidth * m_iHeight; + for(map_tile *pNode = cells, *pLimitNode = pNode + width * height; pNode != pLimitNode; ++pNode) { // TODO: Nicer system for saving object data aBuffer[iBufferNext++] = pNode->flags.tall_west ? 1 : 0; - aBuffer[iBufferNext++] = static_cast(pNode->objects.empty() ? THObjectType::no_object : pNode->objects.front()); + aBuffer[iBufferNext++] = static_cast(pNode->objects.empty() ? object_type::no_object : pNode->objects.front()); // Blocks aBuffer[iBufferNext++] = aReverseBlockLUT[pNode->iBlock[0] & 0xFF]; @@ -547,7 +547,7 @@ iBufferNext = 0; } } - for(THMapNode *pNode = m_pCells, *pLimitNode = pNode + m_iWidth * m_iHeight; + for(map_tile *pNode = cells, *pLimitNode = pNode + width * height; pNode != pLimitNode; ++pNode) { aBuffer[iBufferNext++] = static_cast(pNode->iParcelId & 0xFF); @@ -566,12 +566,12 @@ iBufferNext = 0; std::memset(aBuffer, 0, 56); - for(int i = 0; i < m_iPlayerCount; ++i) + for(int i = 0; i < player_count; ++i) { - _writeTileIndex(aBuffer + iBufferNext, - m_aiInitialCameraX[i], m_aiInitialCameraY[i]); - _writeTileIndex(aBuffer + iBufferNext + 8, - m_aiHeliportX[i], m_aiHeliportY[i]); + write_tile_index(aBuffer + iBufferNext, + initial_camera_x[i], initial_camera_y[i]); + write_tile_index(aBuffer + iBufferNext + 8, + heliport_x[i], heliport_y[i]); iBufferNext += 2; } os.write(reinterpret_cast(aBuffer), 16); @@ -581,7 +581,7 @@ os.close(); } -//! Add or remove divider wall for the given node +//! Add or remove divider wall for the given tile /*! If the given 'pNode' has an indoor border to another parcel in the 'delta' direction: * A divider wall is added in the layer specified by 'block' if the owners @@ -589,15 +589,15 @@ * A divider wall is removed if the owners are the same and 'iParcelId' is involved. \return True if a border was removed, false otherwise */ -static bool addRemoveDividerWalls(THMap* pMap, THMapNode* pNode, const THMapNode* pOriginalNode, +static bool addRemoveDividerWalls(level_map* pMap, map_tile* pNode, const map_tile* pOriginalNode, int iXY, int delta, int block, int iParcelId) { if (iXY > 0 && pOriginalNode->flags.hospital && pOriginalNode[-delta].flags.hospital && pNode->iParcelId != pNode[-delta].iParcelId) { - int iOwner = pMap->getParcelOwner(pNode->iParcelId); - int iOtherOwner = pMap->getParcelOwner(pNode[-delta].iParcelId); + int iOwner = pMap->get_parcel_owner(pNode->iParcelId); + int iOtherOwner = pMap->get_parcel_owner(pNode[-delta].iParcelId); if (iOwner != iOtherOwner) { pNode->iBlock[block] = block + (iOwner ? 143 : 141); @@ -611,15 +611,15 @@ return false; } -std::vector> THMap::setParcelOwner(int iParcelId, int iOwner) +std::vector> level_map::set_parcel_owner(int iParcelId, int iOwner) { std::vector> vSplitTiles; - if(iParcelId <= 0 || m_iParcelCount <= iParcelId || iOwner < 0) + if(iParcelId <= 0 || parcel_count <= iParcelId || iOwner < 0) return vSplitTiles; - m_pPlotOwner[iParcelId] = iOwner; + plot_owner[iParcelId] = iOwner; - THMapNode *pNode = m_pCells; - const THMapNode *pOriginalNode = m_pOriginalCells; + map_tile *pNode = cells; + const map_tile *pOriginalNode = original_cells; for(int iY = 0; iY < 128; ++iY) { @@ -662,70 +662,70 @@ } } - updatePathfinding(); - updateShadows(); - _updatePurchaseMatrix(); + update_pathfinding(); + update_shadows(); + update_purchase_matrix(); return vSplitTiles; } -void THMap::_makeAdjacencyMatrix() +void level_map::make_adjacency_matrix() { - if(m_pParcelAdjacencyMatrix != nullptr) + if(parcel_adjacency_matrix != nullptr) return; - m_pParcelAdjacencyMatrix = new bool[m_iParcelCount * m_iParcelCount]; - for(int i = 0; i < m_iParcelCount; ++i) + parcel_adjacency_matrix = new bool[parcel_count * parcel_count]; + for(int i = 0; i < parcel_count; ++i) { - for(int j = 0; j < m_iParcelCount; ++j) + for(int j = 0; j < parcel_count; ++j) { - m_pParcelAdjacencyMatrix[i * m_iParcelCount + j] = (i == j); + parcel_adjacency_matrix[i * parcel_count + j] = (i == j); } } - const THMapNode *pOriginalNode = m_pOriginalCells; + const map_tile *pOriginalNode = original_cells; for(int iY = 0; iY < 128; ++iY) { for(int iX = 0; iX < 128; ++iX, ++pOriginalNode) { -#define TestAdj(xy, delta) if(xy > 0 && \ +#define TEST_ADJ(xy, delta) if(xy > 0 && \ pOriginalNode->iParcelId != pOriginalNode[-delta].iParcelId && \ pOriginalNode->flags.passable && pOriginalNode[-delta].flags.passable)\ - m_pParcelAdjacencyMatrix[pOriginalNode->iParcelId * m_iParcelCount\ + parcel_adjacency_matrix[pOriginalNode->iParcelId * parcel_count\ + pOriginalNode[-delta].iParcelId] = true, \ - m_pParcelAdjacencyMatrix[pOriginalNode->iParcelId + \ - pOriginalNode[-delta].iParcelId * m_iParcelCount] = true + parcel_adjacency_matrix[pOriginalNode->iParcelId + \ + pOriginalNode[-delta].iParcelId * parcel_count] = true - TestAdj(iX, 1); - TestAdj(iY, 128); -#undef TestAdj + TEST_ADJ(iX, 1); + TEST_ADJ(iY, 128); +#undef TEST_ADJ } } } -void THMap::_makePurchaseMatrix() +void level_map::make_purchase_matrix() { - if(m_pPurchasableMatrix != nullptr) + if(purchasable_matrix != nullptr) return; // Already made - m_pPurchasableMatrix = new bool[4 * m_iParcelCount]; - _updatePurchaseMatrix(); + purchasable_matrix = new bool[4 * parcel_count]; + update_purchase_matrix(); } -void THMap::_updatePurchaseMatrix() +void level_map::update_purchase_matrix() { - if(m_pPurchasableMatrix == nullptr) + if(purchasable_matrix == nullptr) return; // Nothing to update for(int iPlayer = 1; iPlayer <= 4; ++iPlayer) { - for(int iParcel = 0; iParcel < m_iParcelCount; ++iParcel) + for(int iParcel = 0; iParcel < parcel_count; ++iParcel) { bool bPurchasable = false; - if(iParcel != 0 && m_pPlotOwner[iParcel] == 0) + if(iParcel != 0 && plot_owner[iParcel] == 0) { - for(int iParcel2 = 0; iParcel2 < m_iParcelCount; ++iParcel2) + for(int iParcel2 = 0; iParcel2 < parcel_count; ++iParcel2) { - if((m_pPlotOwner[iParcel2] == iPlayer) || (iParcel2 == 0)) + if((plot_owner[iParcel2] == iPlayer) || (iParcel2 == 0)) { - if(areParcelsAdjacent(iParcel, iParcel2)) + if(are_parcels_adjacent(iParcel, iParcel2)) { bPurchasable = true; break; @@ -733,168 +733,169 @@ } } } - m_pPurchasableMatrix[iParcel * 4 + iPlayer - 1] = bPurchasable; + purchasable_matrix[iParcel * 4 + iPlayer - 1] = bPurchasable; } } } -bool THMap::areParcelsAdjacent(int iParcel1, int iParcel2) +bool level_map::are_parcels_adjacent(int iParcel1, int iParcel2) { - if(0 <= iParcel1 && iParcel1 < m_iParcelCount - && 0 <= iParcel2 && iParcel2 < m_iParcelCount) + if(0 <= iParcel1 && iParcel1 < parcel_count + && 0 <= iParcel2 && iParcel2 < parcel_count) { - _makeAdjacencyMatrix(); - return m_pParcelAdjacencyMatrix[iParcel1 * m_iParcelCount + iParcel2]; + make_adjacency_matrix(); + return parcel_adjacency_matrix[iParcel1 * parcel_count + iParcel2]; } return false; } -bool THMap::isParcelPurchasable(int iParcelId, int iPlayer) +bool level_map::is_parcel_purchasable(int iParcelId, int iPlayer) { - if(0 <= iParcelId && iParcelId < m_iParcelCount + if(0 <= iParcelId && iParcelId < parcel_count && 1 <= iPlayer && iPlayer <= 4) { - _makePurchaseMatrix(); - return m_pPurchasableMatrix[iParcelId * 4 + iPlayer - 1]; + make_purchase_matrix(); + return purchasable_matrix[iParcelId * 4 + iPlayer - 1]; } return false; } -void THMap::setPlayerCount(int count) +void level_map::set_player_count(int count) { if (count < 1 || count > 4) throw std::out_of_range("Player count must be between 1 and 4"); - m_iPlayerCount = count; + player_count = count; } -bool THMap::getPlayerCameraTile(int iPlayer, int* pX, int* pY) const +bool level_map::get_player_camera_tile(int iPlayer, int* pX, int* pY) const { - if(iPlayer < 0 || iPlayer >= getPlayerCount()) + if(iPlayer < 0 || iPlayer >= get_player_count()) { if(pX) *pX = 0; if(pY) *pY = 0; return false; } - if(pX) *pX = m_aiInitialCameraX[iPlayer]; - if(pY) *pY = m_aiInitialCameraY[iPlayer]; + if(pX) *pX = initial_camera_x[iPlayer]; + if(pY) *pY = initial_camera_y[iPlayer]; return true; } -bool THMap::getPlayerHeliportTile(int iPlayer, int* pX, int* pY) const +bool level_map::get_player_heliport_tile(int iPlayer, int* pX, int* pY) const { - if(iPlayer < 0 || iPlayer >= getPlayerCount()) + if(iPlayer < 0 || iPlayer >= get_player_count()) { if(pX) *pX = 0; if(pY) *pY = 0; return false; } - if(pX) *pX = m_aiHeliportX[iPlayer]; - if(pY) *pY = m_aiHeliportY[iPlayer]; + if(pX) *pX = heliport_x[iPlayer]; + if(pY) *pY = heliport_y[iPlayer]; return true; } -void THMap::setPlayerCameraTile(int iPlayer, int iX, int iY) +void level_map::set_player_camera_tile(int iPlayer, int iX, int iY) { - if(0 <= iPlayer && iPlayer < getPlayerCount()) + if(0 <= iPlayer && iPlayer < get_player_count()) { - m_aiInitialCameraX[iPlayer] = iX; - m_aiInitialCameraY[iPlayer] = iY; + initial_camera_x[iPlayer] = iX; + initial_camera_y[iPlayer] = iY; } } -void THMap::setPlayerHeliportTile(int iPlayer, int iX, int iY) +void level_map::set_player_heliport_tile(int iPlayer, int iX, int iY) { - if(0 <= iPlayer && iPlayer < getPlayerCount()) + if(0 <= iPlayer && iPlayer < get_player_count()) { - m_aiHeliportX[iPlayer] = iX; - m_aiHeliportY[iPlayer] = iY; + heliport_x[iPlayer] = iX; + heliport_y[iPlayer] = iY; } } -int THMap::getParcelTileCount(int iParcelId) const +int level_map::get_parcel_tile_count(int iParcelId) const { - if(iParcelId < 1 || iParcelId >= m_iParcelCount) + if(iParcelId < 1 || iParcelId >= parcel_count) { return 0; } - return m_pParcelTileCounts[iParcelId]; + return parcel_tile_counts[iParcelId]; } -int THMap::_getParcelTileCount(int iParcelId) const +int level_map::count_parcel_tiles(int iParcelId) const { int iTiles = 0; - for(int iY = 0; iY < m_iHeight; ++iY) + for(int iY = 0; iY < height; ++iY) { - for(int iX = 0; iX < m_iWidth; ++iX) + for(int iX = 0; iX < width; ++iX) { - const THMapNode* pNode = getNodeUnchecked(iX, iY); + const map_tile* pNode = get_tile_unchecked(iX, iY); if(pNode->iParcelId == iParcelId) iTiles++; } } return iTiles; } -THMapNode* THMap::getNode(int iX, int iY) +map_tile* level_map::get_tile(int iX, int iY) { - if(0 <= iX && iX < m_iWidth && 0 <= iY && iY < m_iHeight) - return getNodeUnchecked(iX, iY); + if(0 <= iX && iX < width && 0 <= iY && iY < height) + return get_tile_unchecked(iX, iY); else return nullptr; } -const THMapNode* THMap::getNode(int iX, int iY) const +const map_tile* level_map::get_tile(int iX, int iY) const { - if(0 <= iX && iX < m_iWidth && 0 <= iY && iY < m_iHeight) - return getNodeUnchecked(iX, iY); + if(0 <= iX && iX < width && 0 <= iY && iY < height) + return get_tile_unchecked(iX, iY); else return nullptr; } -const THMapNode* THMap::getOriginalNode(int iX, int iY) const +const map_tile* level_map::get_original_tile(int iX, int iY) const { - if(0 <= iX && iX < m_iWidth && 0 <= iY && iY < m_iHeight) - return getOriginalNodeUnchecked(iX, iY); + if(0 <= iX && iX < width && 0 <= iY && iY < height) + return get_original_tile_unchecked(iX, iY); else return nullptr; } -THMapNode* THMap::getNodeUnchecked(int iX, int iY) +map_tile* level_map::get_tile_unchecked(int iX, int iY) { - return m_pCells + iY * m_iWidth + iX; + return cells + iY * width + iX; } -const THMapNode* THMap::getNodeUnchecked(int iX, int iY) const +const map_tile* level_map::get_tile_unchecked(int iX, int iY) const { - return m_pCells + iY * m_iWidth + iX; + return cells + iY * width + iX; } -const THMapNode* THMap::getOriginalNodeUnchecked(int iX, int iY) const +const map_tile* level_map::get_original_tile_unchecked(int iX, int iY) const { - return m_pOriginalCells + iY * m_iWidth + iX; + return original_cells + iY * width + iX; } -void THMap::setBlockSheet(THSpriteSheet* pSheet) +void level_map::set_block_sheet(sprite_sheet* pSheet) { - m_pBlocks = pSheet; + blocks = pSheet; } -void THMap::setAllWallDrawFlags(uint8_t iFlags) +void level_map::set_all_wall_draw_flags(uint8_t iFlags) { uint16_t iBlockOr = static_cast(iFlags << 8); - THMapNode *pNode = m_pCells; - for(int i = 0; i < m_iWidth * m_iHeight; ++i, ++pNode) + map_tile *pNode = cells; + for(int i = 0; i < width * height; ++i, ++pNode) { pNode->iBlock[1] = static_cast((pNode->iBlock[1] & 0xFF) | iBlockOr); pNode->iBlock[2] = static_cast((pNode->iBlock[2] & 0xFF) | iBlockOr); } } -void IntersectTHClipRect(THClipRect& rcClip,const THClipRect& rcIntersect) +// Definition is in th_gfx.h so this should move +void clip_rect_intersection(clip_rect& rcClip,const clip_rect& rcIntersect) { // The intersection of the rectangles is the higher of the lower bounds and the lower of the higher bounds, clamped to a zero size. - THClipRect::xy_t maxX = static_cast(std::min(rcClip.x + rcClip.w, rcIntersect.x + rcIntersect.w)); - THClipRect::xy_t maxY = static_cast(std::min(rcClip.y + rcClip.h, rcIntersect.y + rcIntersect.h)); + clip_rect::x_y_type maxX = static_cast(std::min(rcClip.x + rcClip.w, rcIntersect.x + rcIntersect.w)); + clip_rect::x_y_type maxY = static_cast(std::min(rcClip.y + rcClip.h, rcIntersect.y + rcIntersect.h)); rcClip.x = std::max(rcClip.x, rcIntersect.x); rcClip.y = std::max(rcClip.y, rcIntersect.y); rcClip.w = maxX - rcClip.x; @@ -911,12 +912,12 @@ } } -void THMap::draw(THRenderTarget* pCanvas, int iScreenX, int iScreenY, +void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY, int iWidth, int iHeight, int iCanvasX, int iCanvasY) const { /* The map is drawn in two passes, with each pass done one scanline at a - time (a scanline is a list of nodes with the same screen Y co-ordinate). + time (a scanline is a list of tiles with the same screen Y co-ordinate). The first pass does floor tiles, as the entire floor needs to be painted below anything else (for example, see the walking north through a door animation, which needs to paint over the floor of the scanline below the @@ -925,87 +926,87 @@ the walls around them. For each scanline, the following is done: 1st pass: - 1) For each node, left to right, the floor tile (layer 0) + 1) For each tile, left to right, the floor tile (layer 0) 2nd pass: - 1) For each node, right to left, the north wall, then the early entities - 2) For each node, left to right, the west wall, then the late entities + 1) For each tile, right to left, the north wall, then the early entities + 2) For each tile, left to right, the west wall, then the late entities */ - if(m_pBlocks == nullptr || m_pCells == nullptr) + if(blocks == nullptr || cells == nullptr) return; - THClipRect rcClip; - rcClip.x = static_cast(iCanvasX); - rcClip.y = static_cast(iCanvasY); - rcClip.w = static_cast(iWidth); - rcClip.h = static_cast(iHeight); - pCanvas->setClipRect(&rcClip); + clip_rect rcClip; + rcClip.x = static_cast(iCanvasX); + rcClip.y = static_cast(iCanvasY); + rcClip.w = static_cast(iWidth); + rcClip.h = static_cast(iHeight); + pCanvas->set_clip_rect(&rcClip); // 1st pass - pCanvas->startNonOverlapping(); - for(THMapNodeIterator itrNode1(this, iScreenX, iScreenY, iWidth, iHeight); itrNode1; ++itrNode1) + pCanvas->start_nonoverlapping_draws(); + for(map_tile_iterator itrNode1(this, iScreenX, iScreenY, iWidth, iHeight); itrNode1; ++itrNode1) { unsigned int iH = 32; unsigned int iBlock = itrNode1->iBlock[0]; - m_pBlocks->getSpriteSize(iBlock & 0xFF, nullptr, &iH); - m_pBlocks->drawSprite(pCanvas, iBlock & 0xFF, - itrNode1.x() + iCanvasX - 32, - itrNode1.y() + iCanvasY - iH + 32, iBlock >> 8); + blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH); + blocks->draw_sprite(pCanvas, iBlock & 0xFF, + itrNode1.tile_x_position_on_screen() + iCanvasX - 32, + itrNode1.tile_y_position_on_screen() + iCanvasY - iH + 32, iBlock >> 8); } - pCanvas->finishNonOverlapping(); + pCanvas->finish_nonoverlapping_draws(); bool bFirst = true; - THMapScanlineIterator formerIterator; + map_scanline_iterator formerIterator; // 2nd pass - for(THMapNodeIterator itrNode2(this, iScreenX, iScreenY, iWidth, iHeight); itrNode2; ++itrNode2) + for(map_tile_iterator itrNode2(this, iScreenX, iScreenY, iWidth, iHeight); itrNode2; ++itrNode2) { if(itrNode2->flags.shadow_full) { - m_pBlocks->drawSprite(pCanvas, 74, itrNode2.x() + iCanvasX - 32, - itrNode2.y() + iCanvasY, THDF_Alpha75); + blocks->draw_sprite(pCanvas, 74, itrNode2.tile_x_position_on_screen() + iCanvasX - 32, + itrNode2.tile_y_position_on_screen() + iCanvasY, thdf_alpha_75); } else if(itrNode2->flags.shadow_half) { - m_pBlocks->drawSprite(pCanvas, 75, itrNode2.x() + iCanvasX - 32, - itrNode2.y() + iCanvasY, THDF_Alpha75); + blocks->draw_sprite(pCanvas, 75, itrNode2.tile_x_position_on_screen() + iCanvasX - 32, + itrNode2.tile_y_position_on_screen() + iCanvasY, thdf_alpha_75); } - if(!itrNode2.isLastOnScanline()) + if(!itrNode2.is_last_on_scanline()) continue; - for(THMapScanlineIterator itrNode(itrNode2, ScanlineBackward, iCanvasX, iCanvasY); itrNode; ++itrNode) + for(map_scanline_iterator itrNode(itrNode2, map_scanline_iterator_direction::backward, iCanvasX, iCanvasY); itrNode; ++itrNode) { unsigned int iH; unsigned int iBlock = itrNode->iBlock[1]; - if(iBlock != 0 && m_pBlocks->getSpriteSize(iBlock & 0xFF, + if(iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) { - m_pBlocks->drawSprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, + blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, itrNode.y() - iH + 32, iBlock >> 8); if(itrNode->flags.shadow_wall) { - THClipRect rcOldClip, rcNewClip; - pCanvas->getClipRect(&rcOldClip); - rcNewClip.x = static_cast(itrNode.x() - 32); - rcNewClip.y = static_cast(itrNode.y() - iH + 32 + 4); - rcNewClip.w = static_cast(64); - rcNewClip.h = static_cast(86 - 4); - IntersectTHClipRect(rcNewClip, rcOldClip); - pCanvas->setClipRect(&rcNewClip); - m_pBlocks->drawSprite(pCanvas, 156, itrNode.x() - 32, - itrNode.y() - 56, THDF_Alpha75); - pCanvas->setClipRect(&rcOldClip); + clip_rect rcOldClip, rcNewClip; + pCanvas->get_clip_rect(&rcOldClip); + rcNewClip.x = static_cast(itrNode.x() - 32); + rcNewClip.y = static_cast(itrNode.y() - iH + 32 + 4); + rcNewClip.w = static_cast(64); + rcNewClip.h = static_cast(86 - 4); + clip_rect_intersection(rcNewClip, rcOldClip); + pCanvas->set_clip_rect(&rcNewClip); + blocks->draw_sprite(pCanvas, 156, itrNode.x() - 32, + itrNode.y() - 56, thdf_alpha_75); + pCanvas->set_clip_rect(&rcOldClip); } } - THDrawable *pItem = (THDrawable*)(itrNode->oEarlyEntities.m_pNext); + drawable *pItem = (drawable*)(itrNode->oEarlyEntities.next); while(pItem) { - pItem->m_fnDraw(pItem, pCanvas, itrNode.x(), itrNode.y()); - pItem = (THDrawable*)(pItem->m_pNext); + pItem->draw_fn(pItem, pCanvas, itrNode.x(), itrNode.y()); + pItem = (drawable*)(pItem->next); } } - THMapScanlineIterator itrNode(itrNode2, ScanlineForward, iCanvasX, iCanvasY); + map_scanline_iterator itrNode(itrNode2, map_scanline_iterator_direction::forward, iCanvasX, iCanvasY); if(!bFirst) { //since the scanline count from one THMapScanlineIterator to another can differ //synchronization between the current iterator and the former one is neeeded @@ -1020,37 +1021,37 @@ bool bNeedsRedraw = false; unsigned int iH; unsigned int iBlock = itrNode->iBlock[2]; - if(iBlock != 0 && m_pBlocks->getSpriteSize(iBlock & 0xFF, + if(iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) { - m_pBlocks->drawSprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, + blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, itrNode.y() - iH + 32, iBlock >> 8); } iBlock = itrNode->iBlock[3]; - if(iBlock != 0 && m_pBlocks->getSpriteSize(iBlock & 0xFF, + if(iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) { - m_pBlocks->drawSprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, + blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32, itrNode.y() - iH + 32, iBlock >> 8); } iBlock = itrNode->iBlock[1]; - if(iBlock != 0 && m_pBlocks->getSpriteSize(iBlock & 0xFF, + if(iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) bNeedsRedraw = true; - if(itrNode->oEarlyEntities.m_pNext) + if(itrNode->oEarlyEntities.next) bNeedsRedraw = true; bool bRedrawAnimations = false; - THDrawable *pItem = (THDrawable*)(itrNode->m_pNext); + drawable *pItem = (drawable*)(itrNode->next); while(pItem) { - pItem->m_fnDraw(pItem, pCanvas, itrNode.x(), itrNode.y()); - if(pItem->m_fnIsMultipleFrameAnimation(pItem)) + pItem->draw_fn(pItem, pCanvas, itrNode.x(), itrNode.y()); + if(pItem->is_multiple_frame_animation_fn(pItem)) bRedrawAnimations = true; - if(pItem->getDrawingLayer() == 1) + if(pItem->get_drawing_layer() == 1) bNeedsRedraw = true; - pItem = (THDrawable*)(pItem->m_pNext); + pItem = (drawable*)(pItem->next); } //if the current tile contained a multiple frame animation (e.g. a doctor walking) @@ -1063,25 +1064,25 @@ //check if an object in the adjacent tile to the left of the current tile needs to be redrawn //and if necessary draw it - pItem = (THDrawable*)(formerIterator.getPreviousNode()->m_pNext); + pItem = (drawable*)(formerIterator.get_previous_tile()->next); while(pItem) { - if (pItem->getDrawingLayer() == 9) + if (pItem->get_drawing_layer() == 9) { - pItem->m_fnDraw(pItem, pCanvas, formerIterator.x() - 64, formerIterator.y()); + pItem->draw_fn(pItem, pCanvas, formerIterator.x() - 64, formerIterator.y()); bTileNeedsRedraw = true; } - pItem = (THDrawable*)(pItem->m_pNext); + pItem = (drawable*)(pItem->next); } //check if an object in the adjacent tile above the current tile needs to be redrawn //and if necessary draw it - pItem = formerIterator ? (THDrawable*)(formerIterator->m_pNext) : nullptr; + pItem = formerIterator ? (drawable*)(formerIterator->next) : nullptr; while(pItem) { - if(pItem->getDrawingLayer() == 8) - pItem->m_fnDraw(pItem, pCanvas, formerIterator.x(), formerIterator.y()); - pItem = (THDrawable*)(pItem->m_pNext); + if(pItem->get_drawing_layer() == 8) + pItem->draw_fn(pItem, pCanvas, formerIterator.x(), formerIterator.y()); + pItem = (drawable*)(pItem->next); } @@ -1091,37 +1092,37 @@ if(bTileNeedsRedraw) { //redraw the north wall - unsigned int iBlock = itrNode.getPreviousNode()->iBlock[1]; - if(iBlock != 0 && m_pBlocks->getSpriteSize(iBlock & 0xFF, + unsigned int iBlock = itrNode.get_previous_tile()->iBlock[1]; + if(iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) { - m_pBlocks->drawSprite(pCanvas, iBlock & 0xFF, itrNode.x() - 96, + blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 96, itrNode.y() - iH + 32, iBlock >> 8); - if(itrNode.getPreviousNode()->flags.shadow_wall) + if(itrNode.get_previous_tile()->flags.shadow_wall) { - THClipRect rcOldClip, rcNewClip; - pCanvas->getClipRect(&rcOldClip); - rcNewClip.x = static_cast(itrNode.x() - 96); - rcNewClip.y = static_cast(itrNode.y() - iH + 32 + 4); - rcNewClip.w = static_cast(64); - rcNewClip.h = static_cast(86 - 4); - IntersectTHClipRect(rcNewClip, rcOldClip); - pCanvas->setClipRect(&rcNewClip); - m_pBlocks->drawSprite(pCanvas, 156, itrNode.x() - 96, - itrNode.y() - 56, THDF_Alpha75); - pCanvas->setClipRect(&rcOldClip); + clip_rect rcOldClip, rcNewClip; + pCanvas->get_clip_rect(&rcOldClip); + rcNewClip.x = static_cast(itrNode.x() - 96); + rcNewClip.y = static_cast(itrNode.y() - iH + 32 + 4); + rcNewClip.w = static_cast(64); + rcNewClip.h = static_cast(86 - 4); + clip_rect_intersection(rcNewClip, rcOldClip); + pCanvas->set_clip_rect(&rcNewClip); + blocks->draw_sprite(pCanvas, 156, itrNode.x() - 96, + itrNode.y() - 56, thdf_alpha_75); + pCanvas->set_clip_rect(&rcOldClip); } } - pItem = (THDrawable*)(itrNode.getPreviousNode()->oEarlyEntities.m_pNext); + pItem = (drawable*)(itrNode.get_previous_tile()->oEarlyEntities.next); while(pItem) { - pItem->m_fnDraw(pItem, pCanvas, itrNode.x() - 64, itrNode.y()); - pItem = (THDrawable*)(pItem->m_pNext); + pItem->draw_fn(pItem, pCanvas, itrNode.x() - 64, itrNode.y()); + pItem = (drawable*)(pItem->next); } - pItem = (THDrawable*)(itrNode.getPreviousNode())->m_pNext; - for(; pItem; pItem = (THDrawable*)(pItem->m_pNext)) - pItem->m_fnDraw(pItem, pCanvas, itrNode.x() - 64, itrNode.y()); + pItem = (drawable*)(itrNode.get_previous_tile())->next; + for(; pItem; pItem = (drawable*)(pItem->next)) + pItem->draw_fn(pItem, pCanvas, itrNode.x() - 64, itrNode.y()); } } bPreviousTileNeedsRedraw = bNeedsRedraw; @@ -1132,46 +1133,46 @@ bFirst = false; } - if(m_pOverlay) + if(overlay) { - for(THMapNodeIterator itrNode(this, iScreenX, iScreenY, iWidth, iHeight); itrNode; ++itrNode) + for(map_tile_iterator itrNode(this, iScreenX, iScreenY, iWidth, iHeight); itrNode; ++itrNode) { - m_pOverlay->drawCell(pCanvas, itrNode.x() + iCanvasX - 32, - itrNode.y() + iCanvasY, this, itrNode.nodeX(), itrNode.nodeY()); + overlay->draw_cell(pCanvas, itrNode.tile_x_position_on_screen() + iCanvasX - 32, + itrNode.tile_y_position_on_screen() + iCanvasY, this, itrNode.tile_x(), itrNode.tile_y()); } } - pCanvas->setClipRect(nullptr); + pCanvas->set_clip_rect(nullptr); } -THDrawable* THMap::hitTest(int iTestX, int iTestY) const +drawable* level_map::hit_test(int iTestX, int iTestY) const { // This function needs to hitTest each drawable object, in the reverse // order to that in which they would be drawn. - if(m_pBlocks == nullptr || m_pCells == nullptr) + if(blocks == nullptr || cells == nullptr) return nullptr; - for(THMapNodeIterator itrNode2(this, iTestX, iTestY, 1, 1, ScanlineBackward); itrNode2; ++itrNode2) + for(map_tile_iterator itrNode2(this, iTestX, iTestY, 1, 1, map_scanline_iterator_direction::backward); itrNode2; ++itrNode2) { - if(!itrNode2.isLastOnScanline()) + if(!itrNode2.is_last_on_scanline()) continue; - for(THMapScanlineIterator itrNode(itrNode2, ScanlineBackward); itrNode; ++itrNode) + for(map_scanline_iterator itrNode(itrNode2, map_scanline_iterator_direction::backward); itrNode; ++itrNode) { - if(itrNode->m_pNext != nullptr) + if(itrNode->next != nullptr) { - THDrawable* pResult = _hitTestDrawables(itrNode->m_pNext, + drawable* pResult = hit_test_drawables(itrNode->next, itrNode.x(), itrNode.y(), 0, 0); if(pResult) return pResult; } } - for(THMapScanlineIterator itrNode(itrNode2, ScanlineForward); itrNode; ++itrNode) + for(map_scanline_iterator itrNode(itrNode2, map_scanline_iterator_direction::forward); itrNode; ++itrNode) { - if(itrNode->oEarlyEntities.m_pNext != nullptr) + if(itrNode->oEarlyEntities.next != nullptr) { - THDrawable* pResult = _hitTestDrawables(itrNode->oEarlyEntities.m_pNext, + drawable* pResult = hit_test_drawables(itrNode->oEarlyEntities.next, itrNode.x(), itrNode.y(), 0, 0); if(pResult) return pResult; @@ -1182,59 +1183,59 @@ return nullptr; } -THDrawable* THMap::_hitTestDrawables(THLinkList* pListStart, int iXs, int iYs, - int iTestX, int iTestY) const +drawable* level_map::hit_test_drawables(link_list* pListStart, int iXs, int iYs, + int iTestX, int iTestY) const { - THLinkList* pListEnd = pListStart; - while(pListEnd->m_pNext) - pListEnd = pListEnd->m_pNext; - THDrawable* pList = (THDrawable*)pListEnd; + link_list* pListEnd = pListStart; + while(pListEnd->next) + pListEnd = pListEnd->next; + drawable* pList = (drawable*)pListEnd; while(true) { - if(pList->m_fnHitTest(pList, iXs, iYs, iTestX, iTestY)) + if(pList->hit_test_fn(pList, iXs, iYs, iTestX, iTestY)) return pList; if(pList == pListStart) return nullptr; else - pList = (THDrawable*)pList->m_pPrev; + pList = (drawable*)pList->prev; } } -int THMap::getNodeOwner(const THMapNode* pNode) const +int level_map::get_tile_owner(const map_tile* pNode) const { - return m_pPlotOwner[pNode->iParcelId]; + return plot_owner[pNode->iParcelId]; } -int THMap::getParcelOwner(int iParcel) const +int level_map::get_parcel_owner(int iParcel) const { - if(0 <= iParcel && iParcel < m_iParcelCount) - return m_pPlotOwner[iParcel]; + if(0 <= iParcel && iParcel < parcel_count) + return plot_owner[iParcel]; else return 0; } -uint16_t THMap::getNodeTemperature(const THMapNode* pNode) const +uint16_t level_map::get_tile_temperature(const map_tile* pNode) const { - return pNode->aiTemperature[m_iCurrentTemperatureIndex]; + return pNode->aiTemperature[current_temperature_index]; } -void THMap::setTemperatureDisplay(THMapTemperatureDisplay eTempDisplay) +void level_map::set_temperature_display(temperature_theme eTempDisplay) { - if (eTempDisplay < THMT_Count) m_eTempDisplay = eTempDisplay; + current_temperature_theme = eTempDisplay; } -uint32_t THMap::thermalNeighbour(uint32_t &iNeighbourSum, bool canTravel, uint32_t relative_idx, THMapNode* pNode, int prevTemp) const +uint32_t level_map::thermal_neighbour(uint32_t &iNeighbourSum, bool canTravel, std::ptrdiff_t relative_idx, map_tile* pNode, int prevTemp) const { int iNeighbourCount = 0; - THMapNode* pNeighbour = pNode + relative_idx; + map_tile* pNeighbour = pNode + relative_idx; // Ensure the neighbour is within the map bounds - THMapNode* pLimitNode = m_pCells + m_iWidth * m_iHeight; - if (pNeighbour < m_pCells || pNeighbour >= pLimitNode) { + map_tile* pLimitNode = cells + width * height; + if (pNeighbour < cells || pNeighbour >= pLimitNode) { return 0; } @@ -1263,26 +1264,26 @@ } -void THMap::updateTemperatures(uint16_t iAirTemperature, +void level_map::update_temperatures(uint16_t iAirTemperature, uint16_t iRadiatorTemperature) { - if(iRadiatorTemperature < iAirTemperature) + if(iRadiatorTemperature < iAirTemperature) { iRadiatorTemperature = iAirTemperature; - const int iPrevTemp = m_iCurrentTemperatureIndex; - m_iCurrentTemperatureIndex ^= 1; - const int iNewTemp = m_iCurrentTemperatureIndex; + } + const int iPrevTemp = current_temperature_index; + current_temperature_index ^= 1; + const int iNewTemp = current_temperature_index; - THMapNode* pLimitNode = m_pCells + m_iWidth * m_iHeight; - for(THMapNode *pNode = m_pCells; pNode != pLimitNode; ++pNode) - { + map_tile* pLimitNode = cells + width * height; + for(map_tile *pNode = cells; pNode != pLimitNode; ++pNode) { // Get average temperature of neighbour cells uint32_t iNeighbourSum = 0; uint32_t iNeighbourCount = 0; - iNeighbourCount += thermalNeighbour(iNeighbourSum, pNode->flags.can_travel_n, -m_iWidth, pNode, iPrevTemp); - iNeighbourCount += thermalNeighbour(iNeighbourSum, pNode->flags.can_travel_s, m_iWidth, pNode, iPrevTemp); - iNeighbourCount += thermalNeighbour(iNeighbourSum, pNode->flags.can_travel_e, 1, pNode, iPrevTemp); - iNeighbourCount += thermalNeighbour(iNeighbourSum, pNode->flags.can_travel_w, -1, pNode, iPrevTemp); + iNeighbourCount += thermal_neighbour(iNeighbourSum, pNode->flags.can_travel_n, -width, pNode, iPrevTemp); + iNeighbourCount += thermal_neighbour(iNeighbourSum, pNode->flags.can_travel_s, width, pNode, iPrevTemp); + iNeighbourCount += thermal_neighbour(iNeighbourSum, pNode->flags.can_travel_e, 1, pNode, iPrevTemp); + iNeighbourCount += thermal_neighbour(iNeighbourSum, pNode->flags.can_travel_w, -1, pNode, iPrevTemp); #define MERGE2(src, other, ratio) (src) = static_cast( \ (static_cast(src) * ((ratio) - 1) + (other)) / (ratio)) @@ -1294,28 +1295,27 @@ // or generally dissipate 0.1% of temperature. uint32_t iMergeTemp = 0; double iMergeRatio = 100; - if(pNode->flags.hospital) - { - for(auto thob : pNode->objects) - { - if(thob == THObjectType::radiator) + if(pNode->flags.hospital) { + for(auto thob : pNode->objects) { + if(thob == object_type::radiator) { iRadiatorNumber++; + } } - if(iRadiatorNumber > 0) - { + if(iRadiatorNumber > 0) { iMergeTemp = iRadiatorTemperature; iMergeRatio = 2 - (iRadiatorNumber - 1) * 0.5; - } - else + } else { iMergeRatio = 1000; - } - else + } + } else { iMergeTemp = iAirTemperature; + } // Diffuse 25% with neighbours pNode->aiTemperature[iNewTemp] = pNode->aiTemperature[iPrevTemp]; - if(iNeighbourCount != 0) + if(iNeighbourCount != 0) { MERGE(iNeighbourSum / iNeighbourCount, 4 - (iRadiatorNumber > 0 ? (iRadiatorNumber - 1) * 1.5 : 0)); + } MERGE(iMergeTemp, iMergeRatio); #undef MERGE @@ -1323,9 +1323,9 @@ } } -void THMap::updatePathfinding() +void level_map::update_pathfinding() { - THMapNode *pNode = m_pCells; + map_tile *pNode = cells; for(int iY = 0; iY < 128; ++iY) { for(int iX = 0; iX < 128; ++iX, ++pNode) @@ -1365,14 +1365,14 @@ //! For shadow casting, a tile is considered to have a wall on a direction //! if it has a door in that direction, or the block is from the hardcoded //! range of wall-like blocks. -static inline bool is_wall(THMapNode *node, size_t block, bool flag) +static inline bool is_wall(map_tile *tile, size_t block, bool flag) { - return flag || (82 <= (node->iBlock[block] & 0xFF) && (node->iBlock[block] & 0xFF) <= 164); + return flag || (82 <= (tile->iBlock[block] & 0xFF) && (tile->iBlock[block] & 0xFF) <= 164); } -void THMap::updateShadows() +void level_map::update_shadows() { - THMapNode *pNode = m_pCells; + map_tile *pNode = cells; for(int iY = 0; iY < 128; ++iY) { for(int iX = 0; iX < 128; ++iX, ++pNode) @@ -1389,7 +1389,7 @@ } else if(iY != 0) { - THMapNode *pNeighbour = pNode - 128; + map_tile *pNeighbour = pNode - 128; pNeighbour->flags.shadow_full = true; if(iX != 0 && !is_wall(pNeighbour, 2, pNode->flags.tall_west)) { @@ -1409,35 +1409,35 @@ #undef IsWall } -void THMap::persist(LuaPersistWriter *pWriter) const +void level_map::persist(lua_persist_writer *pWriter) const { - lua_State *L = pWriter->getStack(); - IntegerRunLengthEncoder oEncoder; + lua_State *L = pWriter->get_stack(); + integer_run_length_encoder oEncoder; uint32_t iVersion = 4; - pWriter->writeVUInt(iVersion); - pWriter->writeVUInt(m_iPlayerCount); - for(int i = 0; i < m_iPlayerCount; ++i) + pWriter->write_uint(iVersion); + pWriter->write_uint(player_count); + for(int i = 0; i < player_count; ++i) { - pWriter->writeVUInt(m_aiInitialCameraX[i]); - pWriter->writeVUInt(m_aiInitialCameraY[i]); - pWriter->writeVUInt(m_aiHeliportX[i]); - pWriter->writeVUInt(m_aiHeliportY[i]); + pWriter->write_uint(initial_camera_x[i]); + pWriter->write_uint(initial_camera_y[i]); + pWriter->write_uint(heliport_x[i]); + pWriter->write_uint(heliport_y[i]); } - pWriter->writeVUInt(m_iParcelCount); - for(int i = 0; i < m_iParcelCount; ++i) + pWriter->write_uint(parcel_count); + for(int i = 0; i < parcel_count; ++i) { - pWriter->writeVUInt(m_pPlotOwner[i]); + pWriter->write_uint(plot_owner[i]); } - for(int i = 0; i < m_iParcelCount; ++i) + for(int i = 0; i < parcel_count; ++i) { - pWriter->writeVUInt(m_pParcelTileCounts[i]); + pWriter->write_uint(parcel_tile_counts[i]); } - pWriter->writeVUInt(m_iWidth); - pWriter->writeVUInt(m_iHeight); - pWriter->writeVUInt(m_iCurrentTemperatureIndex); + pWriter->write_uint(width); + pWriter->write_uint(height); + pWriter->write_uint(current_temperature_index); oEncoder.initialise(6); - for(THMapNode *pNode = m_pCells, *pLimitNode = m_pCells + m_iWidth * m_iHeight; + for(map_tile *pNode = cells, *pLimitNode = cells + width * height; pNode != pLimitNode; ++pNode) { oEncoder.write(pNode->iBlock[0]); @@ -1448,25 +1448,25 @@ oEncoder.write(pNode->iRoomId); // Flags include THOB values, and other things which do not work // well with run-length encoding. - pWriter->writeVUInt(static_cast(pNode->flags)); - pWriter->writeVUInt(pNode->aiTemperature[0]); - pWriter->writeVUInt(pNode->aiTemperature[1]); + pWriter->write_uint(static_cast(pNode->flags)); + pWriter->write_uint(pNode->aiTemperature[0]); + pWriter->write_uint(pNode->aiTemperature[1]); lua_rawgeti(L, luaT_upvalueindex(1), 2); - lua_pushlightuserdata(L, pNode->m_pNext); + lua_pushlightuserdata(L, pNode->next); lua_rawget(L, -2); - pWriter->writeStackObject(-1); + pWriter->write_stack_object(-1); lua_pop(L, 1); - lua_pushlightuserdata(L, pNode->oEarlyEntities.m_pNext); + lua_pushlightuserdata(L, pNode->oEarlyEntities.next); lua_rawget(L, -2); - pWriter->writeStackObject(-1); + pWriter->write_stack_object(-1); lua_pop(L, 2); } oEncoder.finish(); - oEncoder.pumpOutput(pWriter); + oEncoder.pump_output(pWriter); oEncoder.initialise(5); - for(THMapNode *pNode = m_pOriginalCells, *pLimitNode = m_pOriginalCells + m_iWidth * m_iHeight; + for(map_tile *pNode = original_cells, *pLimitNode = original_cells + width * height; pNode != pLimitNode; ++pNode) { oEncoder.write(pNode->iBlock[0]); @@ -1476,19 +1476,19 @@ oEncoder.write(static_cast(pNode->flags)); } oEncoder.finish(); - oEncoder.pumpOutput(pWriter); + oEncoder.pump_output(pWriter); } -void THMap::depersist(LuaPersistReader *pReader) +void level_map::depersist(lua_persist_reader *pReader) { - new (this) THMap; // Call constructor + new (this) level_map; // Call constructor - lua_State *L = pReader->getStack(); + lua_State *L = pReader->get_stack(); int iWidth, iHeight; - IntegerRunLengthDecoder oDecoder; + integer_run_length_decoder oDecoder; uint32_t iVersion; - if(!pReader->readVUInt(iVersion)) return; + if(!pReader->read_uint(iVersion)) return; if(iVersion != 4) { if(iVersion < 2 || iVersion == 128) @@ -1501,79 +1501,79 @@ luaL_error(L, "Cannot load savegame from a newer version."); } } - if(!pReader->readVUInt(m_iPlayerCount)) return; - for(int i = 0; i < m_iPlayerCount; ++i) + if(!pReader->read_uint(player_count)) return; + for(int i = 0; i < player_count; ++i) { - if(!pReader->readVUInt(m_aiInitialCameraX[i])) return; - if(!pReader->readVUInt(m_aiInitialCameraY[i])) return; - if(!pReader->readVUInt(m_aiHeliportX[i])) return; - if(!pReader->readVUInt(m_aiHeliportY[i])) return; - } - if(!pReader->readVUInt(m_iParcelCount)) return; - delete[] m_pPlotOwner; - m_pPlotOwner = new int[m_iParcelCount]; - for(int i = 0; i < m_iParcelCount; ++i) - { - if(!pReader->readVUInt(m_pPlotOwner[i])) return; - } - delete[] m_pParcelTileCounts; - m_pParcelTileCounts = new int[m_iParcelCount]; - m_pParcelTileCounts[0] = 0; + if(!pReader->read_uint(initial_camera_x[i])) return; + if(!pReader->read_uint(initial_camera_y[i])) return; + if(!pReader->read_uint(heliport_x[i])) return; + if(!pReader->read_uint(heliport_y[i])) return; + } + if(!pReader->read_uint(parcel_count)) return; + delete[] plot_owner; + plot_owner = new int[parcel_count]; + for(int i = 0; i < parcel_count; ++i) + { + if(!pReader->read_uint(plot_owner[i])) return; + } + delete[] parcel_tile_counts; + parcel_tile_counts = new int[parcel_count]; + parcel_tile_counts[0] = 0; if(iVersion >= 3) { - for(int i = 0; i < m_iParcelCount; ++i) + for(int i = 0; i < parcel_count; ++i) { - if(!pReader->readVUInt(m_pParcelTileCounts[i])) return; + if(!pReader->read_uint(parcel_tile_counts[i])) return; } } - if(!pReader->readVUInt(iWidth) || !pReader->readVUInt(iHeight)) + if(!pReader->read_uint(iWidth) || !pReader->read_uint(iHeight)) return; - if(!setSize(iWidth, iHeight)) + if(!set_size(iWidth, iHeight)) { - pReader->setError("Unable to set size while depersisting map"); + pReader->set_error("Unable to set size while depersisting map"); return; } if(iVersion >= 4) { - if(!pReader->readVUInt(m_iCurrentTemperatureIndex)) + if(!pReader->read_uint(current_temperature_index)) return; } - for(THMapNode *pNode = m_pCells, *pLimitNode = m_pCells + m_iWidth * m_iHeight; + for(map_tile *pNode = cells, *pLimitNode = cells + width * height; pNode != pLimitNode; ++pNode) { uint32_t f; - if(!pReader->readVUInt(f)) return; + if(!pReader->read_uint(f)) return; pNode->flags = f; if(iVersion >= 4) { - if(!pReader->readVUInt(pNode->aiTemperature[0]) - || !pReader->readVUInt(pNode->aiTemperature[1])) return; + if(!pReader->read_uint(pNode->aiTemperature[0]) + || !pReader->read_uint(pNode->aiTemperature[1])) return; } - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return; - pNode->m_pNext = (THLinkList*)lua_touserdata(L, -1); - if(pNode->m_pNext) + pNode->next = (link_list*)lua_touserdata(L, -1); + if(pNode->next) { - if(pNode->m_pNext->m_pPrev != nullptr) + if(pNode->next->prev != nullptr) std::fprintf(stderr, "Warning: THMap linked-lists are corrupted.\n"); - pNode->m_pNext->m_pPrev = pNode; + pNode->next->prev = pNode; } lua_pop(L, 1); - if(!pReader->readStackObject()) + if(!pReader->read_stack_object()) return; - pNode->oEarlyEntities.m_pNext = (THLinkList*)lua_touserdata(L, -1); - if(pNode->oEarlyEntities.m_pNext) + pNode->oEarlyEntities.next = (link_list*)lua_touserdata(L, -1); + if(pNode->oEarlyEntities.next) { - if(pNode->oEarlyEntities.m_pNext->m_pPrev != nullptr) + if(pNode->oEarlyEntities.next->prev != nullptr) std::fprintf(stderr, "Warning: THMap linked-lists are corrupted.\n"); - pNode->oEarlyEntities.m_pNext->m_pPrev = &pNode->oEarlyEntities; + pNode->oEarlyEntities.next->prev = &pNode->oEarlyEntities; } lua_pop(L, 1); } oDecoder.initialise(6, pReader); - for(THMapNode *pNode = m_pCells, *pLimitNode = m_pCells + m_iWidth * m_iHeight; + for(map_tile *pNode = cells, *pLimitNode = cells + width * height; pNode != pLimitNode; ++pNode) { pNode->iBlock[0] = static_cast(oDecoder.read()); @@ -1584,7 +1584,7 @@ pNode->iRoomId = static_cast(oDecoder.read()); } oDecoder.initialise(5, pReader); - for(THMapNode *pNode = m_pOriginalCells, *pLimitNode = m_pOriginalCells + m_iWidth * m_iHeight; + for(map_tile *pNode = original_cells, *pLimitNode = original_cells + width * height; pNode != pLimitNode; ++pNode) { pNode->iBlock[0] = static_cast(oDecoder.read()); @@ -1596,188 +1596,188 @@ if(iVersion < 3) { - for(int i = 1; i < m_iParcelCount; ++i) - m_pParcelTileCounts[i] = _getParcelTileCount(i); + for(int i = 1; i < parcel_count; ++i) + parcel_tile_counts[i] = get_parcel_tile_count(i); } } -THMapNodeIterator::THMapNodeIterator() - : m_pNode(nullptr) - , m_pMap(nullptr) - , m_iScreenX(0) - , m_iScreenY(0) - , m_iScreenWidth(0) - , m_iScreenHeight(0) +map_tile_iterator::map_tile_iterator() + : tile(nullptr) + , container(nullptr) + , screen_offset_x(0) + , screen_offset_y(0) + , screen_width(0) + , screen_height(0) { } -THMapNodeIterator::THMapNodeIterator(const THMap *pMap, int iScreenX, int iScreenY, +map_tile_iterator::map_tile_iterator(const level_map* pMap, int iScreenX, int iScreenY, int iWidth, int iHeight, - eTHMapScanlineIteratorDirection eScanlineDirection) - : m_pMap(pMap) - , m_iScreenX(iScreenX) - , m_iScreenY(iScreenY) - , m_iScreenWidth(iWidth) - , m_iScreenHeight(iHeight) - , m_iScanlineCount(0) - , m_eDirection(eScanlineDirection) -{ - if(m_eDirection == ScanlineForward) - { - m_iBaseX = 0; - m_iBaseY = (iScreenY - 32) / 16; - if(m_iBaseY < 0) - m_iBaseY = 0; - else if(m_iBaseY >= m_pMap->getHeight()) - { - m_iBaseX = m_iBaseY - m_pMap->getHeight() + 1; - m_iBaseY = m_pMap->getHeight() - 1; - if(m_iBaseX >= m_pMap->getWidth()) - m_iBaseX = m_pMap->getWidth() - 1; + map_scanline_iterator_direction eScanlineDirection) + : container(pMap) + , screen_offset_x(iScreenX) + , screen_offset_y(iScreenY) + , screen_width(iWidth) + , screen_height(iHeight) + , scanline_count(0) + , direction(eScanlineDirection) +{ + if(direction == map_scanline_iterator_direction::forward) + { + base_x = 0; + base_y = (iScreenY - 32) / 16; + if(base_y < 0) + base_y = 0; + else if(base_y >= container->get_height()) + { + base_x = base_y - container->get_height() + 1; + base_y = container->get_height() - 1; + if(base_x >= container->get_width()) + base_x = container->get_width() - 1; } } else { - m_iBaseX = m_pMap->getWidth() - 1; - m_iBaseY = m_pMap->getHeight() - 1; + base_x = container->get_width() - 1; + base_y = container->get_height() - 1; } - m_iX = m_iBaseX; - m_iY = m_iBaseY; - _advanceUntilVisible(); + world_x = base_x; + world_y = base_y; + advance_until_visible(); } -THMapNodeIterator& THMapNodeIterator::operator ++ () +map_tile_iterator& map_tile_iterator::operator ++ () { - --m_iY; - ++m_iX; - _advanceUntilVisible(); + --world_y; + ++world_x; + advance_until_visible(); return *this; } -void THMapNodeIterator::_advanceUntilVisible() +void map_tile_iterator::advance_until_visible() { - m_pNode = nullptr; + tile = nullptr; while(true) { - m_iXs = m_iX; - m_iYs = m_iY; - m_pMap->worldToScreen(m_iXs, m_iYs); - m_iXs -= m_iScreenX; - m_iYs -= m_iScreenY; - if(m_eDirection == ScanlineForward ? - m_iYs >= m_iScreenHeight + ms_iMarginBottom : - m_iYs < -ms_iMarginTop) + x_relative_to_screen = world_x; + y_relative_to_screen = world_y; + container->world_to_screen(x_relative_to_screen, y_relative_to_screen); + x_relative_to_screen -= screen_offset_x; + y_relative_to_screen -= screen_offset_y; + if(direction == map_scanline_iterator_direction::forward ? + y_relative_to_screen >= screen_height + margin_bottom : + y_relative_to_screen < -margin_top) { return; } - if(m_eDirection == ScanlineForward ? - (m_iYs > -ms_iMarginTop) : - (m_iYs < m_iScreenHeight + ms_iMarginBottom)) + if(direction == map_scanline_iterator_direction::forward ? + (y_relative_to_screen > -margin_top) : + (y_relative_to_screen < screen_height + margin_bottom)) { - while(m_iY >= 0 && m_iX < m_pMap->getWidth()) + while(world_y >= 0 && world_x < container->get_width()) { - if(m_iXs < -ms_iMarginLeft) + if(x_relative_to_screen < -margin_left) { // Nothing to do } - else if(m_iXs < m_iScreenWidth + ms_iMarginRight) + else if(x_relative_to_screen < screen_width + margin_right) { - ++m_iScanlineCount; - m_pNode = m_pMap->getNodeUnchecked(m_iX, m_iY); + ++scanline_count; + tile = container->get_tile_unchecked(world_x, world_y); return; } else break; - --m_iY; - ++m_iX; - m_iXs += 64; + --world_y; + ++world_x; + x_relative_to_screen += 64; } } - m_iScanlineCount = 0; - if(m_eDirection == ScanlineForward) + scanline_count = 0; + if(direction == map_scanline_iterator_direction::forward) { - if(m_iBaseY == m_pMap->getHeight() - 1) + if(base_y == container->get_height() - 1) { - if(++m_iBaseX == m_pMap->getWidth()) + if(++base_x == container->get_width()) break; } else - ++m_iBaseY; + ++base_y; } else { - if(m_iBaseX == 0) + if(base_x == 0) { - if(m_iBaseY == 0) + if(base_y == 0) break; else - --m_iBaseY; + --base_y; } else - --m_iBaseX; + --base_x; } - m_iX = m_iBaseX; - m_iY = m_iBaseY; + world_x = base_x; + world_y = base_y; } } -bool THMapNodeIterator::isLastOnScanline() const +bool map_tile_iterator::is_last_on_scanline() const { - return m_iY <= 0 || m_iX + 1 >= m_pMap->getWidth() || - m_iXs + 64 >= m_iScreenWidth + ms_iMarginRight; + return world_y <= 0 || world_x + 1 >= container->get_width() || + x_relative_to_screen + 64 >= screen_width + margin_right; } -THMapScanlineIterator::THMapScanlineIterator() - : m_iNodeStep(0) - , m_iXStep(0) - , m_takenSteps(0) +map_scanline_iterator::map_scanline_iterator() + : tile_step(0) + , x_step(0) + , steps_taken(0) { } -THMapScanlineIterator::THMapScanlineIterator(const THMapNodeIterator& itrNodes, - eTHMapScanlineIteratorDirection eDirection, +map_scanline_iterator::map_scanline_iterator(const map_tile_iterator& itrNodes, + map_scanline_iterator_direction eDirection, int iXOffset, int iYOffset) - : m_iNodeStep((static_cast(eDirection) - 1) * (1 - itrNodes.m_pMap->getWidth())) - , m_iXStep((static_cast(eDirection) - 1) * 64) - , m_takenSteps(0) + : tile_step((static_cast(eDirection) - 1) * (1 - itrNodes.container->get_width())) + , x_step((static_cast(eDirection) - 1) * 64) + , steps_taken(0) { - if(eDirection == ScanlineBackward) + if(eDirection == map_scanline_iterator_direction::backward) { - m_pNode = itrNodes.m_pNode; - m_iXs = itrNodes.x(); + tile = itrNodes.tile; + x_relative_to_screen = itrNodes.tile_x_position_on_screen(); } else { - m_pNode = itrNodes.m_pNode - m_iNodeStep * (itrNodes.m_iScanlineCount - 1); - m_iXs = itrNodes.x() - m_iXStep * (itrNodes.m_iScanlineCount - 1); + tile = itrNodes.tile - tile_step * (itrNodes.scanline_count - 1); + x_relative_to_screen = itrNodes.tile_x_position_on_screen() - x_step * (itrNodes.scanline_count - 1); } - m_iXs += iXOffset; - m_iYs = itrNodes.y() + iYOffset; + x_relative_to_screen += iXOffset; + y_relative_to_screen = itrNodes.tile_y_position_on_screen() + iYOffset; - m_pNodeEnd = m_pNode + m_iNodeStep * itrNodes.m_iScanlineCount; - m_pNodeFirst = m_pNode; + end_tile = tile + tile_step * itrNodes.scanline_count; + first_tile = tile; } -THMapScanlineIterator& THMapScanlineIterator::operator ++ () +map_scanline_iterator& map_scanline_iterator::operator ++ () { - m_pNode += m_iNodeStep; - m_iXs += m_iXStep; - m_takenSteps++; + tile += tile_step; + x_relative_to_screen += x_step; + steps_taken++; return *this; } -//copies the members of the given THMapScanlineIterator and resets the node member to the +//copies the members of the given THMapScanlineIterator and resets the tile member to the //first element. -THMapScanlineIterator THMapScanlineIterator::operator= (const THMapScanlineIterator &iterator) +map_scanline_iterator map_scanline_iterator::operator= (const map_scanline_iterator &iterator) { - m_pNode = iterator.m_pNodeFirst; - m_pNodeEnd = iterator.m_pNodeEnd; - m_iXs = iterator.m_iXs - iterator.m_takenSteps * iterator.m_iXStep; - m_iYs = iterator.m_iYs; - m_iXStep = iterator.m_iXStep; - m_iNodeStep = iterator.m_iNodeStep; + tile = iterator.first_tile; + end_tile = iterator.end_tile; + x_relative_to_screen = iterator.x_relative_to_screen - iterator.steps_taken * iterator.x_step; + y_relative_to_screen = iterator.y_relative_to_screen; + x_step = iterator.x_step; + tile_step = iterator.tile_step; return *this; } diff -Nru corsix-th-0.61/CorsixTH/Src/th_map.h corsix-th-0.62/CorsixTH/Src/th_map.h --- corsix-th-0.61/CorsixTH/Src/th_map.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_map.h 2018-07-21 11:13:17.000000000 +0000 @@ -31,7 +31,7 @@ See game string table section 39 for proof. Section 1 also has names in this order. */ -enum class THObjectType : uint8_t +enum class object_type : uint8_t { no_object = 0, desk = 1, @@ -104,7 +104,7 @@ //! Map flags and object type //! The point of storing the object type here is to allow pathfinding code //! to use object types as pathfinding goals. -struct th_map_node_flags +struct map_tile_flags { enum class key : uint32_t { passable_mask = 1 << 0, @@ -152,40 +152,37 @@ bool buildable_s; //!< Can build on the south side of the tile bool buildable_w; //!< Can build on the west side of the tile - //! Convert the given uint32_t reprentation of the map node flags - //! to a th_map_node_flags instance. - th_map_node_flags& operator =(uint32_t raw); + //! Convert the given uint32_t reprentation of the map_tile flags + //! to a map_tile_flags instance. + map_tile_flags& operator =(uint32_t raw); //! Get/set the flag with the given key - bool& operator[] (th_map_node_flags::key key); + bool& operator[] (map_tile_flags::key key); //! Get the flag with the given key - const bool& operator[](th_map_node_flags::key key) const; + const bool& operator[](map_tile_flags::key key) const; - //! Convert th_map_node_flags into it's uint32_t representation + //! Convert map_tile_flags into it's uint32_t representation operator uint32_t() const; }; -enum THMapTemperatureDisplay -{ - THMT_Red, //!< Default warmth colouring (red gradients) - THMT_MultiColour, //!< Different colours (blue, green, red) - THMT_YellowRed, //!< Gradients of yellow, orange, and red - - THMT_Count, //!< Number of temperature display values. +enum class temperature_theme { + red, //!< Default warmth colouring (red gradients) + multi_colour, //!< Different colours (blue, green, red) + yellow_red //!< Gradients of yellow, orange, and red }; -struct THMapNode : public THLinkList +struct map_tile : public link_list { - THMapNode(); - ~THMapNode(); + map_tile(); + ~map_tile(); - // Linked list for entities rendered at this node + // Linked list for entities rendered at this tile // THLinkList::pPrev (will always be nullptr) // THLinkList::pNext //! Linked list for entities rendered in an early (right-to-left) pass - THLinkList oEarlyEntities; + link_list oEarlyEntities; //! Block tiles for rendering //! For each tile, the lower byte is the index in the sprite sheet, and the @@ -212,13 +209,13 @@ uint16_t aiTemperature[2]; //! Flags for information and object type - th_map_node_flags flags; + map_tile_flags flags; - //! objects in this node - std::list objects; + //! objects in this tile + std::list objects; }; -class THSpriteSheet; +class sprite_sheet; //! Prototype for object callbacks from THMap::loadFromTHFile /*! @@ -229,20 +226,20 @@ * The object flags present in the map data. The meaning of this value is left unspecified. */ -typedef void (*THMapLoadObjectCallback_t)(void*, int, int, THObjectType, uint8_t); +typedef void (*map_load_object_callback_fn)(void*, int, int, object_type, uint8_t); -class THMapOverlay; +class map_overlay; -class THMap +class level_map { public: - THMap(); - ~THMap(); + level_map(); + ~level_map(); - bool setSize(int iWidth, int iHeight); - bool loadBlank(); - bool loadFromTHFile(const uint8_t* pData, size_t iDataLength, - THMapLoadObjectCallback_t fnObjectCallback, + bool set_size(int iWidth, int iHeight); + bool load_blank(); + bool load_from_th_file(const uint8_t* pData, size_t iDataLength, + map_load_object_callback_fn fnObjectCallback, void* pCallbackToken); void save(std::string filename); @@ -252,42 +249,42 @@ The sprites for map floor tiles, wall tiles, and map decorators all come from the given sheet. */ - void setBlockSheet(THSpriteSheet* pSheet); + void set_block_sheet(sprite_sheet* pSheet); //! Set the draw flags on all wall blocks /*! This is typically called with THDF_Alpha50 to draw walls transparently, or with 0 to draw them opaque again. */ - void setAllWallDrawFlags(uint8_t iFlags); + void set_all_wall_draw_flags(uint8_t iFlags); - void updatePathfinding(); - void updateShadows(); - void setTemperatureDisplay(THMapTemperatureDisplay eTempDisplay); - inline THMapTemperatureDisplay getTemperatureDisplay() const {return m_eTempDisplay;} - void updateTemperatures(uint16_t iAirTemperature, + void update_pathfinding(); + void update_shadows(); + void set_temperature_display(temperature_theme eTempDisplay); + inline temperature_theme get_temperature_display() const {return current_temperature_theme;} + void update_temperatures(uint16_t iAirTemperature, uint16_t iRadiatorTemperature); //! Get the map width (in tiles) - inline int getWidth() const {return m_iWidth;} + inline int get_width() const {return width;} //! Get the map height (in tiles) - inline int getHeight() const {return m_iHeight;} + inline int get_height() const {return height;} //! Get the number of plots of land in this map - inline int getParcelCount() const {return m_iParcelCount - 1;} + inline int get_parcel_count() const {return parcel_count - 1;} - inline int getPlayerCount() const {return m_iPlayerCount;} + inline int get_player_count() const {return player_count;} - void setPlayerCount(int count); + void set_player_count(int count); - bool getPlayerCameraTile(int iPlayer, int* pX, int* pY) const; - bool getPlayerHeliportTile(int iPlayer, int* pX, int* pY) const; - void setPlayerCameraTile(int iPlayer, int iX, int iY); - void setPlayerHeliportTile(int iPlayer, int iX, int iY); + bool get_player_camera_tile(int iPlayer, int* pX, int* pY) const; + bool get_player_heliport_tile(int iPlayer, int* pX, int* pY) const; + void set_player_camera_tile(int iPlayer, int iX, int iY); + void set_player_heliport_tile(int iPlayer, int iX, int iY); //! Get the number of tiles inside a given parcel - int getParcelTileCount(int iParcelId) const; + int get_parcel_tile_count(int iParcelId) const; //! Change the owner of a particular parcel /*! @@ -299,7 +296,7 @@ \return vSplitTiles A vector that contains tile coordinates where iParcelId is adjacent to another part of the hospital. */ - std::vector> setParcelOwner(int iParcelId, int iOwner); + std::vector> set_parcel_owner(int iParcelId, int iOwner); //! Get the owner of a particular parcel of land /*! @@ -307,7 +304,7 @@ \return 0 if the parcel is unowned, otherwise the number of the owning player. */ - int getParcelOwner(int iParcelId) const; + int get_parcel_owner(int iParcelId) const; //! Query if two parcels are directly connected /*! @@ -316,7 +313,7 @@ \return true if there is a path between the two parcels which does not go into any other parcels. false otherwise. */ - bool areParcelsAdjacent(int iParcel1, int iParcel2); + bool are_parcels_adjacent(int iParcel1, int iParcel2); //! Query if a given player is in a position to purchase a given parcel /*! @@ -328,7 +325,7 @@ connected to a parcel already owned by the given player. false otherwise. */ - bool isParcelPurchasable(int iParcelId, int iPlayer); + bool is_parcel_purchasable(int iParcelId, int iPlayer); //! Draw the map (and any attached animations) /*! @@ -338,34 +335,34 @@ co-ordinates - they are not world (tile) co-ordinates, nor (relative) screen co-ordinates. */ - void draw(THRenderTarget* pCanvas, int iScreenX, int iScreenY, int iWidth, + void draw(render_target* pCanvas, int iScreenX, int iScreenY, int iWidth, int iHeight, int iCanvasX, int iCanvasY) const; //! Perform a hit-test against the animations attached to the map /*! If there is an animation at world pixel co-ordinates (iTestX, iTestY), then it is returned. Otherwise nullptr is returned. - To perform a hit-test using world (tile) co-ordinates, get the node - itself and query the top 8 bits of THMapNode::iFlags, or traverse the - node's animation lists. + To perform a hit-test using world (tile) co-ordinates, get the tile + itself and query the top 8 bits of map_tile::flags, or traverse the + tile's animation lists. */ - THDrawable* hitTest(int iTestX, int iTestY) const; + drawable* hit_test(int iTestX, int iTestY) const; // When using the unchecked versions, the map co-ordinates MUST be valid. // When using the normal versions, nullptr is returned for invalid co-ords. - THMapNode* getNode(int iX, int iY); - const THMapNode* getNode(int iX, int iY) const; - const THMapNode* getOriginalNode(int iX, int iY) const; - THMapNode* getNodeUnchecked(int iX, int iY); - const THMapNode* getNodeUnchecked(int iX, int iY) const; - const THMapNode* getOriginalNodeUnchecked(int iX, int iY) const; + map_tile* get_tile(int iX, int iY); + const map_tile* get_tile(int iX, int iY) const; + const map_tile* get_original_tile(int iX, int iY) const; + map_tile* get_tile_unchecked(int iX, int iY); + const map_tile* get_tile_unchecked(int iX, int iY) const; + const map_tile* get_original_tile_unchecked(int iX, int iY) const; - uint16_t getNodeTemperature(const THMapNode* pNode) const; - int getNodeOwner(const THMapNode* pNode) const; + uint16_t get_tile_temperature(const map_tile* pNode) const; + int get_tile_owner(const map_tile* pNode) const; //! Convert world (tile) co-ordinates to absolute screen co-ordinates template - static inline void worldToScreen(T& x, T& y) + static inline void world_to_screen(T& x, T& y) { T x_(x); x = (T)32 * (x_ - y); @@ -374,93 +371,93 @@ //! Convert absolute screen co-ordinates to world (tile) co-ordinates template - static inline void screenToWorld(T& x, T& y) + static inline void screen_to_world(T& x, T& y) { T x_(x); x = y / (T)32 + x_ / (T)64; y = y / (T)32 - x_ / (T)64; } - void persist(LuaPersistWriter *pWriter) const; - void depersist(LuaPersistReader *pReader); + void persist(lua_persist_writer *pWriter) const; + void depersist(lua_persist_reader *pReader); - void setOverlay(THMapOverlay *pOverlay, bool bTakeOwnership); + void set_overlay(map_overlay *pOverlay, bool bTakeOwnership); private: - THDrawable* _hitTestDrawables(THLinkList* pListStart, int iXs, int iYs, - int iTestX, int iTestY) const; - void _readTileIndex(const uint8_t* pData, int& iX, int &iY) const; - void _writeTileIndex(uint8_t* pData, int iX, int iY) const; - int _getParcelTileCount(int iParcelId) const; - - //! Calculate a weighted impact of a neighbour node on the temperature of the current node. - //! \param iNeighbourSum Incremented by the temperature of the node multiplied by the weight of the connection. - //! \param canTravel A node flag indicating whether travel between this node and it's neighbour is allowed. - //! \param relative_idx The index of the neighbour node, relative to this node into m_pCells. - //! \param pNode A pointer to the current node being tested. - //! \param prevTemp The array index into THMapNode::aiTemperature that currently stores the temperature of the node (prior to this calculation). + drawable* hit_test_drawables(link_list* pListStart, int iXs, int iYs, + int iTestX, int iTestY) const; + void read_tile_index(const uint8_t* pData, int& iX, int &iY) const; + void write_tile_index(uint8_t* pData, int iX, int iY) const; + + //! Calculate a weighted impact of a neighbour tile on the temperature of the current tile. + //! \param iNeighbourSum Incremented by the temperature of the tile multiplied by the weight of the connection. + //! \param canTravel A tile flag indicating whether travel between this tile and it's neighbour is allowed. + //! \param relative_idx The index of the neighbour tile, relative to this tile into cells. + //! \param pNode A pointer to the current tile being tested. + //! \param prevTemp The array index into map_tile::temperature that currently stores the temperature of the tile (prior to this calculation). //! \return The weight of the connection, 0 if there is no neighbour, 1 through walls, and 4 through air. - uint32_t thermalNeighbour(uint32_t &iNeighbourSum, bool canTravel, uint32_t relative_idx, THMapNode* pNode, int prevTemp) const; + uint32_t thermal_neighbour(uint32_t &iNeighbourSum, bool canTravel, std::ptrdiff_t relative_idx, map_tile* pNode, int prevTemp) const; //! Create the adjacency matrix if it doesn't already exist - void _makeAdjacencyMatrix(); + void make_adjacency_matrix(); //! Create the purchasability matrix if it doesn't already exist - void _makePurchaseMatrix(); + void make_purchase_matrix(); //! If it exists, update the purchasability matrix. - void _updatePurchaseMatrix(); - - THMapNode* m_pCells; - THMapNode* m_pOriginalCells; // Cells at map load time, before any changes - THSpriteSheet* m_pBlocks; - THMapOverlay* m_pOverlay; - bool m_bOwnOverlay; - int* m_pPlotOwner; // 0 for unowned, 1 for player 1, etc. - int m_iWidth; - int m_iHeight; - int m_iPlayerCount; - int m_aiInitialCameraX[4]; - int m_aiInitialCameraY[4]; - int m_aiHeliportX[4]; - int m_aiHeliportY[4]; - int m_iParcelCount; - int m_iCurrentTemperatureIndex; - THMapTemperatureDisplay m_eTempDisplay; - int* m_pParcelTileCounts; + void update_purchase_matrix(); + + int count_parcel_tiles(int iParcelId) const; + + map_tile* cells; + map_tile* original_cells; // Cells at map load time, before any changes + sprite_sheet* blocks; + map_overlay* overlay; + bool owns_overlay; + int* plot_owner; // 0 for unowned, 1 for player 1, etc. + int width; + int height; + int player_count; + int initial_camera_x[4]; + int initial_camera_y[4]; + int heliport_x[4]; + int heliport_y[4]; + int parcel_count; + int current_temperature_index; + temperature_theme current_temperature_theme; + int* parcel_tile_counts; // 2D symmetric array giving true if there is a path between two parcels // which doesn't go into any other parcels. - bool* m_pParcelAdjacencyMatrix; + bool* parcel_adjacency_matrix; // 4 by N matrix giving true if player can purchase parcel. - bool* m_pPurchasableMatrix; + bool* purchasable_matrix; }; -enum eTHMapScanlineIteratorDirection -{ - ScanlineForward = 2, - ScanlineBackward = 0, +enum class map_scanline_iterator_direction { + forward = 2, + backward = 0, }; -//! Utility class for iterating over map nodes within a screen rectangle +//! Utility class for iterating over map tiles within a screen rectangle /*! - To easily iterate over the map nodes which might draw something within a + To easily iterate over the map tiles which might draw something within a certain rectangle of screen space, an instance of this class can be used. By default, it iterates by scanline, top-to-bottom, and then left-to-right within each scanline. Alternatively, by passing ScanlineBackward to the constructor, it will iterate bottom-to-top. Within a scanline, to visit - nodes right-to-left, wait until isLastOnScanline() returns true, then use + tiles right-to-left, wait until isLastOnScanline() returns true, then use an instance of THMapScanlineIterator. */ -class THMapNodeIterator +class map_tile_iterator { public: - THMapNodeIterator(); + map_tile_iterator(); /*! - @arg pMap The map whose nodes should be iterated + @arg pMap The map whose tiles should be iterated @arg iScreenX The X co-ordinate of the top-left corner of the screen-space rectangle to iterate. @arg iScreenY The Y co-ordinate of the top-left corner of the @@ -468,109 +465,112 @@ @arg iWidth The width of the screen-space rectangle to iterate. @arg iHeight The width of the screen-space rectangle to iterate. @arg eScanlineDirection The direction in which to iterate scanlines; - ScanlineForward for top-to-bottom, ScanlineBackward for bottom-to-top. + forward for top-to-bottom, backward for bottom-to-top. */ - THMapNodeIterator(const THMap *pMap, int iScreenX, int iScreenY, - int iWidth, int iHeight, - eTHMapScanlineIteratorDirection eScanlineDirection = ScanlineForward); + map_tile_iterator(const level_map*pMap, int iScreenX, int iScreenY, + int iWidth, int iHeight, + map_scanline_iterator_direction eScanlineDirection = map_scanline_iterator_direction::forward); - //! Returns false iff the iterator has exhausted its nodes - inline operator bool () const {return m_pNode != nullptr;} + //! Returns false iff the iterator has exhausted its tiles + inline operator bool () const {return tile != nullptr;} - //! Advances the iterator to the next node - inline THMapNodeIterator& operator ++ (); + //! Advances the iterator to the next tile + inline map_tile_iterator& operator ++ (); - //! Accessor for the current node - inline const THMapNode* operator -> () const {return m_pNode;} + //! Accessor for the current tile + inline const map_tile* operator -> () const {return tile;} - //! Get the X position of the node relative to the top-left corner of the screen-space rectangle - inline int x() const {return m_iXs;} + //! Get the X position of the tile relative to the top-left corner of the screen-space rectangle + inline int tile_x_position_on_screen() const {return x_relative_to_screen;} - //! Get the Y position of the node relative to the top-left corner of the screen-space rectangle - inline int y() const {return m_iYs;} + //! Get the Y position of the tile relative to the top-left corner of the screen-space rectangle + inline int tile_y_position_on_screen() const {return y_relative_to_screen;} - inline int nodeX() const {return m_iX;} - inline int nodeY() const {return m_iY;} + inline int tile_x() const {return world_x;} + inline int tile_y() const {return world_y;} - inline const THMap *getMap() {return m_pMap;} - inline const THMapNode *getMapNode() {return m_pNode;} - inline int getScanlineCount() { return m_iScanlineCount;} - inline int getNodeStep() {return (static_cast(m_eDirection) - 1) * (1 - m_pMap->getWidth());} + inline const level_map *get_map() {return container;} + inline const map_tile *get_map_tile() {return tile;} + inline int get_scanline_count() { return scanline_count;} + inline int get_tile_step() {return (static_cast(direction) - 1) * (1 - container->get_width());} - //! Returns true iff the next node will be on a different scanline + //! Returns true iff the next tile will be on a different scanline /*! To visit a scanline in right-to-left order, or to revisit a scanline, wait until this method returns true, then use a THMapScanlineIterator. */ - inline bool isLastOnScanline() const; + inline bool is_last_on_scanline() const; private: - // Maximum extents of the visible parts of a node (pixel distances relative + // Maximum extents of the visible parts of a tile (pixel distances relative // to the top-most corner of an isometric cell) // If set too low, things will disappear when near the screen edge // If set too high, rendering will slow down - static const int ms_iMarginTop = 150; - static const int ms_iMarginLeft = 110; - static const int ms_iMarginRight = 110; - static const int ms_iMarginBottom = 150; - - friend class THMapScanlineIterator; - - const THMapNode* m_pNode; - const THMap* m_pMap; - int m_iXs; - int m_iYs; - const int m_iScreenX; - const int m_iScreenY; - const int m_iScreenWidth; - const int m_iScreenHeight; - int m_iBaseX; - int m_iBaseY; - int m_iX; - int m_iY; - int m_iScanlineCount; - eTHMapScanlineIteratorDirection m_eDirection; + static const int margin_top = 150; + static const int margin_left = 110; + static const int margin_right = 110; + static const int margin_bottom = 150; + + friend class map_scanline_iterator; + + const map_tile* tile; + const level_map* container; + + // TODO: Consider removing these, they are trivial to calculate + int x_relative_to_screen; + int y_relative_to_screen; + + const int screen_offset_x; + const int screen_offset_y; + const int screen_width; + const int screen_height; + int base_x; + int base_y; + int world_x; + int world_y; + int scanline_count; + map_scanline_iterator_direction direction; - void _advanceUntilVisible(); + void advance_until_visible(); }; -//! Utility class for re-iterating a scanline visited by a THMapNodeIterator -class THMapScanlineIterator +//! Utility class for re-iterating a scanline visited by a map_tile_iterator +class map_scanline_iterator { public: - THMapScanlineIterator(); + map_scanline_iterator(); /*! - @arg itrNodes A node iterator which has reached the end of a scanline + @arg itrNodes A tile iterator which has reached the end of a scanline @arg eDirection The direction in which to iterate the scanline; - ScanlineForward for left-to-right, ScanlineBackward for right-to-left. + forward for left-to-right, backward for right-to-left. @arg iXOffset If given, values returned by x() will be offset by this. @arg iYOffset If given, values returned by y() will be offset by this. */ - THMapScanlineIterator(const THMapNodeIterator& itrNodes, - eTHMapScanlineIteratorDirection eDirection, + map_scanline_iterator(const map_tile_iterator& itrNodes, + map_scanline_iterator_direction eDirection, int iXOffset = 0, int iYOffset = 0); - inline operator bool () const {return m_pNode != m_pNodeEnd;} - inline THMapScanlineIterator& operator ++ (); + inline operator bool () const {return tile != end_tile;} + inline map_scanline_iterator& operator ++ (); - inline const THMapNode* operator -> () const {return m_pNode;} - inline int x() const {return m_iXs;} - inline int y() const {return m_iYs;} - inline const THMapNode* getNextNode() {return m_pNode + m_iNodeStep;} - inline const THMapNode* getPreviousNode() { return m_pNode - m_iNodeStep;} - THMapScanlineIterator operator= (const THMapScanlineIterator &iterator); - inline const THMapNode* getNode() {return m_pNode;} + inline const map_tile* operator -> () const {return tile;} + inline int x() const {return x_relative_to_screen;} + inline int y() const {return y_relative_to_screen;} + inline const map_tile* get_next_tile() {return tile + tile_step;} + inline const map_tile* get_previous_tile() { return tile - tile_step;} + map_scanline_iterator operator= (const map_scanline_iterator &iterator); + inline const map_tile* get_tile() {return tile;} private: - const THMapNode* m_pNode; - const THMapNode* m_pNodeFirst; - const THMapNode* m_pNodeEnd; - int m_iNodeStep; - int m_iXStep; - int m_iXs; - int m_iYs; - int m_takenSteps; + const map_tile* tile; + const map_tile* first_tile; + const map_tile* end_tile; + int tile_step; + int x_step; + int x_relative_to_screen; + int y_relative_to_screen; + int steps_taken; }; #endif // CORSIX_TH_TH_MAP_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/th_map_overlays.cpp corsix-th-0.62/CorsixTH/Src/th_map_overlays.cpp --- corsix-th-0.61/CorsixTH/Src/th_map_overlays.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_map_overlays.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -25,157 +25,157 @@ #include "th_map.h" #include -THMapOverlayPair::THMapOverlayPair() +map_overlay_pair::map_overlay_pair() { - m_pFirst = nullptr; - m_pSecond = nullptr; - m_bOwnFirst = false; - m_bOwnSecond = false; + first = nullptr; + second = nullptr; + owns_first = false; + owns_second = false; } -THMapOverlayPair::~THMapOverlayPair() +map_overlay_pair::~map_overlay_pair() { - setFirst(nullptr, false); - setSecond(nullptr, false); + set_first(nullptr, false); + set_second(nullptr, false); } -void THMapOverlayPair::setFirst(THMapOverlay* pOverlay, bool bTakeOwnership) +void map_overlay_pair::set_first(map_overlay* pOverlay, bool bTakeOwnership) { - if(m_pFirst && m_bOwnFirst) - delete m_pFirst; - m_pFirst = pOverlay; - m_bOwnFirst = bTakeOwnership; + if(first && owns_first) + delete first; + first = pOverlay; + owns_first = bTakeOwnership; } -void THMapOverlayPair::setSecond(THMapOverlay* pOverlay, bool bTakeOwnership) +void map_overlay_pair::set_second(map_overlay* pOverlay, bool bTakeOwnership) { - if(m_pSecond && m_bOwnSecond) - delete m_pSecond; - m_pSecond = pOverlay; - m_bOwnSecond = bTakeOwnership; + if(second && owns_second) + delete second; + second = pOverlay; + owns_second = bTakeOwnership; } -void THMapOverlayPair::drawCell(THRenderTarget* pCanvas, int iCanvasX, - int iCanvasY, const THMap* pMap, int iNodeX, +void map_overlay_pair::draw_cell(render_target* pCanvas, int iCanvasX, + int iCanvasY, const level_map* pMap, int iNodeX, int iNodeY) { - if(m_pFirst) - m_pFirst->drawCell(pCanvas, iCanvasX, iCanvasY, pMap, iNodeX, iNodeY); - if(m_pSecond) - m_pSecond->drawCell(pCanvas, iCanvasX, iCanvasY, pMap, iNodeX, iNodeY); + if(first) + first->draw_cell(pCanvas, iCanvasX, iCanvasY, pMap, iNodeX, iNodeY); + if(second) + second->draw_cell(pCanvas, iCanvasX, iCanvasY, pMap, iNodeX, iNodeY); } -THMapTextOverlay::THMapTextOverlay() +map_text_overlay::map_text_overlay() { - m_iBackgroundSprite = 0; + background_sprite = 0; } -void THMapTextOverlay::setBackgroundSprite(size_t iSprite) +void map_text_overlay::set_background_sprite(size_t iSprite) { - m_iBackgroundSprite = iSprite; + background_sprite = iSprite; } -void THMapTextOverlay::drawCell(THRenderTarget* pCanvas, int iCanvasX, - int iCanvasY, const THMap* pMap, int iNodeX, +void map_text_overlay::draw_cell(render_target* pCanvas, int iCanvasX, + int iCanvasY, const level_map* pMap, int iNodeX, int iNodeY) { - if(m_pSprites && m_iBackgroundSprite) + if(sprites && background_sprite) { - m_pSprites->drawSprite(pCanvas, m_iBackgroundSprite, iCanvasX, + sprites->draw_sprite(pCanvas, background_sprite, iCanvasX, iCanvasY, 0); } - if(m_pFont) + if(font) { - _drawText(pCanvas, iCanvasX, iCanvasY, getText(pMap, iNodeX, iNodeY)); + draw_text(pCanvas, iCanvasX, iCanvasY, get_text(pMap, iNodeX, iNodeY)); } } -const std::string THMapPositionsOverlay::getText(const THMap* pMap, int iNodeX, int iNodeY) +const std::string map_positions_overlay::get_text(const level_map* pMap, int iNodeX, int iNodeY) { std::ostringstream str; str << iNodeX + 1 << ',' << iNodeY + 1; return str.str(); } -THMapTypicalOverlay::THMapTypicalOverlay() +map_typical_overlay::map_typical_overlay() { - m_pSprites = nullptr; - m_pFont = nullptr; - m_bOwnsSprites = false; - m_bOwnsFont = false; + sprites = nullptr; + font = nullptr; + owns_sprites = false; + owns_font = false; } -THMapTypicalOverlay::~THMapTypicalOverlay() +map_typical_overlay::~map_typical_overlay() { - setSprites(nullptr, false); - setFont(nullptr, false); + set_sprites(nullptr, false); + set_font(nullptr, false); } -void THMapFlagsOverlay::drawCell(THRenderTarget* pCanvas, int iCanvasX, - int iCanvasY, const THMap* pMap, int iNodeX, +void map_flags_overlay::draw_cell(render_target* pCanvas, int iCanvasX, + int iCanvasY, const level_map* pMap, int iNodeX, int iNodeY) { - const THMapNode *pNode = pMap->getNode(iNodeX, iNodeY); + const map_tile *pNode = pMap->get_tile(iNodeX, iNodeY); if(!pNode) return; - if(m_pSprites) + if(sprites) { if(pNode->flags.passable) - m_pSprites->drawSprite(pCanvas, 3, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 3, iCanvasX, iCanvasY, 0); if(pNode->flags.hospital) - m_pSprites->drawSprite(pCanvas, 8, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 8, iCanvasX, iCanvasY, 0); if(pNode->flags.buildable) - m_pSprites->drawSprite(pCanvas, 9, iCanvasX, iCanvasY, 0); - if(pNode->flags.can_travel_n && pMap->getNode(iNodeX, iNodeY - 1)->flags.passable) + sprites->draw_sprite(pCanvas, 9, iCanvasX, iCanvasY, 0); + if(pNode->flags.can_travel_n && pMap->get_tile(iNodeX, iNodeY - 1)->flags.passable) { - m_pSprites->drawSprite(pCanvas, 4, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 4, iCanvasX, iCanvasY, 0); } - if(pNode->flags.can_travel_e && pMap->getNode(iNodeX + 1, iNodeY)->flags.passable) + if(pNode->flags.can_travel_e && pMap->get_tile(iNodeX + 1, iNodeY)->flags.passable) { - m_pSprites->drawSprite(pCanvas, 5, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 5, iCanvasX, iCanvasY, 0); } - if(pNode->flags.can_travel_s && pMap->getNode(iNodeX, iNodeY + 1)->flags.passable) + if(pNode->flags.can_travel_s && pMap->get_tile(iNodeX, iNodeY + 1)->flags.passable) { - m_pSprites->drawSprite(pCanvas, 6, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 6, iCanvasX, iCanvasY, 0); } - if(pNode->flags.can_travel_w && pMap->getNode(iNodeX - 1, iNodeY)->flags.passable) + if(pNode->flags.can_travel_w && pMap->get_tile(iNodeX - 1, iNodeY)->flags.passable) { - m_pSprites->drawSprite(pCanvas, 7, iCanvasX, iCanvasY, 0); + sprites->draw_sprite(pCanvas, 7, iCanvasX, iCanvasY, 0); } } - if(m_pFont) + if(font) { if(!pNode->objects.empty()) { std::ostringstream str; str << 'T' << static_cast(pNode->objects.front()); - _drawText(pCanvas, iCanvasX, iCanvasY - 8, str.str()); + draw_text(pCanvas, iCanvasX, iCanvasY - 8, str.str()); } if(pNode->iRoomId) { std::ostringstream str; str << 'R' << static_cast(pNode->iRoomId); - _drawText(pCanvas, iCanvasX, iCanvasY + 8, str.str()); + draw_text(pCanvas, iCanvasX, iCanvasY + 8, str.str()); } } } -void THMapParcelsOverlay::drawCell(THRenderTarget* pCanvas, int iCanvasX, - int iCanvasY, const THMap* pMap, int iNodeX, +void map_parcels_overlay::draw_cell(render_target* pCanvas, int iCanvasX, + int iCanvasY, const level_map* pMap, int iNodeX, int iNodeY) { - const THMapNode *pNode = pMap->getNode(iNodeX, iNodeY); + const map_tile *pNode = pMap->get_tile(iNodeX, iNodeY); if(!pNode) return; - if(m_pFont) - _drawText(pCanvas, iCanvasX, iCanvasY, std::to_string((int)pNode->iParcelId)); - if(m_pSprites) + if(font) + draw_text(pCanvas, iCanvasX, iCanvasY, std::to_string((int)pNode->iParcelId)); + if(sprites) { uint16_t iParcel = pNode->iParcelId; #define DIR(dx, dy, sprite) \ - pNode = pMap->getNode(iNodeX + dx, iNodeY + dy); \ + pNode = pMap->get_tile(iNodeX + dx, iNodeY + dy); \ if(!pNode || pNode->iParcelId != iParcel) \ - m_pSprites->drawSprite(pCanvas, sprite, iCanvasX, iCanvasY, 0) + sprites->draw_sprite(pCanvas, sprite, iCanvasX, iCanvasY, 0) DIR( 0, -1, 18); DIR( 1, 0, 19); DIR( 0, 1, 20); @@ -185,26 +185,26 @@ } -void THMapTypicalOverlay::_drawText(THRenderTarget* pCanvas, int iX, int iY, +void map_typical_overlay::draw_text(render_target* pCanvas, int iX, int iY, std::string str) { - THFontDrawArea oArea = m_pFont->getTextSize(str.c_str(), str.length()); - m_pFont->drawText(pCanvas, str.c_str(), str.length(), iX + (64 - oArea.iEndX) / 2, - iY + (32 - oArea.iEndY) / 2); + text_layout oArea = font->get_text_dimensions(str.c_str(), str.length()); + font->draw_text(pCanvas, str.c_str(), str.length(), iX + (64 - oArea.end_x) / 2, + iY + (32 - oArea.end_y) / 2); } -void THMapTypicalOverlay::setSprites(THSpriteSheet* pSheet, bool bTakeOwnership) +void map_typical_overlay::set_sprites(sprite_sheet* pSheet, bool bTakeOwnership) { - if(m_pSprites && m_bOwnsSprites) - delete m_pSprites; - m_pSprites = pSheet; - m_bOwnsSprites = bTakeOwnership; + if(sprites && owns_sprites) + delete sprites; + sprites = pSheet; + owns_sprites = bTakeOwnership; } -void THMapTypicalOverlay::setFont(THFont* pFont, bool bTakeOwnership) +void map_typical_overlay::set_font(::font* font, bool take_ownership) { - if(m_pFont && m_bOwnsFont) - delete m_pFont; - m_pFont = pFont; - m_bOwnsFont = bTakeOwnership; + if(this->font && owns_font) + delete this->font; + this->font = font; + owns_font = take_ownership; } diff -Nru corsix-th-0.61/CorsixTH/Src/th_map_overlays.h corsix-th-0.62/CorsixTH/Src/th_map_overlays.h --- corsix-th-0.61/CorsixTH/Src/th_map_overlays.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_map_overlays.h 2018-07-21 11:13:17.000000000 +0000 @@ -26,91 +26,91 @@ #include #include -class THFont; -class THMap; -class THRenderTarget; -class THSpriteSheet; +class font; +class level_map; +class render_target; +class sprite_sheet; -class THMapOverlay +class map_overlay { public: - virtual ~THMapOverlay() = default; + virtual ~map_overlay() = default; - virtual void drawCell(THRenderTarget* pCanvas, int iCanvasX, int iCanvasY, - const THMap* pMap, int iNodeX, int iNodeY) = 0; + virtual void draw_cell(render_target* pCanvas, int iCanvasX, int iCanvasY, + const level_map* pMap, int iNodeX, int iNodeY) = 0; }; -class THMapOverlayPair : public THMapOverlay +class map_overlay_pair : public map_overlay { public: - THMapOverlayPair(); - virtual ~THMapOverlayPair(); + map_overlay_pair(); + virtual ~map_overlay_pair(); - void setFirst(THMapOverlay* pOverlay, bool bTakeOwnership); - void setSecond(THMapOverlay* pOverlay, bool bTakeOwnership); + void set_first(map_overlay* pOverlay, bool bTakeOwnership); + void set_second(map_overlay* pOverlay, bool bTakeOwnership); - void drawCell(THRenderTarget* pCanvas, int iCanvasX, int iCanvasY, - const THMap* pMap, int iNodeX, int iNodeY) override; + void draw_cell(render_target* pCanvas, int iCanvasX, int iCanvasY, + const level_map* pMap, int iNodeX, int iNodeY) override; private: - THMapOverlay *m_pFirst, *m_pSecond; - bool m_bOwnFirst, m_bOwnSecond; + map_overlay *first, *second; + bool owns_first, owns_second; }; -class THMapTypicalOverlay : public THMapOverlay +class map_typical_overlay : public map_overlay { public: - THMapTypicalOverlay(); - virtual ~THMapTypicalOverlay(); + map_typical_overlay(); + virtual ~map_typical_overlay(); - void setSprites(THSpriteSheet* pSheet, bool bTakeOwnership); - void setFont(THFont* pFont, bool bTakeOwnership); + void set_sprites(sprite_sheet* pSheet, bool bTakeOwnership); + void set_font(::font* font, bool take_ownership); protected: - void _drawText(THRenderTarget* pCanvas, int iX, int iY, std::string str); + void draw_text(render_target* pCanvas, int iX, int iY, std::string str); - THSpriteSheet* m_pSprites; - THFont* m_pFont; + sprite_sheet* sprites; + ::font* font; private: - bool m_bOwnsSprites; - bool m_bOwnsFont; + bool owns_sprites; + bool owns_font; }; -class THMapTextOverlay : public THMapTypicalOverlay +class map_text_overlay : public map_typical_overlay { public: - THMapTextOverlay(); - virtual ~THMapTextOverlay() = default; + map_text_overlay(); + virtual ~map_text_overlay() = default; - virtual void drawCell(THRenderTarget* pCanvas, int iCanvasX, int iCanvasY, - const THMap* pMap, int iNodeX, int iNodeY); + virtual void draw_cell(render_target* pCanvas, int iCanvasX, int iCanvasY, + const level_map* pMap, int iNodeX, int iNodeY); - void setBackgroundSprite(size_t iSprite); - virtual const std::string getText(const THMap* pMap, int iNodeX, int iNodeY) = 0; + void set_background_sprite(size_t iSprite); + virtual const std::string get_text(const level_map* pMap, int iNodeX, int iNodeY) = 0; private: - size_t m_iBackgroundSprite; + size_t background_sprite; }; -class THMapPositionsOverlay final : public THMapTextOverlay +class map_positions_overlay final : public map_text_overlay { public: - const std::string getText(const THMap* pMap, int iNodeX, int iNodeY) override; + const std::string get_text(const level_map* pMap, int iNodeX, int iNodeY) override; }; -class THMapFlagsOverlay final : public THMapTypicalOverlay +class map_flags_overlay final : public map_typical_overlay { public: - void drawCell(THRenderTarget* pCanvas, int iCanvasX, int iCanvasY, - const THMap* pMap, int iNodeX, int iNodeY) override; + void draw_cell(render_target* pCanvas, int iCanvasX, int iCanvasY, + const level_map* pMap, int iNodeX, int iNodeY) override; }; -class THMapParcelsOverlay final : public THMapTypicalOverlay +class map_parcels_overlay final : public map_typical_overlay { public: - void drawCell(THRenderTarget* pCanvas, int iCanvasX, int iCanvasY, - const THMap* pMap, int iNodeX, int iNodeY) override; + void draw_cell(render_target* pCanvas, int iCanvasX, int iCanvasY, + const level_map* pMap, int iNodeX, int iNodeY) override; }; #endif diff -Nru corsix-th-0.61/CorsixTH/Src/th_movie.cpp corsix-th-0.62/CorsixTH/Src/th_movie.cpp --- corsix-th-0.61/CorsixTH/Src/th_movie.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_movie.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -39,167 +39,176 @@ #endif } #include -#include +#include #include +#include #if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)) || \ (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100)) #define av_packet_unref av_free_packet #endif -#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101)) || \ - (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 28, 1)) +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 28, 1)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101)) #define av_frame_alloc avcodec_alloc_frame #define av_frame_unref avcodec_get_frame_defaults #define av_frame_free avcodec_free_frame #endif +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 52, 0)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 63, 100)) +void avcodec_free_context(AVCodecContext** ctx) { + avcodec_close(*ctx); + av_free(*ctx); +} +#endif + static void th_movie_audio_callback(int iChannel, void *pStream, int iStreamSize, void *pUserData) { - THMovie *pMovie = (THMovie *)pUserData; - pMovie->copyAudioToStream((uint8_t*)pStream, iStreamSize); + movie_player *pMovie = (movie_player *)pUserData; + pMovie->copy_audio_to_stream((uint8_t*)pStream, iStreamSize); } -THMoviePicture::THMoviePicture(): - m_pBuffer(nullptr), - m_pixelFormat(AV_PIX_FMT_RGB24), - m_mutex{} +movie_picture::movie_picture(): + buffer(nullptr), + pixel_format(AV_PIX_FMT_RGB24), + mutex{} {} -THMoviePicture::~THMoviePicture() +movie_picture::~movie_picture() { - av_freep(&m_pBuffer); + av_freep(&buffer); } -void THMoviePicture::allocate(int iWidth, int iHeight) +void movie_picture::allocate(int iWidth, int iHeight) { - m_iWidth = iWidth; - m_iHeight = iHeight; - av_freep(&m_pBuffer); + width = iWidth; + height = iHeight; + av_freep(&buffer); #if (defined(CORSIX_TH_USE_LIBAV) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 6, 0)) || \ (defined(CORSIX_TH_USE_FFMPEG) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 63, 100)) - int numBytes = av_image_get_buffer_size(m_pixelFormat, m_iWidth, m_iHeight, 1); + int numBytes = av_image_get_buffer_size(pixel_format, width, height, 1); #else - int numBytes = avpicture_get_size(m_pixelFormat, m_iWidth, m_iHeight); + int numBytes = avpicture_get_size(pixel_format, width, height); #endif - m_pBuffer = static_cast(av_mallocz(numBytes)); + buffer = static_cast(av_mallocz(numBytes)); } -void THMoviePicture::deallocate() +void movie_picture::deallocate() { - av_freep(&m_pBuffer); + av_freep(&buffer); } -THMoviePictureBuffer::THMoviePictureBuffer(): - m_aborting(false), - m_fAllocated(false), - m_iCount(0), - m_iReadIndex(0), - m_iWriteIndex(0), - m_pSwsContext(nullptr), - m_pTexture(nullptr), - m_mutex{}, - m_cond{} +movie_picture_buffer::movie_picture_buffer(): + aborting(false), + allocated(false), + picture_count(0), + read_index(0), + write_index(0), + sws_context(nullptr), + texture(nullptr), + mutex{}, + cond{} { } -THMoviePictureBuffer::~THMoviePictureBuffer() +movie_picture_buffer::~movie_picture_buffer() { - sws_freeContext(m_pSwsContext); - if (m_pTexture) + sws_freeContext(sws_context); + if (texture) { - SDL_DestroyTexture(m_pTexture); - m_pTexture = nullptr; + SDL_DestroyTexture(texture); + texture = nullptr; } } -void THMoviePictureBuffer::abort() +void movie_picture_buffer::abort() { - m_aborting = true; - std::lock_guard lock(m_mutex); - m_cond.notify_all(); + aborting = true; + std::lock_guard lock(mutex); + cond.notify_all(); } -void THMoviePictureBuffer::reset() +void movie_picture_buffer::reset() { - m_aborting = false; + aborting = false; } -void THMoviePictureBuffer::allocate(SDL_Renderer *pRenderer, int iWidth, int iHeight) +void movie_picture_buffer::allocate(SDL_Renderer *pRenderer, int iWidth, int iHeight) { - if (m_pTexture) + if (texture) { - SDL_DestroyTexture(m_pTexture); - std::cerr << "THMovie overlay should be deallocated before being allocated!\n"; + SDL_DestroyTexture(texture); + std::cerr << "movie_player overlay should be deallocated before being allocated!\n"; } - m_pTexture = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, iWidth, iHeight); - if (m_pTexture == nullptr) + texture = SDL_CreateTexture(pRenderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, iWidth, iHeight); + if (texture == nullptr) { std::cerr << "Problem creating overlay: " << SDL_GetError() << "\n"; return; } - for(int i = 0; i < ms_pictureBufferSize; i++) + for(int i = 0; i < picture_buffer_size; i++) { - m_aPictureQueue[i].allocate(iWidth, iHeight); + picture_queue[i].allocate(iWidth, iHeight); } - //Do not change m_iWriteIndex, it's used by the other thread. - //m_iReadIndex is only used in this thread. - m_iReadIndex = m_iWriteIndex; + // Do not change write_index, it's used by the other thread. + // read_index is only used in this thread. + read_index = write_index; - std::lock_guard lock(m_mutex); - m_iCount = 0; - m_fAllocated = true; - m_cond.notify_one(); + std::lock_guard lock(mutex); + picture_count = 0; + allocated = true; + cond.notify_one(); } -void THMoviePictureBuffer::deallocate() +void movie_picture_buffer::deallocate() { { - std::lock_guard lock(m_mutex); - m_fAllocated = false; + std::lock_guard lock(mutex); + allocated = false; } - for(int i = 0; i < ms_pictureBufferSize; i++) + for(int i = 0; i < picture_buffer_size; i++) { - std::lock_guard pictureLock(m_aPictureQueue[i].m_mutex); - m_aPictureQueue[i].deallocate(); + std::lock_guard pictureLock(picture_queue[i].mutex); + picture_queue[i].deallocate(); } - if (m_pTexture) + if (texture) { - SDL_DestroyTexture(m_pTexture); - m_pTexture = nullptr; + SDL_DestroyTexture(texture); + texture = nullptr; } } -bool THMoviePictureBuffer::advance() +bool movie_picture_buffer::advance() { if(empty()) { return false; } - m_iReadIndex++; - if(m_iReadIndex == ms_pictureBufferSize) + read_index++; + if(read_index == picture_buffer_size) { - m_iReadIndex = 0; + read_index = 0; } - std::lock_guard lock(m_mutex); - m_iCount--; - m_cond.notify_one(); + std::lock_guard lock(mutex); + picture_count--; + cond.notify_one(); return true; } -void THMoviePictureBuffer::draw(SDL_Renderer *pRenderer, const SDL_Rect &dstrect) +void movie_picture_buffer::draw(SDL_Renderer *pRenderer, const SDL_Rect &dstrect) { if(!empty()) { - auto cur_pic = &(m_aPictureQueue[m_iReadIndex]); + auto cur_pic = &(picture_queue[read_index]); - std::lock_guard pictureLock(cur_pic->m_mutex); - if (cur_pic->m_pBuffer) + std::lock_guard pictureLock(cur_pic->mutex); + if (cur_pic->buffer) { - SDL_UpdateTexture(m_pTexture, nullptr, cur_pic->m_pBuffer, cur_pic->m_iWidth * 3); - int iError = SDL_RenderCopy(pRenderer, m_pTexture, nullptr, &dstrect); + SDL_UpdateTexture(texture, nullptr, cur_pic->buffer, cur_pic->width * 3); + int iError = SDL_RenderCopy(pRenderer, texture, nullptr, &dstrect); if (iError < 0) { std::cerr << "Error displaying movie frame: " << SDL_GetError() << "\n"; @@ -208,57 +217,57 @@ } } -double THMoviePictureBuffer::getNextPts() +double movie_picture_buffer::get_next_pts() { double nextPts; - std::lock_guard lock(m_mutex); - if(!m_fAllocated || m_iCount < 2) + std::lock_guard lock(mutex); + if(!allocated || picture_count < 2) { nextPts = 0; } else { - nextPts = m_aPictureQueue[(m_iReadIndex + 1) % ms_pictureBufferSize].m_dPts; + nextPts = picture_queue[(read_index + 1) % picture_buffer_size].pts; } return nextPts; } -bool THMoviePictureBuffer::empty() +bool movie_picture_buffer::empty() { - std::lock_guard lock(m_mutex); - return (!m_fAllocated || m_iCount == 0); + std::lock_guard lock(mutex); + return (!allocated || picture_count == 0); } -bool THMoviePictureBuffer::full() +bool movie_picture_buffer::full() { - std::lock_guard lock(m_mutex); - return unsafeFull(); + std::lock_guard lock(mutex); + return unsafe_full(); } -bool THMoviePictureBuffer::unsafeFull() +bool movie_picture_buffer::unsafe_full() { - return (!m_fAllocated || m_iCount == ms_pictureBufferSize); + return (!allocated || picture_count == picture_buffer_size); } -int THMoviePictureBuffer::write(AVFrame* pFrame, double dPts) +int movie_picture_buffer::write(AVFrame* pFrame, double dPts) { - THMoviePicture* pMoviePicture = nullptr; - std::unique_lock picBufLock(m_mutex); - while(unsafeFull() && !m_aborting) + movie_picture* pMoviePicture = nullptr; + std::unique_lock picBufLock(mutex); + while(unsafe_full() && !aborting) { - m_cond.wait(picBufLock); + cond.wait(picBufLock); } picBufLock.unlock(); - if(m_aborting) { return -1; } + if(aborting) { return -1; } - pMoviePicture = &m_aPictureQueue[m_iWriteIndex]; - std::unique_lock pictureLock(pMoviePicture->m_mutex); + pMoviePicture = &picture_queue[write_index]; + std::unique_lock pictureLock(pMoviePicture->mutex); - if(pMoviePicture->m_pBuffer) + if(pMoviePicture->buffer) { - m_pSwsContext = sws_getCachedContext(m_pSwsContext, pFrame->width, pFrame->height, (AVPixelFormat)pFrame->format, pMoviePicture->m_iWidth, pMoviePicture->m_iHeight, pMoviePicture->m_pixelFormat, SWS_BICUBIC, nullptr, nullptr, nullptr); - if(m_pSwsContext == nullptr) + sws_context = sws_getCachedContext(sws_context, pFrame->width, pFrame->height, (AVPixelFormat)pFrame->format, pMoviePicture->width, pMoviePicture->height, pMoviePicture->pixel_format, SWS_BICUBIC, nullptr, nullptr, nullptr); + if(sws_context == nullptr) { std::cerr << "Failed to initialize SwsContext\n"; return 1; @@ -268,54 +277,54 @@ AVFrame *pFrameRGB = av_frame_alloc(); #if (defined(CORSIX_TH_USE_LIBAV) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 6, 0)) || \ (defined(CORSIX_TH_USE_FFMPEG) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 63, 100)) - av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, pMoviePicture->m_pBuffer, pMoviePicture->m_pixelFormat, pMoviePicture->m_iWidth, pMoviePicture->m_iHeight, 1); + av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, pMoviePicture->buffer, pMoviePicture->pixel_format, pMoviePicture->width, pMoviePicture->height, 1); #else - avpicture_fill((AVPicture *)pFrameRGB, pMoviePicture->m_pBuffer, pMoviePicture->m_pixelFormat, pMoviePicture->m_iWidth, pMoviePicture->m_iHeight); + avpicture_fill((AVPicture *)pFrameRGB, pMoviePicture->buffer, pMoviePicture->pixel_format, pMoviePicture->width, pMoviePicture->height); #endif /* Rescale the frame data and convert it to RGB24. */ - sws_scale(m_pSwsContext, pFrame->data, pFrame->linesize, 0, pFrame->height, pFrameRGB->data, pFrameRGB->linesize); + sws_scale(sws_context, pFrame->data, pFrame->linesize, 0, pFrame->height, pFrameRGB->data, pFrameRGB->linesize); av_frame_free(&pFrameRGB); - pMoviePicture->m_dPts = dPts; + pMoviePicture->pts = dPts; pictureLock.unlock(); - m_iWriteIndex++; - if(m_iWriteIndex == ms_pictureBufferSize) + write_index++; + if(write_index == picture_buffer_size) { - m_iWriteIndex = 0; + write_index = 0; } picBufLock.lock(); - m_iCount++; + picture_count++; picBufLock.unlock(); } return 0; } -THAVPacketQueue::THAVPacketQueue(): - m_pFirstPacket(nullptr), - m_pLastPacket(nullptr), - iCount(0), - m_mutex{}, - m_cond{} +av_packet_queue::av_packet_queue(): + first_packet(nullptr), + last_packet(nullptr), + count(0), + mutex{}, + cond{} { } -THAVPacketQueue::~THAVPacketQueue() +av_packet_queue::~av_packet_queue() { } -int THAVPacketQueue::getCount() const +int av_packet_queue::get_count() const { - return iCount; + return count; } -void THAVPacketQueue::push(AVPacket *pPacket) +void av_packet_queue::push(AVPacket *pPacket) { -#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100)) || \ - (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 8, 0)) +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 8, 0)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100)) if(av_dup_packet(pPacket) < 0) { throw -1; } #endif @@ -323,31 +332,31 @@ pNode->pkt = *pPacket; pNode->next = nullptr; - std::lock_guard lock(m_mutex); + std::lock_guard lock(mutex); - if(m_pLastPacket == nullptr) + if(last_packet == nullptr) { - m_pFirstPacket = pNode; + first_packet = pNode; } else { - m_pLastPacket->next = pNode; + last_packet->next = pNode; } - m_pLastPacket = pNode; - iCount++; + last_packet = pNode; + count++; - m_cond.notify_one(); + cond.notify_one(); } -AVPacket* THAVPacketQueue::pull(bool fBlock) +AVPacket* av_packet_queue::pull(bool fBlock) { - std::unique_lock lock(m_mutex); + std::unique_lock lock(mutex); - AVPacketList* pNode = m_pFirstPacket; + AVPacketList* pNode = first_packet; if(pNode == nullptr && fBlock) { - m_cond.wait(lock); - pNode = m_pFirstPacket; + cond.wait(lock); + pNode = first_packet; } AVPacket *pPacket; @@ -357,10 +366,9 @@ } else { - m_pFirstPacket = pNode->next; - if(m_pFirstPacket == nullptr) { m_pLastPacket = nullptr; } - iCount--; - + first_packet = pNode->next; + if(first_packet == nullptr) { last_packet = nullptr; } + count--; pPacket = (AVPacket*)av_malloc(sizeof(AVPacket)); *pPacket = pNode->pkt; av_free(pNode); @@ -369,101 +377,105 @@ return pPacket; } -void THAVPacketQueue::release() +void av_packet_queue::release() { - std::lock_guard lock(m_mutex); - m_cond.notify_all(); + std::lock_guard lock(mutex); + cond.notify_all(); } -THMovie::THMovie(): - m_pRenderer(nullptr), - m_sLastError(), - m_pFormatContext(nullptr), - m_pVideoCodecContext(nullptr), - m_pAudioCodecContext(nullptr), - m_pVideoQueue(nullptr), - m_pAudioQueue(nullptr), - m_pMoviePictureBuffer(new THMoviePictureBuffer()), - m_pAudioResampleContext(nullptr), - m_iAudioBufferSize(0), - m_iAudioBufferMaxSize(0), - m_pAudioPacket(nullptr), - m_audio_frame(nullptr), - m_pChunk(nullptr), - m_iChannel(-1), - m_streamThread{}, - m_videoThread{}, - m_decodingAudioMutex{} +movie_player::movie_player(): + renderer(nullptr), + last_error(), + format_context(nullptr), + video_codec_context(nullptr), + audio_codec_context(nullptr), + video_queue(nullptr), + audio_queue(nullptr), + movie_picture_buffer(new ::movie_picture_buffer()), + audio_resample_context(nullptr), + audio_buffer_size(0), + audio_buffer_max_size(0), + audio_packet(nullptr), + audio_frame(nullptr), + empty_audio_chunk(nullptr), + audio_channel(-1), + stream_thread{}, + video_thread{}, + decoding_audio_mutex{} { +#if defined(CORSIX_TH_USE_LIBAV) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)) av_register_all(); +#endif - m_flushPacket = (AVPacket*)av_malloc(sizeof(AVPacket)); - av_init_packet(m_flushPacket); - m_flushPacket->data = (uint8_t *)"FLUSH"; - m_flushPacket->size = 5; + flush_packet = (AVPacket*)av_malloc(sizeof(AVPacket)); + av_init_packet(flush_packet); + flush_packet->data = (uint8_t *)"FLUSH"; + flush_packet->size = 5; - m_pbChunkBuffer = (uint8_t*)std::calloc(ms_audioBufferSize, sizeof(uint8_t)); + audio_chunk_buffer = (uint8_t*)std::calloc(audio_chunk_buffer_capacity, sizeof(uint8_t)); } -THMovie::~THMovie() +movie_player::~movie_player() { unload(); - av_packet_unref(m_flushPacket); - av_free(m_flushPacket); - free(m_pbChunkBuffer); + av_packet_unref(flush_packet); + av_free(flush_packet); + free(audio_chunk_buffer); + delete movie_picture_buffer; } -void THMovie::setRenderer(SDL_Renderer *pRenderer) +void movie_player::set_renderer(SDL_Renderer *pRenderer) { - m_pRenderer = pRenderer; + renderer = pRenderer; } -bool THMovie::moviesEnabled() const +bool movie_player::movies_enabled() const { return true; } -bool THMovie::load(const char* szFilepath) +bool movie_player::load(const char* szFilepath) { int iError = 0; AVCodec* m_pVideoCodec; AVCodec* m_pAudioCodec; unload(); //Unload any currently loaded video to free memory - m_fAborting = false; + aborting = false; - iError = avformat_open_input(&m_pFormatContext, szFilepath, nullptr, nullptr); + iError = avformat_open_input(&format_context, szFilepath, nullptr, nullptr); if(iError < 0) { - av_strerror(iError, m_szErrorBuffer, ms_movieErrorBufferSize); - m_sLastError = std::string(m_szErrorBuffer); + av_strerror(iError, error_buffer, movie_error_buffer_capacity); + last_error = std::string(error_buffer); return false; } - iError = avformat_find_stream_info(m_pFormatContext, nullptr); + iError = avformat_find_stream_info(format_context, nullptr); if(iError < 0) { - av_strerror(iError, m_szErrorBuffer, ms_movieErrorBufferSize); - m_sLastError = std::string(m_szErrorBuffer); + av_strerror(iError, error_buffer, movie_error_buffer_capacity); + last_error = std::string(error_buffer); return false; } - m_iVideoStream = av_find_best_stream(m_pFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, &m_pVideoCodec, 0); - m_pVideoCodecContext = getCodecContextForStream(m_pVideoCodec, m_pFormatContext->streams[m_iVideoStream]); - avcodec_open2(m_pVideoCodecContext, m_pVideoCodec, nullptr); + video_stream_index = av_find_best_stream(format_context, AVMEDIA_TYPE_VIDEO, -1, -1, &m_pVideoCodec, 0); + video_codec_context = get_codec_context_for_stream(m_pVideoCodec, format_context->streams[video_stream_index]); + avcodec_open2(video_codec_context, m_pVideoCodec, nullptr); - m_iAudioStream = av_find_best_stream(m_pFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &m_pAudioCodec, 0); - if(m_iAudioStream >= 0) + audio_stream_index = av_find_best_stream(format_context, AVMEDIA_TYPE_AUDIO, -1, -1, &m_pAudioCodec, 0); + if(audio_stream_index >= 0) { - m_pAudioCodecContext = getCodecContextForStream(m_pAudioCodec, m_pFormatContext->streams[m_iAudioStream]); - avcodec_open2(m_pAudioCodecContext, m_pAudioCodec, nullptr); + audio_codec_context = get_codec_context_for_stream(m_pAudioCodec, format_context->streams[audio_stream_index]); + avcodec_open2(audio_codec_context, m_pAudioCodec, nullptr); } return true; } -AVCodecContext* THMovie::getCodecContextForStream(AVCodec* codec, AVStream* stream) const +AVCodecContext* movie_player::get_codec_context_for_stream(AVCodec* codec, AVStream* stream) const { #if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 14, 0)) || \ (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 33, 100)) @@ -475,276 +487,284 @@ #endif } -void THMovie::unload() +void movie_player::unload() { - m_fAborting = true; + aborting = true; - if(m_pAudioQueue) + if(audio_queue) { - m_pAudioQueue->release(); + audio_queue->release(); } - if(m_pVideoQueue) + if(video_queue) { - m_pVideoQueue->release(); + video_queue->release(); } - m_pMoviePictureBuffer->abort(); + movie_picture_buffer->abort(); - if(m_streamThread.joinable()) + if(stream_thread.joinable()) { - m_streamThread.join(); + stream_thread.join(); } - if(m_videoThread.joinable()) + if(video_thread.joinable()) { - m_videoThread.join(); + video_thread.join(); } //wait until after other threads are closed to clear the packet queues //so we don't free something being used. - if(m_pAudioQueue) + if(audio_queue) { - while(m_pAudioQueue->getCount() > 0) + while(audio_queue->get_count() > 0) { - AVPacket* p = m_pAudioQueue->pull(false); + AVPacket* p = audio_queue->pull(false); av_packet_unref(p); + av_free(p); } - delete m_pAudioQueue; - m_pAudioQueue = nullptr; + delete audio_queue; + audio_queue = nullptr; } - if(m_pVideoQueue) + if(video_queue) { - while(m_pVideoQueue->getCount() > 0) + while(video_queue->get_count() > 0) { - AVPacket* p = m_pVideoQueue->pull(false); + AVPacket* p = video_queue->pull(false); av_packet_unref(p); + av_free(p); } - delete m_pVideoQueue; - m_pVideoQueue = nullptr; + delete video_queue; + video_queue = nullptr; } - m_pMoviePictureBuffer->deallocate(); - - if(m_pVideoCodecContext) + movie_picture_buffer->deallocate(); +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 14, 0)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 33, 100)) + if(video_codec_context) { - avcodec_close(m_pVideoCodecContext); - m_pVideoCodecContext = nullptr; + avcodec_free_context(&video_codec_context); + video_codec_context = nullptr; } +#endif - if(m_iChannel >= 0) + if(audio_channel >= 0) { - Mix_UnregisterAllEffects(m_iChannel); - Mix_HaltChannel(m_iChannel); - Mix_FreeChunk(m_pChunk); - m_iChannel = -1; + Mix_UnregisterAllEffects(audio_channel); + Mix_HaltChannel(audio_channel); + Mix_FreeChunk(empty_audio_chunk); + audio_channel = -1; } - std::lock_guard audioLock(m_decodingAudioMutex); + std::lock_guard audioLock(decoding_audio_mutex); - if(m_iAudioBufferMaxSize > 0) + if(audio_buffer_max_size > 0) { - av_free(m_pbAudioBuffer); - m_iAudioBufferMaxSize = 0; + av_free(audio_buffer); + audio_buffer_max_size = 0; } - if(m_pAudioCodecContext) +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 14, 0)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 33, 100)) + if(audio_codec_context) { - avcodec_close(m_pAudioCodecContext); - m_pAudioCodecContext = nullptr; + avcodec_free_context(&audio_codec_context); + audio_codec_context = nullptr; } - av_frame_free(&m_audio_frame); +#endif + av_frame_free(&audio_frame); #ifdef CORSIX_TH_USE_FFMPEG - swr_free(&m_pAudioResampleContext); + swr_free(&audio_resample_context); #elif defined(CORSIX_TH_USE_LIBAV) // avresample_free doesn't skip nullptr on it's own. - if (m_pAudioResampleContext != nullptr) + if (audio_resample_context != nullptr) { - avresample_free(&m_pAudioResampleContext); - m_pAudioResampleContext = nullptr; + avresample_free(&audio_resample_context); + audio_resample_context = nullptr; } #endif - if(m_pAudioPacket) + if(audio_packet) { - m_pAudioPacket->data = m_pbAudioPacketData; - m_pAudioPacket->size = m_iAudioPacketSize; - av_packet_unref(m_pAudioPacket); - av_free(m_pAudioPacket); - m_pAudioPacket = nullptr; - m_pbAudioPacketData = nullptr; - m_iAudioPacketSize = 0; + audio_packet->data = audio_packet_data; + audio_packet->size = audio_packet_size; + av_packet_unref(audio_packet); + av_free(audio_packet); + audio_packet = nullptr; + audio_packet_data = nullptr; + audio_packet_size = 0; } - if(m_pFormatContext) + if(format_context) { - avformat_close_input(&m_pFormatContext); + avformat_close_input(&format_context); } } -void THMovie::play(int iChannel) +void movie_player::play(int iChannel) { - if(!m_pRenderer) + if(!renderer) { - m_sLastError = std::string("Cannot play before setting the renderer"); + last_error = std::string("Cannot play before setting the renderer"); return; } - m_pVideoQueue = new THAVPacketQueue(); - m_pMoviePictureBuffer->reset(); - m_pMoviePictureBuffer->allocate(m_pRenderer, m_pVideoCodecContext->width, m_pVideoCodecContext->height); + video_queue = new av_packet_queue(); + movie_picture_buffer->reset(); + movie_picture_buffer->allocate(renderer, video_codec_context->width, video_codec_context->height); - m_pAudioPacket = nullptr; - m_iAudioPacketSize = 0; - m_pbAudioPacketData = nullptr; + audio_packet = nullptr; + audio_packet_size = 0; + audio_packet_data = nullptr; - m_iAudioBufferSize = 0; - m_iAudioBufferIndex = 0; - m_iAudioBufferMaxSize = 0; + audio_buffer_size = 0; + audio_buffer_index = 0; + audio_buffer_max_size = 0; - m_pAudioQueue = new THAVPacketQueue(); - m_iCurSyncPts = 0; - m_iCurSyncPtsSystemTime = SDL_GetTicks(); + audio_queue = new av_packet_queue(); + current_sync_pts = 0; + current_sync_pts_system_time = SDL_GetTicks(); - if(m_iAudioStream >= 0) + if(audio_stream_index >= 0) { - Mix_QuerySpec(&m_iMixerFrequency, nullptr, &m_iMixerChannels); + Mix_QuerySpec(&mixer_frequency, nullptr, &mixer_channels); #ifdef CORSIX_TH_USE_FFMPEG - m_pAudioResampleContext = swr_alloc_set_opts( - m_pAudioResampleContext, - m_iMixerChannels==1?AV_CH_LAYOUT_MONO:AV_CH_LAYOUT_STEREO, + audio_resample_context = swr_alloc_set_opts( + audio_resample_context, + mixer_channels==1?AV_CH_LAYOUT_MONO:AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, - m_iMixerFrequency, - m_pAudioCodecContext->channel_layout, - m_pAudioCodecContext->sample_fmt, - m_pAudioCodecContext->sample_rate, + mixer_frequency, + audio_codec_context->channel_layout, + audio_codec_context->sample_fmt, + audio_codec_context->sample_rate, 0, nullptr); - swr_init(m_pAudioResampleContext); + swr_init(audio_resample_context); #elif defined(CORSIX_TH_USE_LIBAV) - m_pAudioResampleContext = avresample_alloc_context(); - av_opt_set_int(m_pAudioResampleContext, "in_channel_layout", m_pAudioCodecContext->channel_layout, 0); - av_opt_set_int(m_pAudioResampleContext, "out_channel_layout", m_iMixerChannels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO, 0); - av_opt_set_int(m_pAudioResampleContext, "in_sample_rate", m_pAudioCodecContext->sample_rate, 0); - av_opt_set_int(m_pAudioResampleContext, "out_sample_rate", m_iMixerFrequency, 0); - av_opt_set_int(m_pAudioResampleContext, "in_sample_fmt", m_pAudioCodecContext->sample_fmt, 0); - av_opt_set_int(m_pAudioResampleContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); - avresample_open(m_pAudioResampleContext); + audio_resample_context = avresample_alloc_context(); + av_opt_set_int(audio_resample_context, "in_channel_layout", audio_codec_context->channel_layout, 0); + av_opt_set_int(audio_resample_context, "out_channel_layout", mixer_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO, 0); + av_opt_set_int(audio_resample_context, "in_sample_rate", audio_codec_context->sample_rate, 0); + av_opt_set_int(audio_resample_context, "out_sample_rate", mixer_frequency, 0); + av_opt_set_int(audio_resample_context, "in_sample_fmt", audio_codec_context->sample_fmt, 0); + av_opt_set_int(audio_resample_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + avresample_open(audio_resample_context); #endif - m_pChunk = Mix_QuickLoad_RAW(m_pbChunkBuffer, ms_audioBufferSize); + empty_audio_chunk = Mix_QuickLoad_RAW(audio_chunk_buffer, audio_chunk_buffer_capacity); - m_iChannel = Mix_PlayChannel(iChannel, m_pChunk, -1); - if(m_iChannel < 0) + audio_channel = Mix_PlayChannel(iChannel, empty_audio_chunk, -1); + if(audio_channel < 0) { - m_iChannel = -1; - m_sLastError = std::string(Mix_GetError()); + audio_channel = -1; + last_error = std::string(Mix_GetError()); + Mix_FreeChunk(empty_audio_chunk); } else { - Mix_RegisterEffect(m_iChannel, th_movie_audio_callback, nullptr, this); + Mix_RegisterEffect(audio_channel, th_movie_audio_callback, nullptr, this); } } - m_streamThread = std::thread(&THMovie::readStreams, this); - m_videoThread = std::thread(&THMovie::runVideo, this); + stream_thread = std::thread(&movie_player::read_streams, this); + video_thread = std::thread(&movie_player::run_video, this); } -void THMovie::stop() +void movie_player::stop() { - m_fAborting = true; + aborting = true; } -int THMovie::getNativeHeight() const +int movie_player::get_native_height() const { int iHeight = 0; - if(m_pVideoCodecContext) + if(video_codec_context) { - iHeight = m_pVideoCodecContext->height; + iHeight = video_codec_context->height; } return iHeight; } -int THMovie::getNativeWidth() const +int movie_player::get_native_width() const { int iWidth = 0; - if(m_pVideoCodecContext) + if(video_codec_context) { - iWidth = m_pVideoCodecContext->width; + iWidth = video_codec_context->width; } return iWidth; } -bool THMovie::hasAudioTrack() const +bool movie_player::has_audio_track() const { - return (m_iAudioStream >= 0); + return (audio_stream_index >= 0); } -const char* THMovie::getLastError() const +const char* movie_player::get_last_error() const { - return m_sLastError.c_str(); + return last_error.c_str(); } -void THMovie::clearLastError() +void movie_player::clear_last_error() { - m_sLastError.clear(); + last_error.clear(); } -void THMovie::refresh(const SDL_Rect &destination_rect) +void movie_player::refresh(const SDL_Rect &destination_rect) { SDL_Rect dest_rect; dest_rect = SDL_Rect{ destination_rect.x, destination_rect.y, destination_rect.w, destination_rect.h }; - if(!m_pMoviePictureBuffer->empty()) + if(!movie_picture_buffer->empty()) { - double dCurTime = SDL_GetTicks() - m_iCurSyncPtsSystemTime + m_iCurSyncPts * 1000.0; - double dNextPts = m_pMoviePictureBuffer->getNextPts(); + double dCurTime = SDL_GetTicks() - current_sync_pts_system_time + current_sync_pts * 1000.0; + double dNextPts = movie_picture_buffer->get_next_pts(); if(dNextPts > 0 && dNextPts * 1000.0 <= dCurTime) { - m_pMoviePictureBuffer->advance(); + movie_picture_buffer->advance(); } - m_pMoviePictureBuffer->draw(m_pRenderer, dest_rect); + movie_picture_buffer->draw(renderer, dest_rect); } } -void THMovie::allocatePictureBuffer() +void movie_player::allocate_picture_buffer() { - if(!m_pVideoCodecContext) + if(!video_codec_context) { return; } - m_pMoviePictureBuffer->allocate(m_pRenderer, getNativeWidth(), getNativeHeight()); + movie_picture_buffer->allocate(renderer, get_native_width(), get_native_height()); } -void THMovie::deallocatePictureBuffer() +void movie_player::deallocate_picture_buffer() { - m_pMoviePictureBuffer->deallocate(); + movie_picture_buffer->deallocate(); } -void THMovie::readStreams() +void movie_player::read_streams() { AVPacket packet; int iError; - while(!m_fAborting) + while(!aborting) { - iError = av_read_frame(m_pFormatContext, &packet); + iError = av_read_frame(format_context, &packet); if(iError < 0) { - if(iError == AVERROR_EOF || m_pFormatContext->pb->error || m_pFormatContext->pb->eof_reached) + if(iError == AVERROR_EOF || format_context->pb->error || format_context->pb->eof_reached) { break; } } else { - if(packet.stream_index == m_iVideoStream) + if(packet.stream_index == video_stream_index) { - m_pVideoQueue->push(&packet); + video_queue->push(&packet); } - else if (packet.stream_index == m_iAudioStream) + else if (packet.stream_index == audio_stream_index) { - m_pAudioQueue->push(&packet); + audio_queue->push(&packet); } else { @@ -753,33 +773,33 @@ } } - while(!m_fAborting) + while(!aborting) { - if(m_pVideoQueue->getCount() == 0 && m_pAudioQueue->getCount() == 0 && m_pMoviePictureBuffer->getNextPts() == 0) + if(video_queue->get_count() == 0 && audio_queue->get_count() == 0 && movie_picture_buffer->get_next_pts() == 0) { break; } - SDL_Delay(10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } SDL_Event endEvent; endEvent.type = SDL_USEREVENT_MOVIE_OVER; SDL_PushEvent(&endEvent); - m_fAborting = true; + aborting = true; } -void THMovie::runVideo() +void movie_player::run_video() { AVFrame *pFrame = av_frame_alloc(); double dClockPts; int iError; - while(!m_fAborting) + while(!aborting) { av_frame_unref(pFrame); #ifdef CORSIX_TH_MOVIE_USE_SEND_PACKET_API - iError = getFrame(m_iVideoStream, pFrame); + iError = get_frame(video_stream_index, pFrame); if (iError == AVERROR_EOF) { @@ -791,7 +811,7 @@ break; } #else - iError = getVideoFrame(pFrame); + iError = get_video_frame(pFrame); if(iError < 0) { break; @@ -802,8 +822,8 @@ } #endif - dClockPts = getPresentationTimeForFrame(pFrame, m_iVideoStream); - iError = m_pMoviePictureBuffer->write(pFrame, dClockPts); + dClockPts = get_presentation_time_for_frame(pFrame, video_stream_index); + iError = movie_picture_buffer->write(pFrame, dClockPts); if(iError < 0) { @@ -811,11 +831,11 @@ } } - avcodec_flush_buffers(m_pVideoCodecContext); + avcodec_flush_buffers(video_codec_context); av_frame_free(&pFrame); } -double THMovie::getPresentationTimeForFrame(AVFrame* frame, int streamIndex) const +double movie_player::get_presentation_time_for_frame(AVFrame* frame, int streamIndex) const { int64_t pts; #ifdef CORSIX_TH_USE_LIBAV @@ -827,8 +847,10 @@ #else #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 18, 100) pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp"); -#else +#elif LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100) pts = av_frame_get_best_effort_timestamp(frame); +#else + pts = frame->best_effort_timestamp; #endif //LIBAVCODEC_VERSION_INT #endif //CORSIX_T_USE_LIBAV @@ -837,25 +859,25 @@ pts = 0; } - return pts * av_q2d(m_pFormatContext->streams[streamIndex]->time_base); + return pts * av_q2d(format_context->streams[streamIndex]->time_base); } #ifdef CORSIX_TH_MOVIE_USE_SEND_PACKET_API -int THMovie::getFrame(int stream, AVFrame* pFrame) +int movie_player::get_frame(int stream, AVFrame* pFrame) { int iError = AVERROR(EAGAIN); AVCodecContext* ctx; - THAVPacketQueue* pq; + av_packet_queue* pq; - if (stream == m_iVideoStream) + if (stream == video_stream_index) { - ctx = m_pVideoCodecContext; - pq = m_pVideoQueue; + ctx = video_codec_context; + pq = video_queue; } - else if (stream == m_iAudioStream) + else if (stream == audio_stream_index) { - ctx = m_pAudioCodecContext; - pq = m_pAudioQueue; + ctx = audio_codec_context; + pq = audio_queue; } else { @@ -870,6 +892,10 @@ { AVPacket* pkt = pq->pull(true); int res = avcodec_send_packet(ctx, pkt); + if (pkt != nullptr) { + av_packet_unref(pkt); + av_free(pkt); + } if (res == AVERROR(EAGAIN)) { @@ -882,25 +908,25 @@ } #else -int THMovie::getVideoFrame(AVFrame *pFrame) +int movie_player::get_video_frame(AVFrame *pFrame) { int iGotPicture = 0; int iError; - AVPacket *pPacket = m_pVideoQueue->pull(true); + AVPacket *pPacket = video_queue->pull(true); if(pPacket == nullptr) { return -1; } - if(pPacket->data == m_flushPacket->data) + if(pPacket->data == flush_packet->data) { //TODO: Flush return 0; } - iError = avcodec_decode_video2(m_pVideoCodecContext, pFrame, &iGotPicture, pPacket); + iError = avcodec_decode_video2(video_codec_context, pFrame, &iGotPicture, pPacket); av_packet_unref(pPacket); av_free(pPacket); @@ -919,51 +945,51 @@ } #endif -void THMovie::copyAudioToStream(uint8_t *pbStream, int iStreamSize) +void movie_player::copy_audio_to_stream(uint8_t *pbStream, int iStreamSize) { - std::lock_guard audioLock(m_decodingAudioMutex); + std::lock_guard audioLock(decoding_audio_mutex); bool fFirst = true; - while(iStreamSize > 0 && !m_fAborting) + while(iStreamSize > 0 && !aborting) { - if(m_iAudioBufferIndex >= m_iAudioBufferSize) + if(audio_buffer_index >= audio_buffer_size) { - int iAudioSize = decodeAudioFrame(fFirst); + int iAudioSize = decode_audio_frame(fFirst); fFirst = false; if(iAudioSize <= 0) { - std::memset(m_pbAudioBuffer, 0, m_iAudioBufferSize); + std::memset(audio_buffer, 0, audio_buffer_size); } else { - m_iAudioBufferSize = iAudioSize; + audio_buffer_size = iAudioSize; } - m_iAudioBufferIndex = 0; + audio_buffer_index = 0; } - int iCopyLength = m_iAudioBufferSize - m_iAudioBufferIndex; + int iCopyLength = audio_buffer_size - audio_buffer_index; if(iCopyLength > iStreamSize) { iCopyLength = iStreamSize; } - std::memcpy(pbStream, (uint8_t *)m_pbAudioBuffer + m_iAudioBufferIndex, iCopyLength); + std::memcpy(pbStream, (uint8_t *)audio_buffer + audio_buffer_index, iCopyLength); iStreamSize -= iCopyLength; pbStream += iCopyLength; - m_iAudioBufferIndex += iCopyLength; + audio_buffer_index += iCopyLength; } } -int THMovie::decodeAudioFrame(bool fFirst) +int movie_player::decode_audio_frame(bool fFirst) { #ifdef CORSIX_TH_MOVIE_USE_SEND_PACKET_API - if (!m_audio_frame) + if (!audio_frame) { - m_audio_frame = av_frame_alloc(); + audio_frame = av_frame_alloc(); } else { - av_frame_unref(m_audio_frame); + av_frame_unref(audio_frame); } - int iError = getFrame(m_iAudioStream, m_audio_frame); + int iError = get_frame(audio_stream_index, audio_frame); if (iError == AVERROR_EOF) { @@ -975,71 +1001,71 @@ return 0; } - double dClockPts = getPresentationTimeForFrame(m_audio_frame, m_iAudioStream); - m_iCurSyncPts = dClockPts; - m_iCurSyncPtsSystemTime = SDL_GetTicks(); + double dClockPts = get_presentation_time_for_frame(audio_frame, audio_stream_index); + current_sync_pts = dClockPts; + current_sync_pts_system_time = SDL_GetTicks(); #else int iGotFrame = 0; bool fNewPacket = false; bool fFlushComplete = false; - while(!iGotFrame && !m_fAborting) + while(!iGotFrame && !aborting) { - if(!m_pAudioPacket || m_pAudioPacket->size == 0) + if(!audio_packet || audio_packet->size == 0) { - if(m_pAudioPacket) + if(audio_packet) { - m_pAudioPacket->data = m_pbAudioPacketData; - m_pAudioPacket->size = m_iAudioPacketSize; - av_packet_unref(m_pAudioPacket); - av_free(m_pAudioPacket); - m_pAudioPacket = nullptr; + audio_packet->data = audio_packet_data; + audio_packet->size = audio_packet_size; + av_packet_unref(audio_packet); + av_free(audio_packet); + audio_packet = nullptr; } - m_pAudioPacket = m_pAudioQueue->pull(true); - if(m_fAborting) + audio_packet = audio_queue->pull(true); + if(aborting) { break; } - m_pbAudioPacketData = m_pAudioPacket->data; - m_iAudioPacketSize = m_pAudioPacket->size; + audio_packet_data = audio_packet->data; + audio_packet_size = audio_packet->size; - if(m_pAudioPacket == nullptr) + if(audio_packet == nullptr) { fNewPacket = false; return -1; } fNewPacket = true; - if(m_pAudioPacket->data == m_flushPacket->data) + if(audio_packet->data == flush_packet->data) { - avcodec_flush_buffers(m_pAudioCodecContext); + avcodec_flush_buffers(audio_codec_context); fFlushComplete = false; } } if(fFirst) { - int64_t iStreamPts = m_pAudioPacket->pts; + int64_t iStreamPts = audio_packet->pts; if(iStreamPts != AV_NOPTS_VALUE) { - //There is a time_base in m_pAudioCodecContext too, but that one is wrong. - double dClockPts = iStreamPts * av_q2d(m_pFormatContext->streams[m_iAudioStream]->time_base); - m_iCurSyncPts = dClockPts; - m_iCurSyncPtsSystemTime = SDL_GetTicks(); + //There is a time_base in audio_codec_context too, but that one is wrong. + double dClockPts = iStreamPts * av_q2d(format_context->streams[audio_stream_index]->time_base); + current_sync_pts = dClockPts; + current_sync_pts_system_time = SDL_GetTicks(); } fFirst = false; } - while(m_pAudioPacket->size > 0 || (!m_pAudioPacket->data && fNewPacket)) + while(audio_packet->size > 0 || (!audio_packet->data && fNewPacket)) { - if(!m_audio_frame) + if(!audio_frame) { - m_audio_frame = av_frame_alloc(); + audio_frame = av_frame_alloc(); } else { - av_frame_unref(m_audio_frame); + av_frame_unref(audio_frame); } if(fFlushComplete) @@ -1049,19 +1075,19 @@ fNewPacket = false; - int iBytesConsumed = avcodec_decode_audio4(m_pAudioCodecContext, m_audio_frame, &iGotFrame, m_pAudioPacket); + int iBytesConsumed = avcodec_decode_audio4(audio_codec_context, audio_frame, &iGotFrame, audio_packet); if(iBytesConsumed < 0) { - m_pAudioPacket->size = 0; + audio_packet->size = 0; break; } - m_pAudioPacket->data += iBytesConsumed; - m_pAudioPacket->size -= iBytesConsumed; + audio_packet->data += iBytesConsumed; + audio_packet->size -= iBytesConsumed; if(!iGotFrame) { - if(m_pAudioPacket->data && (m_pAudioCodecContext->codec->capabilities & CODEC_CAP_DELAY)) + if(audio_packet->data && (audio_codec_context->codec->capabilities & CODEC_CAP_DELAY)) { fFlushComplete = true; } @@ -1070,51 +1096,51 @@ } #endif //over-estimate output samples - int iOutSamples = (int)av_rescale_rnd(m_audio_frame->nb_samples, m_iMixerFrequency, m_pAudioCodecContext->sample_rate, AV_ROUND_UP); - int iSampleSize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * iOutSamples * m_iMixerChannels; + int iOutSamples = (int)av_rescale_rnd(audio_frame->nb_samples, mixer_frequency, audio_codec_context->sample_rate, AV_ROUND_UP); + int iSampleSize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * iOutSamples * mixer_channels; - if(iSampleSize > m_iAudioBufferMaxSize) + if(iSampleSize > audio_buffer_max_size) { - if(m_iAudioBufferMaxSize > 0) + if(audio_buffer_max_size > 0) { - av_free(m_pbAudioBuffer); + av_free(audio_buffer); } - m_pbAudioBuffer = (uint8_t*)av_malloc(iSampleSize); - m_iAudioBufferMaxSize = iSampleSize; + audio_buffer = (uint8_t*)av_malloc(iSampleSize); + audio_buffer_max_size = iSampleSize; } #ifdef CORSIX_TH_USE_FFMPEG - swr_convert(m_pAudioResampleContext, &m_pbAudioBuffer, iOutSamples, (const uint8_t**)&m_audio_frame->data[0], m_audio_frame->nb_samples); + swr_convert(audio_resample_context, &audio_buffer, iOutSamples, (const uint8_t**)&audio_frame->data[0], audio_frame->nb_samples); #elif defined(CORSIX_TH_USE_LIBAV) - avresample_convert(m_pAudioResampleContext, &m_pbAudioBuffer, 0, iOutSamples, (uint8_t**)&m_audio_frame->data[0], 0, m_audio_frame->nb_samples); + avresample_convert(audio_resample_context, &audio_buffer, 0, iOutSamples, (uint8_t**)&audio_frame->data[0], 0, audio_frame->nb_samples); #endif return iSampleSize; } #else //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV -THMovie::THMovie() {} -THMovie::~THMovie() {} -void THMovie::setRenderer(SDL_Renderer *pRenderer) {} -bool THMovie::moviesEnabled() const { return false; } -bool THMovie::load(const char* filepath) { return true; } -void THMovie::unload() {} -void THMovie::play(int iChannel) +movie_player::movie_player() {} +movie_player::~movie_player() {} +void movie_player::set_renderer(SDL_Renderer *renderer) {} +bool movie_player::movies_enabled() const { return false; } +bool movie_player::load(const char* file_path) { return true; } +void movie_player::unload() {} +void movie_player::play(int iChannel) { SDL_Event endEvent; endEvent.type = SDL_USEREVENT_MOVIE_OVER; SDL_PushEvent(&endEvent); } -void THMovie::stop() {} -int THMovie::getNativeHeight() const { return 0; } -int THMovie::getNativeWidth() const { return 0; } -bool THMovie::hasAudioTrack() const { return false; } -const char* THMovie::getLastError() const { return nullptr; } -void THMovie::clearLastError() {} -void THMovie::refresh(const SDL_Rect &destination_rect) {} -void THMovie::allocatePictureBuffer() {} -void THMovie::deallocatePictureBuffer() {} -void THMovie::readStreams() {} -void THMovie::runVideo() {} -void THMovie::copyAudioToStream(uint8_t *stream, int length) {} +void movie_player::stop() {} +int movie_player::get_native_height() const { return 0; } +int movie_player::get_native_width() const { return 0; } +bool movie_player::has_audio_track() const { return false; } +const char* movie_player::get_last_error() const { return nullptr; } +void movie_player::clear_last_error() {} +void movie_player::refresh(const SDL_Rect &destination_rect) {} +void movie_player::allocate_picture_buffer() {} +void movie_player::deallocate_picture_buffer() {} +void movie_player::read_streams() {} +void movie_player::run_video() {} +void movie_player::copy_audio_to_stream(uint8_t *stream, int length) {} #endif //CORSIX_TH_USE_FFMPEG diff -Nru corsix-th-0.61/CorsixTH/Src/th_movie.h corsix-th-0.62/CorsixTH/Src/th_movie.h --- corsix-th-0.61/CorsixTH/Src/th_movie.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_movie.h 2018-07-21 11:13:17.000000000 +0000 @@ -63,15 +63,15 @@ #endif -//! \brief A picture in THMoviePictureBuffer +//! \brief A picture in movie_picture_buffer //! //! Stores the picture from a frame in the movie from the time that it is //! processed until it should be drawn. -class THMoviePicture +class movie_picture { public: - THMoviePicture(); - ~THMoviePicture(); + movie_picture(); + ~movie_picture(); //! Allocate the buffer to hold a picture of the given size void allocate(int iWidth, int iHeight); @@ -79,20 +79,20 @@ //! Delete the buffer void deallocate(); - uint8_t* m_pBuffer; ///< Pixel data in #m_pixelFormat - const AVPixelFormat m_pixelFormat; ///< The format of pixels to output - int m_iWidth; ///< Picture width - int m_iHeight; ///< Picture height - double m_dPts; ///< Presentation time stamp - std::mutex m_mutex; ///< Mutex protecting this picture + uint8_t* buffer; ///< Pixel data in #m_pixelFormat + const AVPixelFormat pixel_format; ///< The format of pixels to output + int width; ///< Picture width + int height; ///< Picture height + double pts; ///< Presentation time stamp + std::mutex mutex; ///< Mutex protecting this picture }; //! A buffer for holding movie pictures and drawing them to the renderer -class THMoviePictureBuffer +class movie_picture_buffer { public: - THMoviePictureBuffer(); - ~THMoviePictureBuffer(); + movie_picture_buffer(); + ~movie_picture_buffer(); //NB: The following functions are called by the main program thread @@ -103,14 +103,14 @@ void reset(); //! Ready the picture buffer for a new renderer or new picture dimensions - //! by allocating each THMoviePicture in the queue, resetting the read + //! by allocating each movie_picture in the queue, resetting the read //! index and allocating a new texture. //! //! \remark Must be run on the program's graphics thread void allocate(SDL_Renderer *pRenderer, int iWidth, int iHeight); //! Destroy the associated texture and deallocate each of the - //! THMoviePictures in the queue so that the program can release + //! movie_pictures in the queue so that the program can release //! the renderer //! //! \remark Must be run on the program's graphics thread @@ -119,7 +119,7 @@ //! Advance the read index bool advance(); - //! Draw the THMoviePicture at the current read index + //! Draw the movie_picture at the current read index //! //! \param pRenderer The renderer to draw the picture to //! \param dstrect The rectangle on the renderer to draw to @@ -128,11 +128,11 @@ void draw(SDL_Renderer *pRenderer, const SDL_Rect &dstrect); //! Get the next presentation time stamp - double getNextPts(); + double get_next_pts(); //! Return whether there are any pictures left to draw in the picture queue //! - //! \remark If the THPictureBuffer is not allocated it cannot be read from + //! \remark If the movie_picture_buffer is not allocated it cannot be read from //! or written to. Consequently it is both full and empty. bool empty(); @@ -140,7 +140,7 @@ //! Return whether there is space to add any more frame data to the queue //! - //! \remark If the THPictureBuffer is not allocated it cannot be read from + //! \remark If the movie_picture_buffer is not allocated it cannot be read from //! or written to. Consequently it is both full and empty. bool full(); @@ -155,33 +155,33 @@ //! Return whether there is space to add any more frame data to the queue //! //! \remark Requires external locking - bool unsafeFull(); + bool unsafe_full(); - static const size_t ms_pictureBufferSize = 4; ///< The number of elements to allocate in the picture queue - std::atomic m_aborting; ///< Whether we are in the process of aborting - bool m_fAllocated; ///< Whether the picture buffer has been allocated (and hasn't since been deallocated) - int m_iCount; ///< The number of elements currently written to the picture queue - int m_iReadIndex; ///< The position in the picture queue to be read next - int m_iWriteIndex; ///< The position in the picture queue to be written to next - SwsContext* m_pSwsContext; ///< The context for software scaling and pixel conversion when writing to the picture queue - SDL_Texture *m_pTexture; ///< The (potentially hardware) texture to draw the picture to. In OpenGL this should only be accessed on the main thread - std::mutex m_mutex; ///< A mutex for restricting access to the picture buffer to a single thread - std::condition_variable m_cond; ///< A condition for indicating access to the picture buffer - THMoviePicture m_aPictureQueue[ms_pictureBufferSize]; ///< The picture queue, a looping FIFO queue of THMoviePictures + static const size_t picture_buffer_size = 4; ///< The number of elements to allocate in the picture queue + std::atomic aborting; ///< Whether we are in the process of aborting + bool allocated; ///< Whether the picture buffer has been allocated (and hasn't since been deallocated) + int picture_count; ///< The number of elements currently written to the picture queue + int read_index; ///< The position in the picture queue to be read next + int write_index; ///< The position in the picture queue to be written to next + SwsContext* sws_context; ///< The context for software scaling and pixel conversion when writing to the picture queue + SDL_Texture *texture; ///< The (potentially hardware) texture to draw the picture to. In OpenGL this should only be accessed on the main thread + std::mutex mutex; ///< A mutex for restricting access to the picture buffer to a single thread + std::condition_variable cond; ///< A condition for indicating access to the picture buffer + movie_picture picture_queue[picture_buffer_size]; ///< The picture queue, a looping FIFO queue of movie_pictures }; //! The AVPacketQueue is a thread safe queue of movie packets -class THAVPacketQueue +class av_packet_queue { public: //! Construct a new empty packet queue - THAVPacketQueue(); + av_packet_queue(); //! Destroy the packet queue. //! //! \remarks Does not free the included packets. The packet queue should be //! flushed before it is destroyed. - ~THAVPacketQueue(); + ~av_packet_queue(); //! Push a new packet on the back of the queue void push(AVPacket *packet); @@ -193,39 +193,39 @@ AVPacket* pull(bool block); //! Return the number of packets in the queue - int getCount() const; + int get_count() const; //! Release a blocking pull without writing a new packet to the queue. void release(); private: - AVPacketList *m_pFirstPacket; ///< The packet at the front of the queue - AVPacketList *m_pLastPacket; ///< The packet at the end of the queue - int iCount; ///< The number of packets in the queue - std::mutex m_mutex; ///< A mutex restricting access to the packet queue to a single thread - std::condition_variable m_cond; ///< A condition to wait on for signaling the packet queue + AVPacketList *first_packet; ///< The packet at the front of the queue + AVPacketList *last_packet; ///< The packet at the end of the queue + int count; ///< The number of packets in the queue + std::mutex mutex; ///< A mutex restricting access to the packet queue to a single thread + std::condition_variable cond; ///< A condition to wait on for signaling the packet queue }; #endif //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV //! Movie player for CorsixTH //! //! The movie player is designed to be preinitialized and used for multiple -//! movies. After initializing the movie player, call THMovie::setRenderer -//! to assign the current SDL renderer to the movie player. Then THMovie::load -//! the desired movie and finally THMovie::play it. -class THMovie +//! movies. After initializing the movie player, call movie_player::set_renderer +//! to assign the current SDL renderer to the movie player. Then movie_player::load +//! the desired movie and finally movie_player::play it. +class movie_player { public: - //! Construct a new THMovie - THMovie(); + //! Construct a new movie_player + movie_player(); - //! Destroy the THMovie - ~THMovie(); + //! Destroy the movie_player + ~movie_player(); //! Assign the renderer on which to draw the movie - void setRenderer(SDL_Renderer *pRenderer); + void set_renderer(SDL_Renderer *pRenderer); //! Return whether movies were compiled into CorsixTH - bool moviesEnabled() const; + bool movies_enabled() const; //! Load the movie with the given file name bool load(const char* szFilepath); @@ -245,20 +245,20 @@ void stop(); //! Return the original height of the movie - int getNativeHeight() const; + int get_native_height() const; //! Return the original width of the movie - int getNativeWidth() const; + int get_native_width() const; //! Return whether the movie has an audio stream - bool hasAudioTrack() const; + bool has_audio_track() const; //! Return a text description of the last error encountered - const char* getLastError() const; + const char* get_last_error() const; //! Clear the last error so that if there is no more errors before the next - //! call to THMovie::getLastError() it will return an empty string. - void clearLastError(); + //! call to movie_player::get_last_error() it will return an empty string. + void clear_last_error(); //! Draw the next frame if it is time to do so //! @@ -271,48 +271,48 @@ //! \remark This destroys the textures and other resources that may lock //! the renderer from being deleted. If the target changes you would call //! this, then free and switch renderers in the outside program, then call - //! THMovie::setRenderer and finally THMovie::allocatePictureBuffer. + //! movie_player::set_renderer and finally movie_player::allocate_picture_buffer. //! \remark Up to the size of the picture buffer frames may be lost during //! this process. - void deallocatePictureBuffer(); + void deallocate_picture_buffer(); //! Allocate the picture buffer for the current renderer - void allocatePictureBuffer(); + void allocate_picture_buffer(); //! Read packets from the movie and allocate them to the appropriate stream //! packet queues. Signal if we have reached the end of the movie. //! //! \remark This should not be called externally. It is public as it is the //! entry point of a thread. - void readStreams(); + void read_streams(); //! Read video frames from the video packet queue and write them to the //! picture queue. //! //! \remark This should not be called externally. It is public as it is the //! entry point of a thread. - void runVideo(); + void run_video(); //! Read audio from the audio packet queue, and copy it into the audio //! buffer for playback - void copyAudioToStream(uint8_t *pbStream, int iStreamSize); + void copy_audio_to_stream(uint8_t *pbStream, int iStreamSize); private: #if (defined(CORSIX_TH_USE_FFMPEG) || defined(CORSIX_TH_USE_LIBAV)) && defined(CORSIX_TH_USE_SDL_MIXER) - static const size_t ms_movieErrorBufferSize = 128; ///< Buffer to hold last error description - static const size_t ms_audioBufferSize = 1024; ///< Buffer for audio playback + static const size_t movie_error_buffer_capacity = 128; ///< Buffer to hold last error description + static const size_t audio_chunk_buffer_capacity = 1024; ///< Buffer for audio playback //! Get the AVCodecContext associated with a given stream - AVCodecContext* getCodecContextForStream(AVCodec* codec, AVStream* stream) const; + AVCodecContext* get_codec_context_for_stream(AVCodec* codec, AVStream* stream) const; //! Get the time the given frame should be played (from the start of the stream) //! //! \param frame The video or audio frame //! \param streamIndex The position of the stream in m_pFormatContexts streams array - double getPresentationTimeForFrame(AVFrame* frame, int streamIndex) const; + double get_presentation_time_for_frame(AVFrame* frame, int streamIndex) const; //! Decode audio from the movie into a format suitable for playback - int decodeAudioFrame(bool fFirst); + int decode_audio_frame(bool fFirst); #ifdef CORSIX_TH_MOVIE_USE_SEND_PACKET_API //! Convert packet data into frames @@ -321,70 +321,71 @@ //! \param pFrame An empty frame which gets populated by the data in the //! packet queue. //! \returns FFMPEG result of avcodec_recieve_frame - int getFrame(int stream, AVFrame* pFrame); + int get_frame(int stream, AVFrame* pFrame); #else //! Convert video packet data into a frame. //! //! \param pFrame An empty frame which gets populated by the data in the //! video packet queue. //! \returns 1 if the frame was received, 0 if it was not, and < 0 on error - int getVideoFrame(AVFrame *pFrame); + int get_video_frame(AVFrame *pFrame); #endif - SDL_Renderer *m_pRenderer; ///< The renderer to draw to + SDL_Renderer *renderer; ///< The renderer to draw to //! A description of the last error - std::string m_sLastError; + std::string last_error; //! A buffer for passing to ffmpeg to get error details - char m_szErrorBuffer[ms_movieErrorBufferSize]; + char error_buffer[movie_error_buffer_capacity]; - bool m_fAborting; ///< Indicate that we are in process of aborting playback + // TODO: Should be atomic + bool aborting; ///< Indicate that we are in process of aborting playback - std::mutex m_decodingAudioMutex; ///< Synchronize access to #m_pAudioBuffer + std::mutex decoding_audio_mutex; ///< Synchronize access to #m_pAudioBuffer - AVFormatContext* m_pFormatContext; ///< Information related to the loaded movie and all of its streams - int m_iVideoStream; ///< The index of the video stream - int m_iAudioStream; ///< The index of the audio stream - AVCodecContext* m_pVideoCodecContext; ///< The video codec and information related to video - AVCodecContext* m_pAudioCodecContext; ///< The audio codec and information related to audio + AVFormatContext* format_context; ///< Information related to the loaded movie and all of its streams + int video_stream_index; ///< The index of the video stream + int audio_stream_index; ///< The index of the audio stream + AVCodecContext *video_codec_context; ///< The video codec and information related to video + AVCodecContext *audio_codec_context; ///< The audio codec and information related to audio //queues for transferring data between threads - THAVPacketQueue *m_pVideoQueue; ///< Packets from the video stream - THAVPacketQueue *m_pAudioQueue; ///< Packets from the audio stream - THMoviePictureBuffer *m_pMoviePictureBuffer; ///< Buffer of processed video + av_packet_queue *video_queue; ///< Packets from the video stream + av_packet_queue *audio_queue; ///< Packets from the audio stream + ::movie_picture_buffer *movie_picture_buffer; ///< Buffer of processed video //clock sync parameters - int m_iCurSyncPtsSystemTime; ///< System time matching #m_iCurSyncPts - double m_iCurSyncPts; ///< The current presentation time stamp (from the audio stream) + int current_sync_pts_system_time; ///< System time matching #m_iCurSyncPts + double current_sync_pts; ///< The current presentation time stamp (from the audio stream) #ifdef CORSIX_TH_USE_FFMPEG - SwrContext* m_pAudioResampleContext; ///< Context for resampling audio for playback with ffmpeg + SwrContext* audio_resample_context; ///< Context for resampling audio for playback with ffmpeg #elif defined(CORSIX_TH_USE_LIBAV) - AVAudioResampleContext* m_pAudioResampleContext; ///< Context for resampling audio for playback with libav + AVAudioResampleContext* audio_resample_context; ///< Context for resampling audio for playback with libav #endif - int m_iAudioBufferSize; ///< The current size of audio data in #m_pbAudioBuffer - int m_iAudioBufferIndex; ///< The current position for writing in #m_pbAudioBuffer - int m_iAudioBufferMaxSize; ///< The capacity of #m_pbAudioBuffer (allocated size) - uint8_t* m_pbAudioBuffer; ///< An audio buffer for playback - - AVPacket* m_pAudioPacket; ///< The current audio packet being decoded (audio frames don't necessarily line up with packets) - int m_iAudioPacketSize; ///< The size of #m_pbAudioPacketData - uint8_t *m_pbAudioPacketData; ///< Original data for #m_pAudioPacket, kept so that it can be freed after the packet is processed - AVFrame* m_audio_frame; ///< The frame we are decoding audio into - - Mix_Chunk* m_pChunk; ///< Empty chunk needed for SDL_mixer - uint8_t* m_pbChunkBuffer; ///< 0'd out buffer for the SDL_Mixer chunk - - int m_iChannel; ///< The channel to play audio on, -1 for none - int m_iMixerChannels; ///< How many channels to play on (1 - mono, 2 - stereo) - int m_iMixerFrequency; ///< The frequency of audio expected by SDL_Mixer + int audio_buffer_size; ///< The current size of audio data in #m_pbAudioBuffer + int audio_buffer_index; ///< The current position for writing in #m_pbAudioBuffer + int audio_buffer_max_size; ///< The capacity of #m_pbAudioBuffer (allocated size) + uint8_t* audio_buffer; ///< An audio buffer for playback + + AVPacket* audio_packet; ///< The current audio packet being decoded (audio frames don't necessarily line up with packets) + int audio_packet_size; ///< The size of #m_pbAudioPacketData + uint8_t *audio_packet_data; ///< Original data for #m_pAudioPacket, kept so that it can be freed after the packet is processed + AVFrame* audio_frame; ///< The frame we are decoding audio into + + Mix_Chunk* empty_audio_chunk; ///< Empty chunk needed for SDL_mixer + uint8_t* audio_chunk_buffer; ///< 0'd out buffer for the SDL_Mixer chunk + + int audio_channel; ///< The channel to play audio on, -1 for none + int mixer_channels; ///< How many channels to play on (1 - mono, 2 - stereo) + int mixer_frequency; ///< The frequency of audio expected by SDL_Mixer - AVPacket* m_flushPacket; ///< A representative packet indicating a flush is required. + AVPacket* flush_packet; ///< A representative packet indicating a flush is required. - std::thread m_streamThread; ///< The thread responsible for reading the movie streams - std::thread m_videoThread; ///< The thread responsible for decoding the video stream + std::thread stream_thread; ///< The thread responsible for reading the movie streams + std::thread video_thread; ///< The thread responsible for decoding the video stream #endif //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV }; diff -Nru corsix-th-0.61/CorsixTH/Src/th_pathfind.cpp corsix-th-0.62/CorsixTH/Src/th_pathfind.cpp --- corsix-th-0.61/CorsixTH/Src/th_pathfind.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_pathfind.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -29,21 +29,21 @@ #include #include -BasePathing::BasePathing(THPathfinder *pf) : m_pPf(pf) +abstract_pathfinder::abstract_pathfinder(pathfinder *pf) : parent(pf) { } -node_t *BasePathing::pathingInit(const THMap *pMap, int iStartX, int iStartY) +path_node *abstract_pathfinder::init(const level_map *pMap, int iStartX, int iStartY) { - int iWidth = pMap->getWidth(); - m_pPf->m_pDestination = nullptr; - m_pPf->_allocNodeCache(iWidth, pMap->getHeight()); - node_t *pNode = m_pPf->m_pNodes + iStartY * iWidth + iStartX; + int iWidth = pMap->get_width(); + parent->destination = nullptr; + parent->allocate_node_cache(iWidth, pMap->get_height()); + path_node *pNode = parent->nodes + iStartY * iWidth + iStartX; pNode->prev = nullptr; pNode->distance = 0; - pNode->guess = makeGuess(pNode); - m_pPf->m_ppDirtyList[0] = pNode; - m_pPf->m_iDirtyCount = 1; - m_pPf->m_openHeap.clear(); + pNode->guess = guess_distance(pNode); + parent->dirty_node_list[0] = pNode; + parent->dirty_node_count = 1; + parent->open_heap.clear(); return pNode; } @@ -51,24 +51,24 @@ flags are set as to prevent travelling off the map (as well as to prevent walking through walls). */ -bool BasePathing::pathingNeighbours(node_t *pNode, th_map_node_flags flags, int iWidth) +bool abstract_pathfinder::search_neighbours(path_node *pNode, map_tile_flags flags, int iWidth) { if(flags.can_travel_w) - if(tryNode(pNode, flags, pNode - 1, THTD_West)) return true; + if(try_node(pNode, flags, pNode - 1, travel_direction::west)) return true; if(flags.can_travel_e) - if (tryNode(pNode, flags, pNode + 1, THTD_East)) return true; + if (try_node(pNode, flags, pNode + 1, travel_direction::east)) return true; if(flags.can_travel_n) - if (tryNode(pNode, flags, pNode - iWidth, THTD_North)) return true; + if (try_node(pNode, flags, pNode - iWidth, travel_direction::north)) return true; if(flags.can_travel_s) - if (tryNode(pNode, flags, pNode + iWidth, THTD_South)) return true; + if (try_node(pNode, flags, pNode + iWidth, travel_direction::south)) return true; return false; } -void BasePathing::pathingTryNode(node_t *pNode, th_map_node_flags neighbour_flags, bool passable, node_t *pNeighbour) +void abstract_pathfinder::record_neighbour_if_passable(path_node *pNode, map_tile_flags neighbour_flags, bool passable, path_node *pNeighbour) { if(neighbour_flags.passable || !passable) { @@ -76,201 +76,201 @@ { pNeighbour->prev = pNode; pNeighbour->distance = pNode->distance + 1; - pNeighbour->guess = makeGuess(pNeighbour); - m_pPf->m_ppDirtyList[m_pPf->m_iDirtyCount++] = pNeighbour; - m_pPf->_openHeapPush(pNeighbour); + pNeighbour->guess = guess_distance(pNeighbour); + parent->dirty_node_list[parent->dirty_node_count++] = pNeighbour; + parent->push_to_open_heap(pNeighbour); } else if(pNode->distance + 1 < pNeighbour->distance) { pNeighbour->prev = pNode; pNeighbour->distance = pNode->distance + 1; /* guess doesn't change, and already in the dirty list */ - m_pPf->_openHeapPromote(pNeighbour); + parent->open_heap_promote(pNeighbour); } } } -int PathFinder::makeGuess(node_t *pNode) +int basic_pathfinder::guess_distance(path_node *pNode) { // As diagonal movement is not allowed, the minimum distance between two // points is the sum of the distance in X and the distance in Y. - return abs(pNode->x - m_iEndX) + abs(pNode->y - m_iEndY); + return abs(pNode->x - destination_x) + abs(pNode->y - destination_y); } -bool PathFinder::tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) +bool basic_pathfinder::try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) { - th_map_node_flags neighbour_flags = m_pMap->getNodeUnchecked(pNeighbour->x, pNeighbour->y)->flags; - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + map_tile_flags neighbour_flags = map->get_tile_unchecked(pNeighbour->x, pNeighbour->y)->flags; + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); return false; } -bool PathFinder::findPath(const THMap *pMap, int iStartX, int iStartY, int iEndX, int iEndY) +bool basic_pathfinder::find_path(const level_map *pMap, int iStartX, int iStartY, int iEndX, int iEndY) { if(pMap == nullptr) - pMap = m_pPf->m_pDefaultMap; - if(pMap == nullptr || pMap->getNode(iEndX, iEndY) == nullptr - || !pMap->getNodeUnchecked(iEndX, iEndY)->flags.passable) + pMap = parent->default_map; + if(pMap == nullptr || pMap->get_tile(iEndX, iEndY) == nullptr + || !pMap->get_tile_unchecked(iEndX, iEndY)->flags.passable) { - m_pPf->m_pDestination = nullptr; + parent->destination = nullptr; return false; } - m_pMap = pMap; - m_iEndX = iEndX; - m_iEndY = iEndY; - - node_t *pNode = pathingInit(pMap, iStartX, iStartY); - int iWidth = pMap->getWidth(); - node_t *pTarget = m_pPf->m_pNodes + iEndY * iWidth + iEndX; + map = pMap; + destination_x = iEndX; + destination_y = iEndY; + + path_node *pNode = init(pMap, iStartX, iStartY); + int iWidth = pMap->get_width(); + path_node *pTarget = parent->nodes + iEndY * iWidth + iEndX; while(true) { if(pNode == pTarget) { - m_pPf->m_pDestination = pTarget; + parent->destination = pTarget; return true; } - th_map_node_flags flags = pMap->getNodeUnchecked(pNode->x, pNode->y)->flags; - if (pathingNeighbours(pNode, flags, iWidth)) return true; + map_tile_flags flags = pMap->get_tile_unchecked(pNode->x, pNode->y)->flags; + if (search_neighbours(pNode, flags, iWidth)) return true; - if (m_pPf->m_openHeap.empty()) { - m_pPf->m_pDestination = nullptr; + if (parent->open_heap.empty()) { + parent->destination = nullptr; break; } else { - pNode = m_pPf->_openHeapPop(); + pNode = parent->pop_from_open_heap(); } } return false; } -int HospitalFinder::makeGuess(node_t *pNode) +int hospital_finder::guess_distance(path_node *pNode) { return 0; } -bool HospitalFinder::tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) +bool hospital_finder::try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) { - th_map_node_flags neighbour_flags = m_pMap->getNodeUnchecked(pNeighbour->x, pNeighbour->y)->flags; - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + map_tile_flags neighbour_flags = map->get_tile_unchecked(pNeighbour->x, pNeighbour->y)->flags; + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); return false; } -bool HospitalFinder::findPathToHospital(const THMap *pMap, int iStartX, int iStartY) +bool hospital_finder::find_path_to_hospital(const level_map *pMap, int iStartX, int iStartY) { if(pMap == nullptr) - pMap = m_pPf->m_pDefaultMap; - if(pMap == nullptr || pMap->getNode(iStartX, iStartY) == nullptr - || !pMap->getNodeUnchecked(iStartX, iStartY)->flags.passable) + pMap = parent->default_map; + if(pMap == nullptr || pMap->get_tile(iStartX, iStartY) == nullptr + || !pMap->get_tile_unchecked(iStartX, iStartY)->flags.passable) { - m_pPf->m_pDestination = nullptr; + parent->destination = nullptr; return false; } - m_pMap = pMap; + map = pMap; - node_t *pNode = pathingInit(pMap, iStartX, iStartY); - int iWidth = pMap->getWidth(); + path_node *pNode = init(pMap, iStartX, iStartY); + int iWidth = pMap->get_width(); while(true) { - th_map_node_flags flags = pMap->getNodeUnchecked(pNode->x, pNode->y)->flags; + map_tile_flags flags = pMap->get_tile_unchecked(pNode->x, pNode->y)->flags; if(flags.hospital) { - m_pPf->m_pDestination = pNode; + parent->destination = pNode; return true; } - if (pathingNeighbours(pNode, flags, iWidth)) return true; + if (search_neighbours(pNode, flags, iWidth)) return true; - if (m_pPf->m_openHeap.empty()) { - m_pPf->m_pDestination = nullptr; + if (parent->open_heap.empty()) { + parent->destination = nullptr; break; } else { - pNode = m_pPf->_openHeapPop(); + pNode = parent->pop_from_open_heap(); } } return false; } -int IdleTileFinder::makeGuess(node_t *pNode) +int idle_tile_finder::guess_distance(path_node *pNode) { return 0; } -bool IdleTileFinder::tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) +bool idle_tile_finder::try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) { - th_map_node_flags neighbour_flags = m_pMap->getNodeUnchecked(pNeighbour->x, pNeighbour->y)->flags; + map_tile_flags neighbour_flags = map->get_tile_unchecked(pNeighbour->x, pNeighbour->y)->flags; /* When finding an idle tile, do not navigate through doors */ switch(direction) { - case THTD_North: + case travel_direction::north: if(!flags.door_north) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_East: + case travel_direction::east: if(!neighbour_flags.door_west) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_South: + case travel_direction::south: if(!neighbour_flags.door_north) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_West: + case travel_direction::west: if(!flags.door_west) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; } /* Identify the neighbour in the open list nearest to the start */ if(pNeighbour->prev != pNeighbour && pNeighbour->open_idx != -1) { - int iDX = pNeighbour->x - m_iStartX; - int iDY = pNeighbour->y - m_iStartY; + int iDX = pNeighbour->x - start_x; + int iDY = pNeighbour->y - start_y; double fDistance = sqrt((double)(iDX * iDX + iDY * iDY)); - if(m_pBestNext == nullptr || fDistance < m_fBestDistance) + if(best_next_node == nullptr || fDistance < best_distance) { - m_pBestNext = pNeighbour; m_fBestDistance = fDistance; + best_next_node = pNeighbour; best_distance = fDistance; } } return false; } -bool IdleTileFinder::findIdleTile(const THMap *pMap, int iStartX, int iStartY, int iN) +bool idle_tile_finder::find_idle_tile(const level_map *pMap, int iStartX, int iStartY, int iN) { if(pMap == nullptr) - pMap = m_pPf->m_pDefaultMap; + pMap = parent->default_map; if(pMap == nullptr) { - m_pPf->m_pDestination = nullptr; + parent->destination = nullptr; return false; } - m_iStartX = iStartX; - m_iStartY = iStartY; - m_pMap = pMap; - - node_t *pNode = pathingInit(pMap, iStartX, iStartY); - int iWidth = pMap->getWidth(); - node_t *pPossibleResult = nullptr; + start_x = iStartX; + start_y = iStartY; + map = pMap; + + path_node *pNode = init(pMap, iStartX, iStartY); + int iWidth = pMap->get_width(); + path_node *pPossibleResult = nullptr; while(true) { pNode->open_idx = -1; - th_map_node_flags flags = pMap->getNodeUnchecked(pNode->x, pNode->y)->flags; + map_tile_flags flags = pMap->get_tile_unchecked(pNode->x, pNode->y)->flags; if(!flags.do_not_idle && flags.passable && flags.hospital) { if(iN == 0) { - m_pPf->m_pDestination = pNode; + parent->destination = pNode; return true; } else @@ -280,49 +280,49 @@ } } - m_pBestNext = nullptr; - m_fBestDistance = 0.0; + best_next_node = nullptr; + best_distance = 0.0; - if (pathingNeighbours(pNode, flags, iWidth)) return true; + if (search_neighbours(pNode, flags, iWidth)) return true; - if (m_pPf->m_openHeap.empty()) { - m_pPf->m_pDestination = nullptr; + if (parent->open_heap.empty()) { + parent->destination = nullptr; break; } - if(m_pBestNext) + if(best_next_node) { // Promote the best neighbour to the front of the open list // This causes sequential iN to give neighbouring results for most iN - m_pBestNext->guess = -m_pBestNext->distance; - m_pPf->_openHeapPromote(m_pBestNext); + best_next_node->guess = -best_next_node->distance; + parent->open_heap_promote(best_next_node); } - pNode = m_pPf->_openHeapPop(); + pNode = parent->pop_from_open_heap(); } if(pPossibleResult) { - m_pPf->m_pDestination = pPossibleResult; + parent->destination = pPossibleResult; return true; } return false; } -int Objectsvisitor::makeGuess(node_t *pNode) +int object_visitor::guess_distance(path_node *pNode) { return 0; } -bool Objectsvisitor::tryNode(node_t *pNode, th_map_node_flags flags, node_t *pNeighbour, int direction) +bool object_visitor::try_node(path_node *pNode, map_tile_flags flags, path_node *pNeighbour, travel_direction direction) { int iObjectNumber = 0; - const THMapNode *pMapNode = m_pMap->getNodeUnchecked(pNeighbour->x, pNeighbour->y); - th_map_node_flags neighbour_flags = m_pMap->getNodeUnchecked(pNeighbour->x, pNeighbour->y)->flags; + const map_tile *pMapNode = map->get_tile_unchecked(pNeighbour->x, pNeighbour->y); + map_tile_flags neighbour_flags = map->get_tile_unchecked(pNeighbour->x, pNeighbour->y)->flags; for(auto thob : pMapNode->objects) { - if(thob == m_eTHOB) + if(thob == target) iObjectNumber++; } - if(m_bAnyObjectType) + if(target_any_object_type) iObjectNumber = 1; bool bSucces = false; for(int i = 0; i < iObjectNumber; i++) @@ -332,119 +332,119 @@ /* The direction which was last travelled in to reach (x,y); */ /* 0 (north), 1 (east), 2 (south), 3 (west) */ /* The distance to the object from the search starting point */ - lua_pushvalue(m_pL, m_iVisitFunction); - lua_pushinteger(m_pL, pNeighbour->x + 1); - lua_pushinteger(m_pL, pNeighbour->y + 1); - lua_pushinteger(m_pL, direction); - lua_pushinteger(m_pL, pNode->distance); - lua_call(m_pL, 4, 1); - if(lua_toboolean(m_pL, -1) != 0) + lua_pushvalue(L, visit_function_index); + lua_pushinteger(L, pNeighbour->x + 1); + lua_pushinteger(L, pNeighbour->y + 1); + lua_pushinteger(L, static_cast(direction)); + lua_pushinteger(L, pNode->distance); + lua_call(L, 4, 1); + if(lua_toboolean(L, -1) != 0) { bSucces = true; } - lua_pop(m_pL, 1); + lua_pop(L, 1); } if(bSucces) return true; - if(pNode->distance < m_iMaxDistance) + if(pNode->distance < max_distance) { switch(direction) { - case THTD_North: + case travel_direction::north: if(!flags.door_north) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_East: + case travel_direction::east: if(!neighbour_flags.door_west) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_South: + case travel_direction::south: if(!neighbour_flags.door_north) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; - case THTD_West: + case travel_direction::west: if(!flags.door_west) - pathingTryNode(pNode, neighbour_flags, flags.passable, pNeighbour); + record_neighbour_if_passable(pNode, neighbour_flags, flags.passable, pNeighbour); break; } } return false; } -bool Objectsvisitor::visitObjects(const THMap *pMap, int iStartX, int iStartY, - THObjectType eTHOB, int iMaxDistance, +bool object_visitor::visit_objects(const level_map *pMap, int iStartX, int iStartY, + object_type eTHOB, int iMaxDistance, lua_State *L, int iVisitFunction, bool anyObjectType) { if(pMap == nullptr) - pMap = m_pPf->m_pDefaultMap; + pMap = parent->default_map; if(pMap == nullptr) { - m_pPf->m_pDestination = nullptr; + parent->destination = nullptr; return false; } - m_pL = L; - m_iVisitFunction = iVisitFunction; - m_iMaxDistance = iMaxDistance; - m_bAnyObjectType = anyObjectType; - m_eTHOB = eTHOB; - m_pMap = pMap; + this->L = L; + visit_function_index = iVisitFunction; + max_distance = iMaxDistance; + target_any_object_type = anyObjectType; + target = eTHOB; + map = pMap; - node_t *pNode = pathingInit(pMap, iStartX, iStartY); - int iWidth = pMap->getWidth(); + path_node *pNode = init(pMap, iStartX, iStartY); + int iWidth = pMap->get_width(); while(true) { - th_map_node_flags flags = pMap->getNodeUnchecked(pNode->x, pNode->y)->flags; - if (pathingNeighbours(pNode, flags, iWidth)) return true; + map_tile_flags flags = pMap->get_tile_unchecked(pNode->x, pNode->y)->flags; + if (search_neighbours(pNode, flags, iWidth)) return true; - if (m_pPf->m_openHeap.empty()) { - m_pPf->m_pDestination = nullptr; + if (parent->open_heap.empty()) { + parent->destination = nullptr; break; } else { - pNode = m_pPf->_openHeapPop(); + pNode = parent->pop_from_open_heap(); } } return false; } -THPathfinder::THPathfinder() : m_oPathFinder(this), m_oHospitalFinder(this), - m_oIdleTileFinder(this), m_oObjectsvisitor(this), - m_openHeap() +pathfinder::pathfinder() : basic_pathfinder(this), hospital_finder(this), + idle_tile_finder(this), object_visitor(this), + open_heap() { - m_pNodes = nullptr; - m_ppDirtyList = nullptr; - m_pDestination = nullptr; - m_pDefaultMap = nullptr; - m_iNodeCacheWidth = 0; - m_iNodeCacheHeight = 0; - m_iDirtyCount = 0; + nodes = nullptr; + dirty_node_list = nullptr; + destination = nullptr; + default_map = nullptr; + node_cache_width = 0; + node_cache_height = 0; + dirty_node_count = 0; } -THPathfinder::~THPathfinder() +pathfinder::~pathfinder() { - delete[] m_pNodes; - delete[] m_ppDirtyList; + delete[] nodes; + delete[] dirty_node_list; } -void THPathfinder::setDefaultMap(const THMap *pMap) +void pathfinder::set_default_map(const level_map *pMap) { - m_pDefaultMap = pMap; + default_map = pMap; } -void THPathfinder::_allocNodeCache(int iWidth, int iHeight) +void pathfinder::allocate_node_cache(int iWidth, int iHeight) { - if(m_iNodeCacheWidth != iWidth || m_iNodeCacheHeight != iHeight) + if(node_cache_width != iWidth || node_cache_height != iHeight) { - delete[] m_pNodes; - m_pNodes = new node_t[iWidth * iHeight]; - node_t *pNode = m_pNodes; + delete[] nodes; + nodes = new path_node[iWidth * iHeight]; + path_node *pNode = nodes; for(int iY = 0; iY < iHeight; ++iY) { for(int iX = 0; iX < iWidth; ++iX, ++pNode) @@ -456,34 +456,34 @@ // path, and thus can be left uninitialised. } } - delete[] m_ppDirtyList; - m_ppDirtyList = new node_t*[iWidth * iHeight]; - m_iNodeCacheWidth = iWidth; - m_iNodeCacheHeight = iHeight; + delete[] dirty_node_list; + dirty_node_list = new path_node*[iWidth * iHeight]; + node_cache_width = iWidth; + node_cache_height = iHeight; } else { - for(int i = 0; i < m_iDirtyCount; ++i) + for(int i = 0; i < dirty_node_count; ++i) { - m_ppDirtyList[i]->prev = m_ppDirtyList[i]; + dirty_node_list[i]->prev = dirty_node_list[i]; // Other fields are undefined as the node is not part of a path, // and thus can keep their old values. } } - m_iDirtyCount = 0; + dirty_node_count = 0; } -int THPathfinder::getPathLength() const +int pathfinder::get_path_length() const { - if(m_pDestination != nullptr) - return m_pDestination->distance; + if(destination != nullptr) + return destination->distance; else return -1; } -bool THPathfinder::getPathEnd(int* pX, int* pY) const +bool pathfinder::get_path_end(int* pX, int* pY) const { - if(m_pDestination == nullptr) + if(destination == nullptr) { if(pX) *pX = -1; @@ -492,28 +492,28 @@ return false; } if(pX) - *pX = m_pDestination->x; + *pX = destination->x; if(pY) - *pY = m_pDestination->y; + *pY = destination->y; return true; } -void THPathfinder::pushResult(lua_State *L) const +void pathfinder::push_result(lua_State *L) const { lua_checkstack(L, 3); - if(m_pDestination == nullptr) + if(destination == nullptr) { lua_pushnil(L); lua_pushliteral(L, "no path"); return; } - int iLength = m_pDestination->distance; + int iLength = destination->distance; lua_createtable(L, iLength + 1, 0); lua_createtable(L, iLength + 1, 0); - for(const node_t* pNode = m_pDestination; pNode; pNode = pNode->prev) + for(const path_node* pNode = destination; pNode; pNode = pNode->prev) { lua_pushinteger(L, pNode->x + 1); lua_rawseti(L, -3, pNode->distance + 1); @@ -522,57 +522,57 @@ } } -void THPathfinder::_openHeapPush(node_t* pNode) +void pathfinder::push_to_open_heap(path_node* pNode) { - pNode->open_idx = m_openHeap.size(); - m_openHeap.push_back(pNode); - _openHeapPromote(pNode); + pNode->open_idx = open_heap.size(); + open_heap.push_back(pNode); + open_heap_promote(pNode); } -void THPathfinder::_openHeapPromote(node_t* pNode) +void pathfinder::open_heap_promote(path_node* pNode) { int i = pNode->open_idx; while(i > 0) { int parent = (i - 1) / 2; - node_t *pParent = m_openHeap[parent]; + path_node *pParent = open_heap[parent]; if(pParent->value() <= pNode->value()) break; pParent->open_idx = i; - m_openHeap[i] = pParent; - m_openHeap[parent] = pNode; + open_heap[i] = pParent; + open_heap[parent] = pNode; i = parent; } pNode->open_idx = i; } -node_t* THPathfinder::_openHeapPop() +path_node* pathfinder::pop_from_open_heap() { - node_t *pResult = m_openHeap[0]; - node_t *pNode = m_openHeap.back(); - m_openHeap.pop_back(); + path_node *pResult = open_heap[0]; + path_node *pNode = open_heap.back(); + open_heap.pop_back(); - if (m_openHeap.empty()) { + if (open_heap.empty()) { return pResult; } - m_openHeap[0] = pNode; + open_heap[0] = pNode; int i = 0; int min = 0; int left = i * 2 + 1; const int value = pNode->value(); - while(left < m_openHeap.size()) + while(left < open_heap.size()) { min = i; const int right = (i + 1) * 2; int minvalue = value; - node_t *pSwap = nullptr; - node_t *pTest = m_openHeap[left]; + path_node *pSwap = nullptr; + path_node *pTest = open_heap[left]; if(pTest->value() < minvalue) min = left, minvalue = pTest->value(), pSwap = pTest; - if(right < m_openHeap.size()) + if(right < open_heap.size()) { - pTest = m_openHeap[right]; + pTest = open_heap[right]; if(pTest->value() < minvalue) min = right, pSwap = pTest; } @@ -580,8 +580,8 @@ break; pSwap->open_idx = i; - m_openHeap[i] = pSwap; - m_openHeap[min] = pNode; + open_heap[i] = pSwap; + open_heap[min] = pNode; i = min; left = i * 2 + 1; } @@ -589,52 +589,52 @@ return pResult; } -void THPathfinder::persist(LuaPersistWriter *pWriter) const +void pathfinder::persist(lua_persist_writer *pWriter) const { - if(m_pDestination == nullptr) + if(destination == nullptr) { - pWriter->writeVUInt(0); + pWriter->write_uint(0); return; } - pWriter->writeVUInt(getPathLength() + 1); - pWriter->writeVUInt(m_iNodeCacheWidth); - pWriter->writeVUInt(m_iNodeCacheHeight); - for(const node_t* pNode = m_pDestination; pNode; pNode = pNode->prev) + pWriter->write_uint(get_path_length() + 1); + pWriter->write_uint(node_cache_width); + pWriter->write_uint(node_cache_height); + for(const path_node* pNode = destination; pNode; pNode = pNode->prev) { - pWriter->writeVUInt(pNode->x); - pWriter->writeVUInt(pNode->y); + pWriter->write_uint(pNode->x); + pWriter->write_uint(pNode->y); } } -void THPathfinder::depersist(LuaPersistReader *pReader) +void pathfinder::depersist(lua_persist_reader *pReader) { - new (this) THPathfinder; // Call constructor + new (this) pathfinder; // Call constructor int iLength; - if(!pReader->readVUInt(iLength)) + if(!pReader->read_uint(iLength)) return; if(iLength == 0) return; int iWidth, iHeight; - if(!pReader->readVUInt(iWidth) || !pReader->readVUInt(iHeight)) + if(!pReader->read_uint(iWidth) || !pReader->read_uint(iHeight)) return; - _allocNodeCache(iWidth, iHeight); + allocate_node_cache(iWidth, iHeight); int iX, iY; - if(!pReader->readVUInt(iX) || !pReader->readVUInt(iY)) + if(!pReader->read_uint(iX) || !pReader->read_uint(iY)) return; - node_t *pNode = m_pNodes + iY * iWidth + iX; - m_pDestination = pNode; + path_node *pNode = nodes + iY * iWidth + iX; + destination = pNode; for(int i = 0; i <= iLength - 2; ++i) { - if(!pReader->readVUInt(iX) || !pReader->readVUInt(iY)) + if(!pReader->read_uint(iX) || !pReader->read_uint(iY)) return; - node_t *pPrevNode = m_pNodes + iY * iWidth + iX; + path_node *pPrevNode = nodes + iY * iWidth + iX; pNode->distance = iLength - 1 - i; pNode->prev = pPrevNode; - m_ppDirtyList[m_iDirtyCount++] = pNode; + dirty_node_list[dirty_node_count++] = pNode; pNode = pPrevNode; } pNode->distance = 0; pNode->prev = nullptr; - m_ppDirtyList[m_iDirtyCount++] = pNode; + dirty_node_list[dirty_node_count++] = pNode; } diff -Nru corsix-th-0.61/CorsixTH/Src/th_pathfind.h corsix-th-0.62/CorsixTH/Src/th_pathfind.h --- corsix-th-0.61/CorsixTH/Src/th_pathfind.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_pathfind.h 2018-07-21 11:13:17.000000000 +0000 @@ -24,28 +24,27 @@ #define CORSIX_TH_TH_PATHFIND_H_ #include "th_map.h" -class LuaPersistReader; -class LuaPersistWriter; -class THPathfinder; +class lua_persist_reader; +class lua_persist_writer; +class pathfinder; /** Directions of movement. */ -enum TravelDirections -{ - THTD_North = 0, ///< Move to the north. - THTD_East = 1, ///< Move to the east. - THTD_South = 2, ///< Move to the south. - THTD_West = 3, ///< Move to the west. +enum class travel_direction { + north = 0, ///< Move to the north. + east = 1, ///< Move to the east. + south = 2, ///< Move to the south. + west = 3 ///< Move to the west. }; /** Node in the path finder routines. */ -struct node_t +struct path_node { //! Pointer to the previous node in the path to this cell. /*! Points to nullptr if this is the first cell in the path, or points to itself if it is not part of a path. */ - const node_t* prev; + const path_node* prev; //! X-position of this cell (constant) int x; @@ -81,11 +80,11 @@ }; /** Base class of the path finders. */ -class BasePathing +class abstract_pathfinder { public: - BasePathing(THPathfinder *pf); - virtual ~BasePathing() = default; + abstract_pathfinder(pathfinder *pf); + virtual ~abstract_pathfinder() = default; //! Initialize the path finder. /*! @@ -94,7 +93,7 @@ @param iStarty Y coordinate of the start position. @return The initial node to expand. */ - node_t *pathingInit(const THMap *pMap, int iStartX, int iStarty); + path_node *init(const level_map *pMap, int iStartX, int iStarty); //! Expand the \a pNode to its neighbours. /*! @@ -103,16 +102,16 @@ @param iWidth Width of the map. @return Whether the search is done. */ - bool pathingNeighbours(node_t *pNode, th_map_node_flags flags, int iWidth); + bool search_neighbours(path_node *pNode, map_tile_flags flags, int iWidth); - void pathingTryNode(node_t *pNode, th_map_node_flags neighbour_flags, - bool passable, node_t *pNeighbour); + void record_neighbour_if_passable(path_node *pNode, map_tile_flags neighbour_flags, + bool passable, path_node *pNeighbour); //! Guess distance to the destination for \a pNode. /*! @param pNode Node to fill. */ - virtual int makeGuess(node_t *pNode) = 0; + virtual int guess_distance(path_node *pNode) = 0; //! Try the \a pNeighbour node. /*! @@ -122,155 +121,155 @@ @param direction Direction of travel. @return Whether the search is done. */ - virtual bool tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) = 0; + virtual bool try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) = 0; protected: - THPathfinder *m_pPf; ///< Path finder parent object, containing shared data. - const THMap *m_pMap; ///< Map being searched. + pathfinder *parent; ///< Path finder parent object, containing shared data. + const level_map *map; ///< Map being searched. }; -class PathFinder : public BasePathing +class basic_pathfinder : public abstract_pathfinder { public: - PathFinder(THPathfinder *pf) : BasePathing(pf) { } + basic_pathfinder(pathfinder *pf) : abstract_pathfinder(pf) { } - int makeGuess(node_t *pNode) override; - bool tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) override; + int guess_distance(path_node *pNode) override; + bool try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) override; - bool findPath(const THMap *pMap, int iStartX, int iStartY, int iEndX, int iEndY); + bool find_path(const level_map *pMap, int iStartX, int iStartY, int iEndX, int iEndY); - int m_iEndX; ///< X coordinate of the destination of the path. - int m_iEndY; ///< Y coordinate of the destination of the path. + int destination_x; ///< X coordinate of the destination of the path. + int destination_y; ///< Y coordinate of the destination of the path. }; -class HospitalFinder : public BasePathing +class hospital_finder : public abstract_pathfinder { public: - HospitalFinder(THPathfinder *pf) : BasePathing(pf) { } + hospital_finder(pathfinder *pf) : abstract_pathfinder(pf) { } - int makeGuess(node_t *pNode) override; - bool tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) override; + int guess_distance(path_node *pNode) override; + bool try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) override; - bool findPathToHospital(const THMap *pMap, int iStartX, int iStartY); + bool find_path_to_hospital(const level_map *pMap, int iStartX, int iStartY); }; -class IdleTileFinder : public BasePathing +class idle_tile_finder : public abstract_pathfinder { public: - IdleTileFinder(THPathfinder *pf) : BasePathing(pf) { } + idle_tile_finder(pathfinder *pf) : abstract_pathfinder(pf) { } - int makeGuess(node_t *pNode) override; - bool tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) override; - - bool findIdleTile(const THMap *pMap, int iStartX, int iStartY, int iN); - - node_t *m_pBestNext; - double m_fBestDistance; - int m_iStartX; ///< X coordinate of the start position. - int m_iStartY; ///< Y coordinate of the start position. + int guess_distance(path_node *pNode) override; + bool try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) override; + + bool find_idle_tile(const level_map *pMap, int iStartX, int iStartY, int iN); + + path_node *best_next_node; + double best_distance; + int start_x; ///< X coordinate of the start position. + int start_y; ///< Y coordinate of the start position. }; -class Objectsvisitor : public BasePathing +class object_visitor : public abstract_pathfinder { public: - Objectsvisitor(THPathfinder *pf) : BasePathing(pf) { } + object_visitor(pathfinder *pf) : abstract_pathfinder(pf) { } - int makeGuess(node_t *pNode) override; - bool tryNode(node_t *pNode, th_map_node_flags flags, - node_t *pNeighbour, int direction) override; + int guess_distance(path_node *pNode) override; + bool try_node(path_node *pNode, map_tile_flags flags, + path_node *pNeighbour, travel_direction direction) override; - bool visitObjects(const THMap *pMap, int iStartX, int iStartY, - THObjectType eTHOB, int iMaxDistance, + bool visit_objects(const level_map *pMap, int iStartX, int iStartY, + object_type eTHOB, int iMaxDistance, lua_State *L, int iVisitFunction, bool anyObjectType); - lua_State *m_pL; - int m_iVisitFunction; - int m_iMaxDistance; - bool m_bAnyObjectType; - THObjectType m_eTHOB; + lua_State *L; + int visit_function_index; + int max_distance; + bool target_any_object_type; + object_type target; }; //! Finds paths through maps /*! A pathfinder is used for finding a path through a map. A single pathfinder instance is not reentrant, but separate instances are. Users of the class - should call findPath() to test if there is a path between two points on a - map, and then use getPathLength() and/or pushResult() to get the actual + should call find_path() to test if there is a path between two points on a + map, and then use get_path_length() and/or push_result() to get the actual path. Internally, the A* search algorithm is used. The open set is implemented as - a heap in m_openHeap, and there is no explicit closed set. For each cell - of the map, a node_t structure is created (and cached between searches if + a heap in open_heap, and there is no explicit closed set. For each cell + of the map, a path_node structure is created (and cached between searches if the map size is constant), which holds information about said map cell in the current search. The algorithm is implemented in such a way that most path find operations do not need to allocate (or free) any memory. */ -class THPathfinder +class pathfinder { public: - THPathfinder(); - ~THPathfinder(); + pathfinder(); + ~pathfinder(); - void setDefaultMap(const THMap *pMap); + void set_default_map(const level_map *pMap); - inline bool findPath(const THMap *pMap, int iStartX, int iStartY, int iEndX, + inline bool find_path(const level_map *pMap, int iStartX, int iStartY, int iEndX, int iEndY) { - return m_oPathFinder.findPath(pMap, iStartX, iStartY, iEndX, iEndY); + return basic_pathfinder.find_path(pMap, iStartX, iStartY, iEndX, iEndY); } - inline bool findIdleTile(const THMap *pMap, int iStartX, int iStartY, int iN) + inline bool find_idle_tile(const level_map *pMap, int iStartX, int iStartY, int iN) { - return m_oIdleTileFinder.findIdleTile(pMap, iStartX, iStartY, iN); + return idle_tile_finder.find_idle_tile(pMap, iStartX, iStartY, iN); } - inline bool findPathToHospital(const THMap *pMap, int iStartX, int iStartY) + inline bool find_path_to_hospital(const level_map *pMap, int iStartX, int iStartY) { - return m_oHospitalFinder.findPathToHospital(pMap, iStartX, iStartY); + return hospital_finder.find_path_to_hospital(pMap, iStartX, iStartY); } - inline bool visitObjects(const THMap *pMap, int iStartX, int iStartY, - THObjectType eTHOB, int iMaxDistance, lua_State *L, + inline bool visit_objects(const level_map *pMap, int iStartX, int iStartY, + object_type eTHOB, int iMaxDistance, lua_State *L, int iVisitFunction, bool anyObjectType) { - return m_oObjectsvisitor.visitObjects( + return object_visitor.visit_objects( pMap, iStartX, iStartY, eTHOB, iMaxDistance, L, iVisitFunction, anyObjectType); } - int getPathLength() const; - bool getPathEnd(int* pX, int* pY) const; - void pushResult(lua_State *L) const; + int get_path_length() const; + bool get_path_end(int* pX, int* pY) const; + void push_result(lua_State *L) const; - void persist(LuaPersistWriter *pWriter) const; - void depersist(LuaPersistReader *pReader); + void persist(lua_persist_writer *pWriter) const; + void depersist(lua_persist_reader *pReader); //! Allocate node cache for all tiles of the map. /*! @param iWidth Width of the map. @param iHeight Height of the map. */ - void _allocNodeCache(int iWidth, int iHeight); + void allocate_node_cache(int iWidth, int iHeight); - node_t* _openHeapPop(); - void _openHeapPush(node_t* pNode); - void _openHeapPromote(node_t* pNode); + path_node* pop_from_open_heap(); + void push_to_open_heap(path_node* pNode); + void open_heap_promote(path_node* pNode); - const THMap *m_pDefaultMap; + const level_map *default_map; //! 2D array of nodes, one for each map cell - node_t *m_pNodes; + path_node *nodes; //! Array of "dirty" nodes which need to be reset before the next path find /*! This array is always large enough to hold every single node, and - #m_iDirtyCount holds the number of items currently in the array. + #dirty_node_count holds the number of items currently in the array. */ - node_t **m_ppDirtyList; + path_node **dirty_node_list; //! Heap of not yet evaluated nodes as a 0-based array /*! @@ -279,18 +278,18 @@ value(i) <= value(i * 2 + 2) This causes the array to be a minimum binary heap. */ - std::vector m_openHeap; + std::vector open_heap; - node_t *m_pDestination; - int m_iNodeCacheWidth; - int m_iNodeCacheHeight; - int m_iDirtyCount; + path_node *destination; + int node_cache_width; + int node_cache_height; + int dirty_node_count; private: - PathFinder m_oPathFinder; - HospitalFinder m_oHospitalFinder; - IdleTileFinder m_oIdleTileFinder; - Objectsvisitor m_oObjectsvisitor; + ::basic_pathfinder basic_pathfinder; + ::hospital_finder hospital_finder; + ::idle_tile_finder idle_tile_finder; + ::object_visitor object_visitor; }; #endif // CORSIX_TH_TH_PATHFIND_H_ diff -Nru corsix-th-0.61/CorsixTH/Src/th_sound.cpp corsix-th-0.62/CorsixTH/Src/th_sound.cpp --- corsix-th-0.61/CorsixTH/Src/th_sound.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_sound.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -26,49 +26,49 @@ #include #include -THSoundArchive::THSoundArchive() +sound_archive::sound_archive() { - m_pFiles = nullptr; - m_pData = nullptr; + sound_files = nullptr; + data = nullptr; } -THSoundArchive::~THSoundArchive() +sound_archive::~sound_archive() { - delete[] m_pData; + delete[] data; } -bool THSoundArchive::loadFromTHFile(const uint8_t* pData, size_t iDataLength) +bool sound_archive::load_from_th_file(const uint8_t* pData, size_t iDataLength) { - if(iDataLength < sizeof(uint32_t) + sizeof(th_header_t)) + if(iDataLength < sizeof(uint32_t) + sizeof(sound_dat_file_header)) return false; uint32_t iHeaderPosition = reinterpret_cast(pData + iDataLength)[-1]; - if(static_cast(iHeaderPosition) >= iDataLength - sizeof(th_header_t)) + if(static_cast(iHeaderPosition) >= iDataLength - sizeof(sound_dat_file_header)) return false; - m_oHeader = *reinterpret_cast(pData + iHeaderPosition); + header = *reinterpret_cast(pData + iHeaderPosition); - delete[] m_pData; - m_pData = new (std::nothrow) uint8_t[iDataLength]; - if(m_pData == nullptr) + delete[] data; + data = new (std::nothrow) uint8_t[iDataLength]; + if(data == nullptr) return false; - std::memcpy(m_pData, pData, iDataLength); + std::memcpy(data, pData, iDataLength); - m_pFiles = reinterpret_cast(m_pData + m_oHeader.table_position); - m_iFileCount = m_oHeader.table_length / sizeof(th_fileinfo_t); + sound_files = reinterpret_cast(data + header.table_position); + sound_file_count = header.table_length / sizeof(sound_dat_sound_info); return true; } -size_t THSoundArchive::getSoundCount() const +size_t sound_archive::get_number_of_sounds() const { - return m_iFileCount; + return sound_file_count; } -const char* THSoundArchive::getSoundFilename(size_t iIndex) const +const char* sound_archive::get_sound_name(size_t iIndex) const { - if(iIndex >= m_iFileCount) + if(iIndex >= sound_file_count) return nullptr; - return m_pFiles[iIndex].filename; + return sound_files[iIndex].sound_name; } #define FOURCC(c1, c2, c3, c4) \ @@ -77,9 +77,9 @@ | static_cast(static_cast(c3) << 16) \ | static_cast(static_cast(c4) << 24) ) -size_t THSoundArchive::getSoundDuration(size_t iIndex) +size_t sound_archive::get_sound_duration(size_t iIndex) { - SDL_RWops *pFile = loadSound(iIndex); + SDL_RWops *pFile = load_sound(iIndex); if(!pFile) return 0; @@ -150,179 +150,179 @@ #undef FOURCC -SDL_RWops* THSoundArchive::loadSound(size_t iIndex) +SDL_RWops* sound_archive::load_sound(size_t iIndex) { - if(iIndex >= m_iFileCount) + if(iIndex >= sound_file_count) return nullptr; - th_fileinfo_t *pFile = m_pFiles + iIndex; - return SDL_RWFromConstMem(m_pData + pFile->position, pFile->length); + sound_dat_sound_info *pFile = sound_files + iIndex; + return SDL_RWFromConstMem(data + pFile->position, pFile->length); } #ifdef CORSIX_TH_USE_SDL_MIXER -THSoundEffects* THSoundEffects::ms_pSingleton = nullptr; +sound_player* sound_player::singleton = nullptr; -THSoundEffects::THSoundEffects() +sound_player::sound_player() { - m_ppSounds = nullptr; - m_iSoundCount = 0; - ms_pSingleton = this; - m_iCameraX = 0; - m_iCameraY = 0; - m_fCameraRadius = 1.0; - m_fMasterVolume = 1.0; - m_fSoundEffectsVolume = 0.5; - m_iPostionlessVolume = MIX_MAX_VOLUME; - m_bSoundEffectsOn = true; + sounds = nullptr; + sound_count = 0; + singleton = this; + camera_x = 0; + camera_y = 0; + camera_radius = 1.0; + master_volume = 1.0; + sound_effect_volume = 0.5; + positionless_volume = MIX_MAX_VOLUME; + sound_effects_enabled = true; #define NUM_CHANNELS 32 #if NUM_CHANNELS >= 32 - m_iChannelStatus = ~0; + available_channels_bitmap = ~0; Mix_AllocateChannels(32); #else - m_iChannelStatus = (1 << NUM_CHANNELS) - 1; + channels_in_use_bitmap = (1 << NUM_CHANNELS) - 1; Mix_AllocateChannels(NUM_CHANNELS); #endif #undef NUM_CHANNELS - Mix_ChannelFinished(_onChannelFinish); + Mix_ChannelFinished(on_channel_finished); } -THSoundEffects::~THSoundEffects() +sound_player::~sound_player() { - setSoundArchive(nullptr); - if(ms_pSingleton == this) - ms_pSingleton = nullptr; + populate_from(nullptr); + if(singleton == this) + singleton = nullptr; } -void THSoundEffects::_onChannelFinish(int iChannel) +void sound_player::on_channel_finished(int iChannel) { - THSoundEffects *pThis = getSingleton(); + sound_player *pThis = get_singleton(); if(pThis == nullptr) return; - pThis->releaseChannel(iChannel); + pThis->release_channel(iChannel); } -THSoundEffects* THSoundEffects::getSingleton() +sound_player* sound_player::get_singleton() { - return ms_pSingleton; + return singleton; } -void THSoundEffects::setSoundArchive(THSoundArchive *pArchive) +void sound_player::populate_from(sound_archive *pArchive) { - for(size_t i = 0; i < m_iSoundCount; ++i) + for(size_t i = 0; i < sound_count; ++i) { - Mix_FreeChunk(m_ppSounds[i]); + Mix_FreeChunk(sounds[i]); } - delete[] m_ppSounds; - m_ppSounds = nullptr; - m_iSoundCount = 0; + delete[] sounds; + sounds = nullptr; + sound_count = 0; if(pArchive == nullptr) return; - m_ppSounds = new Mix_Chunk*[pArchive->getSoundCount()]; - for(; m_iSoundCount < pArchive->getSoundCount(); ++m_iSoundCount) + sounds = new Mix_Chunk*[pArchive->get_number_of_sounds()]; + for(; sound_count < pArchive->get_number_of_sounds(); ++sound_count) { - m_ppSounds[m_iSoundCount] = nullptr; - SDL_RWops *pRwop = pArchive->loadSound(m_iSoundCount); + sounds[sound_count] = nullptr; + SDL_RWops *pRwop = pArchive->load_sound(sound_count); if(pRwop) { - m_ppSounds[m_iSoundCount] = Mix_LoadWAV_RW(pRwop, 1); - if(m_ppSounds[m_iSoundCount]) - Mix_VolumeChunk(m_ppSounds[m_iSoundCount], MIX_MAX_VOLUME); + sounds[sound_count] = Mix_LoadWAV_RW(pRwop, 1); + if(sounds[sound_count]) + Mix_VolumeChunk(sounds[sound_count], MIX_MAX_VOLUME); } } } -void THSoundEffects::playSound(size_t iIndex, double dVolume) +void sound_player::play(size_t iIndex, double dVolume) { - if(m_iChannelStatus == 0 || iIndex >= m_iSoundCount || !m_ppSounds[iIndex]) + if(available_channels_bitmap == 0 || iIndex >= sound_count || !sounds[iIndex]) return; - _playRaw(iIndex, (int)(m_iPostionlessVolume*dVolume)); + play_raw(iIndex, (int)(positionless_volume * dVolume)); } -void THSoundEffects::playSoundAt(size_t iIndex, int iX, int iY) +void sound_player::play_at(size_t iIndex, int iX, int iY) { - if(m_bSoundEffectsOn) - playSoundAt(iIndex, m_fSoundEffectsVolume, iX, iY); + if(sound_effects_enabled) + play_at(iIndex, sound_effect_volume, iX, iY); } -void THSoundEffects::playSoundAt(size_t iIndex, double dVolume, int iX, int iY) +void sound_player::play_at(size_t iIndex, double dVolume, int iX, int iY) { - if(m_iChannelStatus == 0 || iIndex >= m_iSoundCount || !m_ppSounds[iIndex]) + if(available_channels_bitmap == 0 || iIndex >= sound_count || !sounds[iIndex]) return; - double fDX = (double)(iX - m_iCameraX); - double fDY = (double)(iY - m_iCameraY); + double fDX = (double)(iX - camera_x); + double fDY = (double)(iY - camera_y); double fDistance = sqrt(fDX * fDX + fDY * fDY); - if(fDistance > m_fCameraRadius) + if(fDistance > camera_radius) return; - fDistance = fDistance / m_fCameraRadius; + fDistance = fDistance / camera_radius; - double fVolume = m_fMasterVolume * (1.0 - fDistance * 0.8) * (double)MIX_MAX_VOLUME * dVolume; + double fVolume = master_volume * (1.0 - fDistance * 0.8) * (double)MIX_MAX_VOLUME * dVolume; - _playRaw(iIndex, (int)(fVolume + 0.5)); + play_raw(iIndex, (int)(fVolume + 0.5)); } -void THSoundEffects::setSoundEffectsVolume(double dVolume) +void sound_player::set_sound_effect_volume(double dVolume) { - m_fSoundEffectsVolume = dVolume; + sound_effect_volume = dVolume; } -void THSoundEffects::setSoundEffectsOn(bool bOn) +void sound_player::set_sound_effects_enabled(bool bOn) { - m_bSoundEffectsOn = bOn; + sound_effects_enabled = bOn; } -int THSoundEffects::reserveChannel() +int sound_player::reserve_channel() { // NB: Callers ensure that m_iChannelStatus != 0 int iChannel = 0; - for(; (m_iChannelStatus & (1 << iChannel)) == 0; ++iChannel) {} - m_iChannelStatus &=~ (1 << iChannel); + for(; (available_channels_bitmap & (1 << iChannel)) == 0; ++iChannel) {} + available_channels_bitmap &=~ (1 << iChannel); return iChannel; } -void THSoundEffects::releaseChannel(int iChannel) +void sound_player::release_channel(int iChannel) { - m_iChannelStatus |= (1 << iChannel); + available_channels_bitmap |= (1 << iChannel); } -void THSoundEffects::_playRaw(size_t iIndex, int iVolume) +void sound_player::play_raw(size_t iIndex, int iVolume) { - int iChannel = reserveChannel(); + int iChannel = reserve_channel(); Mix_Volume(iChannel, iVolume); - Mix_PlayChannelTimed(iChannel, m_ppSounds[iIndex], 0, -1); + Mix_PlayChannelTimed(iChannel, sounds[iIndex], 0, -1); } -void THSoundEffects::setCamera(int iX, int iY, int iRadius) +void sound_player::set_camera(int iX, int iY, int iRadius) { - m_iCameraX = iX; - m_iCameraY = iY; - m_fCameraRadius = (double)iRadius; - if(m_fCameraRadius < 0.001) - m_fCameraRadius = 0.001; + camera_x = iX; + camera_y = iY; + camera_radius = (double)iRadius; + if(camera_radius < 0.001) + camera_radius = 0.001; } #else // CORSIX_TH_USE_SDL_MIXER -THSoundEffects::THSoundEffects() {} -THSoundEffects::~THSoundEffects() {} -THSoundEffects* THSoundEffects::getSingleton() {return nullptr;} -void THSoundEffects::setSoundArchive(THSoundArchive *pArchive) {} -void THSoundEffects::playSound(size_t iIndex, double dVolume) {} -void THSoundEffects::playSoundAt(size_t iIndex, int iX, int iY) {} -void THSoundEffects::playSoundAt(size_t iIndex, double dVolume, int iX, int iY) {} -int THSoundEffects::reserveChannel() { return 0; } -void THSoundEffects::releaseChannel(int iChannel) {} -void THSoundEffects::setCamera(int iX, int iY, int iRadius) {} -void THSoundEffects::setSoundEffectsVolume(double dVolume) {} -void THSoundEffects::setSoundEffectsOn(bool iOn) {} +sound_effect_player::sound_effect_player() {} +sound_effect_player::~sound_effect_player() {} +sound_effect_player* sound_effect_player::get_singleton() {return nullptr;} +void sound_effect_player::set_sound_archive(THSoundArchive *pArchive) {} +void sound_effect_player::play(size_t iIndex, double dVolume) {} +void sound_effect_player::play_at(size_t iIndex, int iX, int iY) {} +void sound_effect_player::play_at(size_t iIndex, double dVolume, int iX, int iY) {} +int sound_effect_player::reserve_channel() { return 0; } +void sound_effect_player::release_channel(int iChannel) {} +void sound_effect_player::set_camera(int iX, int iY, int iRadius) {} +void sound_effect_player::set_sound_effect_volume(double dVolume) {} +void sound_effect_player::set_sound_effects_enabled(bool iOn) {} #endif // CORSIX_TH_USE_SDL_MIXER diff -Nru corsix-th-0.61/CorsixTH/Src/th_sound.h corsix-th-0.62/CorsixTH/Src/th_sound.h --- corsix-th-0.61/CorsixTH/Src/th_sound.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/th_sound.h 2018-07-21 11:13:17.000000000 +0000 @@ -28,35 +28,35 @@ #endif //! Utility class for accessing Theme Hospital's SOUND-0.DAT -class THSoundArchive +class sound_archive { public: - THSoundArchive(); - ~THSoundArchive(); + sound_archive(); + ~sound_archive(); - bool loadFromTHFile(const uint8_t* pData, size_t iDataLength); + bool load_from_th_file(const uint8_t* pData, size_t iDataLength); //! Returns the number of sounds present in the archive - size_t getSoundCount() const; + size_t get_number_of_sounds() const; //! Gets the name of the sound at a given index - const char* getSoundFilename(size_t iIndex) const; + const char *get_sound_name(size_t iIndex) const; //! Gets the duration (in miliseconds) of the sound at a given index - size_t getSoundDuration(size_t iIndex); + size_t get_sound_duration(size_t iIndex); //! Opens the sound at a given index into an SDL_RWops structure /*! The caller is responsible for closing/freeing the result. */ - SDL_RWops* loadSound(size_t iIndex); + SDL_RWops* load_sound(size_t iIndex); private: #if CORSIX_TH_USE_PACK_PRAGMAS #pragma pack(push) #pragma pack(1) #endif - struct th_header_t + struct sound_dat_file_header { uint8_t unknown1[50]; uint32_t table_position; @@ -69,9 +69,9 @@ uint8_t unknown4[48]; } CORSIX_TH_PACKED_FLAGS; - struct th_fileinfo_t + struct sound_dat_sound_info { - char filename[18]; + char sound_name[18]; uint32_t position; uint32_t unknown1; uint32_t length; @@ -81,48 +81,49 @@ #pragma pack(pop) #endif - th_header_t m_oHeader; - th_fileinfo_t* m_pFiles; - uint8_t* m_pData; - size_t m_iFileCount; + // TODO: header is only used in one function, should not be class variable. + sound_dat_file_header header; + sound_dat_sound_info* sound_files; + uint8_t* data; + size_t sound_file_count; }; -class THSoundEffects +class sound_player { public: - THSoundEffects(); - ~THSoundEffects(); + sound_player(); + ~sound_player(); - static THSoundEffects* getSingleton(); + static sound_player* get_singleton(); - void setSoundArchive(THSoundArchive *pArchive); + void populate_from(sound_archive *pArchive); - void playSound(size_t iIndex, double dVolume); - void playSoundAt(size_t iIndex, int iX, int iY); - void playSoundAt(size_t iIndex, double dVolume, int iX, int iY); - void setSoundEffectsVolume(double dVolume); - void setSoundEffectsOn(bool bOn); - void setCamera(int iX, int iY, int iRadius); - int reserveChannel(); - void releaseChannel(int iChannel); + void play(size_t iIndex, double dVolume); + void play_at(size_t iIndex, int iX, int iY); + void play_at(size_t iIndex, double dVolume, int iX, int iY); + void set_sound_effect_volume(double dVolume); + void set_sound_effects_enabled(bool bOn); + void set_camera(int iX, int iY, int iRadius); + int reserve_channel(); + void release_channel(int iChannel); private: #ifdef CORSIX_TH_USE_SDL_MIXER - static THSoundEffects* ms_pSingleton; - static void _onChannelFinish(int iChannel); + static sound_player* singleton; + static void on_channel_finished(int iChannel); - inline void _playRaw(size_t iIndex, int iVolume); + inline void play_raw(size_t iIndex, int iVolume); - Mix_Chunk **m_ppSounds; - size_t m_iSoundCount; - uint32_t m_iChannelStatus; - int m_iCameraX; - int m_iCameraY; - double m_fCameraRadius; - double m_fMasterVolume; - double m_fSoundEffectsVolume; - int m_iPostionlessVolume; - bool m_bSoundEffectsOn; + Mix_Chunk **sounds; + size_t sound_count; + uint32_t available_channels_bitmap; ///< The bit index corresponding to a channel is 1 if the channel is available and 0 if it is reserved or in use. + int camera_x; + int camera_y; + double camera_radius; + double master_volume; + double sound_effect_volume; + int positionless_volume; + bool sound_effects_enabled; #endif // CORSIX_TH_USE_SDL_MIXER }; diff -Nru corsix-th-0.61/CorsixTH/Src/xmi2mid.cpp corsix-th-0.62/CorsixTH/Src/xmi2mid.cpp --- corsix-th-0.61/CorsixTH/Src/xmi2mid.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/xmi2mid.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -31,49 +31,49 @@ /*! Utility class for reading or writing to memory as if it were a file. */ -class MemoryBuffer +class memory_buffer { public: - MemoryBuffer() - : m_pData(nullptr), m_pPointer(nullptr), m_pEnd(nullptr), m_pBufferEnd(nullptr) + memory_buffer() + : data(nullptr), pointer(nullptr), data_end(nullptr), buffer_end(nullptr) { } - MemoryBuffer(const uint8_t* pData, size_t iLength) + memory_buffer(const uint8_t* pData, size_t iLength) { - m_pData = m_pPointer = (char*)pData; - m_pEnd = m_pData + iLength; - m_pBufferEnd = nullptr; + data = pointer = (char*)pData; + data_end = data + iLength; + buffer_end = nullptr; } - ~MemoryBuffer() + ~memory_buffer() { - if(m_pBufferEnd != nullptr) - delete[] m_pData; + if(buffer_end != nullptr) + delete[] data; } - uint8_t* takeData(size_t *pLength) + uint8_t* take_data(size_t *pLength) { if(pLength) - *pLength = m_pEnd - m_pData; - uint8_t* pResult = (unsigned char*)m_pData; - m_pData = m_pPointer = m_pEnd = m_pBufferEnd = nullptr; + *pLength = data_end - data; + uint8_t* pResult = (unsigned char*)data; + data = pointer = data_end = buffer_end = nullptr; return pResult; } size_t tell() const { - return m_pPointer - m_pData; + return pointer - data; } bool seek(size_t position) { - if(m_pData + position > m_pEnd) + if(data + position > data_end) { - if(!_realloc(position)) + if(!resize_buffer(position)) return false; } - m_pPointer = m_pData + position; + pointer = data + position; return true; } @@ -81,25 +81,25 @@ { if(distance < 0) { - if(m_pPointer + distance < m_pData) + if(pointer + distance < data) return false; } - return seek(m_pPointer - m_pData + distance); + return seek(pointer - data + distance); } - bool scanTo(const void* pData, size_t iLength) + bool scan_to(const void* pData, size_t iLength) { - for(; m_pPointer + iLength <= m_pEnd; ++m_pPointer) + for(; pointer + iLength <= data_end; ++pointer) { - if(std::memcmp(m_pPointer, pData, iLength) == 0) + if(std::memcmp(pointer, pData, iLength) == 0) return true; } return false; } - const char* getPointer() const + const char* get_pointer() const { - return m_pPointer; + return pointer; } template @@ -111,14 +111,14 @@ template bool read(T* values, size_t count) { - if(m_pPointer + sizeof(T) * count > m_pEnd) + if(pointer + sizeof(T) * count > data_end) return false; - std::memcpy(values, m_pPointer, sizeof(T) * count); - m_pPointer += sizeof(T) * count; + std::memcpy(values, pointer, sizeof(T) * count); + pointer += sizeof(T) * count; return true; } - unsigned int readBigEndianUInt24() + unsigned int read_big_endian_uint24() { uint8_t iByte0, iByte1, iByte2; if(read(iByte0) && read(iByte1) && read(iByte2)) @@ -127,7 +127,7 @@ return 0; } - unsigned int readUIntVar() + unsigned int read_variable_length_uint() { unsigned int iValue = 0; uint8_t iByte; @@ -153,21 +153,21 @@ { if(!skip(static_cast(sizeof(T) * count))) return false; - std::memcpy(m_pPointer - sizeof(T) * count, values, sizeof(T) * count); + std::memcpy(pointer - sizeof(T) * count, values, sizeof(T) * count); return true; } - bool writeBigEndianUInt16(uint16_t iValue) + bool write_big_endian_uint16(uint16_t iValue) { - return write(_byteSwap(iValue)); + return write(byte_swap(iValue)); } - bool writeBigEndianUInt32(uint32_t iValue) + bool write_big_endian_uint32(uint32_t iValue) { - return write(_byteSwap(iValue)); + return write(byte_swap(iValue)); } - bool writeUIntVar(unsigned int iValue) + bool write_variable_length_uint(unsigned int iValue) { int iByteCount = 1; unsigned int iBuffer = iValue & 0x7F; @@ -185,14 +185,14 @@ return true; } - bool isEOF() const + bool is_end_of_buffer() const { - return m_pPointer == m_pEnd; + return pointer == data_end; } private: template - static T _byteSwap(T value) + static T byte_swap(T value) { T swapped = 0; for(int i = 0; i < static_cast(sizeof(T)) * 8; i += 8) @@ -202,75 +202,75 @@ return swapped; } - bool _realloc(size_t size) + bool resize_buffer(size_t size) { - if(m_pData + size <= m_pBufferEnd) + if(data + size <= buffer_end) { - m_pEnd = m_pData + size; + data_end = data + size; return true; } char *pNewData = new (std::nothrow) char[size * 2]; if(pNewData == nullptr) return false; - size_t iOldLength = m_pEnd - m_pData; - std::memcpy(pNewData, m_pData, size > iOldLength ? iOldLength : size); - m_pPointer = m_pPointer - m_pData + pNewData; - if(m_pBufferEnd != nullptr) - delete[] m_pData; - m_pData = pNewData; - m_pEnd = pNewData + size; - m_pBufferEnd = pNewData + size * 2; + size_t iOldLength = data_end - data; + std::memcpy(pNewData, data, size > iOldLength ? iOldLength : size); + pointer = pointer - data + pNewData; + if(buffer_end != nullptr) + delete[] data; + data = pNewData; + data_end = pNewData + size; + buffer_end = pNewData + size * 2; return true; } - char *m_pData, *m_pPointer, *m_pEnd, *m_pBufferEnd; + char *data, *pointer, *data_end, *buffer_end; }; -struct midi_token_t +struct midi_token { - int iTime; - unsigned int iBufferLength; - const char *pBuffer; - uint8_t iType; - uint8_t iData; + int time; + unsigned int buffer_length; + const char *buffer; + uint8_t type; + uint8_t data; }; -static bool operator < (const midi_token_t& oLeft, const midi_token_t& oRight) +static bool operator < (const midi_token& oLeft, const midi_token& oRight) { - return oLeft.iTime < oRight.iTime; + return oLeft.time < oRight.time; } -struct midi_token_list_t : std::vector +struct midi_token_list : std::vector { - midi_token_t* append(int iTime, uint8_t iType) + midi_token* append(int iTime, uint8_t iType) { - push_back(midi_token_t()); - midi_token_t* pToken = &back(); - pToken->iTime = iTime; - pToken->iType = iType; + push_back(midi_token()); + midi_token* pToken = &back(); + pToken->time = iTime; + pToken->type = iType; return pToken; } }; -uint8_t* TranscodeXmiToMid(const unsigned char* pXmiData, - size_t iXmiLength, size_t* pMidLength) +uint8_t* transcode_xmi_to_midi(const unsigned char* xmi_data, + size_t xmi_length, size_t* midi_length) { - MemoryBuffer bufInput(pXmiData, iXmiLength); - MemoryBuffer bufOutput; + memory_buffer bufInput(xmi_data, xmi_length); + memory_buffer bufOutput; - if(!bufInput.scanTo("EVNT", 4) || !bufInput.skip(8)) + if(!bufInput.scan_to("EVNT", 4) || !bufInput.skip(8)) return nullptr; - midi_token_list_t lstTokens; - midi_token_t* pToken; + midi_token_list lstTokens; + midi_token* pToken; int iTokenTime = 0; int iTempo = 500000; bool bTempoSet = false; bool bEnd = false; uint8_t iTokenType, iExtendedType; - while(!bufInput.isEOF() && !bEnd) + while(!bufInput.is_end_of_buffer() && !bEnd) { while(true) { @@ -283,20 +283,20 @@ iTokenTime += static_cast(iTokenType) * 3; } pToken = lstTokens.append(iTokenTime, iTokenType); - pToken->pBuffer = bufInput.getPointer() + 1; + pToken->buffer = bufInput.get_pointer() + 1; switch(iTokenType & 0xF0) { case 0xC0: case 0xD0: - if(!bufInput.read(pToken->iData)) + if(!bufInput.read(pToken->data)) return nullptr; - pToken->pBuffer = nullptr; + pToken->buffer = nullptr; break; case 0x80: case 0xA0: case 0xB0: case 0xE0: - if(!bufInput.read(pToken->iData)) + if(!bufInput.read(pToken->data)) return nullptr; if(!bufInput.skip(1)) return nullptr; @@ -304,13 +304,13 @@ case 0x90: if(!bufInput.read(iExtendedType)) return nullptr; - pToken->iData = iExtendedType; + pToken->data = iExtendedType; if(!bufInput.skip(1)) return nullptr; - pToken = lstTokens.append(iTokenTime + bufInput.readUIntVar() * 3, + pToken = lstTokens.append(iTokenTime + bufInput.read_variable_length_uint() * 3, iTokenType); - pToken->iData = iExtendedType; - pToken->pBuffer = "\0"; + pToken->data = iExtendedType; + pToken->buffer = "\0"; break; case 0xF0: iExtendedType = 0; @@ -326,23 +326,23 @@ if(!bTempoSet) { bufInput.skip(1); - iTempo = bufInput.readBigEndianUInt24() * 3; + iTempo = bufInput.read_big_endian_uint24() * 3; bTempoSet = true; bufInput.skip(-4); } else { lstTokens.pop_back(); - if(!bufInput.skip(bufInput.readUIntVar())) + if(!bufInput.skip(bufInput.read_variable_length_uint())) return nullptr; break; } } } - pToken->iData = iExtendedType; - pToken->iBufferLength = bufInput.readUIntVar(); - pToken->pBuffer = bufInput.getPointer(); - if(!bufInput.skip(pToken->iBufferLength)) + pToken->data = iExtendedType; + pToken->buffer_length = bufInput.read_variable_length_uint(); + pToken->buffer = bufInput.get_pointer(); + if(!bufInput.skip(pToken->buffer_length)) return nullptr; break; } @@ -352,7 +352,7 @@ return nullptr; if(!bufOutput.write("MThd\0\0\0\x06\0\0\0\x01", 12)) return nullptr; - if(!bufOutput.writeBigEndianUInt16(static_cast((iTempo * 3) / 25000))) + if(!bufOutput.write_big_endian_uint16(static_cast((iTempo * 3) / 25000))) return nullptr; if(!bufOutput.write("MTrk\xBA\xAD\xF0\x0D", 8)) return nullptr; @@ -363,40 +363,40 @@ iTokenType = 0; bEnd = false; - for(midi_token_list_t::iterator itr = lstTokens.begin(), + for(midi_token_list::iterator itr = lstTokens.begin(), itrEnd = lstTokens.end(); itr != itrEnd && !bEnd; ++itr) { - if(!bufOutput.writeUIntVar(itr->iTime - iTokenTime)) + if(!bufOutput.write_variable_length_uint(itr->time - iTokenTime)) return nullptr; - iTokenTime = itr->iTime; - if(itr->iType >= 0xF0) + iTokenTime = itr->time; + if(itr->type >= 0xF0) { - if(!bufOutput.write(iTokenType = itr->iType)) + if(!bufOutput.write(iTokenType = itr->type)) return nullptr; if(iTokenType == 0xFF) { - if(!bufOutput.write(itr->iData)) + if(!bufOutput.write(itr->data)) return nullptr; - if(itr->iData == 0x2F) + if(itr->data == 0x2F) bEnd = true; } - if(!bufOutput.writeUIntVar(itr->iBufferLength)) + if(!bufOutput.write_variable_length_uint(itr->buffer_length)) return nullptr; - if(!bufOutput.write(itr->pBuffer, itr->iBufferLength)) + if(!bufOutput.write(itr->buffer, itr->buffer_length)) return nullptr; } else { - if(itr->iType != iTokenType) + if(itr->type != iTokenType) { - if(!bufOutput.write(iTokenType = itr->iType)) + if(!bufOutput.write(iTokenType = itr->type)) return nullptr; } - if(!bufOutput.write(itr->iData)) + if(!bufOutput.write(itr->data)) return nullptr; - if(itr->pBuffer) + if(itr->buffer) { - if(!bufOutput.write(itr->pBuffer, 1)) + if(!bufOutput.write(itr->buffer, 1)) return nullptr; } } @@ -404,9 +404,9 @@ uint32_t iLength = static_cast(bufOutput.tell() - 22); bufOutput.seek(18); - bufOutput.writeBigEndianUInt32(iLength); + bufOutput.write_big_endian_uint32(iLength); - return bufOutput.takeData(pMidLength); + return bufOutput.take_data(midi_length); } #endif diff -Nru corsix-th-0.61/CorsixTH/Src/xmi2mid.h corsix-th-0.62/CorsixTH/Src/xmi2mid.h --- corsix-th-0.61/CorsixTH/Src/xmi2mid.h 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/Src/xmi2mid.h 2018-07-21 11:13:17.000000000 +0000 @@ -25,13 +25,13 @@ #include "config.h" #ifdef CORSIX_TH_USE_SDL_MIXER -uint8_t* TranscodeXmiToMid(const unsigned char* pXmiData, - size_t iXmiLength, size_t* pMidLength); +uint8_t* transcode_xmi_to_midi(const unsigned char* xmi_data, + size_t xmi_length, size_t* midi_length); #else // CORSIX_TH_USE_SDL_MIXER -inline uint8_t* TranscodeXmiToMid(const unsigned char* pXmiData, - size_t iXmiLength, size_t* pMidLength) +inline uint8_t* transcode_xmi_to_midi(const unsigned char* xmi_data, + size_t xmi_length, size_t* midi_length) { // When SDL_mixer isn't being used, there is no need to transocde XMI to // MIDI, so the function always fails. diff -Nru corsix-th-0.61/CorsixTH/SrcUnshared/main.cpp corsix-th-0.62/CorsixTH/SrcUnshared/main.cpp --- corsix-th-0.61/CorsixTH/SrcUnshared/main.cpp 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/CorsixTH/SrcUnshared/main.cpp 2018-07-21 11:13:17.000000000 +0000 @@ -39,7 +39,7 @@ result = 1, }; }; -static void cleanup() +static void cleanup(lua_State* L) { #ifdef CORSIX_TH_USE_SDL_MIXER while(Mix_QuerySpec(nullptr, nullptr, nullptr)) @@ -48,14 +48,16 @@ } #endif SDL_Quit(); + + lua_close(L); } //! Program entry point /*! - Prepares a Lua state for, and catches errors from, CorsixTH_lua_main(). By + Prepares a Lua state for, and catches errors from, lua_main(). By executing in Lua mode as soon as possible, errors can be nicely caught sooner, hence this function does as little as possible and leaves the rest - for CorsixTH_lua_main(). + for lua_main(). */ int main(int argc, char** argv) { @@ -82,11 +84,11 @@ "Cannot open Lua state.\n"); return 0; } - lua_atpanic(L, CorsixTH_lua_panic); + lua_atpanic(L, lua_panic); luaL_openlibs(L); lua_settop(L, 0); - lua_pushcfunction(L, CorsixTH_lua_stacktrace); - lua_pushcfunction(L, CorsixTH_lua_main); + lua_pushcfunction(L, lua_stacktrace); + lua_pushcfunction(L, lua_main); // Move command line parameters onto the Lua stack lua_checkstack(L, argc); @@ -107,7 +109,7 @@ fprintf(stderr, "An error has occurred in CorsixTH:\n" "Uncaught non-string Lua error\n"); } - lua_pushcfunction(L, Bootstrap_lua_error_report); + lua_pushcfunction(L, bootstrap_lua_error_report); lua_insert(L, -2); if(lua_pcall(L, 1, 0, 0) != 0) { @@ -118,7 +120,7 @@ lua_getfield(L, LUA_REGISTRYINDEX, "_RESTART"); bRun = lua_toboolean(L, -1) != 0; - cleanup(); + cleanup(L); if(bRun) { diff -Nru corsix-th-0.61/debian/changelog corsix-th-0.62/debian/changelog --- corsix-th-0.61/debian/changelog 2018-01-11 22:42:02.000000000 +0000 +++ corsix-th-0.62/debian/changelog 2018-08-13 13:59:23.000000000 +0000 @@ -1,3 +1,25 @@ +corsix-th (0.62-1) unstable; urgency=medium + + [ Phil Morrell ] + * add gbp.conf + * add contrib disclaimer + * lintian testsuite fix, bump metadata + * allow more variety in signature files + * fix dh_auto_test nocheck indentation #902392 + * add more verbose flags for S-V 4.2 + * remove obsolete packaging + * convert manpage to markdown, build with pandoc + + [ Sebastian Ramacher ] + * New upstream version 0.62 + * debian/: Make cmake install files in correct location. + * debian/copyright: Update copyright info + * debian/control: + - Recommend timidity. (Closes: #904838) + - Update ffmpeg Build-Depends according to build system. + + -- Phil Morrell Mon, 13 Aug 2018 14:59:23 +0100 + corsix-th (0.61-1) unstable; urgency=medium [ Alexandre Detiste ] diff -Nru corsix-th-0.61/debian/compat corsix-th-0.62/debian/compat --- corsix-th-0.61/debian/compat 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/compat 2018-08-13 01:26:00.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru corsix-th-0.61/debian/control corsix-th-0.62/debian/control --- corsix-th-0.61/debian/control 2018-01-11 22:15:13.000000000 +0000 +++ corsix-th-0.62/debian/control 2018-08-13 12:38:33.000000000 +0000 @@ -1,22 +1,26 @@ Source: corsix-th Section: contrib/games Priority: optional -Maintainer: Debian Games Team +Maintainer: Debian Games Team Uploaders: Alexandre Detiste , Phil Morrell , Build-Depends: cmake, - debhelper (>= 10), + debhelper (>= 11), imagemagick, - libavdevice-dev (>= 7:2.8), + libavcodec-dev (>= 7:2.8), + libavformat-dev (>= 7:2.8), libfreetype6-dev, liblua5.2-dev, libsdl2-dev, libsdl2-mixer-dev, + libswresample-dev (>= 7:2.8), + libswscale-dev (>= 7:2.8), lua-busted, lua5.2, -Standards-Version: 4.1.1 + pandoc, +Standards-Version: 4.2.0 Homepage: http://corsixth.com Vcs-Git: https://salsa.debian.org/games-team/corsix-th.git Vcs-Browser: https://salsa.debian.org/games-team/corsix-th @@ -31,6 +35,7 @@ ${shlibs:Depends}, Recommends: theme-hospital-data | theme-hospital-demo-data | game-data-packager, + timidity, Description: Open source clone of Theme Hospital Theme Hospital was a simulation computer game developed by Bullfrog Productions and published by Electronic Arts in 1997, in which the player @@ -42,6 +47,7 @@ Package: corsix-th-data Architecture: all +Multi-Arch: foreign Depends: ${misc:Depends}, Description: Open source clone of Theme Hospital (data package) diff -Nru corsix-th-0.61/debian/copyright corsix-th-0.62/debian/copyright --- corsix-th-0.61/debian/copyright 2018-01-11 22:04:56.000000000 +0000 +++ corsix-th-0.62/debian/copyright 2018-08-13 01:26:00.000000000 +0000 @@ -1,62 +1,67 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: CorsixTH +Upstream-Contact: Stephen E. Baker Source: https://github.com/CorsixTH/CorsixTH +Disclaimer: This package is not part of Debian due to lack of Free assets. It + is only possible to run the free engine with the original proprietary assets. +License: Expat Files: * Copyright: © 2009-2016 Peter "Corsix" Cawley © 2009-2016 Edvin "Lego3" Linge, - © 2009-2014 Nicolas "MeV" Elie © 2009-2013 Manuel "Roujin" Wolf + © 2009-2012,2014 Nicolas "MeV" Elie + © 2009 Haico "brainball" van Roeden © 2009-2012 Darrel "redneon" Blake © 2009 Manuel König - © 2009 Haico "brainball" van Roeden - © 2010-2016 Erlend Mongstad - © 2010-2011 Ole "Froksen" Frandsen - © 2010 Wendell Misiedjan + © 2010 M.Chalon © 2010 Sjors Gielen © 2010 Sam Wong + © 2010 Edwin "Dutchy" Smulders + © 2010 Miika-Petteri Matikainen + © 2010-2016 Erlend Mongstad + © 2010-2011 Ole "Froksen" Frandsen © 2010 Robin "RobseRob" Madsen © 2010 RAS - © 2010 Miika-Petteri Matikainen - © 2010 M.Chalon - © 2010 Justin Pasher © 2010 Jukka Kauppinen - © 2010 Edwin "Dutchy" Smulders © 2010 "Fabiomsouto" + © 2010 Justin Pasher + © 2010 Wendell Misiedjan + © 2011 David "ChronosHD" Horváth + © 2011 Adam Kirk + © 2011 Ted "IntelOrca" John + © 2011 Chris James + © 2011 John Pirie + © 2011-2015 Mark Lawlor © 2011-2016 William "Sadger" Gatens © 2011-2017 Ola "Grimdoc" Skogrand - © 2011-2015 Mark Lawlor © 2011-2015 Jørgen P. Tjernø © 2011-2012 Zbyněk "teh dude :D" Schwarz + © 2011 Rene "Kleeze" Bergfort © 2011-2012 Sérgio "Get_It" Ribeiro - © 2011 Ted "IntelOrca" John © 2011 Sergei Larionov - © 2011 Rene "Kleeze" Bergfort - © 2011 John Pirie - © 2011 David "ChronosHD" Horváth - © 2011 Chris James © 2011 Alexey Pinyagin - © 2011 Adam Kirk - © 2012-2017 Stephen "TheCycoONE" Baker - © 2012-2013 Ryan Hugh Dean + © 2012-2018 Stephen "TheCycoONE" Baker + © 2012 Alex Ghiran © 2012-2013 Luis "Driver" Duarte - © 2012 lwglwsss + © 2012-2013 Ryan Hugh Dean © 2012 Henrique Poyatos - © 2012 Alex Ghiran - © 2013-2017 Albert "Alberth" Hofkamp - © 2013-2015 Maarten Peters - © 2013-2014 Alan Woolley - © 2013 nullstein - © 2013 YoungSeok Yoon + © 2012 lwglwsss © 2013 Koanxd aka Snowblind © 2013 Chris "ChrizmanTV" Wilkinson + © 2013-2014 Alan Woolley + © 2013 YoungSeok Yoon + © 2013-2015 Maarten Peters + © 2013 nullstein © 2013 BuTcHeR (extragry.pl) + © 2013-2017 Albert "Alberth" Hofkamp © 2014-2015 Joseph "J-Shep" Sheppard © 2014 Phillipp Röll © 2014 Leonardo "LeonardoGamer" Malaman © 2015 Víctor "mccunyao" González © 2015 Josh Keegan - © 2016 Toby Lane + © 2016,2018 Toby Lane © 2016 Phil Morrell © 2017 Arne Zelasko © 2017 Víctor "IlDucci" @@ -65,8 +70,9 @@ © 2017 Steven Price © 2017 Radomir Wojtera © 2017 David Fairbrother - © 2017 Altieres Lima - © 2017 Justin "mugmuggy" Mugford + © 2017-2018 Altieres Lima + © 2017-2018 Justin "mugmuggy" Mugford + © 2018 Pavel Schoffer License: Expat Files: debian/* @@ -77,36 +83,15 @@ License: Expat Files: - AnimView/rnc.cpp + common/rnc.cpp Copyright: 2009 Jon Skeet, Simon Tatham 2011 Edvin "Lego3" Linge License: Expat -Files: - AnimView/tinyxml.cpp - AnimView/tinyxmlerror.cpp - AnimView/tinyxml.h - AnimView/tinyxmlparser.cpp -Copyright: 2000-2007, Lee Thomason - 2002-2004, Yves Berquin -License: zlib - -Files: - AnimView/tinystr.cpp - AnimView/tinystr.h -Copyright: 2000-2007, Lee Thomason - 2002-2004, Yves Berquin - 2005, Tyge Lovset -License: zlib - Files: CMake/CMakeFFmpegLibavMacros.cmake Copyright: cmake project License: BSD-3-Clause -Files: CMake/FindDirectX.cmake -Copyright: ogre3d.org -License: Public-Domain - Files: CMake/FindFFmpeg.cmake CMake/FindLibAV.cmake Copyright: @@ -117,17 +102,6 @@ © 2015, Alexander Bessman License: BSD-3-Clause -Files: CMake/FindLua.cmake -Copyright: - © 2013 Martin Felis - © 2013 Edvin "Lego3" Linge - © 2015 Stephen E. Baker -License: Public-Domain - -Files: CMake/FindPkgMacros.cmake -Copyright: ogre3d.org -License: Public-Domain - Files: CMake/FindSDL2.cmake CMake/FindSDL2_mixer.cmake Copyright: @@ -229,10 +203,6 @@ Copyright: © 2010 Manuel "Roujin" Wolf, Edvin "Lego3" Linge License: BSD-3-Clause -Files: CorsixTH/Src/jit_opt.h -Copyright: © 2005-2008 Mike Pall -License: Expat - Files: CorsixTH/Src/random.c Copyright: © 1997-2002 Makoto Matsumoto and Takuji Nishimura diff -Nru corsix-th-0.61/debian/corsix-th.6 corsix-th-0.62/debian/corsix-th.6 --- corsix-th-0.61/debian/corsix-th.6 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/corsix-th.6 2018-08-13 13:01:25.000000000 +0000 @@ -1,59 +1,61 @@ -.TH corsix-th 6 2017-11-29 +.\" Automatically generated by Pandoc 1.17.2 +.\" +.TH "corsix\-th" "6" "2018\-08\-13" "" "Games Manual" +.hy .SH NAME +.PP corsix\-th \- A Theme Hospital engine reimplementation. -. .SH SYNOPSIS -.B corsix\-th -.RB [\-\-interpreter= -.RI lua file] -.RB [\-\-config\-file -.RI config file] -.RB [\-\-load= -.RI save file] -.RB [\-\-dump=strings] +.PP +\f[B]corsix\-th\f[] [\-\-interpreter=\f[I]luafile\f[]] [\-\-config\-file +\f[I]configfile\f[]] [\-\-load= \f[I]savefile\f[]] [\-\-dump=strings] .SH DESCRIPTION +.PP Theme Hospital was a simulation computer game developed by Bullfrog -Productions and published by Electronic Arts in 1997, in which the player -designs and operates a hospital. -.br -This project aims to reimplement the game engine -of Theme Hospital, and be able to load the original -game data files. This means that you will need a -purchased copy of Theme Hospital, or a copy of the -demo, in order to use CorsixTH. -.br -On Debian systems these data files can be -packaged with -.I game\-data\-packager -. +Productions and published by Electronic Arts in 1997, in which the +player designs and operates a hospital. +.PP +This project aims to reimplement the game engine of Theme Hospital, and +be able to load the original game data files. +This means that you will need a purchased copy of Theme Hospital, or a +copy of the demo, in order to use CorsixTH. +.PP +On Debian systems these data files can be packaged with +\f[I]game\-data\-packager\f[] .SH OPTIONS -This is a list of the options accepted by -.B corsix\-th +.PP +This is a list of the options accepted by \f[B]corsix\-th\f[] .TP -.B \-\-interpreter= -.RI lua file -Specify an alternative file to use as the main interpreter (bootstrap code) +.B \-\-interpreter=\f[I]luafile\f[] +Specify an alternative file to use as the main interpreter (bootstrap +code) +.RS +.RE .TP -.B \-\-config\-file -.RI config file +.B \-\-config\-file \f[I]configfile\f[] Use an alternative configuration file +.RS +.RE .TP -.B \-\-load= -.RI save file -If specified, loads the given save file immediately on start-up +.B \-\-load=\f[I]savefile\f[] +If specified, loads the given save file immediately on start\-up +.RS +.RE .TP .B \-\-dump=strings Turns on debugging mode +.RS +.RE .SH FILES -The save files are stored in -.I ~/.config/CorsixTH/Saves/ -. +.PP +The save files are stored in \f[I]~/.config/CorsixTH/Saves/\f[] .SH SEE ALSO -\fIgame\-data\-packager\fP(6) +.PP +\f[I]game\-data\-packager\f[](6) .SH AUTHOR +.PP CorsixTH was written by Peter "Corsix" Cawley et al. .PP -Copyright \(co 2012 Chris Butler \fI\fP -Copyright \(co 2015 Alexandre Detiste \fI\fP -This man page was written for the Debian project, -but may be used by others. +Copyright © 2012 Chris Butler \f[I]\f[] Copyright © +2015 Alexandre Detiste \f[I]\f[] This man page was +written for the Debian project, but may be used by others. diff -Nru corsix-th-0.61/debian/corsix-th.6.md corsix-th-0.62/debian/corsix-th.6.md --- corsix-th-0.61/debian/corsix-th.6.md 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/debian/corsix-th.6.md 2018-08-13 13:01:14.000000000 +0000 @@ -0,0 +1,56 @@ +% corsix-th(6) | Games Manual +% +% 2018-08-13 + +# NAME + +corsix-th - A Theme Hospital engine reimplementation. + +# SYNOPSIS + +**corsix-th** [--interpreter=*luafile*] [--config-file *configfile*] [--load= *savefile*] [--dump=strings] + +# DESCRIPTION + +Theme Hospital was a simulation computer game developed by Bullfrog +Productions and published by Electronic Arts in 1997, in which the player +designs and operates a hospital. + +This project aims to reimplement the game engine +of Theme Hospital, and be able to load the original +game data files. This means that you will need a +purchased copy of Theme Hospital, or a copy of the +demo, in order to use CorsixTH. + +On Debian systems these data files can be +packaged with *game-data-packager* + +# OPTIONS +This is a list of the options accepted by **corsix-th** + +--interpreter=*luafile* +: Specify an alternative file to use as the main interpreter (bootstrap code) + +--config-file *configfile* +: Use an alternative configuration file + +--load=*savefile* +: If specified, loads the given save file immediately on start-up + +--dump=strings +: Turns on debugging mode + +# FILES +The save files are stored in *~/.config/CorsixTH/Saves/* + +# SEE ALSO +*game-data-packager*(6) + +# AUTHOR + +CorsixTH was written by Peter "Corsix" Cawley et al. + +Copyright © 2012 Chris Butler ** +Copyright © 2015 Alexandre Detiste ** +This man page was written for the Debian project, +but may be used by others. diff -Nru corsix-th-0.61/debian/corsix-th-data.install corsix-th-0.62/debian/corsix-th-data.install --- corsix-th-0.61/debian/corsix-th-data.install 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/debian/corsix-th-data.install 2018-08-13 01:26:00.000000000 +0000 @@ -0,0 +1 @@ +usr/share/games/corsix-th diff -Nru corsix-th-0.61/debian/corsix-th.install corsix-th-0.62/debian/corsix-th.install --- corsix-th-0.61/debian/corsix-th.install 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/corsix-th.install 2018-08-13 01:26:00.000000000 +0000 @@ -1,2 +1,2 @@ debian/corsix-th.desktop usr/share/applications -debian/scripts/corsix-th usr/games +usr/games diff -Nru corsix-th-0.61/debian/corsix-th.links corsix-th-0.62/debian/corsix-th.links --- corsix-th-0.61/debian/corsix-th.links 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/corsix-th.links 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/games/corsix-th/CorsixTH usr/share/games/corsix-th/CorsixTH diff -Nru corsix-th-0.61/debian/gbp.conf corsix-th-0.62/debian/gbp.conf --- corsix-th-0.61/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ corsix-th-0.62/debian/gbp.conf 2018-08-13 01:26:00.000000000 +0000 @@ -0,0 +1,7 @@ +[buildpackage] +pristine-tar = True +pristine-tar-commit = True + +[import-orig] +pristine-tar = True +uscan = True diff -Nru corsix-th-0.61/debian/README.source corsix-th-0.62/debian/README.source --- corsix-th-0.61/debian/README.source 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/README.source 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -There is an embedded copy of tinyxml library in AnimView/ -but the contents of this directory are not used -to build the Debian package. diff -Nru corsix-th-0.61/debian/rules corsix-th-0.62/debian/rules --- corsix-th-0.61/debian/rules 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/rules 2018-08-13 12:35:37.000000000 +0000 @@ -5,30 +5,32 @@ %: dh $@ +override_dh_auto_configure: + dh_auto_configure -- -DCMAKE_INSTALL_BINDIR=/usr/games/ -DCMAKE_INSTALL_DATADIR=/usr/share/games/ + override_dh_auto_install: dh_auto_install - rm debian/tmp/usr/CorsixTH/CorsixTH.ico - rm debian/tmp/usr/CorsixTH/LICENSE.txt - - mkdir -p debian/corsix-th/usr/lib/games/corsix-th/ - mv debian/tmp/usr/CorsixTH/CorsixTH debian/corsix-th/usr/lib/games/corsix-th/ + rm -v debian/tmp/usr/share/games/corsix-th/LICENSE.txt for size in $$(identify ico:CorsixTH/CorsixTH.ico | awk '{print $$3}'); \ do \ - mkdir -p debian/corsix-th/usr/share/icons/hicolor/$$size/apps/ ; \ + mkdir -vp debian/corsix-th/usr/share/icons/hicolor/$$size/apps/ ; \ convert ico:`identify ico:CorsixTH/CorsixTH.ico | sed -n "/ $$size /s/^.*=>\(CorsixTH\/CorsixTH.ico\[[0-9]\+]\) .*/\1/gp"` \ -verbose debian/corsix-th/usr/share/icons/hicolor/$$size/apps/corsix-th.png ; \ done - mkdir -p debian/corsix-th/usr/share/icons/hicolor/scalable/apps/ - install -m0644 CorsixTH/Original_Logo.svg debian/corsix-th/usr/share/icons/hicolor/scalable/apps/corsix-th.svg - - mkdir -p debian/corsix-th-data/usr/share/games/corsix-th/ - mv debian/tmp/usr/CorsixTH/* debian/corsix-th-data/usr/share/games/corsix-th/ + mkdir -vp debian/corsix-th/usr/share/icons/hicolor/scalable/apps/ + install -vm0644 CorsixTH/Original_Logo.svg debian/corsix-th/usr/share/icons/hicolor/scalable/apps/corsix-th.svg override_dh_auto_test: +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) dh_auto_test busted -C CorsixTH/Luatest --verbose +endif + +ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS))) +build: debian/corsix-th.6 +endif -override_dh_installchangelogs: - dh_installchangelogs CorsixTH/changelog.txt +%.6: %.6.md + pandoc --verbose --standalone $< --to man --output $@ diff -Nru corsix-th-0.61/debian/scripts/corsix-th corsix-th-0.62/debian/scripts/corsix-th --- corsix-th-0.61/debian/scripts/corsix-th 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/scripts/corsix-th 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/sh -cd /usr/share/games/corsix-th -exec ./CorsixTH $@ diff -Nru corsix-th-0.61/debian/watch corsix-th-0.62/debian/watch --- corsix-th-0.61/debian/watch 2018-01-11 21:07:38.000000000 +0000 +++ corsix-th-0.62/debian/watch 2018-08-13 01:26:00.000000000 +0000 @@ -1,5 +1,10 @@ version=4 -opts=uversionmangle=s/-/~/,\ -pgpsigurlmangle=s`archive/v@ANY_VERSION@(@ARCHIVE_EXT@)`releases/download/v$1/CorsixTH-$1$2\.asc` \ - https://github.com/CorsixTH/CorsixTH/tags \ + +opts="pgpmode=next,uversionmangle=s/-/~/" \ + https://github.com/CorsixTH/CorsixTH/releases \ (?:.*/)?v?@ANY_VERSION@@ARCHIVE_EXT@ + +opts="pgpmode=previous,uversionmangle=s/-/~/" \ + https://github.com/CorsixTH/CorsixTH/releases \ + (?:.*/)?(?:CorsixTH)?v?@ANY_VERSION@@SIGNATURE_EXT@ \ + previous diff -Nru corsix-th-0.61/DoxyGen/animview.doxygen corsix-th-0.62/DoxyGen/animview.doxygen --- corsix-th-0.61/DoxyGen/animview.doxygen 2017-12-21 01:26:53.000000000 +0000 +++ corsix-th-0.62/DoxyGen/animview.doxygen 1970-01-01 00:00:00.000000000 +0000 @@ -1,2291 +0,0 @@ -# Doxyfile 1.8.6 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "Anim View" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "TH Animation Viewer" - -# With the PROJECT_LOGO tag one can specify an logo or icon that is included in -# the documentation. The maximum height of the logo should not exceed 55 pixels -# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo -# to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = animview - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = NO - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a -# new page for each member. If set to NO, the documentation of a member will be -# part of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. -# -# Note For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO these classes will be included in the various overviews. This option has -# no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the -# todo list. This list is created by putting \todo commands in the -# documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the -# test list. This list is created by putting \test commands in the -# documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES the list -# will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO doxygen will only warn about wrong or incomplete parameter -# documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. -# Note: If this tag is empty the current directory is searched. - -INPUT = ../AnimView/ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER ) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES, then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the stylesheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler ( hhc.exe). If non-empty -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated ( -# YES) or that it should be included in the master .chm file ( NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using prerendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /