pax_global_header00006660000000000000000000000064125760333000014511gustar00rootroot0000000000000052 comment=de2dedd33c7a5400e32df7bdb4a889aa1d1ccbf2 cen64-qt-20150915-alpha/000077500000000000000000000000001257603330000144055ustar00rootroot00000000000000cen64-qt-20150915-alpha/.gitignore000066400000000000000000000000101257603330000163640ustar00rootroot00000000000000*.user* cen64-qt-20150915-alpha/.travis.yml000066400000000000000000000052471257603330000165260ustar00rootroot00000000000000language: cpp sudo: required env: matrix: - BUILD=windows - BUILD=native os: - linux - osx matrix: exclude: - os: osx env: BUILD=windows install: - "./build-scripts/travis-ci.sh setup_qt" - "./build-scripts/travis-ci.sh get_quazip" script: - "./build-scripts/travis-ci.sh build" before_deploy: - "./build-scripts/travis-ci.sh package" deploy: - provider: s3 access_key_id: secure: GsN4LS6DXbwkMlUchj6RX/E/id4g+PTjFYzwATjVuk+Yilipdn/vpGWGLthJpNN9ontgXaTI9+R8vBgAxR6IRmmMHGafYQVBnH0n/RwA9qG4UTV5DEO/Vje2fXUAIxsinHG7jqJewIOAODvfkj4uG+DgUUv9V3BgWUl0whPyoAlkoXlZJ6iCWrCdgQ6RSXKqIJbaIjd1m5AvATXVTkpW2V6Fqk0/uTZDAM7pGVpY3Ddkpo1Xt6djRyz1W9Y9GyxxcUh9ecyeK2TdUoy8bvm43EnCNtLbOqSdkF1zWWU7uguDfYXw5tHtxf5BWbP2H1addGdExLHsFvG88zW0YhxzLWEhKaPQOvTstMZ1QUvP2b5pUVE/VyRF7he2xoG3X8UOHk0KKgO+8BxQo5sydt/91IuyJ9DVZxmHHWvIrOm5PJxF82RfmVxw8lTR5mb8Y9A0cN+KBa7QaLwPo+vLOqREIQh2Vk12aP/9GXwZF0NLv2vusvoosOJ9NsTR6gtMKY8nkbBLTLnxWNm94OEm2dLAL9qc4Gl5InitVEoJA51eK+EVpvdVWnqaC+TSL8482Xly+hYIyBOkBgywkP2FEszonleK/BMu7J+fEmoJz2FtnTumGOszm8hioy/p2eGv8ilgpeIP9yq4CPVBdoucVI4sNeq53VF6jyexhfF/zkkBPOk= secret_access_key: secure: tUdQW5zil2MP3vYQFYEF7Y6bUeADbvr36S8EJdNdAsxu+1dRSdLsUg04qzD8bNb7GN1Ez+b3XiEc5TZx4zRZ44O8I/Sdggcpb5JqUhOJjwQIq3VFBsJll4OIJkt536sSh2S/YpYkIU45npatcHZVrxxqy/Gs4R89tyltwzjy6bMgQjOF8bRaXZnu4Yz8pn7GyVCHAXJ4Y+09su7qZnTjixe9097SgJMAzSLh8aqBIqkT0ULuU8ePaM1xOIwMuq7PjYi/QtDN19yOyGIHt8ceQ1VA16uio1UdOys4PHKY+2a9WMcT344OGLN5pQ5qYLuJYnFrjlnW2fBWfM9CG1Tua+jjiegyLMl7FPxja1V5ML2q/EzZemQkpoy9AiJQUO+8AMACK7osSFUIfx2f+Ppj2sjCXgb0FJtey0kSiATLsHBFx5lAlkGuv2vTM090bOQ6zWoymmIu5O9rnox2fh5PS5XfJ0yB9BVWHBC9p1VYRq17/keOPTDcsdXVd6gkNzdDlDgKEqrwcEltYynWEL/qQqVOFYj5thxpaxG79z5nKnGew87gigr5iHp8/B4OqzzGwMovSYYLmS3ihAycuwzHdUeXoZ+r+PyYjqGvMZURVemqXsz/mXkbH5NdgXOd7Q7ZStvs3X9uzqq7LaCrKiYaGLeVWEY/YB8cvGLWW4uS8gw= bucket: dh4 skip_cleanup: true local_dir: build upload-dir: cen64-qt/latest on: branch: master - provider: releases api_key: secure: QuZh8ZFU3Zxa2EIVujUsPAT0USGQDElDZdsf7DpKF16POJcnL5UwUZnlc4BtiU15yb8AUUsrsIMn14lUYLI9EzYxoUamrNczEnp6k+4IGfsXV9XtKu084MS5rVS6L8hTpizf7qeEy+9qjDw6Du05PM6Olcxq5Us8Ozbecd8ga1PgU3LUgToGT3E/3Sj9TapFg0VrlyxSkrN4eSBbhoU8MQpJ8SjSZtEgQYYwX+c4VX9BqMcSzFO6qHinyq3cME6Z/HIj4m8jsX/tq3NdXhy+QQRg3+O8vMRaL+mbAEPrGUQw79gCv1ZUIRcShKvWPbwZH16wlc21+YCBbsuYJC6Htv2/MQaiN+Dfhx33/AjsRdZ63IKgvDHPMy737U2pdi5i98qPr1npXPo50eWIF5kYB8TgW8w/LHu8dH4fnTBXAO/t4b9vqt/AicmWhcoS0r3K1SoAX75ULHCv0Ruz1ftTuudxtSHHsXkBEyqxHM5up/0Od5r9STW36GeDSTpVyi+3gj6rMbOXIfEHxp5wDZ/L7P6F+es03UpCsg/thTzdNz4UA9WKa9mZt1Ul/WvizSH7fPMN1dNhuUbkcggZb0P96l/Dr8n9yzJ4tIDWsSSc4d+7KscVL/XXORLFiKD1QOirgyBWRd9efeChRDeEgb0Gf8DlbeLZ8wg3BYtUvPLy1Hc= skip_cleanup: true file_glob: true file: build/cen64-qt_* on: tags: true cen64-qt-20150915-alpha/LICENSE000066400000000000000000000027231257603330000154160ustar00rootroot00000000000000Copyright (c) 2013, Dan Hasting All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cen64-qt-20150915-alpha/README.md000066400000000000000000000043401257603330000156650ustar00rootroot00000000000000# CEN64-Qt [![Build Status](https://travis-ci.org/dh4/cen64-qt.svg?branch=master)](https://travis-ci.org/dh4/cen64-qt) A basic cross-platform frontend for CEN64. ![CEN64-Qt Grid View](https://dl.dropboxusercontent.com/u/232085155/cen64-qt/github.jpg) ## Getting CEN64-Qt ### Stable Stable releases can be found on the [releases](https://github.com/dh4/cen64-qt/releases) page. Note these are currently only alpha releases versioned with the date. I don't plan to adopt a version scheme until CEN64 is more stable. ### Development Automatic builds of the latest git commit can be downloaded here: Linux: [cen64-qt_linux_git-latest.tar.gz](https://s3.amazonaws.com/dh4/cen64-qt/latest/cen64-qt_linux_git-latest.tar.gz) Windows: [cen64-qt_win_git-latest.zip](https://s3.amazonaws.com/dh4/cen64-qt/latest/cen64-qt_win_git-latest.zip) OSX: [cen64-qt_osx_git-latest.dmg](https://s3.amazonaws.com/dh4/cen64-qt/latest/cen64-qt_osx_git-latest.dmg) Be aware that these may contain bugs not present in the stable releases. ## Building ### Linux You'll need to make sure you have qmake, g++, the Qt development libraries and the QuaZIP development files installed. On Debian/Ubuntu, this can be accomplished by: ``` # apt-get install qt5-qmake g++ qtbase5-dev libquazip-qt5-dev libqt5sql5-sqlite ``` Once the needed packages are installed, create the Makefile with qmake and then build with make: ``` $ qmake $ make ``` If qmake returns "qmake: could not find a Qt installation of ''", you can try running `QT_SELECT=qt5 qmake` or `/usr/lib/x86_64-linux-gnu/qt5/bin/qmake`. Some distributions also contain a `qmake-qt5` symlink. #### Building with Qt4 Install the Qt4 dependencies instead. On Debian/Ubuntu: ``` # apt-get install qt4-qmake g++ libqt4-dev libquazip-dev libqt4-sql-sqlite ``` Then create the Makefile with qmake and build with make: ``` $ qmake-qt4 $ make ``` #### Compiling QuaZIP statically You also have the option to compile QuaZIP statically. Download the QuaZIP sources from Sourceforge. Place the contents of `quazip-/quazip/` in `quazip/` within the project directory. Then run: ``` $ qmake CONFIG+=linux_quazip_static $ make ``` You will see warnings after the qmake step if the QuaZIP sources are in the wrong place. cen64-qt-20150915-alpha/build-scripts/000077500000000000000000000000001257603330000171715ustar00rootroot00000000000000cen64-qt-20150915-alpha/build-scripts/platform/000077500000000000000000000000001257603330000210155ustar00rootroot00000000000000cen64-qt-20150915-alpha/build-scripts/platform/linux.sh000077500000000000000000000013331257603330000225130ustar00rootroot00000000000000#!/bin/bash [[ -z $WORKING_DIR ]] && WORKING_DIR=$(pwd) [[ -z $VERSION ]] && VERSION=$(git log --oneline -n 1 | awk '{print $1}') case "$1" in 'setup_qt') sudo apt-get update -qq sudo apt-get -y install qt4-qmake libqt4-dev libqt4-sql-sqlite ;; 'get_quazip') wget http://downloads.sourceforge.net/quazip/quazip-0.7.1.tar.gz tar -xvzf quazip-0.7.1.tar.gz > /dev/null mv quazip-0.7.1/quazip . ;; 'build') ./build-scripts/revision.sh qmake-qt4 CONFIG+=linux_quazip_static make ;; 'package') mkdir build mv resources/README.txt . tar -cvzpf build/cen64-qt_linux_$VERSION.tar.gz cen64-qt README.txt ;; esac cen64-qt-20150915-alpha/build-scripts/platform/osx.sh000077500000000000000000000030521257603330000221650ustar00rootroot00000000000000#!/bin/bash [[ -z $WORKING_DIR ]] && WORKING_DIR=$(pwd) [[ -z $VERSION ]] && VERSION=$(git log --oneline -n 1 | awk '{print $1}') case "$1" in 'setup_qt') mkdir $WORKING_DIR/../osx cd $WORKING_DIR/../osx if [[ $BUILD_OSX_QT ]]; then # Build Qt git clone --branch v5.5.0 --depth 1 https://code.qt.io/qt/qtbase.git cd qtbase ./configure -release -static -qt-sql-sqlite -opensource -confirm-license make sub-src else # Fetch pre-build Qt wget https://www.dropbox.com/s/mfw6qwfir62fy9p/macosx-qt5.tar.gz tar -xvzf macosx-qt5.tar.gz >& /dev/null fi cd $WORKING_DIR/cen64-qt ;; 'get_quazip') wget http://downloads.sourceforge.net/quazip/quazip-0.7.1.tar.gz tar -xvzf quazip-0.7.1.tar.gz >& /dev/null mv quazip-0.7.1/quazip . ;; 'build') ./build-scripts/revision.sh $WORKING_DIR/../osx/qtbase/bin/qmake -config release LIBS+="-dead_strip" make ;; 'package') mkdir build hdiutil create -megabytes 20 -fs HFS+ -volname CEN64-Qt cen64-qt_osx_$VERSION hdiutil attach cen64-qt_osx_$VERSION.dmg cp -r CEN64-Qt.app /Volumes/CEN64-Qt/CEN64-Qt.app cp resources/README.txt /Volumes/CEN64-Qt/README.txt hdiutil detach /Volumes/CEN64-Qt hdiutil convert -format UDZO -o cen64-qt_osx_$VERSION.dmg \ -ov cen64-qt_osx_$VERSION.dmg mv cen64-qt_osx_$VERSION.dmg build/ ;; esac cen64-qt-20150915-alpha/build-scripts/platform/windows.sh000077500000000000000000000027441257603330000230550ustar00rootroot00000000000000#!/bin/bash [[ -z $WORKING_DIR ]] && WORKING_DIR=$(pwd) [[ -z $VERSION ]] && VERSION=$(git log --oneline -n 1 | awk '{print $1}') case "$1" in 'setup_qt') cd $WORKING_DIR/../ if [[ $BUILD_MXE_QT ]]; then # Build Qt with mxe sudo apt-get update -qq apt-get install \ autoconf automake autopoint bash bison bzip2 cmake flex \ gettext git g++ gperf intltool libffi-dev libtool \ libltdl-dev libssl-dev libxml-parser-perl make openssl \ p7zip-full patch perl pkg-config python ruby scons sed \ unzip wget xz-utils git clone https://github.com/mxe/mxe.git cd mxe make qtbase else # Fetch pre-built mxe Qt wget https://www.dropbox.com/s/jr6l4lnixizqtln/travis-mxe-qt5.tar.gz tar -xvzf travis-mxe-qt5.tar.gz > /dev/null fi cd $WORKING_DIR/cen64-qt ;; 'get_quazip') wget http://downloads.sourceforge.net/quazip/quazip-0.7.1.tar.gz tar -xvzf quazip-0.7.1.tar.gz > /dev/null mv quazip-0.7.1/quazip . ;; 'build') export PATH=$PATH:$WORKING_DIR/../mxe/usr/bin ./build-scripts/revision.sh i686-w64-mingw32.static-qmake-qt5 make ;; 'package') mkdir build mv release/cen64-qt.exe resources/README.txt . zip build/cen64-qt_win_$VERSION.zip cen64-qt.exe README.txt ;; esac cen64-qt-20150915-alpha/build-scripts/revision.sh000077500000000000000000000005031257603330000213640ustar00rootroot00000000000000#!/bin/bash git log --oneline -n 1 | grep 'Bump version' if [[ $? == 1 ]]; then REVISION=$(git log --oneline -n 1 | awk '{print $1}') sed -i -e "s/Version = \"\([0-9.]*\)\"/Version = \"\1~git:$REVISION\"/g" src/global.h fi cat src/global.h | grep Version | awk '{print $(NF)}' | sed -e 's/[";~]//g' -e 's/:/-/g' cen64-qt-20150915-alpha/build-scripts/travis-ci.sh000077500000000000000000000007041257603330000214320ustar00rootroot00000000000000#!/bin/bash export WORKING_DIR=$HOME/build/dh4 if [[ $1 == 'package' ]]; then VERSION=$(echo $TRAVIS_TAG | sed -e 's/v//g' -e 's/-alpha//g') [[ -z $VERSION ]] && VERSION='git-latest' export VERSION=$VERSION fi case "$TRAVIS_OS_NAME-$BUILD" in 'linux-windows') ./build-scripts/platform/windows.sh $1 ;; 'linux-native') ./build-scripts/platform/linux.sh $1 ;; 'osx-native') ./build-scripts/platform/osx.sh $1 ;; esac cen64-qt-20150915-alpha/cen64-qt.pro000066400000000000000000000030431257603330000164700ustar00rootroot00000000000000QT += core network xml sql lessThan(QT_MAJOR_VERSION, 5) { QT += gui } else { QT += widgets } macx { TARGET = CEN64-Qt } else { TARGET = cen64-qt } TEMPLATE = app macx:ICON = macosx/cen64.icns win32:RC_FILE = windows/icon.rc SOURCES += src/main.cpp \ src/common.cpp \ src/mainwindow.cpp \ src/aboutdialog.cpp \ src/settingsdialog.cpp \ src/treewidgetitem.cpp \ src/clickablewidget.cpp \ src/v64converter.cpp \ src/downloaddialog.cpp \ src/logdialog.cpp \ src/emulatorhandler.cpp \ src/romcollection.cpp \ src/thegamesdbscrapper.cpp HEADERS += src/global.h \ src/common.h \ src/mainwindow.h \ src/aboutdialog.h \ src/settingsdialog.h \ src/treewidgetitem.h \ src/clickablewidget.h \ src/v64converter.h \ src/downloaddialog.h \ src/logdialog.h \ src/emulatorhandler.h \ src/romcollection.h \ src/thegamesdbscrapper.h RESOURCES += resources/cen64qt.qrc FORMS += src/settingsdialog.ui win32|macx|linux_quazip_static { CONFIG += staticlib DEFINES += QUAZIP_STATIC #Download quazip source and copy the quazip directory to project SOURCES += quazip/*.cpp SOURCES += quazip/*.c HEADERS += quazip/*.h } else { lessThan(QT_MAJOR_VERSION, 5) { LIBS += -lquazip } else { # Debian distributions use a different library name for Qt5 quazip system("uname -a | grep -E 'Debian|Ubuntu' > /dev/null") { LIBS += -lquazip-qt5 } else { LIBS += -lquazip5 } } } cen64-qt-20150915-alpha/macosx/000077500000000000000000000000001257603330000156775ustar00rootroot00000000000000cen64-qt-20150915-alpha/macosx/cen64.icns000066400000000000000000000640301257603330000174770ustar00rootroot00000000000000icnshTOC 8is32s8mkil32l8mkit32t8mk@is32]8% FlISY?-flNS( *63W4/@G>.$ :4>E'2(E'$$   ]S&8  cXwSByk7.A>p>6Q[H.$;0@H'/(E(##    C+/'9!5)+=. 8 %*)<+*011 .$ 98;A&!6(E%   s8mkg#'J  zgҸ onWr3†b␄}Yr"B/xxÍSgt~<Խً?FfYh(OAL>  il32  ES+7# nOS;[I HvHUF]R ggRZ|XlXqH<v Y}<]u ]2hK5Nt;= D('*K&5\ 7[*J;?A>>4JS",/,Q@+)"%3)-*#( <E15IE=AFC@)'*K&5\ 9\(H9<><;1LT",/,Q@+)!&3*.+* <E*f<55YE?/).:L !<3("+0!,b,#$:,28B0JHA6:MH=I%$*!!)-C# !"#%B''90*.55 G''*K&5\ 5[,M>CCAA7HQ",/,Q@+)"%2(+('<E!"#&'(^  !"##"!Wj$())'&%$"!  !"%%&(%W2W/121122&"4784qǂ.=<;:9M{;?V~YT=x y{3 0{#y?>>D443;210/.--.,6h* Aq_E8ny}"## 3n.3|#$$*"! "\3 K 8pu&( |N&òie waKIHGFDHEfA~%2Df( ` - \Df yŔuſxDfY^:"iDf}x BDfvav6 C!h{Q&.$O.RkA &?; N ᷾ĩ -q$!ſ̀%˼ؽJ'Ӻ鳯_¿\ۺO '*>Ėoi aܾⷾăgy!ⶼ>MmnoYuĹ ҽÊƹAHՆռ ɹو~¾҇ھ=E ȹXΆb ĻJDžl տ} |پ۴└Kq̗uv|}wsȻ`*zxxz v2S'^ΦriWY99:;YYs}λX%N& RpQ v69 G]Ā ʺ\@ wE ;b K3>!"#&'(^  !"##"!Wj$())'&%$"!  !"%%&(%W2W/121122&"4784qǂ.=<;:9M{;?V~YT=x y{3 0{#y?>>D443;210/.--.,6h* Aq_E8ny}"## 3n.3|#$$*"! "\3 K 8pu&( |N&òie waKIHGFDHEfA~%2Df( ` - \Df yŔuſxDfY^:"iDf}x BDfvav6 C!h{Q&.$O.RkA &%va75_fepQ Z\eche(03KSE740=С\(2,B\ ~/33774>E =MLBG*: N0104533~|yvchq<$#mlCVV0S E/0/130.*'$"iA&,;w}NH} e+,+)+)'$"  e ]q(78pӾ8qIw! ;Hgiia'+2v{zwwvtsqplg1I48`LS*h$QRU^?"&'I/F;>Z=sx7C' ;!#!ey9Spd;v4uB*-Y * ^N  3KnX5xasF* w xc`abdefgfwB}fa]xtJQ20S w$&/TC:'i|{~{{ōdK05qrL*zxxz v2S'a~cTB>IeppcQGG=:03!"%"32BINPbcF4-CHQfT%N& RpQ v69 :dsldZRJ OX_kq_3 wE ;b K 3>!"#&'(^  !"##"!Wj$())'&%$"!  !"%%&(%W2W/121122&"4784qǂ.=<;:9M{;?V~YT=x y{3 0{#y?>>D443;210/.--.,6h* Aq_E8ny}"## 3n.3|#$$*"! "\3 K 8pu&( |N&òie waKIHGFDHEfA~%2Df( ` - \Df yŔuſxDfY^:"iDf}x BDfvav6 C!h{Q&.$O.RkA &2W1! JC3l3ܤX΃9 Αo_[ZZZZZZZZZZZZZZZZZZZZZZZZYS=֕ra\ZZZZZZZZZZZZZZZZZZZZZZZZYM./ѓp`[ZZ]]ZZZ[byB Sn2 @u7 rr>0&#)@MMA*$&)*Ci{)0 2ZJ9UI3/O+M VF)Sv <6>^ :x  J . 7 z.;D>`""KQ 2 : i+11-5 +3*S A I$υ; +T mx} $E[`aaaaaaaaaaaaaaaaaaaaa_Q2+T 8S 4_ +T ғ}zzzzzzzzzzzzzzzzzzzzzzzzzzvכ}zzzzzzzzzzzzzzzzzzzzyyyyyzC+T R@F%+T *V+S (=&{ )O 35 /k wX> )k\ 'gԌ> 5זE{e 2K]deeeeeeeeeeeeeeeeeeeeeeeeeee]E0J\deeeeeeeeeeeeeeeeeeeeeeeeeecV6-NU8AVH#      icnV C cen64-qt-20150915-alpha/resources/000077500000000000000000000000001257603330000164175ustar00rootroot00000000000000cen64-qt-20150915-alpha/resources/README.txt000066400000000000000000000003211257603330000201110ustar00rootroot00000000000000Github Repository: https://www.github.com/dh4/cen64-qt Qt is licensed under the LGPL v2.1: https://www.gnu.org/licenses/lgpl-2.1.html Qt's source code can be viewed here: https://qt.gitorious.org/qt cen64-qt-20150915-alpha/resources/cen64-qt.desktop000077500000000000000000000003621257603330000213570ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Type=Application Name=CEN64-Qt GenericName=CEN64 Frontend Comment=A basic cross-platform frontend for CEN64 Exec=cen64-qt Icon=cen64-qt Terminal=false Categories=Game;Emulator; Keywords=emulator;cen64;Nintendo;64; cen64-qt-20150915-alpha/resources/cen64qt.qrc000066400000000000000000000003241257603330000204110ustar00rootroot00000000000000 images/cen64.png other/LICENSE images/not-found.png images/no-cart.png cen64-qt-20150915-alpha/resources/images/000077500000000000000000000000001257603330000176645ustar00rootroot00000000000000cen64-qt-20150915-alpha/resources/images/cen64.png000066400000000000000000000157221257603330000213200ustar00rootroot00000000000000PNG  IHDR>abKGD pHYs.#.#x?vtIME : hdB_IDATxyxUV: Y {Xȸ##0ʋیqAQQtuAQA@qP|ǑUM$,fIwꪺGW&)'~nS"|lyz&I9|@YYƮ]X%J/<)IQ]~-^21] ]W>ՁPE!lU/$0K&RgYYHw9' pl(lI &s,ەii} X($1轻_Rmʩ"&mm=$#An1wda% @N 'O$JPBKsXh_h8vrŖ2dI݇oZ `+h{= "৲:T9{tgߍFڷL'r^+#J*91{̻ Vʛ?TգT30z@6(5A2Biҟߓ5y sm$m4{V2: #wh'Fv!^%Aj{by-pc @1Mjd(?,e~4|ڽ[~*_/ MLΚ%Y%ouHoH)lr\^Z\Psp}p⦲o͍0fMQ+?<f4ʘWp @`Ͳ R`+KK`(巫c_"sƠ3U U$i`1Mb[:M}4=3gOK 8GI!L{~d۷SVɊQ?? u9nյ% }xՉ?; jAW+g4FqI 8A"#8T1FtHP8tP5A]CPӡU ݇shL@%IxmCbBrWÿ:5E [NvgY]/]V)KyU$F+ xPXyE5Fg"ZWjk%q):ӑ־)"wfM4Hh&ECњhMj L2A=`1 &dּ98%k?Ho xj)֕OWIUa,Rr_M @2Abh[SȜqzL22N;SB9P_EuU0ȈQ?RIEiuU׸8#sr10 dM:޷Ej^dhTUM9i(k /-<__lY7ۦy=;ťTWq'+w}35Czâ] ڥwۇ}/˖Nd HVُ0K|{p2,r%8[2ңB$**РW+I2A" =1oLy5;к@sY{pw+^]Pu1lp4b-!.)m;= p~L\BKOإ>}4[.LLu$K]F3=4Z Ͻ (d#jAM)\5;pp7,ۧzMӡMc pPJ `of~k%HNDFBotsZG*1Y#&q§p%GKbl a]umurP&(zڂzM)PZ]G`Gp҈3*ϱU+Z]j \gt~kUE5zj :c} Hh%. BDNrn=QGIo]xh۷r:/Z[)4T!P掆"x.);UZ2<-]5Uj4֞Bo?ua9[ P|E}9W cDOQQYσ?׍>6f,?Qr AWW6KW۰zK+tl6Iao<.IW[׈@Rf14|!@4FBH!hDι%nƒΏ' ~<:9'\i7.K @*wAa(n8rmwԿ,#^+}owЊSF~! ՈhX\3'%CF@OԬovЉ$Qn/^5vS;Fwڗr*_~-33-[\ 9ox.qlӧo,..&8]u8gXKznRFTp>Nr*S`,ӏUJ!Yl@IC’9L3gj01:ӡk:Ԡ3HZse{ѫUts)%n,@6WWP[D*wd?vU8?fIUUDE,lR £,˭vl^1z ٸq]۶mdǻo~_~~QcW9C\{ӭiة(AS-5D#֚ 𸽨Q6+,IH͈-A]>: ak4#yJB{oy2c4*w{nn~31fdeeӗ̜9%"s)]nݵ֭%KJt^0.:F+M6ma&amrǍ1b$Inݺ~ڢwd^.W{f*R#*"HO>KW]uU#[m6[ɓ'IK7n=zW圗`!Ǫ#OHIIa.'|Xqs',akVG*رc$EvFll,WU5wf,(/@ n7;;{o]]%RYii+V0duVOXH/7XlEz iҥfEMн{I&p~ _{o6v999ݻ*¤)1#V:t Ǔ6{ر+|d~*Yu^d>L^zOqqc @!Cfjtn/4& +1ȃ>~%77Hv;dw=zv<9.\ @1/n? sڣGς y w#>>~a#eXHEE[ou+!9\[Ӵ[n5\... oΜ9o.^8}UQQQcϟ?瞻_~oq_.+Tdȑ7Xw>{y{SSS;9rƍG]dɒq/dff~X-[l @AM&^{o˩jkkOe_J6m4?"??l_CRRҟ>ecƌy" l)c .\p¤I21qg'LPPPf\KC tԩm`7eYgر=W_ܹs2eʳC )h^˖- }.**".- W05\^H555.SRcݤ(3tn}GAEE)))O:UcrD*@JJ z,..& ftvAp>eE~,CRRXo=ř(%N3#2J6܅$ˍ$RH .(p:jR4b:tdEQR 9v;f͚0clڵkgee-[`qιp^t鄕+Wf/_|ά1=}VZ55&&&_ԨQ_s\rv=;xz}.-TUb1[Gal0Fc&#|,\.Wtv9V@.Hs0{lɓ[ɷDp$3jT9=}sN]wu>rypMnذ8!k׮z<1x]L(J RDvzt $IƏ9sWrRNshj„ ߖRJ{SLI6ΫȭYs,W>~@zX6tC- "2lذ#- 0X}# |p{zށ5?daa޽{_y|c xԴ%%%_r·*ҼO>6tЁ۶m@ܹs#TWh(aɘ1 +1%~]ԈR/Zhbs0l:^Nz饗 s^#˲sjq8p8Ofs}0sڵlٲeDzGpB{zz{s9y7j,?r6|{Nz)4E8qݻX|'|(99#M[n\.v֍Ϙ1=Ih{w8 \(On)ŋ&,hѢG}oN<)-KY~}q>L^J7@v 5(Z}'^z\N?zP]]P!\=ؼ3g~~7 8KQJ0x|pѐ!C.;v|@^6E`WEIjjH+٭[7,_VJ5Ҋc~c2iӦ  '/d꺮ݷo~,Ko)***҆s.TY|;vl_9?fY:w9hРgTUxGVTTsטBH6mCif/++ݾ}ZJfiKA3H^L[0rWϵ e2`lq-^,yR;Ji c#,2ynPmWjzer 4S4ӕTkg"2L3@v 9w!@ @ @ @ @ @ @ @ @ @ \){go/IENDB`cen64-qt-20150915-alpha/resources/images/no-cart.png000066400000000000000000000060631257603330000217420ustar00rootroot00000000000000PNG  IHDR,MbKGD pHYs  tIME .;6EiTXtCommentCREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 75 t oIDATxb#A8 ޮݽW6GDe?,* @` , X@` ,X@`  X, @` ,X@`  X, @` |>~㱌ʞj%J} wXyXޟR4MT˥m[):Zf31 C!Qry\.2՞W j! nd2Q{|Y~z0swvp(=$Ix:ovv;Ƕlp8=wԭZFvUh+hgYu]\V=ig].HգVEj[EM`՗eYYQ6cYVj[[XtTgq,Y=Nkh:Jb& g^. Pv2 0 C|yyE݊j,˲T~,K @v u]aH[ }fj2~'Xm|~V.q=d PNn|ii!PmKjsteDZ}nE`z=*Ǎk 7hJ=˲,<7Bٶ-׶?0 f4XR]Y锺L&`K݊B]TjZjbض]tYԭ,4A߯BcL. v]W!o"ƼYɥ;eQ"DU0 [Xh(dVWg< MX,*/R0dWU MlNf4MeZ&Xh4M%Jz-7B]. ð%c7B]q\uQԳ,vl-ӉzɲL(k[Vr<y ,AV1 C0E`dYVXEm A`5n\7gGY׼|>W3wӉ7Be)\.K^a2ϥ( . UӨ{-EQ4ΒBe{I`p1X|>KbFEǒ)z0l\B%,K(^\, ׭޲nӋF`As"Q]*,TֵnE穉}iTYtv(2!,Q˥cV$ [+Xx<[ms!, DZr8y_k9Jה^84U8 6NF^'///yjG'I6A`U^Q2U֭LӔt_oZsֺUYXﻮ+H9\.E, ~|up8u3ږ6lL`4U[rG&_as\.F`,ZGt!iv inu cke _yx"˲Ȳ,uz<_ft:htjŧ@HHIpzߟE׋n**MvcUw]vbjlV4  ^-Mx}dYdplg#X:1p88iJOEi>|p" >4u" aX5,,b8հ\. q@ *A *cݚL*XP IeUxQݎVfikm & |[eq{{[oá!X%]z^eW@fyc,/Y!V^ |]eqssSXu+1K3o ^43̻,},,?n…,xv:bXf)MjZ\]]Y]xHӴT5N ݕd,lVm߯n@fې۷Vc,xlb>YVX,Jd͂>~X{_3Lb4@ϱZ,&6PJ$@븻+UzLS/setPixmap(QPixmap(":/images/cen64.png")); QFile licenseFile(":/other/LICENSE"); licenseFile.open(QIODevice::ReadOnly); license = new QPlainTextEdit(licenseFile.readAll(), this); license->setReadOnly(true); licenseFile.close(); QString description = tr("A basic frontend for CEN64 using Qt."); QString copyright = "CEN64 Copyright (c) 2013, Tyler J. Stachecki"; QString cen64 = "CEN64 website"; QString github = "Github repository"; descriptionLabel = new QLabel(description, this); copyrightLabel = new QLabel(copyright, this); cen64Link = new QLabel(cen64, this); githubLink = new QLabel(github, this); cen64Link->setOpenExternalLinks(true); githubLink->setOpenExternalLinks(true); buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this); aboutLayout->addWidget(icon, 0, 0, 4, 1); aboutLayout->addWidget(descriptionLabel, 0, 1); aboutLayout->addWidget(license, 1, 1); aboutLayout->addWidget(copyrightLabel, 2, 1); aboutLayout->addWidget(cen64Link, 3, 1); aboutLayout->addWidget(githubLink, 4, 1); aboutLayout->addWidget(buttonBox, 5, 1); aboutLayout->setColumnStretch(1, 1); aboutLayout->setRowStretch(1, 1); aboutLayout->setColumnMinimumWidth(0, 150); connect(buttonBox, SIGNAL(accepted()), this, SLOT(close())); setLayout(aboutLayout); } cen64-qt-20150915-alpha/src/aboutdialog.h000066400000000000000000000041151257603330000176400ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include #include #include #include #include #include "global.h" class AboutDialog : public QDialog { Q_OBJECT public: explicit AboutDialog(QWidget *parent = 0); private: QDialogButtonBox *buttonBox; QGridLayout *aboutLayout; QLabel *cen64Link; QLabel *copyrightLabel; QLabel *descriptionLabel; QLabel *githubLink; QLabel *icon; QPlainTextEdit *license; }; #endif // ABOUTDIALOG_H cen64-qt-20150915-alpha/src/clickablewidget.cpp000066400000000000000000000036671257603330000210310ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "clickablewidget.h" ClickableWidget::ClickableWidget(QWidget *parent) : QWidget(parent) { } void ClickableWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) emit singleClicked(this); } void ClickableWidget::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) emit doubleClicked(this); } cen64-qt-20150915-alpha/src/clickablewidget.h000066400000000000000000000037561257603330000204750ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef CLICKABLEWIDGET_H #define CLICKABLEWIDGET_H #include #include class ClickableWidget : public QWidget { Q_OBJECT public: explicit ClickableWidget(QWidget *parent = 0); protected: void mousePressEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); signals: void singleClicked(QWidget *current); void doubleClicked(QWidget *current); }; #endif // CLICKABLEWIDGET_H cen64-qt-20150915-alpha/src/common.cpp000066400000000000000000000250771257603330000172030ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "common.h" QByteArray byteswap(QByteArray romData) { QByteArray flipped; if (romData.left(4).toHex() == "37804012") { for (int i = 0; i < romData.length(); i += 2) { flipped.append(romData[i + 1]); flipped.append(romData[i]); } return flipped; } else { return romData; } } QString getDataLocation() { QString dataDir; #ifdef Q_OS_WIN dataDir = QCoreApplication::applicationDirPath(); #else #if QT_VERSION >= 0x050000 dataDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) .replace("CEN64/CEN64-Qt","cen64-qt"); #else dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation) .remove("data/").replace("CEN64/CEN64-Qt","cen64-qt"); #endif #endif QDir data(dataDir); if (!data.exists()) data.mkpath(dataDir); return dataDir; } QColor getColor(QString color, int transparency) { if (transparency <= 255) { if (color == "Black") return QColor(0, 0, 0, transparency); else if (color == "White") return QColor(255, 255, 255, transparency); else if (color == "Light Gray") return QColor(200, 200, 200, transparency); else if (color == "Dark Gray") return QColor(50, 50, 59, transparency); else if (color == "Green") return QColor(0, 255, 0, transparency); else if (color == "Cyan") return QColor(30, 175, 255, transparency); else if (color == "Blue") return QColor(0, 0, 255, transparency); else if (color == "Purple") return QColor(128, 0, 128, transparency); else if (color == "Red") return QColor(255, 0, 0, transparency); else if (color == "Pink") return QColor(246, 96, 171, transparency); else if (color == "Orange") return QColor(255, 165, 0, transparency); else if (color == "Yellow") return QColor(255, 255, 0, transparency); else if (color == "Brown") return QColor(127, 70, 44, transparency); } return QColor(0, 0, 0, 255); } int getDefaultWidth(QString id, int imageWidth) { if (id == "Overview") return 400; else if (id == "GoodName" || id.left(8) == "Filename" || id == "Game Title") return 300; else if (id == "MD5") return 250; else if (id == "Internal Name" || id == "Publisher" || id == "Developer") return 200; else if (id == "ESRB" || id == "Genre") return 150; else if (id == "Save Type" || id == "Release Date") return 100; else if (id == "CRC1" || id == "CRC2") return 90; else if (id == "Size" || id == "Rumble" || id == "Players" || id == "Rating") return 75; else if (id == "Game Cover") return imageWidth; else return 100; } int getGridSize(QString which) { QString size = SETTINGS.value("Grid/imagesize","Medium").toString(); if (which == "height") { if (SETTINGS.value("Grid/label", "true").toString() == "true") { if (size == "Extra Small") return 65; if (size == "Small") return 90; if (size == "Medium") return 145; if (size == "Large") return 190; if (size == "Extra Large") return 250; } else { if (size == "Extra Small") return 47; if (size == "Small") return 71; if (size == "Medium") return 122; if (size == "Large") return 172; if (size == "Extra Large") return 224; } } else if (which == "width") { if (size == "Extra Small") return 60; if (size == "Small") return 90; if (size == "Medium") return 160; if (size == "Large") return 225; if (size == "Extra Large") return 300; } else if (which == "font") { if (size == "Extra Small") return 5; if (size == "Small") return 7; if (size == "Medium") return 10; if (size == "Large") return 12; if (size == "Extra Large") return 13; } return 0; } QSize getImageSize(QString view) { QString size = SETTINGS.value(view+"/imagesize","Medium").toString(); if (view == "Table") { if (size == "Extra Small") return QSize(33, 24); if (size == "Small") return QSize(48, 35); if (size == "Medium") return QSize(69, 50); if (size == "Large") return QSize(103, 75); if (size == "Extra Large") return QSize(138, 100); } else if (view == "Grid" || view == "List") { if (size == "Extra Small") return QSize(48, 35); if (size == "Small") return QSize(69, 50); if (size == "Medium") return QSize(138, 100); if (size == "Large") return QSize(203, 150); if (size == "Extra Large") return QSize(276, 200); } return QSize(); } QString getRomInfo(QString identifier, const Rom *rom, bool removeWarn, bool sort) { QString text = ""; if (identifier == "GoodName") text = rom->goodName; else if (identifier == "Filename") text = rom->baseName; else if (identifier == "Filename (extension)") text = rom->fileName; else if (identifier == "Zip File") text = rom->zipFile; else if (identifier == "Internal Name") text = rom->internalName; else if (identifier == "Size") text = rom->size; else if (identifier == "MD5") text = rom->romMD5.toLower(); else if (identifier == "CRC1") text = rom->CRC1.toLower(); else if (identifier == "CRC2") text = rom->CRC2.toLower(); else if (identifier == "Players") text = rom->players; else if (identifier == "Rumble") text = rom->rumble; else if (identifier == "Save Type") text = rom->saveType; else if (identifier == "Game Title") text = rom->gameTitle; else if (identifier == "Release Date") text = rom->releaseDate; else if (identifier == "Overview") text = rom->overview; else if (identifier == "ESRB") text = rom->esrb; else if (identifier == "Genre") text = rom->genre; else if (identifier == "Publisher") text = rom->publisher; else if (identifier == "Developer") text = rom->developer; else if (identifier == "Rating") text = rom->rating; if (!removeWarn) return text; else if (text == "Unknown ROM" || text == "Requires catalog file" || text == "Not found") { if (sort) return "ZZZ"; //Sort warnings at the end else return ""; } else return text; } QGraphicsDropShadowEffect *getShadow(bool active) { QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; if (active) { shadow->setBlurRadius(25.0); shadow->setColor(getColor(SETTINGS.value("Grid/activecolor","Cyan").toString(), 255)); shadow->setOffset(0); } else { shadow->setBlurRadius(10.0); shadow->setColor(getColor(SETTINGS.value("Grid/inactivecolor","Black").toString(), 200)); shadow->setOffset(0); } return shadow; } QStringList getZippedFiles(QString completeFileName) { QuaZip zipFile(completeFileName); zipFile.open(QuaZip::mdUnzip); QStringList files = zipFile.getFileNameList(); zipFile.close(); return files; } QByteArray *getZippedRom(QString romFileName, QString zipFile) { QuaZipFile zippedFile(zipFile, romFileName); zippedFile.open(QIODevice::ReadOnly); QByteArray *romData = new QByteArray(); romData->append(zippedFile.readAll()); zippedFile.close(); return romData; } bool romSorter(const Rom &firstRom, const Rom &lastRom) { QString sort, direction; QString layout = SETTINGS.value("View/layout", "None").toString(); if (layout == "Grid View") { sort = SETTINGS.value("Grid/sort", "Filename").toString(); direction = SETTINGS.value("Grid/sortdirection", "ascending").toString(); } else if (layout == "List View") { sort = SETTINGS.value("List/sort", "Filename").toString(); direction = SETTINGS.value("List/sortdirection", "ascending").toString(); } else //just return sort by filename return firstRom.fileName < lastRom.fileName; QString sortFirst = "", sortLast = ""; if (sort == "Size") { int firstSize = firstRom.sortSize; int lastSize = lastRom.sortSize; if (direction == "descending") return firstSize > lastSize; else return firstSize < lastSize; } else if (sort == "Release Date") { sortFirst = firstRom.sortDate; sortLast = lastRom.sortDate; } else { sortFirst = getRomInfo(sort, &firstRom, true, true); sortLast = getRomInfo(sort, &lastRom, true, true); } if (sortFirst == sortLast) { //Equal so sort on filename sortFirst = firstRom.fileName; sortLast = lastRom.fileName; } if (direction == "descending") return sortFirst > sortLast; else return sortFirst < sortLast; } cen64-qt-20150915-alpha/src/common.h000066400000000000000000000063521257603330000166430ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef COMMON_H #define COMMON_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" typedef struct { QString fileName; QString directory; QString romMD5; QString internalName; QString zipFile; QString baseName; QString size; int sortSize; QString goodName; QString CRC1; QString CRC2; QString players; QString saveType; QString rumble; QString gameTitle; QString releaseDate; QString sortDate; QString overview; QString esrb; QString genre; QString publisher; QString developer; QString rating; QPixmap image; int count; bool imageExists; } Rom; bool romSorter(const Rom &firstRom, const Rom &lastRom); int getDefaultWidth(QString id, int imageWidth); int getGridSize(QString which); QByteArray byteswap(QByteArray romData); QStringList getZippedFiles(QString completeFileName); QByteArray *getZippedRom(QString romFileName, QString zipFile); QColor getColor(QString color, int transparency = 255); QGraphicsDropShadowEffect *getShadow(bool active); QSize getImageSize(QString view); QString getDataLocation(); QString getRomInfo(QString identifier, const Rom *rom, bool removeWarn = false, bool sort = false); #endif // COMMON_H cen64-qt-20150915-alpha/src/downloaddialog.cpp000066400000000000000000000065641257603330000207020ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "downloaddialog.h" DownloadDialog::DownloadDialog(QString fileText, QString defaultText, QString romMD5, QWidget *parent) : QDialog(parent) { this->romMD5 = romMD5; this->parent = parent; setWindowTitle(tr("Search Game Information")); downloadLayout = new QGridLayout(this); fileLabel = new QLabel(tr("File: ") + fileText, this); gameNameLabel = new QLabel(tr("Name of Game:"), this); gameIDLabel = new QLabel(tr("or Game ID:"), this); defaultText.remove(QRegExp("\\W*(\\(|\\[).+(\\)|\\])\\W*")); gameNameField = new QLineEdit(defaultText, this); gameIDField = new QLineEdit(this); gameIDField->setToolTip(tr("From thegamesdb.net URL of game")); downloadButtonBox = new QDialogButtonBox(Qt::Horizontal, this); downloadButtonBox->addButton(tr("Search"), QDialogButtonBox::AcceptRole); downloadButtonBox->addButton(QDialogButtonBox::Cancel); downloadLayout->addWidget(fileLabel, 0, 0, 1, 2); downloadLayout->addWidget(gameNameLabel, 1, 0); downloadLayout->addWidget(gameIDLabel, 2, 0); downloadLayout->addWidget(gameNameField, 1, 1); downloadLayout->addWidget(gameIDField, 2, 1); downloadLayout->addWidget(downloadButtonBox, 4, 0, 1, 3); downloadLayout->setRowStretch(3,1); downloadLayout->setColumnStretch(1,1); downloadLayout->setColumnMinimumWidth(1, 300); downloadLayout->setRowMinimumHeight(0, 20); downloadLayout->setRowMinimumHeight(3, 20); connect(downloadButtonBox, SIGNAL(accepted()), this, SLOT(runDownloader())); connect(downloadButtonBox, SIGNAL(rejected()), this, SLOT(close())); setLayout(downloadLayout); } void DownloadDialog::runDownloader() { close(); scrapper = new TheGamesDBScrapper(parent, true); scrapper->downloadGameInfo(romMD5, gameNameField->text(), gameIDField->text()); } cen64-qt-20150915-alpha/src/downloaddialog.h000066400000000000000000000044331257603330000203400ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef DOWNLOADDIALOG_H #define DOWNLOADDIALOG_H #include #include #include #include #include #include "common.h" #include "thegamesdbscrapper.h" class DownloadDialog : public QDialog { Q_OBJECT public: explicit DownloadDialog(QString fileText, QString defaultText, QString romMD5, QWidget *parent = 0); private: QDialogButtonBox *downloadButtonBox; QGridLayout *downloadLayout; QLabel *fileLabel; QLabel *gameNameLabel; QLabel *gameIDLabel; QLineEdit *gameNameField; QLineEdit *gameIDField; QString romMD5; QWidget *parent; TheGamesDBScrapper *scrapper; private slots: void runDownloader(); }; #endif // DOWNLOADDIALOG_H cen64-qt-20150915-alpha/src/emulatorhandler.cpp000066400000000000000000000272321257603330000210740ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "emulatorhandler.h" EmulatorHandler::EmulatorHandler(QWidget *parent) : QObject(parent) { this->parent = parent; lastOutput = ""; } void EmulatorHandler::checkStatus(int status) { if (status > 0) { QMessageBox exitDialog(parent); exitDialog.setWindowTitle(tr("Warning")); exitDialog.setText(tr("CEN64 quit unexpectedly. Check the log for more information.")); exitDialog.setIcon(QMessageBox::Warning); exitDialog.addButton(QMessageBox::Ok); exitDialog.addButton("View Log...", QMessageBox::HelpRole); int ret = exitDialog.exec(); if (ret == 0) emit showLog(); } updateStatus("Emulation stopped", 3000); } void EmulatorHandler::cleanTemp() { QFile::remove(QDir::tempPath() + "/cen64-qt/temp.bin"); QFile::remove(QDir::tempPath() + "/cen64-qt/64dd-temp.bin"); } void EmulatorHandler::emitFinished() { emit finished(); } QStringList EmulatorHandler::parseArgString(QString argString) { QStringList result; QString arg; bool inQuote = false; bool inApos = false; for (int i = 0; i < argString.size(); i++) { // Check if inside of a quote if (argString.at(i) == QLatin1Char('"')) { inQuote = !inQuote; // Only continue if outside of both quotes and apostrophes if (arg.isEmpty() || (!inQuote && !inApos)) continue; } // Same check for apostrophes if (argString.at(i) == QLatin1Char('\'')) { inApos = !inApos; if (arg.isEmpty() || (!inQuote && !inApos)) continue; } if (!inQuote && !inApos && argString.at(i).isSpace()) { if (!arg.isEmpty()) { result += arg; arg.clear(); } } else arg += argString.at(i); } if (!arg.isEmpty()) result += arg; return result; } void EmulatorHandler::readOutput() { QString output = emulatorProc->readAllStandardOutput(); QStringList outputList = output.split("\n"); int lastIndex = outputList.lastIndexOf(QRegExp("^.*VI/s.*MHz$")); if (lastIndex >= 0) updateStatus(outputList[lastIndex]); lastOutput.append(output); } void EmulatorHandler::startEmulator(QDir romDir, QString romFileName, QString zipFileName, QDir ddDir, QString ddFileName, QString ddZipName) { QString completeRomPath = "", complete64DDPath = ""; bool zip = false, ddZip = false; //If zipped file, extract and write to temp location for loading QStringList zippedFiles; zippedFiles << zipFileName << ddZipName; bool ddZipCheck = false; foreach (QString zippedFile, zippedFiles) { if (zippedFile != "") { QString fileInZip, tempName, romPath, zipFile; if (!ddZipCheck) { zip = true; tempName = "/temp.bin"; fileInZip = romFileName; zipFile = romDir.absoluteFilePath(zippedFile); } else { ddZip = true; tempName = "/64dd-temp.bin"; fileInZip = ddFileName; zipFile = ddDir.absoluteFilePath(zippedFile); } QByteArray *romData = getZippedRom(fileInZip, zipFile); QString tempDir = QDir::tempPath() + "/cen64-qt"; QDir().mkdir(tempDir); romPath = tempDir + tempName; QFile tempRom(romPath); tempRom.open(QIODevice::WriteOnly); tempRom.write(*romData); tempRom.close(); delete romData; if (!ddZipCheck) completeRomPath = romPath; else complete64DDPath = romPath; } ddZipCheck = true; } if (zipFileName == "" && romFileName != "") completeRomPath = romDir.absoluteFilePath(romFileName); if (ddZipName == "" && ddFileName != "") complete64DDPath = ddDir.absoluteFilePath(ddFileName); QString cen64Path = SETTINGS.value("Paths/cen64", "").toString(); QString pifPath = SETTINGS.value("Paths/pifrom", "").toString(); QString ddIPLPath = SETTINGS.value("Paths/ddiplrom", "").toString(); QString input = SETTINGS.value("input", "").toString(); bool ddMode = false; if (SETTINGS.value("Emulation/64dd", "").toString() == "true") ddMode = true; QFile cen64File(cen64Path); QFile pifFile(pifPath); QFile ddIPL(ddIPLPath); QFile romFile(completeRomPath); QFile ddFile(complete64DDPath); //Sanity checks if (!cen64File.exists() || QFileInfo(cen64File).isDir() || !QFileInfo(cen64File).isExecutable()) { QMessageBox::warning(parent, tr("Warning"), tr("CEN64 executable not found.")); if (zip || ddZip) cleanTemp(); return; } if (!pifFile.exists() || QFileInfo(pifFile).isDir()) { QMessageBox::warning(parent, tr("Warning"), tr("PIF IPL file not found.")); if (zip || ddZip) cleanTemp(); return; } if (ddIPLPath != "" && (!ddIPL.exists() || QFileInfo(ddIPL).isDir())) { QMessageBox::warning(parent, tr("Warning"), tr("64DD IPL file not found.")); if (zip || ddZip) cleanTemp(); return; } if (completeRomPath != "" && (!romFile.exists() || QFileInfo(romFile).isDir())) { QMessageBox::warning(parent, tr("Warning"), tr("ROM file not found.")); if (zip || ddZip) cleanTemp(); return; } if (completeRomPath == "" && complete64DDPath != "" && (!ddFile.exists() || QFileInfo(ddFile).isDir())) { QMessageBox::warning(parent, tr("Warning"), tr("64DD ROM file not found.")); if (zip || ddZip) cleanTemp(); return; } if (completeRomPath == "" && complete64DDPath == "") { QMessageBox::warning(parent, tr("Warning"), tr("No ROM selected.")); if (zip || ddZip) cleanTemp(); return; } if (completeRomPath != "") { romFile.open(QIODevice::ReadOnly); QByteArray romCheck = romFile.read(4); romFile.close(); if (romCheck.toHex() != "80371240") { if (romCheck.toHex() == "e848d316") { // 64DD file instead if (complete64DDPath == "" && ddMode) { complete64DDPath = completeRomPath; ddFile.setFileName(complete64DDPath); completeRomPath = ""; } else { QMessageBox::warning(parent, tr("Warning"), tr("64DD not enabled.")); if (zip || ddZip) cleanTemp(); return; } } else { QMessageBox::warning(parent, tr("Warning"), tr("Not a valid Z64 File.")); if (zip || ddZip) cleanTemp(); return; } } } if (complete64DDPath != "" && ddMode) { ddFile.open(QIODevice::ReadOnly); QByteArray romCheck = ddFile.read(4); ddFile.close(); if (romCheck.toHex() != "e848d316") { QMessageBox::warning(parent, tr("Warning"), tr("Not a valid 64DD File.")); if (zip || ddZip) cleanTemp(); return; } } QStringList args; // args << "-controller" << input; // if (SETTINGS.value("Saves/individualsave", "").toString() == "true") { // QString eepromPath = SETTINGS.value("Saves/eeprom", "").toString(); // QString sramPath = SETTINGS.value("Saves/sram", "").toString(); // if (eepromPath != "") // args << "-eeprom" << eepromPath; // if (sramPath != "") // args << "-sram" << sramPath; // } else { // QString savesPath = SETTINGS.value("Saves/directory", "").toString(); // if (savesPath != "") { // QDir savesDir(savesPath); // if (savesDir.exists()) { // romFile.open(QIODevice::ReadOnly); // QByteArray *romData = new QByteArray(romFile.readAll()); // romFile.close(); // QString romMD5 = QString(QCryptographicHash::hash(*romData, // QCryptographicHash::Md5).toHex()); // QString romBaseName = QFileInfo(romFile).completeBaseName(); // QString eepromFileName = romBaseName + "." + romMD5 + ".eeprom"; // QString sramFileName = romBaseName + "." + romMD5 + ".sram"; // QString eepromPath = savesDir.absoluteFilePath(eepromFileName); // QString sramPath = savesDir.absoluteFilePath(sramFileName); // args << "-eeprom" << eepromPath << "-sram" << sramPath; // delete romData; // } // } // } if (ddIPLPath != "" && complete64DDPath != "" && ddMode) args << "-ddipl" << ddIPLPath << "-ddrom" << complete64DDPath; else if (completeRomPath == "") { QMessageBox::warning(parent, tr("Warning"), tr("No ROM selected or 64DD not enabled.")); if (zip || ddZip) cleanTemp(); return; } QString otherParameters = SETTINGS.value("Other/parameters", "").toString(); if (otherParameters != "") args.append(parseArgString(otherParameters)); args << pifPath; if (completeRomPath != "") args << completeRomPath; emulatorProc = new QProcess(this); connect(emulatorProc, SIGNAL(finished(int)), this, SLOT(emitFinished())); connect(emulatorProc, SIGNAL(finished(int)), this, SLOT(checkStatus(int))); if (zip || ddZip) connect(emulatorProc, SIGNAL(finished(int)), this, SLOT(cleanTemp())); if (SETTINGS.value("Other/consoleoutput", "").toString() == "true") emulatorProc->setProcessChannelMode(QProcess::ForwardedChannels); else { connect(emulatorProc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput())); emulatorProc->setProcessChannelMode(QProcess::MergedChannels); } //clear log lastOutput = ""; emulatorProc->start(cen64Path, args); updateStatus("Emulation started", 3000); emit started(); } void EmulatorHandler::stopEmulator() { emulatorProc->terminate(); } void EmulatorHandler::updateStatus(QString message, int timeout) { emit statusUpdate(message, timeout); } cen64-qt-20150915-alpha/src/emulatorhandler.h000066400000000000000000000050121257603330000205310ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef EMULATORHANDLER_H #define EMULATORHANDLER_H #include #include #include #include #include #include #include "common.h" class EmulatorHandler : public QObject { Q_OBJECT public: explicit EmulatorHandler(QWidget *parent = 0); void startEmulator(QDir romDir, QString romFileName, QString zipFileName = "", QDir ddDir = QDir(), QString ddFileName = "", QString ddZipName = ""); void stopEmulator(); QString lastOutput; signals: void finished(); void showLog(); void started(); void statusUpdate(QString message, int timeout); private: void updateStatus(QString message, int timeout = 0); QStringList parseArgString(QString argString); QProcess *emulatorProc; QWidget *parent; private slots: void checkStatus(int status); void cleanTemp(); void emitFinished(); void readOutput(); }; #endif // EMULATORHANDLER_H cen64-qt-20150915-alpha/src/global.h000066400000000000000000000034241257603330000166100ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef GLOBAL_H #define GLOBAL_H #include #ifdef Q_OS_WIN #define SETTINGS QSettings("cen64-qt.ini", QSettings::IniFormat) #else #define SETTINGS QSettings("cen64", "cen64-qt") #endif #endif // GLOBAL_H cen64-qt-20150915-alpha/src/logdialog.cpp000066400000000000000000000047231257603330000176470ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "logdialog.h" LogDialog::LogDialog(QString lastOutput, QWidget *parent) : QDialog(parent) { setWindowTitle(tr("CEN64 Log")); setMinimumSize(600, 400); logLayout = new QGridLayout(this); logLayout->setContentsMargins(5, 10, 5, 10); logArea = new QTextEdit(this); logArea->setWordWrapMode(QTextOption::NoWrap); QFont font; #ifdef Q_OS_LINUX font.setFamily("Monospace"); font.setPointSize(9); #else font.setFamily("Courier"); font.setPointSize(10); #endif font.setFixedPitch(true); logArea->setFont(font); logArea->setPlainText(lastOutput); logButtonBox = new QDialogButtonBox(Qt::Horizontal, this); logButtonBox->addButton(tr("Close"), QDialogButtonBox::AcceptRole); logLayout->addWidget(logArea, 0, 0); logLayout->addWidget(logButtonBox, 1, 0); connect(logButtonBox, SIGNAL(accepted()), this, SLOT(close())); setLayout(logLayout); } cen64-qt-20150915-alpha/src/logdialog.h000066400000000000000000000036531257603330000173150ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef LOGDIALOG_H #define LOGDIALOG_H #include #include #include #include class LogDialog : public QDialog { Q_OBJECT public: explicit LogDialog(QString lastOutput, QWidget *parent = 0); private: QDialogButtonBox *logButtonBox; QGridLayout *logLayout; QTextEdit *logArea; }; #endif // LOGDIALOG_H cen64-qt-20150915-alpha/src/main.cpp000066400000000000000000000045411257603330000166300ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include #include #include "global.h" #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication application(argc, argv); QCoreApplication::setOrganizationName("CEN64"); QCoreApplication::setApplicationName("CEN64-Qt"); MainWindow window; QString maximized = SETTINGS.value("Geometry/maximized", "").toString(); QString windowx = SETTINGS.value("Geometry/windowx", "").toString(); QString windowy = SETTINGS.value("Geometry/windowy", "").toString(); if (maximized == "true") { window.showMaximized(); } else { window.show(); } if (windowx == "" && windowy == "") { window.move(QApplication::desktop()->screen()->rect().center() - window.rect().center()); } return application.exec(); } cen64-qt-20150915-alpha/src/mainwindow.cpp000066400000000000000000001353431257603330000200650ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("CEN64-Qt")); setWindowIcon(QIcon(":/images/cen64.png")); emulation = new EmulatorHandler(this); connect(emulation, SIGNAL(started()), this, SLOT(disableButtons())); connect(emulation, SIGNAL(finished()), this, SLOT(enableButtons())); connect(emulation, SIGNAL(showLog()), this, SLOT(openLog())); connect(emulation, SIGNAL(statusUpdate(QString, int)), this, SLOT(updateStatusBar(QString, int))); romCollection = new RomCollection(QStringList() << "*.z64" << "*.n64" << "*.zip" << "*.ndd", QStringList() << SETTINGS.value("Paths/roms","").toString().split("|"), this); connect(romCollection, SIGNAL(updateStarted(bool)), this, SLOT(disableViews(bool))); connect(romCollection, SIGNAL(romAdded(Rom*, int)), this, SLOT(addToView(Rom*, int))); connect(romCollection, SIGNAL(ddRomAdded(Rom*)), this, SLOT(addTo64DDView(Rom*))); connect(romCollection, SIGNAL(updateEnded(int, bool)), this, SLOT(enableViews(int, bool))); mainWidget = new QWidget(this); setCentralWidget(mainWidget); setGeometry(QRect(SETTINGS.value("Geometry/windowx", 0).toInt(), SETTINGS.value("Geometry/windowy", 0).toInt(), SETTINGS.value("Geometry/width", 900).toInt(), SETTINGS.value("Geometry/height", 600).toInt())); createMenu(); createRomView(); statusBar = new QStatusBar; if (SETTINGS.value("View/statusbar", "").toString() == "") statusBar->hide(); QString ddipl = SETTINGS.value("Paths/ddiplrom", "").toString(); QString ddEnabled = SETTINGS.value("Emulation/64dd", "").toString(); QString currentView = SETTINGS.value("View/layout", "None").toString(); if (ddipl != "" && ddEnabled == "true" && currentView != "None") ddView->setHidden(false); mainLayout = new QVBoxLayout(mainWidget); mainLayout->setMenuBar(menuBar); mainLayout->addWidget(viewSplitter); mainLayout->addWidget(statusBar); mainLayout->setMargin(0); mainWidget->setLayout(mainLayout); mainWidget->setMinimumSize(300, 200); } void MainWindow::addTo64DDView(Rom *currentRom) { fileItem = new TreeWidgetItem(ddView); fileItem->setText(0, currentRom->fileName); //Filename for launching ROM fileItem->setText(1, currentRom->directory); //Directory ROM is located in fileItem->setText(2, ""); //GoodName or Internal Name for searching (currently blank) fileItem->setText(3, currentRom->romMD5.toLower()); //MD5 for cache info fileItem->setText(4, currentRom->zipFile); //Zip file fileItem->setText(5, QFileInfo(currentRom->fileName).completeBaseName()); //Visible filename ddView->addTopLevelItem(fileItem); } void MainWindow::addToView(Rom *currentRom, int count) { if (SETTINGS.value("View/layout", "None") == "Table View") addToTableView(currentRom); else if (SETTINGS.value("View/layout", "None") == "Grid View") addToGridView(currentRom, count); else if (SETTINGS.value("View/layout", "None") == "List View") addToListView(currentRom, count); } void MainWindow::addToGridView(Rom *currentRom, int count) { if (ddAction->isChecked()) // Add place for "No Cart" entry count++; ClickableWidget *gameGridItem = new ClickableWidget(gridWidget); gameGridItem->setMinimumWidth(getGridSize("width")); gameGridItem->setMaximumWidth(getGridSize("width")); gameGridItem->setGraphicsEffect(getShadow(false)); //Assign ROM data to widget for use in click events gameGridItem->setProperty("fileName", currentRom->fileName); gameGridItem->setProperty("directory", currentRom->directory); if (currentRom->goodName == "Unknown ROM" || currentRom->goodName == "Requires catalog file") gameGridItem->setProperty("search", currentRom->internalName); else gameGridItem->setProperty("search", currentRom->goodName); gameGridItem->setProperty("romMD5", currentRom->romMD5); gameGridItem->setProperty("zipFile", currentRom->zipFile); QGridLayout *gameGridLayout = new QGridLayout(gameGridItem); gameGridLayout->setColumnStretch(0, 1); gameGridLayout->setColumnStretch(3, 1); gameGridLayout->setRowMinimumHeight(1, getImageSize("Grid").height()); QLabel *gridImageLabel = new QLabel(gameGridItem); gridImageLabel->setMinimumHeight(getImageSize("Grid").height()); gridImageLabel->setMinimumWidth(getImageSize("Grid").width()); QPixmap image; if (currentRom->imageExists) { //Use uniform aspect ratio to account for fluctuations in TheGamesDB box art Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio; //Don't warp aspect ratio though if image is too far away from standard size (JP box art) float aspectRatio = float(currentRom->image.width()) / currentRom->image.height(); if (aspectRatio < 1.1 || aspectRatio > 1.8) aspectRatioMode = Qt::KeepAspectRatio; image = currentRom->image.scaled(getImageSize("Grid"), aspectRatioMode, Qt::SmoothTransformation); } else { if (ddAction->isChecked() && count == 0) image = QPixmap(":/images/no-cart.png").scaled(getImageSize("Grid"), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); else image = QPixmap(":/images/not-found.png").scaled(getImageSize("Grid"), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } gridImageLabel->setPixmap(image); gridImageLabel->setAlignment(Qt::AlignCenter); gameGridLayout->addWidget(gridImageLabel, 1, 1); if (SETTINGS.value("Grid/label","true") == "true") { QLabel *gridTextLabel = new QLabel(gameGridItem); //Don't allow label to be wider than image gridTextLabel->setMaximumWidth(getImageSize("Grid").width()); QString text = ""; QString labelText = SETTINGS.value("Grid/labeltext","Filename").toString(); text = getRomInfo(labelText, currentRom); if (ddAction->isChecked() && count == 0) text = "No Cart"; gridTextLabel->setText(text); QString textHex = getColor(SETTINGS.value("Grid/labelcolor","White").toString()).name(); int fontSize = getGridSize("font"); gridTextLabel->setStyleSheet("QLabel { font-weight: bold; color: " + textHex + "; font-size: " + QString::number(fontSize) + "px; }"); gridTextLabel->setWordWrap(true); gridTextLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop); gameGridLayout->addWidget(gridTextLabel, 2, 1); } gameGridItem->setLayout(gameGridLayout); gameGridItem->setMinimumHeight(gameGridItem->sizeHint().height()); int columnCount = SETTINGS.value("Grid/columncount", "4").toInt(); gridLayout->addWidget(gameGridItem, count / columnCount + 1, count % columnCount + 1); gridWidget->adjustSize(); connect(gameGridItem, SIGNAL(singleClicked(QWidget*)), this, SLOT(highlightGridWidget(QWidget*))); connect(gameGridItem, SIGNAL(doubleClicked(QWidget*)), this, SLOT(launchRomFromWidget(QWidget*))); } void MainWindow::addToListView(Rom *currentRom, int count) { if (ddAction->isChecked()) // Add place for "No Cart" entry count++; QStringList visible = SETTINGS.value("List/columns", "Filename|Internal Name|Size").toString().split("|"); if (visible.join("") == "" && SETTINGS.value("List/displaycover", "") != "true") //Otherwise no columns, so don't bother populating return; ClickableWidget *gameListItem = new ClickableWidget(listWidget); gameListItem->setContentsMargins(0, 0, 20, 0); //Assign ROM data to widget for use in click events gameListItem->setProperty("fileName", currentRom->fileName); gameListItem->setProperty("directory", currentRom->directory); if (currentRom->goodName == "Unknown ROM" || currentRom->goodName == "Requires catalog file") gameListItem->setProperty("search", currentRom->internalName); else gameListItem->setProperty("search", currentRom->goodName); gameListItem->setProperty("romMD5", currentRom->romMD5); gameListItem->setProperty("zipFile", currentRom->zipFile); QGridLayout *gameListLayout = new QGridLayout(gameListItem); gameListLayout->setColumnStretch(3, 1); //Add image if (SETTINGS.value("List/displaycover", "") == "true") { QLabel *listImageLabel = new QLabel(gameListItem); listImageLabel->setMinimumHeight(getImageSize("List").height()); listImageLabel->setMinimumWidth(getImageSize("List").width()); QPixmap image; if (currentRom->imageExists) image = currentRom->image.scaled(getImageSize("List"), Qt::KeepAspectRatio, Qt::SmoothTransformation); else { if (ddAction->isChecked() && count == 0) image = QPixmap(":/images/no-cart.png").scaled(getImageSize("List"), Qt::KeepAspectRatio, Qt::SmoothTransformation); else image = QPixmap(":/images/not-found.png").scaled(getImageSize("List"), Qt::KeepAspectRatio, Qt::SmoothTransformation); } listImageLabel->setPixmap(image); listImageLabel->setAlignment(Qt::AlignCenter); gameListLayout->addWidget(listImageLabel, 0, 1); } //Create text label QLabel *listTextLabel = new QLabel("", gameListItem); QString listText = ""; int i = 0; foreach (QString current, visible) { QString addition = ""; if (i == 0 && SETTINGS.value("List/firstitemheader","true") == "true") addition += "

"; else addition += "" + current + ": "; addition += getRomInfo(current, currentRom, true) + "
"; if (i == 0 && SETTINGS.value("List/firstitemheader","true") == "true") addition += "

"; if (addition != "" + current + ":
") listText += addition; i++; } //Remove last break tag listText.remove(QRegExp("
$")); if (ddAction->isChecked() && count == 0) listText = "

No Cart

"; listTextLabel->setText(listText); listTextLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); listTextLabel->setWordWrap(true); gameListLayout->addWidget(listTextLabel, 0, 3); gameListLayout->setColumnMinimumWidth(0, 20); gameListLayout->setColumnMinimumWidth(2, 10); gameListItem->setLayout(gameListLayout); if (count != 0) { QFrame *separator = new QFrame(); separator->setFrameShape(QFrame::HLine); separator->setStyleSheet("margin:0;padding:0;"); listLayout->addWidget(separator); } listLayout->addWidget(gameListItem); connect(gameListItem, SIGNAL(singleClicked(QWidget*)), this, SLOT(highlightListWidget(QWidget*))); connect(gameListItem, SIGNAL(doubleClicked(QWidget*)), this, SLOT(launchRomFromWidget(QWidget*))); } void MainWindow::addToTableView(Rom *currentRom) { QStringList visible = SETTINGS.value("Table/columns", "Filename|Size").toString().split("|"); if (visible.join("") == "") //Otherwise no columns, so don't bother populating return; fileItem = new TreeWidgetItem(tableView); //Filename for launching ROM fileItem->setText(0, currentRom->fileName); //Directory ROM is located in fileItem->setText(1, currentRom->directory); //GoodName or Internal Name for searching if (currentRom->goodName == "Unknown ROM" || currentRom->goodName == "Requires catalog file") fileItem->setText(2, currentRom->internalName); else fileItem->setText(2, currentRom->goodName); //MD5 for cache info fileItem->setText(3, currentRom->romMD5.toLower()); //Zip file fileItem->setText(4, currentRom->zipFile); int i = 5, c = 0; bool addImage = false; foreach (QString current, visible) { QString text = getRomInfo(current, currentRom); fileItem->setText(i, text); if (current == "GoodName" || current == "Game Title") { if (text == "Unknown ROM" || text == "Requires catalog file" || text == "Not found") { fileItem->setForeground(i, QBrush(Qt::gray)); fileItem->setData(i, Qt::UserRole, "ZZZ"); //end of sorting } else fileItem->setData(i, Qt::UserRole, text); } if (current == "Size") fileItem->setData(i, Qt::UserRole, currentRom->sortSize); if (current == "Release Date") fileItem->setData(i, Qt::UserRole, currentRom->sortDate); if (current == "Game Cover") { c = i; addImage = true; } QStringList center, right; center << "MD5" << "CRC1" << "CRC2" << "Rumble" << "ESRB" << "Genre" << "Publisher" << "Developer"; right << "Size" << "Players" << "Save Type" << "Release Date" << "Rating"; if (center.contains(current)) fileItem->setTextAlignment(i, Qt::AlignHCenter | Qt::AlignVCenter); else if (right.contains(current)) fileItem->setTextAlignment(i, Qt::AlignRight | Qt::AlignVCenter); i++; } tableView->addTopLevelItem(fileItem); if (currentRom->imageExists && addImage) { QPixmap image(currentRom->image.scaled(getImageSize("Table"), Qt::KeepAspectRatio, Qt::SmoothTransformation)); QWidget *imageContainer = new QWidget(tableView); QGridLayout *imageGrid = new QGridLayout(imageContainer); QLabel *imageLabel = new QLabel(imageContainer); imageLabel->setPixmap(image); imageGrid->addWidget(imageLabel, 1, 1); imageGrid->setColumnStretch(0, 1); imageGrid->setColumnStretch(2, 1); imageGrid->setRowStretch(0, 1); imageGrid->setRowStretch(2, 1); imageGrid->setContentsMargins(0,0,0,0); imageContainer->setLayout(imageGrid); tableView->setItemWidget(fileItem, c, imageContainer); } } void MainWindow::closeEvent(QCloseEvent *event) { SETTINGS.setValue("Geometry/windowx", geometry().x()); SETTINGS.setValue("Geometry/windowy", geometry().y()); SETTINGS.setValue("Geometry/width", geometry().width()); SETTINGS.setValue("Geometry/height", geometry().height()); if (isMaximized()) SETTINGS.setValue("Geometry/maximized", true); else SETTINGS.setValue("Geometry/maximized", ""); saveColumnWidths(); QStringList sizes; foreach(int size, viewSplitter->sizes()) sizes << QString::number(size); SETTINGS.setValue("View/64ddsize", sizes.join("|")); event->accept(); } void MainWindow::createMenu() { menuBar = new QMenuBar(this); fileMenu = new QMenu(tr("&File"), this); openAction = fileMenu->addAction(tr("&Open ROM...")); fileMenu->addSeparator(); convertAction = fileMenu->addAction(tr("&Convert V64...")); refreshAction = fileMenu->addAction(tr("&Refresh List")); downloadAction = fileMenu->addAction(tr("&Download/Update Info...")); deleteAction = fileMenu->addAction(tr("D&elete Current Info...")); #ifndef Q_OS_OSX //OSX does not show the quit action so the separator is unneeded fileMenu->addSeparator(); #endif quitAction = fileMenu->addAction(tr("&Quit")); openAction->setIcon(QIcon::fromTheme("document-open")); refreshAction->setIcon(QIcon::fromTheme("view-refresh")); quitAction->setIcon(QIcon::fromTheme("application-exit")); downloadAction->setEnabled(false); deleteAction->setEnabled(false); menuBar->addMenu(fileMenu); emulationMenu = new QMenu(tr("&Emulation"), this); startAction = emulationMenu->addAction(tr("&Start")); stopAction = emulationMenu->addAction(tr("St&op")); emulationMenu->addSeparator(); ddAction = emulationMenu->addAction(tr("Enable 64DD")); emulationMenu->addSeparator(); logAction = emulationMenu->addAction(tr("View Log...")); startAction->setIcon(QIcon::fromTheme("media-playback-start")); stopAction->setIcon(QIcon::fromTheme("media-playback-stop")); startAction->setEnabled(false); stopAction->setEnabled(false); ddAction->setCheckable(true); if (SETTINGS.value("Paths/ddiplrom", "").toString() != "") { if (SETTINGS.value("Emulation/64dd", "").toString() == "true") ddAction->setChecked(true); } else ddAction->setEnabled(false); menuBar->addMenu(emulationMenu); settingsMenu = new QMenu(tr("&Settings"), this); inputMenu = settingsMenu->addMenu(tr("&Input")); inputMenu->setIcon(QIcon::fromTheme("input-gaming")); inputGroup = new QActionGroup(this); QStringList inputs; inputs << "keyboard" << "mayflash64" << "retrolink" << "wiiu" << "x360"; QString inputValue = SETTINGS.value("input","keyboard").toString(); foreach (QString inputName, inputs) { QAction *input = inputMenu->addAction(inputName); input->setData(inputName); input->setCheckable(true); inputGroup->addAction(input); //Only enable input actions when CEN64 is not running menuEnable << input; if(inputValue == inputName) input->setChecked(true); } #ifndef Q_OS_OSX //OSX does not show the configure action so the separator is unneeded settingsMenu->addSeparator(); #endif configureAction = settingsMenu->addAction(tr("&Configure...")); configureAction->setIcon(QIcon::fromTheme("preferences-other")); menuBar->addMenu(settingsMenu); viewMenu = new QMenu(tr("&View"), this); layoutMenu = viewMenu->addMenu(tr("&Layout")); layoutGroup = new QActionGroup(this); QStringList layouts; layouts << "None" << "Table View" << "Grid View" << "List View"; QString layoutValue = SETTINGS.value("View/layout", "None").toString(); foreach (QString layoutName, layouts) { QAction *layoutItem = layoutMenu->addAction(layoutName); layoutItem->setData(layoutName); layoutItem->setCheckable(true); layoutGroup->addAction(layoutItem); //Only enable layout changes when CEN64 is not running menuEnable << layoutItem; if(layoutValue == layoutName) layoutItem->setChecked(true); } viewMenu->addSeparator(); statusBarAction = viewMenu->addAction(tr("&Status Bar")); statusBarAction->setCheckable(true); if (SETTINGS.value("View/statusbar", "") == "true") statusBarAction->setChecked(true); menuBar->addMenu(viewMenu); helpMenu = new QMenu(tr("&Help"), this); aboutAction = helpMenu->addAction(tr("&About")); aboutAction->setIcon(QIcon::fromTheme("help-about")); menuBar->addMenu(helpMenu); //Create list of actions that are enabled only when CEN64 is not running menuEnable << startAction << ddAction << logAction << openAction << convertAction << downloadAction << deleteAction << refreshAction << configureAction << quitAction; //Create list of actions that are disabled when CEN64 is not running menuDisable << stopAction; connect(openAction, SIGNAL(triggered()), this, SLOT(openRom())); connect(convertAction, SIGNAL(triggered()), this, SLOT(openConverter())); connect(refreshAction, SIGNAL(triggered()), romCollection, SLOT(addRoms())); connect(downloadAction, SIGNAL(triggered()), this, SLOT(openDownloader())); connect(deleteAction, SIGNAL(triggered()), this, SLOT(openDeleteDialog())); connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); connect(startAction, SIGNAL(triggered()), this, SLOT(launchRomFromMenu())); connect(stopAction, SIGNAL(triggered()), this, SLOT(stopEmulator())); connect(ddAction, SIGNAL(triggered()), this, SLOT(update64DD())); connect(logAction, SIGNAL(triggered()), this, SLOT(openLog())); connect(configureAction, SIGNAL(triggered()), this, SLOT(openSettings())); connect(statusBarAction, SIGNAL(triggered()), this, SLOT(updateStatusBarView())); connect(aboutAction, SIGNAL(triggered()), this, SLOT(openAbout())); connect(inputGroup, SIGNAL(triggered(QAction*)), this, SLOT(updateInputSetting())); connect(layoutGroup, SIGNAL(triggered(QAction*)), this, SLOT(updateLayoutSetting())); } void MainWindow::createRomView() { viewSplitter = new QSplitter(this); viewSplitter->setOrientation(Qt::Vertical); //Create empty view emptyView = new QScrollArea(this); emptyView->setStyleSheet("QScrollArea { border: none; }"); emptyView->setBackgroundRole(QPalette::Base); emptyView->setAutoFillBackground(true); emptyView->setHidden(true); emptyLayout = new QGridLayout(emptyView); emptyIcon = new QLabel(emptyView); emptyIcon->setPixmap(QPixmap(":/images/cen64.png")); emptyLayout->addWidget(emptyIcon, 1, 1); emptyLayout->setColumnStretch(0, 1); emptyLayout->setColumnStretch(2, 1); emptyLayout->setRowStretch(0, 1); emptyLayout->setRowStretch(2, 1); emptyView->setLayout(emptyLayout); //Create table view tableView = new QTreeWidget(this); tableView->setWordWrap(false); tableView->setAllColumnsShowFocus(true); tableView->setRootIsDecorated(false); tableView->setSortingEnabled(true); tableView->setStyleSheet("QTreeView { border: none; } QTreeView::item { height: 25px; }"); headerView = new QHeaderView(Qt::Horizontal, this); tableView->setHeader(headerView); tableView->setHidden(true); //Create grid view gridView = new QScrollArea(this); gridView->setObjectName("gridView"); gridView->setStyleSheet("#gridView { border: none; }"); gridView->setBackgroundRole(QPalette::Dark); gridView->setAlignment(Qt::AlignHCenter); gridView->setHidden(true); gridView->verticalScrollBar()->setObjectName("vScrollBar"); gridView->horizontalScrollBar()->setObjectName("hScrollBar"); setGridBackground(); gridWidget = new QWidget(gridView); gridWidget->setObjectName("gridWidget"); gridView->setWidget(gridWidget); gridLayout = new QGridLayout(gridWidget); gridLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); gridLayout->setRowMinimumHeight(0, 10); gridWidget->setLayout(gridLayout); gridCurrent = false; currentGridRom = 0; //Create list view listView = new QScrollArea(this); listView->setStyleSheet("QScrollArea { border: none; }"); listView->setBackgroundRole(QPalette::Base); listView->setWidgetResizable(true); listView->setHidden(true); listWidget = new QWidget(listView); listView->setWidget(listWidget); listLayout = new QVBoxLayout(listWidget); listLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); listWidget->setLayout(listLayout); listCurrent = false; currentListRom = 0; //Create 64DD view ddView = new QTreeWidget(this); ddView->setWordWrap(false); ddView->setAllColumnsShowFocus(true); ddView->setRootIsDecorated(false); ddView->setStyleSheet("QTreeView { border: none; } QTreeView::item { height: 25px; }"); ddView->setHeaderLabels(QStringList() << "" << "" << "" << "" << "" << "64DD ROM"); ddView->header()->setHidden(true); ddView->setColumnHidden(0, true); //Hidden filename for launching emulator ddView->setColumnHidden(1, true); //Hidden directory of ROM location ddView->setColumnHidden(2, true); //Hidden goodname for searching ddView->setColumnHidden(3, true); //Hidden md5 for cache info ddView->setColumnHidden(4, true); //Hidden column for zip file ddView->setHidden(true); viewSplitter->addWidget(emptyView); viewSplitter->addWidget(tableView); viewSplitter->addWidget(gridView); viewSplitter->addWidget(listView); viewSplitter->addWidget(ddView); //Restore 64DD Panel size QStringList sizes = SETTINGS.value("View/64ddsize", "").toString().split("|"); QList sizeInts; int mainSize = 1, ddSize = 1; if (!sizes.isEmpty()) ddSize = sizes.last().toInt(); foreach (QString size, sizes) { if (size.toInt() != 0) { mainSize = size.toInt(); //Set all views to same height in case user switches view break; } } if (ddSize == 0) ddSize = 1; sizeInts << mainSize << mainSize << mainSize << mainSize << ddSize; viewSplitter->setSizes(sizeInts); QString visibleLayout = SETTINGS.value("View/layout", "None").toString(); if (visibleLayout == "Table View") tableView->setHidden(false); else if (visibleLayout == "Grid View") gridView->setHidden(false); else if (visibleLayout == "List View") listView->setHidden(false); else emptyView->setHidden(false); romCollection->cachedRoms(); connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(enableButtons())); connect(tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(launchRomFromTable())); connect(ddView, SIGNAL(clicked(QModelIndex)), this, SLOT(enableButtons())); connect(ddView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(launchRomFromMenu())); connect(headerView, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSortOrder(int,Qt::SortOrder))); } void MainWindow::disableButtons() { toggleMenus(false); } void MainWindow::disableViews(bool imageUpdated) { QStringList tableVisible = SETTINGS.value("Table/columns", "Filename|Size").toString().split("|"); resetLayouts(imageUpdated); tableView->clear(); ddView->clear(); if (ddAction->isChecked()) { //64DD enabled so show "No Cart" options fileItem = new TreeWidgetItem(tableView); if (tableVisible.at(0) == "Game Cover") { fileItem->setText(6, " No Cart"); fileItem->setForeground(6, QBrush(Qt::gray)); } else { fileItem->setText(5, " No Cart"); fileItem->setForeground(5, QBrush(Qt::gray)); } tableView->addTopLevelItem(fileItem); Rom dummyRom; dummyRom.imageExists = false; addToGridView(&dummyRom, -1); addToListView(&dummyRom, -1); fileItem = new TreeWidgetItem(ddView); fileItem->setText(5, "No Disk"); fileItem->setForeground(5, QBrush(Qt::gray)); ddView->addTopLevelItem(fileItem); } tableView->setEnabled(false); gridView->setEnabled(false); listView->setEnabled(false); ddView->setEnabled(false); downloadAction->setEnabled(false); deleteAction->setEnabled(false); startAction->setEnabled(false); stopAction->setEnabled(false); //Save position in current layout positionx = 0; positiony = 0; if (SETTINGS.value("View/layout", "None") == "Table View") { positionx = tableView->horizontalScrollBar()->value(); positiony = tableView->verticalScrollBar()->value(); } else if (SETTINGS.value("View/layout", "None") == "Grid View") { positionx = gridView->horizontalScrollBar()->value(); positiony = gridView->verticalScrollBar()->value(); } else if (SETTINGS.value("View/layout", "None") == "List View") { positionx = listView->horizontalScrollBar()->value(); positiony = listView->verticalScrollBar()->value(); } } void MainWindow::enableButtons() { toggleMenus(true); } void MainWindow::enableViews(int romCount, bool cached) { if (romCount != 0) { //else no ROMs, so leave views disabled QStringList tableVisible = SETTINGS.value("Table/columns", "Filename|Size").toString().split("|"); if (tableVisible.join("") != "") tableView->setEnabled(true); gridView->setEnabled(true); listView->setEnabled(true); ddView->setEnabled(true); if (cached) { QTimer *timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(0); timer->start(); if (SETTINGS.value("View/layout", "None") == "Table View") connect(timer, SIGNAL(timeout()), this, SLOT(setTablePosition())); else if (SETTINGS.value("View/layout", "None") == "Grid View") connect(timer, SIGNAL(timeout()), this, SLOT(setGridPosition())); else if (SETTINGS.value("View/layout", "None") == "List View") connect(timer, SIGNAL(timeout()), this, SLOT(setListPosition())); } } } QString MainWindow::getCurrentRomInfo(int index) { if (index < 3) { const char *infoChar; int table; switch (index) { case 0: infoChar = "fileName"; table = 0; break; case 1: infoChar = "search"; table = 2; break; case 2: infoChar = "romMD5"; table = 3; break; default: infoChar = ""; table = 0; break; } QString visibleLayout = SETTINGS.value("View/layout", "None").toString(); if (visibleLayout == "Table View") return tableView->currentItem()->data(table, 0).toString(); else if (visibleLayout == "Grid View" && gridCurrent) return gridLayout->itemAt(currentGridRom)->widget()->property(infoChar).toString(); else if (visibleLayout == "List View" && listCurrent) return listLayout->itemAt(currentListRom)->widget()->property(infoChar).toString(); } return ""; } void MainWindow::highlightGridWidget(QWidget *current) { //Set all to inactive shadow QLayoutItem *gridItem; for (int item = 0; (gridItem = gridLayout->itemAt(item)) != NULL; item++) { gridItem->widget()->setGraphicsEffect(getShadow(false)); if (gridItem->widget() == current) currentGridRom = item; } //Set current to active shadow current->setGraphicsEffect(getShadow(true)); gridCurrent = true; toggleMenus(true); } void MainWindow::highlightListWidget(QWidget *current) { //Reset all margins QLayoutItem *listItem; for (int item = 0; (listItem = listLayout->itemAt(item)) != NULL; item++) { listItem->widget()->setContentsMargins(0, 0, 20, 0); if (listItem->widget() == current) currentListRom = item; } //Give current left margin to stand out current->setContentsMargins(20, 0, 0, 0); listCurrent = true; toggleMenus(true); } void MainWindow::launchRom(QDir romDir, QString romFileName, QString zipFileName) { if (ddAction->isChecked() && ddView->currentItem() != NULL) { QString ddFileName = QVariant(ddView->currentItem()->data(0, 0)).toString(); QString ddDirName = QVariant(ddView->currentItem()->data(1, 0)).toString(); QString ddZipName = QVariant(ddView->currentItem()->data(4, 0)).toString(); emulation->startEmulator(romDir, romFileName, zipFileName, QDir(ddDirName), ddFileName, ddZipName); } else emulation->startEmulator(romDir, romFileName, zipFileName); } void MainWindow::launchRomFromMenu() { QString visibleLayout = layoutGroup->checkedAction()->data().toString(); if (visibleLayout == "Table View") launchRomFromTable(); else if (visibleLayout == "Grid View") launchRomFromWidget(gridLayout->itemAt(currentGridRom)->widget()); else if (visibleLayout == "List View") launchRomFromWidget(listLayout->itemAt(currentListRom)->widget()); } void MainWindow::launchRomFromTable() { if (tableView->currentItem() != NULL) { QString romFileName = QVariant(tableView->currentItem()->data(0, 0)).toString(); QString romDirName = QVariant(tableView->currentItem()->data(1, 0)).toString(); QString zipFileName = QVariant(tableView->currentItem()->data(4, 0)).toString(); launchRom(QDir(romDirName), romFileName, zipFileName); } else { launchRom(QDir(), "", ""); } } void MainWindow::launchRomFromWidget(QWidget *current) { QString romFileName = current->property("fileName").toString(); QString romDirName = current->property("directory").toString(); QString zipFileName = current->property("zipFile").toString(); launchRom(QDir(romDirName), romFileName, zipFileName); } void MainWindow::launchRomFromZip() { QString fileName = zipList->currentItem()->text(); zipDialog->close(); emulation->startEmulator(QDir(), fileName, openPath); } void MainWindow::openAbout() { AboutDialog aboutDialog(this); aboutDialog.exec(); } void MainWindow::openConverter() { V64Converter v64converter(romCollection->romPaths.at(0), this); } void MainWindow::openDeleteDialog() { scrapper = new TheGamesDBScrapper(this); scrapper->deleteGameInfo(getCurrentRomInfo(0), getCurrentRomInfo(2)); delete scrapper; romCollection->cachedRoms(); } void MainWindow::openDownloader() { DownloadDialog downloadDialog(getCurrentRomInfo(0), getCurrentRomInfo(1), getCurrentRomInfo(2), this); downloadDialog.exec(); romCollection->cachedRoms(); } void MainWindow::openLog() { if (emulation->lastOutput == "") { QMessageBox::information(this, "No Output", QString("There is no log. Either CEN64 has not ") + "yet run or there was no output from the last run."); } else { LogDialog logDialog(emulation->lastOutput, this); logDialog.exec(); } } void MainWindow::openSettings() { QString tableImageBefore = SETTINGS.value("Table/imagesize", "Medium").toString(); QString columnsBefore = SETTINGS.value("Table/columns", "Filename|Size").toString(); QString downloadBefore = SETTINGS.value("Other/downloadinfo", "").toString(); SettingsDialog settingsDialog(this, 0); settingsDialog.exec(); QString tableImageAfter = SETTINGS.value("Table/imagesize", "Medium").toString(); QString columnsAfter = SETTINGS.value("Table/columns", "Filename|Size").toString(); QString downloadAfter = SETTINGS.value("Other/downloadinfo", "").toString(); //Reset columns widths if user has selected different columns to display if (columnsBefore != columnsAfter) { SETTINGS.setValue("Table/width", ""); tableView->setColumnCount(3); tableView->setHeaderLabels(QStringList("")); } QStringList romSave = SETTINGS.value("Paths/roms","").toString().split("|"); if (romCollection->romPaths != romSave) { romCollection->updatePaths(romSave); romCollection->addRoms(); } else if (downloadBefore == "" && downloadAfter == "true") { romCollection->addRoms(); } else { if (tableImageBefore != tableImageAfter) romCollection->cachedRoms(true); else romCollection->cachedRoms(false); } if (SETTINGS.value("Paths/ddiplrom", "").toString() != "") { ddAction->setEnabled(true); } else { ddAction->setEnabled(false); ddAction->setChecked(false); update64DD(); } setGridBackground(); toggleMenus(true); } void MainWindow::openRom() { QString filter = "N64 ROMs ("; foreach (QString type, romCollection->getFileTypes(true)) filter += type + " "; filter += ");;All Files (*)"; openPath = QFileDialog::getOpenFileName(this, tr("Open ROM File"), romCollection->romPaths.at(0), filter); if (openPath != "") { if (QFileInfo(openPath).suffix() == "zip") { QStringList zippedFiles = getZippedFiles(openPath); QString last; int count = 0; foreach (QString file, zippedFiles) { QString ext = file.right(4).toLower(); if (romCollection->getFileTypes().contains("*" + ext)) { last = file; count++; } } if (count == 0) QMessageBox::information(this, tr("No ROMs"), tr("No ROMs found in ZIP file.")); else if (count == 1) emulation->startEmulator(QDir(QFileInfo(openPath).dir()), last, openPath); else { //More than one ROM in zip file, so let user select openZipDialog(zippedFiles); } } else emulation->startEmulator(QDir(QFileInfo(openPath).dir()), openPath); } } void MainWindow::openZipDialog(QStringList zippedFiles) { zipDialog = new QDialog(this); zipDialog->setWindowTitle(tr("Select ROM")); zipDialog->setMinimumSize(200, 150); zipDialog->resize(300, 150); zipLayout = new QGridLayout(zipDialog); zipLayout->setContentsMargins(5, 10, 5, 10); zipList = new QListWidget(zipDialog); foreach (QString file, zippedFiles) { QString ext = file.right(4); if (romCollection->getFileTypes().contains("*" + ext)) zipList->addItem(file); } zipList->setCurrentRow(0); zipButtonBox = new QDialogButtonBox(Qt::Horizontal, zipDialog); zipButtonBox->addButton(tr("Launch"), QDialogButtonBox::AcceptRole); zipButtonBox->addButton(QDialogButtonBox::Cancel); zipLayout->addWidget(zipList, 0, 0); zipLayout->addWidget(zipButtonBox, 1, 0); connect(zipList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(launchRomFromZip())); connect(zipButtonBox, SIGNAL(accepted()), this, SLOT(launchRomFromZip())); connect(zipButtonBox, SIGNAL(rejected()), zipDialog, SLOT(close())); zipDialog->setLayout(zipLayout); zipDialog->exec(); } void MainWindow::resetLayouts(bool imageUpdated) { QStringList tableVisible = SETTINGS.value("Table/columns", "Filename|Size").toString().split("|"); int hidden = 5; saveColumnWidths(); QStringList widths = SETTINGS.value("Table/width", "").toString().split("|"); headerLabels.clear(); headerLabels << "" << "" << "" << "" << "" << tableVisible; //First 5 blank for hidden columns //Remove Game Cover title for aesthetics for (int i = 0; i < headerLabels.size(); i++) if (headerLabels.at(i) == "Game Cover") headerLabels.replace(i, ""); tableView->setColumnCount(headerLabels.size()); tableView->setHeaderLabels(headerLabels); headerView->setSortIndicatorShown(false); int height = 0, width = 0; if (tableVisible.contains("Game Cover")) { //Get optimal height/width for cover column height = getImageSize("Table").height() * 1.1; width = getImageSize("Table").width() * 1.2; tableView->setStyleSheet("QTreeView { border: none; } QTreeView::item { height: " + QString::number(height) + "px; }"); } else tableView->setStyleSheet("QTreeView { border: none; } QTreeView::item { height: 25px; }"); QStringList sort = SETTINGS.value("Table/sort", "").toString().split("|"); if (sort.size() == 2) { if (sort[1] == "descending") headerView->setSortIndicator(tableVisible.indexOf(sort[0]) + hidden, Qt::DescendingOrder); else headerView->setSortIndicator(tableVisible.indexOf(sort[0]) + hidden, Qt::AscendingOrder); } tableView->setColumnHidden(0, true); //Hidden filename for launching emulator tableView->setColumnHidden(1, true); //Hidden directory of ROM location tableView->setColumnHidden(2, true); //Hidden goodname for searching tableView->setColumnHidden(3, true); //Hidden md5 for cache info tableView->setColumnHidden(4, true); //Hidden column for zip file int i = hidden; foreach (QString current, tableVisible) { if (i == hidden) { int c = i; if (current == "Game Cover") c++; //If first column is game cover, use next column if (SETTINGS.value("Table/stretchfirstcolumn", "true") == "true") #if QT_VERSION >= 0x050000 tableView->header()->setSectionResizeMode(c, QHeaderView::Stretch); #else tableView->header()->setResizeMode(c, QHeaderView::Stretch); #endif else #if QT_VERSION >= 0x050000 tableView->header()->setSectionResizeMode(c, QHeaderView::Interactive); #else tableView->header()->setResizeMode(c, QHeaderView::Interactive); #endif } if (widths.size() == tableVisible.size()) tableView->setColumnWidth(i, widths[i - hidden].toInt()); else tableView->setColumnWidth(i, getDefaultWidth(current, width)); //Overwrite saved value if switching image sizes if (imageUpdated && current == "Game Cover") tableView->setColumnWidth(i, width); i++; } //Reset grid view QLayoutItem *gridItem; while ((gridItem = gridLayout->takeAt(0)) != NULL) { delete gridItem->widget(); delete gridItem; } gridCurrent = false; //Reset list view QLayoutItem *listItem; while ((listItem = listLayout->takeAt(0)) != NULL) { delete listItem->widget(); delete listItem; } listCurrent = false; } void MainWindow::saveColumnWidths() { QStringList widths; for (int i = 5; i < tableView->columnCount(); i++) { widths << QString::number(tableView->columnWidth(i)); } if (widths.size() > 0) SETTINGS.setValue("Table/width", widths.join("|")); } void MainWindow::saveSortOrder(int column, Qt::SortOrder order) { QString columnName = headerLabels.value(column); if (order == Qt::DescendingOrder) SETTINGS.setValue("Table/sort", columnName + "|descending"); else SETTINGS.setValue("Table/sort", columnName + "|ascending"); } void MainWindow::setGridBackground() { gridView->setStyleSheet("#gridView { border: none; }"); QString background = SETTINGS.value("Grid/background", "").toString(); if (background != "") { QFile backgroundFile(background); if (backgroundFile.exists() && !QFileInfo(backgroundFile).isDir()) gridView->setStyleSheet(QString() + "#gridView { " + "border: none; " + "background: url(" + background + "); " + "background-attachment: fixed; " + "background-position: top center; " + "} #gridWidget { background: transparent; } " ); } } void MainWindow::setGridPosition() { gridView->horizontalScrollBar()->setValue(positionx); gridView->verticalScrollBar()->setValue(positiony); } void MainWindow::setListPosition() { listView->horizontalScrollBar()->setValue(positionx); listView->verticalScrollBar()->setValue(positiony); } void MainWindow::setTablePosition() { tableView->horizontalScrollBar()->setValue(positionx); tableView->verticalScrollBar()->setValue(positiony); } void MainWindow::stopEmulator() { emulation->stopEmulator(); } void MainWindow::toggleMenus(bool active) { foreach (QAction *next, menuEnable) next->setEnabled(active); foreach (QAction *next, menuDisable) next->setEnabled(!active); tableView->setEnabled(active); gridView->setEnabled(active); listView->setEnabled(active); if (tableView->currentItem() == NULL && !gridCurrent && !listCurrent && ddView->currentItem() == NULL) { downloadAction->setEnabled(false); deleteAction->setEnabled(false); startAction->setEnabled(false); } if (SETTINGS.value("Other/downloadinfo", "").toString() == "") { downloadAction->setEnabled(false); deleteAction->setEnabled(false); } if (SETTINGS.value("Paths/ddiplrom", "").toString() == "") ddAction->setEnabled(false); } void MainWindow::updateInputSetting() { SETTINGS.setValue("input", inputGroup->checkedAction()->data().toString()); } void MainWindow::updateLayoutSetting() { QString visibleLayout = layoutGroup->checkedAction()->data().toString(); SETTINGS.setValue("View/layout", visibleLayout); emptyView->setHidden(true); tableView->setHidden(true); gridView->setHidden(true); listView->setHidden(true); ddView->setHidden(true); romCollection->cachedRoms(); if (visibleLayout == "Table View") tableView->setHidden(false); else if (visibleLayout == "Grid View") gridView->setHidden(false); else if (visibleLayout == "List View") listView->setHidden(false); else emptyView->setHidden(false); //Don't snow 64DD panel for empty view QString ddipl = SETTINGS.value("Paths/ddiplrom", "").toString(); QString ddEnabled = SETTINGS.value("Emulation/64dd", "").toString(); if (visibleLayout != "None" && ddipl != "" && ddEnabled == "true") ddView->setHidden(false); startAction->setEnabled(false); downloadAction->setEnabled(false); deleteAction->setEnabled(false); } void MainWindow::update64DD() { QString ddipl = SETTINGS.value("Paths/ddiplrom", "").toString(); if(ddAction->isChecked() && ddipl != "") { SETTINGS.setValue("Emulation/64dd", true); if (SETTINGS.value("View/layout", "None").toString() != "None") ddView->setHidden(false); viewSplitter->setSizes(QList() << 500 << 500 << 500 << 500 << 100); } else { SETTINGS.setValue("Emulation/64dd", ""); ddView->setHidden(true); } romCollection->cachedRoms(); } void MainWindow::updateStatusBar(QString message, int timeout) { statusBar->showMessage(message, timeout); } void MainWindow::updateStatusBarView() { if(statusBarAction->isChecked()) { SETTINGS.setValue("View/statusbar", true); statusBar->show(); } else { SETTINGS.setValue("View/statusbar", ""); statusBar->hide(); } } cen64-qt-20150915-alpha/src/mainwindow.h000066400000000000000000000122711257603330000175240ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include #include "aboutdialog.h" #include "clickablewidget.h" #include "common.h" #include "downloaddialog.h" #include "emulatorhandler.h" #include "global.h" #include "logdialog.h" #include "romcollection.h" #include "settingsdialog.h" #include "treewidgetitem.h" #include "v64converter.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); protected: void closeEvent(QCloseEvent *event); private: void addToGridView(Rom *currentRom, int count); void addToListView(Rom *currentRom, int count); void addToTableView(Rom *currentRom); void createMenu(); void createRomView(); void launchRom(QDir romDir, QString romFileName, QString zipFileName); void openZipDialog(QStringList zippedFiles); void resetLayouts(bool imageUpdated = false); void saveColumnWidths(); void setGridBackground(); void toggleMenus(bool active); int currentGridRom; int currentListRom; int positionx; int positiony; bool gridCurrent; bool listCurrent; QString getCurrentRomInfo(int index); QString openPath; QStringList headerLabels; QAction *aboutAction; QAction *configureAction; QAction *convertAction; QAction *deleteAction; QAction *downloadAction; QAction *logAction; QAction *ddAction; QAction *openAction; QAction *quitAction; QAction *refreshAction; QAction *startAction; QAction *statusBarAction; QAction *stopAction; QActionGroup *inputGroup; QActionGroup *layoutGroup; QDialog *zipDialog; QDialogButtonBox *zipButtonBox; QGridLayout *emptyLayout; QGridLayout *gridLayout; QGridLayout *zipLayout; QHeaderView *headerView; QHeaderView *ddHeaderView; QLabel *emptyIcon; QList menuEnable; QList menuDisable; QListWidget *zipList; QMenu *emulationMenu; QMenu *fileMenu; QMenu *helpMenu; QMenu *inputMenu; QMenu *layoutMenu; QMenu *settingsMenu; QMenu *viewMenu; QMenuBar *menuBar; QScrollArea *emptyView; QScrollArea *listView; QScrollArea *gridView; QSplitter *viewSplitter; QStatusBar *statusBar; QTreeWidget *ddView; QTreeWidget *tableView; QVBoxLayout *listLayout; QVBoxLayout *mainLayout; QWidget *gridWidget; QWidget *listWidget; QWidget *mainWidget; EmulatorHandler *emulation; RomCollection *romCollection; TheGamesDBScrapper *scrapper; TreeWidgetItem *fileItem; private slots: void addTo64DDView(Rom *currentRom); void addToView(Rom *currentRom, int count); void disableButtons(); void disableViews(bool imageUpdated); void enableButtons(); void enableViews(int romCount, bool cached); void highlightGridWidget(QWidget *current); void highlightListWidget(QWidget *current); void launchRomFromMenu(); void launchRomFromTable(); void launchRomFromWidget(QWidget *current); void launchRomFromZip(); void openAbout(); void openConverter(); void openDeleteDialog(); void openDownloader(); void openLog(); void openSettings(); void openRom(); void saveSortOrder(int column, Qt::SortOrder order); void setGridPosition(); void setListPosition(); void setTablePosition(); void stopEmulator(); void updateInputSetting(); void updateLayoutSetting(); void update64DD(); void updateStatusBar(QString message, int timeout); void updateStatusBarView(); }; #endif // MAINWINDOW_H cen64-qt-20150915-alpha/src/romcollection.cpp000066400000000000000000000377461257603330000205720ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "romcollection.h" RomCollection::RomCollection(QStringList fileTypes, QStringList romPaths, QWidget *parent) : QObject(parent) { this->fileTypes = fileTypes; this->romPaths = romPaths; this->romPaths.removeAll(""); this->parent = parent; setupDatabase(); } Rom RomCollection::addRom(QByteArray *romData, QString fileName, QString directory, QString zipFile, QSqlQuery query, bool ddRom) { Rom currentRom; currentRom.fileName = fileName; currentRom.directory = directory; if (ddRom) currentRom.internalName = ""; else currentRom.internalName = QString(romData->mid(32, 20)).trimmed(); currentRom.romMD5 = QString(QCryptographicHash::hash(*romData, QCryptographicHash::Md5).toHex()); currentRom.zipFile = zipFile; currentRom.sortSize = romData->size(); query.bindValue(":filename", currentRom.fileName); query.bindValue(":directory", currentRom.directory); query.bindValue(":internal_name", currentRom.internalName); query.bindValue(":md5", currentRom.romMD5); query.bindValue(":zip_file", currentRom.zipFile); query.bindValue(":size", currentRom.sortSize); if (ddRom) query.bindValue(":dd_rom", 1); else query.bindValue(":dd_rom", 0); query.exec(); if (!ddRom) initializeRom(¤tRom, false); return currentRom; } void RomCollection::addRoms() { emit updateStarted(); //Count files so we know how to setup the progress dialog int totalCount = 0; foreach (QString romPath, romPaths) { QDir romDir(romPath); if (romDir.exists()) { QStringList files = romDir.entryList(fileTypes, QDir::Files | QDir::NoSymLinks); totalCount += files.size(); } } QList roms; QList ddRoms; if (totalCount != 0) { int count = 0; setupProgressDialog(totalCount); database.open(); QSqlQuery query("DELETE FROM rom_collection", database); query.prepare(QString("INSERT INTO rom_collection ") + "(filename, directory, internal_name, md5, zip_file, size, dd_rom) " + "VALUES (:filename, :directory, :internal_name, :md5, :zip_file, :size, :dd_rom)"); scrapper = new TheGamesDBScrapper(parent); foreach (QString romPath, romPaths) { QDir romDir(romPath); QStringList files = romDir.entryList(fileTypes, QDir::Files | QDir::NoSymLinks); int romCount = 0; foreach (QString fileName, files) { QString completeFileName = romDir.absoluteFilePath(fileName); QFile file(completeFileName); //If file is a zip file, extract info from any zipped ROMs if (QFileInfo(file).suffix().toLower() == "zip") { foreach (QString zippedFile, getZippedFiles(completeFileName)) { //check for ROM files QByteArray *romData = getZippedRom(zippedFile, completeFileName); if (romData->left(4).toHex() == "80371240") { //Z64 ROM roms.append(addRom(romData, zippedFile, romPath, fileName, query)); romCount++; } else if (romData->left(4).toHex() == "e848d316") { //64DD ROM ddRoms.append(addRom(romData, zippedFile, romPath, fileName, query, true)); romCount++; } delete romData; } } else { //Just a normal file file.open(QIODevice::ReadOnly); QByteArray *romData = new QByteArray(file.readAll()); file.close(); if (romData->left(4).toHex() == "80371240") { //Z64 ROM roms.append(addRom(romData, fileName, romPath, "", query)); romCount++; } else if (romData->left(4).toHex() == "e848d316") { //64DD ROM ddRoms.append(addRom(romData, fileName, romPath, "", query, true)); romCount++; } delete romData; } count++; progress->setValue(count); QCoreApplication::processEvents(QEventLoop::AllEvents); } if (romCount == 0) QMessageBox::warning(parent, "Warning", "No ROMs found in " + romPath + "."); } delete scrapper; database.close(); progress->close(); } else if (romPaths.size() != 0) { QMessageBox::warning(parent, "Warning", "No ROMs found."); } //Emit signals for regular roms qSort(roms.begin(), roms.end(), romSorter); for (int i = 0; i < roms.size(); i++) emit romAdded(&roms[i], i); //Emit signals for 64DD roms qSort(ddRoms.begin(), ddRoms.end(), romSorter); for (int i = 0; i < ddRoms.size(); i++) emit ddRomAdded(&ddRoms[i]); emit updateEnded(roms.size()); } void RomCollection::cachedRoms(bool imageUpdated) { emit updateStarted(imageUpdated); database.open(); QSqlQuery query(QString("SELECT filename, directory, md5, internal_name, zip_file, size, dd_rom ") + "FROM rom_collection", database); query.last(); int romCount = query.at() + 1; query.seek(-1); if (romCount == -1) { //Nothing cached so try adding ROMs instead addRoms(); return; } QList roms; QList ddRoms; int count = 0; bool showProgress = false; QTime checkPerformance; while (query.next()) { Rom currentRom; currentRom.fileName = query.value(0).toString(); currentRom.directory = query.value(1).toString(); currentRom.romMD5 = query.value(2).toString(); currentRom.internalName = query.value(3).toString(); currentRom.zipFile = query.value(4).toString(); currentRom.sortSize = query.value(5).toInt(); int ddRom = query.value(6).toInt(); //Check performance of adding first item to see if progress dialog needs to be shown if (count == 0) checkPerformance.start(); if (ddRom == 1) ddRoms.append(currentRom); else { initializeRom(¤tRom, true); roms.append(currentRom); } if (count == 0) { int runtime = checkPerformance.elapsed(); //check if operation expected to take longer than two seconds if (runtime * romCount > 2000) { setupProgressDialog(romCount); showProgress = true; } } count++; if (showProgress) { progress->setValue(count); QCoreApplication::processEvents(QEventLoop::AllEvents); } } database.close(); if (showProgress) progress->close(); //Emit signals for regular roms qSort(roms.begin(), roms.end(), romSorter); for (int i = 0; i < roms.size(); i++) emit romAdded(&roms[i], i); //Emit signals for 64DD roms qSort(ddRoms.begin(), ddRoms.end(), romSorter); for (int i = 0; i < ddRoms.size(); i++) emit ddRomAdded(&ddRoms[i]); emit updateEnded(roms.size(), true); } QStringList RomCollection::getFileTypes(bool archives) { QStringList returnList = fileTypes; if (!archives) returnList.removeOne("*.zip"); return returnList; } void RomCollection::initializeRom(Rom *currentRom, bool cached) { QSettings *romCatalog = new QSettings(parent); QString catalogFile = SETTINGS.value("Paths/catalog", "").toString(); QDir romDir(currentRom->directory); //Default text for GoodName to notify user currentRom->goodName = "Requires catalog file"; currentRom->imageExists = false; bool getGoodName = false; if (QFileInfo(catalogFile).exists()) { romCatalog = new QSettings(catalogFile, QSettings::IniFormat, parent); getGoodName = true; } QFile file(romDir.absoluteFilePath(currentRom->fileName)); currentRom->romMD5 = currentRom->romMD5.toUpper(); currentRom->baseName = QFileInfo(file).completeBaseName(); currentRom->size = QObject::tr("%1 MB").arg((currentRom->sortSize + 1023) / 1024 / 1024); if (getGoodName) { //Join GoodName on ", ", otherwise entries with a comma won't show QVariant goodNameVariant = romCatalog->value(currentRom->romMD5+"/GoodName","Unknown ROM"); currentRom->goodName = goodNameVariant.toStringList().join(", "); QStringList CRC = romCatalog->value(currentRom->romMD5+"/CRC","").toString().split(" "); if (CRC.size() == 2) { currentRom->CRC1 = CRC[0]; currentRom->CRC2 = CRC[1]; } QString newMD5 = romCatalog->value(currentRom->romMD5+"/RefMD5","").toString(); if (newMD5 == "") newMD5 = currentRom->romMD5; currentRom->players = romCatalog->value(newMD5+"/Players","").toString(); currentRom->saveType = romCatalog->value(newMD5+"/SaveType","").toString(); currentRom->rumble = romCatalog->value(newMD5+"/Rumble","").toString(); } if (!cached && SETTINGS.value("Other/downloadinfo", "").toString() == "true") { if (currentRom->goodName != "Unknown ROM" && currentRom->goodName != "Requires catalog file") { scrapper->downloadGameInfo(currentRom->romMD5, currentRom->goodName); } else { //tweak internal name by adding spaces to get better results QString search = currentRom->internalName; search.replace(QRegExp("([a-z])([A-Z])"),"\\1 \\2"); search.replace(QRegExp("([^ \\d])(\\d)"),"\\1 \\2"); scrapper->downloadGameInfo(currentRom->romMD5, search); } } if (SETTINGS.value("Other/downloadinfo", "").toString() == "true") { QString cacheDir = getDataLocation() + "/cache"; QString dataFile = cacheDir + "/" + currentRom->romMD5.toLower() + "/data.xml"; QFile file(dataFile); file.open(QIODevice::ReadOnly); QString dom = file.readAll(); file.close(); QDomDocument xml; xml.setContent(dom); QDomNode game = xml.elementsByTagName("Game").at(0); //Remove any non-standard characters QString regex = "[^A-Za-z 0-9 \\.,\\?'""!@#\\$%\\^&\\*\\(\\)-_=\\+;:<>\\/\\\\|\\}\\{\\[\\]`~]*"; currentRom->gameTitle = game.firstChildElement("GameTitle").text().remove(QRegExp(regex)); if (currentRom->gameTitle == "") currentRom->gameTitle = "Not found"; currentRom->releaseDate = game.firstChildElement("ReleaseDate").text(); //Fix missing 0's in date currentRom->releaseDate.replace(QRegExp("^(\\d)/(\\d{2})/(\\d{4})"), "0\\1/\\2/\\3"); currentRom->releaseDate.replace(QRegExp("^(\\d{2})/(\\d)/(\\d{4})"), "\\1/0\\2/\\3"); currentRom->releaseDate.replace(QRegExp("^(\\d)/(\\d)/(\\d{4})"), "0\\1/0\\2/\\3"); currentRom->sortDate = currentRom->releaseDate; currentRom->sortDate.replace(QRegExp("(\\d{2})/(\\d{2})/(\\d{4})"), "\\3-\\1-\\2"); currentRom->overview = game.firstChildElement("Overview").text().remove(QRegExp(regex)); currentRom->esrb = game.firstChildElement("ESRB").text(); int count = 0; QDomNode genreNode = game.firstChildElement("Genres").firstChild(); while(!genreNode.isNull()) { if (count != 0) currentRom->genre += "/" + genreNode.toElement().text(); else currentRom->genre = genreNode.toElement().text(); genreNode = genreNode.nextSibling(); count++; } currentRom->publisher = game.firstChildElement("Publisher").text(); currentRom->developer = game.firstChildElement("Developer").text(); currentRom->rating = game.firstChildElement("Rating").text(); foreach (QString ext, QStringList() << "jpg" << "png") { QString imageFile = getDataLocation() + "/cache/" + currentRom->romMD5.toLower() + "/boxart-front." + ext; QFile cover(imageFile); if (cover.exists()&& currentRom->image.load(imageFile)) { currentRom->imageExists = true; break; } } } } void RomCollection::setupDatabase() { // Bump this when updating rom_collection structure // Will cause clients to delete and recreate the table int dbVersion = 1; database = QSqlDatabase::addDatabase("QSQLITE"); database.setDatabaseName(getDataLocation() + "/cen64-qt.sqlite"); if (!database.open()) QMessageBox::warning(parent, "Database Not Loaded", "Could not connect to Sqlite database. Application may misbehave."); QSqlQuery version = database.exec("PRAGMA user_version"); version.next(); if (version.value(0).toInt() != dbVersion) { //old database version, reset rom_collection version.finish(); database.exec("DROP TABLE rom_collection"); database.exec("PRAGMA user_version = " + QString::number(dbVersion)); } database.exec(QString() + "CREATE TABLE IF NOT EXISTS rom_collection (" + "rom_id INTEGER PRIMARY KEY ASC, " + "filename TEXT NOT NULL, " + "directory TEXT NOT NULL, " + "md5 TEXT NOT NULL, " + "internal_name TEXT, " + "zip_file TEXT, " + "size INTEGER, " + "dd_rom INTEGER)"); database.close(); } void RomCollection::setupProgressDialog(int size) { progress = new QProgressDialog("Loading ROMs...", "Cancel", 0, size, parent); #if QT_VERSION >= 0x050000 progress->setWindowFlags(progress->windowFlags() & ~Qt::WindowCloseButtonHint); progress->setWindowFlags(progress->windowFlags() & ~Qt::WindowMinimizeButtonHint); progress->setWindowFlags(progress->windowFlags() & ~Qt::WindowContextHelpButtonHint); #else progress->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint); #endif progress->setCancelButton(0); progress->setWindowModality(Qt::WindowModal); progress->show(); } void RomCollection::updatePaths(QStringList romPaths) { this->romPaths = romPaths; this->romPaths.removeAll(""); } cen64-qt-20150915-alpha/src/romcollection.h000066400000000000000000000054451257603330000202260ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef ROMCOLLECTION_H #define ROMCOLLECTION_H #include #include #include #include #include #include "common.h" #include "global.h" #include "thegamesdbscrapper.h" class RomCollection : public QObject { Q_OBJECT public: explicit RomCollection(QStringList fileTypes, QStringList romPaths, QWidget *parent = 0); void cachedRoms(bool imageUpdated = false); void updatePaths(QStringList romPaths); QStringList getFileTypes(bool archives = false); QStringList romPaths; public slots: void addRoms(); signals: void ddRomAdded(Rom *currentRom); void romAdded(Rom *currentRom, int count); void updateEnded(int romCount, bool cached = false); void updateStarted(bool imageUpdated = false); private: void initializeRom(Rom *currentRom, bool cached); void setupDatabase(); void setupProgressDialog(int size); Rom addRom(QByteArray *romData, QString fileName, QString directory, QString zipFile, QSqlQuery query, bool ddRom = false); QStringList fileTypes; QWidget *parent; QProgressDialog *progress; QSqlDatabase database; TheGamesDBScrapper *scrapper; }; #endif // ROMCOLLECTION_H cen64-qt-20150915-alpha/src/settingsdialog.cpp000066400000000000000000000525131257603330000207260ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "settingsdialog.h" #include "ui_settingsdialog.h" SettingsDialog::SettingsDialog(QWidget *parent, int activeTab) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); ui->tabWidget->setCurrentIndex(activeTab); //Populate Paths tab ui->cen64Path->setText(SETTINGS.value("Paths/cen64", "").toString()); ui->pifPath->setText(SETTINGS.value("Paths/pifrom", "").toString()); ui->ddPath->setText(SETTINGS.value("Paths/ddiplrom", "").toString()); ui->catalogPath->setText(SETTINGS.value("Paths/catalog", "").toString()); QStringList romDirectories = SETTINGS.value("Paths/roms", "").toString().split("|"); romDirectories.removeAll(""); foreach (QString directory, romDirectories) ui->romList->addItem(directory); ui->savesPath->setText(SETTINGS.value("Saves/directory", "").toString()); ui->eepromPath->setText(SETTINGS.value("Saves/eeprom", "").toString()); ui->sramPath->setText(SETTINGS.value("Saves/sram", "").toString()); //Widgets enabled when save checkbox is active saveEnable << ui->eepromPathLabel << ui->eepromPath << ui->eepromButton << ui->sramPathLabel << ui->sramPath << ui->sramButton; //Widgets disabled when save checkbox is active saveDisable << ui->savesPathLabel << ui->savesPath << ui->savesButton; if (SETTINGS.value("Saves/individualsave", "").toString() == "true") { toggleSaves(true); ui->saveOption->setChecked(true); } else toggleSaves(false); connect(ui->cen64Button, SIGNAL(clicked()), this, SLOT(browseCen64())); connect(ui->pifButton, SIGNAL(clicked()), this, SLOT(browsePIF())); connect(ui->ddButton, SIGNAL(clicked()), this, SLOT(browse64DD())); connect(ui->catalogButton, SIGNAL(clicked()), this, SLOT(browseCatalog())); connect(ui->romAddButton, SIGNAL(clicked()), this, SLOT(addRomDirectory())); connect(ui->romRemoveButton, SIGNAL(clicked()), this, SLOT(removeRomDirectory())); connect(ui->savesButton, SIGNAL(clicked()), this, SLOT(browseSaves())); connect(ui->eepromButton, SIGNAL(clicked()), this, SLOT(browseEEPROM())); connect(ui->sramButton, SIGNAL(clicked()), this, SLOT(browseSRAM())); connect(ui->saveOption, SIGNAL(toggled(bool)), this, SLOT(toggleSaves(bool))); //Populate Table tab QStringList sizes; sizes << "Extra Small" << "Small" << "Medium" << "Large" << "Extra Large"; if (SETTINGS.value("Other/downloadinfo", "").toString() == "true") populateTableAndListTab(true); else populateTableAndListTab(false); if (SETTINGS.value("Table/stretchfirstcolumn", "true").toString() == "true") ui->tableStretchOption->setChecked(true); ui->tableSizeBox->insertItems(0, sizes); int tableSizeIndex = sizes.indexOf(SETTINGS.value("Table/imagesize","Medium").toString()); if (tableSizeIndex >= 0) ui->tableSizeBox->setCurrentIndex(tableSizeIndex); connect(ui->tableAddButton, SIGNAL(clicked()), this, SLOT(tableAddColumn())); connect(ui->tableRemoveButton, SIGNAL(clicked()), this, SLOT(tableRemoveColumn())); connect(ui->tableSortUpButton, SIGNAL(clicked()), this, SLOT(tableSortUp())); connect(ui->tableSortDownButton, SIGNAL(clicked()), this, SLOT(tableSortDown())); //Populate Grid tab QStringList colors; colors << "Black" << "White" << "Light Gray" << "Dark Gray" << "Green" << "Cyan" << "Blue" << "Purple" << "Red" << "Pink" << "Orange" << "Yellow" << "Brown"; ui->gridSizeBox->insertItems(0, sizes); int gridSizeIndex = sizes.indexOf(SETTINGS.value("Grid/imagesize","Medium").toString()); if (gridSizeIndex >= 0) ui->gridSizeBox->setCurrentIndex(gridSizeIndex); int gridColumnCount = SETTINGS.value("Grid/columncount","4").toInt(); ui->columnCountBox->setValue(gridColumnCount); ui->shadowActiveBox->insertItems(0, colors); int activeIndex = colors.indexOf(SETTINGS.value("Grid/activecolor","Cyan").toString()); if (activeIndex >= 0) ui->shadowActiveBox->setCurrentIndex(activeIndex); ui->shadowInactiveBox->insertItems(0, colors); int inactiveIndex = colors.indexOf(SETTINGS.value("Grid/inactivecolor","Black").toString()); if (inactiveIndex >= 0) ui->shadowInactiveBox->setCurrentIndex(inactiveIndex); //Widgets to enable when label active labelEnable << ui->labelTextLabel << ui->labelTextBox << ui->labelColorLabel << ui->labelColorBox; if (SETTINGS.value("Grid/label", "true").toString() == "true") { toggleLabel(true); ui->labelOption->setChecked(true); } else toggleLabel(false); ui->labelColorBox->insertItems(0, colors); int labelColorIndex = colors.indexOf(SETTINGS.value("Grid/labelcolor","White").toString()); if (labelColorIndex >= 0) ui->labelColorBox->setCurrentIndex(labelColorIndex); ui->backgroundPath->setText(SETTINGS.value("Grid/background", "").toString()); if (SETTINGS.value("Grid/sortdirection", "ascending").toString() == "descending") ui->gridDescendingOption->setChecked(true); connect(ui->backgroundButton, SIGNAL(clicked()), this, SLOT(browseBackground())); connect(ui->labelOption, SIGNAL(toggled(bool)), this, SLOT(toggleLabel(bool))); //Populate List tab listCoverEnable << ui->listSizeLabel << ui->listSizeBox; if (SETTINGS.value("List/displaycover", "").toString() == "true") { toggleListCover(true); ui->listCoverOption->setChecked(true); } else toggleListCover(false); if (SETTINGS.value("List/firstitemheader", "true").toString() == "true") ui->listHeaderOption->setChecked(true); ui->listSizeBox->insertItems(0, sizes); int listSizeIndex = sizes.indexOf(SETTINGS.value("List/imagesize","Medium").toString()); if (listSizeIndex >= 0) ui->listSizeBox->setCurrentIndex(listSizeIndex); if (SETTINGS.value("List/sortdirection", "ascending").toString() == "descending") ui->listDescendingOption->setChecked(true); connect(ui->listCoverOption, SIGNAL(toggled(bool)), this, SLOT(toggleListCover(bool))); connect(ui->listAddButton, SIGNAL(clicked()), this, SLOT(listAddColumn())); connect(ui->listRemoveButton, SIGNAL(clicked()), this, SLOT(listRemoveColumn())); connect(ui->listSortUpButton, SIGNAL(clicked()), this, SLOT(listSortUp())); connect(ui->listSortDownButton, SIGNAL(clicked()), this, SLOT(listSortDown())); //Populate Other tab downloadEnable << ui->tableSizeLabel << ui->tableSizeBox << ui->listCoverOption << ui->listSizeLabel << ui->listSizeBox; if (SETTINGS.value("Other/downloadinfo", "").toString() == "true") { toggleDownload(true); ui->downloadOption->setChecked(true); } else toggleDownload(false); if (SETTINGS.value("Other/consoleoutput", "").toString() == "true") ui->outputOption->setChecked(true); #ifdef Q_OS_WIN //Remove when Other tab has options on Windows ui->outputLabel->setVisible(false); ui->outputOption->setVisible(false); #endif ui->parametersLine->setText(SETTINGS.value("Other/parameters", "").toString()); connect(ui->downloadOption, SIGNAL(toggled(bool)), this, SLOT(toggleDownload(bool))); connect(ui->downloadOption, SIGNAL(toggled(bool)), this, SLOT(populateTableAndListTab(bool))); connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(editSettings())); connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } SettingsDialog::~SettingsDialog() { delete ui; } void SettingsDialog::addColumn(QListWidget *currentList, QListWidget *availableList) { int row = availableList->currentRow(); if (row >= 0) { currentList->addItem(availableList->currentItem()->text()); delete availableList->takeItem(row); } } void SettingsDialog::addRomDirectory() { QString path = QFileDialog::getExistingDirectory(this, tr("ROM Directory")); if (path != "") { //check for duplicates bool found = false; foreach (QListWidgetItem *item, ui->romList->findItems("*", Qt::MatchWildcard)) if (path == item->text()) found = true; if (!found) ui->romList->addItem(path); } } void SettingsDialog::browse64DD() { QString path = QFileDialog::getOpenFileName(this, tr("64DD IPL ROM File")); if (path != "") ui->ddPath->setText(path); } void SettingsDialog::browseBackground() { QString path = QFileDialog::getOpenFileName(this, tr("Background Image")); if (path != "") ui->backgroundPath->setText(path); } void SettingsDialog::browseCatalog() { QString path = QFileDialog::getOpenFileName(this, tr("Catalog File")); if (path != "") ui->catalogPath->setText(path); } void SettingsDialog::browseCen64() { QString path = QFileDialog::getOpenFileName(this, tr("CEN64 Executable")); if (path != "") ui->cen64Path->setText(path); } void SettingsDialog::browseEEPROM() { QString path = QFileDialog::getOpenFileName(this, tr("EEPROM File")); if (path != "") ui->eepromPath->setText(path); } void SettingsDialog::browsePIF() { QString path = QFileDialog::getOpenFileName(this, tr("PIF IPL ROM File")); if (path != "") ui->pifPath->setText(path); } void SettingsDialog::browseSaves() { QString path = QFileDialog::getExistingDirectory(this, tr("Save Directory")); if (path != "") ui->savesPath->setText(path); } void SettingsDialog::browseSRAM() { QString path = QFileDialog::getOpenFileName(this, tr("SRAM File")); if (path != "") ui->sramPath->setText(path); } void SettingsDialog::editSettings() { //Set download option first if (ui->downloadOption->isChecked()) { SETTINGS.setValue("Other/downloadinfo", true); populateAvailable(true); //This removes thegamesdb.net options if user unselects download } else { SETTINGS.setValue("Other/downloadinfo", ""); populateAvailable(false); } //Paths tab SETTINGS.setValue("Paths/cen64", ui->cen64Path->text()); SETTINGS.setValue("Paths/pifrom", ui->pifPath->text()); SETTINGS.setValue("Paths/ddiplrom", ui->ddPath->text()); SETTINGS.setValue("Paths/catalog", ui->catalogPath->text()); SETTINGS.setValue("Saves/directory", ui->savesPath->text()); SETTINGS.setValue("Saves/eeprom", ui->eepromPath->text()); SETTINGS.setValue("Saves/sram", ui->sramPath->text()); QStringList romDirectories; foreach (QListWidgetItem *item, ui->romList->findItems("*", Qt::MatchWildcard)) romDirectories << item->text(); SETTINGS.setValue("Paths/roms", romDirectories.join("|")); if (ui->saveOption->isChecked()) SETTINGS.setValue("Saves/individualsave", true); else SETTINGS.setValue("Saves/individualsave", ""); //Table tab QStringList tableVisibleItems; foreach (QListWidgetItem *item, ui->tableCurrentList->findItems("*", Qt::MatchWildcard)) if (available.contains(item->text())) tableVisibleItems << item->text(); SETTINGS.setValue("Table/columns", tableVisibleItems.join("|")); if (ui->tableStretchOption->isChecked()) SETTINGS.setValue("Table/stretchfirstcolumn", true); else SETTINGS.setValue("Table/stretchfirstcolumn", ""); SETTINGS.setValue("Table/imagesize", ui->tableSizeBox->currentText()); //Grid tab SETTINGS.setValue("Grid/imagesize", ui->gridSizeBox->currentText()); SETTINGS.setValue("Grid/columncount", ui->columnCountBox->value()); SETTINGS.setValue("Grid/inactivecolor", ui->shadowInactiveBox->currentText()); SETTINGS.setValue("Grid/activecolor", ui->shadowActiveBox->currentText()); SETTINGS.setValue("Grid/background", ui->backgroundPath->text()); if (ui->labelOption->isChecked()) SETTINGS.setValue("Grid/label", true); else SETTINGS.setValue("Grid/label", ""); SETTINGS.setValue("Grid/labeltext", ui->labelTextBox->currentText()); SETTINGS.setValue("Grid/labelcolor", ui->labelColorBox->currentText()); SETTINGS.setValue("Grid/sort", ui->gridSortBox->currentText()); if (ui->gridDescendingOption->isChecked()) SETTINGS.setValue("Grid/sortdirection", "descending"); else SETTINGS.setValue("Grid/sortdirection", "ascending"); //List tab QStringList listVisibleItems; foreach (QListWidgetItem *item, ui->listCurrentList->findItems("*", Qt::MatchWildcard)) if (available.contains(item->text())) listVisibleItems << item->text(); SETTINGS.setValue("List/columns", listVisibleItems.join("|")); if (ui->listHeaderOption->isChecked()) SETTINGS.setValue("List/firstitemheader", true); else SETTINGS.setValue("List/firstitemheader", ""); if (ui->listCoverOption->isChecked() && ui->downloadOption->isChecked()) SETTINGS.setValue("List/displaycover", true); else SETTINGS.setValue("List/displaycover", ""); SETTINGS.setValue("List/imagesize", ui->listSizeBox->currentText()); SETTINGS.setValue("List/sort", ui->listSortBox->currentText()); if (ui->listDescendingOption->isChecked()) SETTINGS.setValue("List/sortdirection", "descending"); else SETTINGS.setValue("List/sortdirection", "ascending"); //Other tab #ifndef Q_OS_WIN if (ui->outputOption->isChecked()) SETTINGS.setValue("Other/consoleoutput", true); else SETTINGS.setValue("Other/consoleoutput", ""); #endif SETTINGS.setValue("Other/parameters", ui->parametersLine->text()); close(); } void SettingsDialog::listAddColumn() { addColumn(ui->listCurrentList, ui->listAvailableList); } void SettingsDialog::listRemoveColumn() { removeColumn(ui->listCurrentList, ui->listAvailableList); } void SettingsDialog::listSortDown() { sortDown(ui->listCurrentList); } void SettingsDialog::listSortUp() { sortUp(ui->listCurrentList); } void SettingsDialog::populateAvailable(bool downloadItems) { available.clear(); labelOptions.clear(); sortOptions.clear(); available << "Filename" << "Filename (extension)" << "Zip File" << "GoodName" << "Internal Name" << "Size" << "MD5" << "CRC1" << "CRC2" << "Players" << "Rumble" << "Save Type"; labelOptions << "Filename" << "Filename (extension)" << "GoodName" << "Internal Name"; sortOptions << "Filename" << "GoodName" << "Internal Name" << "Size"; if (downloadItems) { available << "Game Title" << "Release Date" << "Overview" << "ESRB" << "Genre" << "Publisher" << "Developer" << "Rating" << "Game Cover"; labelOptions << "Game Title" << "Release Date" << "Genre"; sortOptions << "Game Title" << "Release Date" << "ESRB" << "Genre" << "Publisher" << "Developer" << "Rating"; } available.sort(); labelOptions.sort(); sortOptions.sort(); } void SettingsDialog::populateTableAndListTab(bool downloadItems) { populateAvailable(downloadItems); //Table columns and sort fields QStringList tableCurrent, tableAvailable; tableCurrent = SETTINGS.value("Table/columns", "Filename|Size").toString().split("|"); tableAvailable = available; foreach (QString cur, tableCurrent) { if (tableAvailable.contains(cur)) tableAvailable.removeOne(cur); else //Someone added an invalid item tableCurrent.removeOne(cur); } ui->tableAvailableList->clear(); ui->tableAvailableList->addItems(tableAvailable); ui->tableAvailableList->sortItems(); ui->tableCurrentList->clear(); ui->tableCurrentList->addItems(tableCurrent); //Grid sort field and label text ui->labelTextBox->clear(); ui->labelTextBox->insertItems(0, labelOptions); int labelTextIndex = labelOptions.indexOf(SETTINGS.value("Grid/labeltext","Filename").toString()); if (labelTextIndex >= 0) ui->labelTextBox->setCurrentIndex(labelTextIndex); ui->gridSortBox->clear(); ui->gridSortBox->insertItems(0, sortOptions); int gridSortIndex = sortOptions.indexOf(SETTINGS.value("Grid/sort","Filename").toString()); if (gridSortIndex >= 0) ui->gridSortBox->setCurrentIndex(gridSortIndex); //List items and sort field QStringList listCurrent, listAvailable; listCurrent = SETTINGS.value("List/columns", "Filename|Internal Name|Size").toString().split("|"); listAvailable = available; listAvailable.removeOne("Game Cover"); //Game Cover handled separately foreach (QString cur, listCurrent) { if (listAvailable.contains(cur)) listAvailable.removeOne(cur); else //Someone added an invalid item listCurrent.removeOne(cur); } ui->listAvailableList->clear(); ui->listAvailableList->addItems(listAvailable); ui->listAvailableList->sortItems(); ui->listCurrentList->clear(); ui->listCurrentList->addItems(listCurrent); ui->listSortBox->clear(); ui->listSortBox->insertItems(0, sortOptions); int listSortIndex = sortOptions.indexOf(SETTINGS.value("List/sort","Filename").toString()); if (listSortIndex >= 0) ui->listSortBox->setCurrentIndex(listSortIndex); } void SettingsDialog::removeColumn(QListWidget *currentList, QListWidget *availableList) { int row = currentList->currentRow(); if (row >= 0) { availableList->addItem(currentList->currentItem()->text()); delete currentList->takeItem(row); availableList->sortItems(); } } void SettingsDialog::removeRomDirectory() { int row = ui->romList->currentRow(); if (row >= 0) delete ui->romList->takeItem(row); } void SettingsDialog::sortDown(QListWidget *currentList) { int row = currentList->currentRow(); if (row > 0) { QListWidgetItem *item = currentList->takeItem(row); currentList->insertItem(row - 1, item); currentList->setCurrentRow(row - 1); } } void SettingsDialog::sortUp(QListWidget *currentList) { int row = currentList->currentRow(); if (row >= 0 && row < currentList->count() - 1) { QListWidgetItem *item = currentList->takeItem(row); currentList->insertItem(row + 1, item); currentList->setCurrentRow(row + 1); } } void SettingsDialog::tableAddColumn() { addColumn(ui->tableCurrentList, ui->tableAvailableList); } void SettingsDialog::tableRemoveColumn() { removeColumn(ui->tableCurrentList, ui->tableAvailableList); } void SettingsDialog::tableSortDown() { sortDown(ui->tableCurrentList); } void SettingsDialog::tableSortUp() { sortUp(ui->tableCurrentList); } void SettingsDialog::toggleDownload(bool active) { foreach (QWidget *next, downloadEnable) next->setEnabled(active); if (active) toggleListCover(ui->listCoverOption->isChecked()); } void SettingsDialog::toggleLabel(bool active) { foreach (QWidget *next, labelEnable) next->setEnabled(active); } void SettingsDialog::toggleListCover(bool active) { foreach (QWidget *next, listCoverEnable) next->setEnabled(active); } void SettingsDialog::toggleSaves(bool active) { foreach (QWidget *next, saveEnable) next->setEnabled(active); foreach (QWidget *next, saveDisable) next->setEnabled(!active); } cen64-qt-20150915-alpha/src/settingsdialog.h000066400000000000000000000062301257603330000203660ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H #include #include #include "global.h" namespace Ui { class SettingsDialog; } class SettingsDialog : public QDialog { Q_OBJECT public: explicit SettingsDialog(QWidget *parent = 0, int activeTab = 0); ~SettingsDialog(); private: void populateAvailable(bool downloadItems); Ui::SettingsDialog *ui; QList downloadEnable; QList labelEnable; QList listCoverEnable; QList saveEnable; QList saveDisable; QStringList available; QStringList labelOptions; QStringList sortOptions; private slots: void addColumn(QListWidget *currentList, QListWidget *availableList); void addRomDirectory(); void browse64DD(); void browseBackground(); void browseCatalog(); void browseCen64(); void browseEEPROM(); void browsePIF(); void browseSaves(); void browseSRAM(); void editSettings(); void listAddColumn(); void listRemoveColumn(); void listSortDown(); void listSortUp(); void removeColumn(QListWidget *currentList, QListWidget *availableList); void removeRomDirectory(); void populateTableAndListTab(bool downloadItems); void sortDown(QListWidget *currentList); void sortUp(QListWidget *currentList); void tableAddColumn(); void tableRemoveColumn(); void tableSortDown(); void tableSortUp(); void toggleDownload(bool active); void toggleLabel(bool active); void toggleListCover(bool active); void toggleSaves(bool active); }; #endif // SETTINGSDIALOG_H cen64-qt-20150915-alpha/src/settingsdialog.ui000066400000000000000000001074331257603330000205630ustar00rootroot00000000000000 SettingsDialog 0 0 600 600 550 550 Settings Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok QTabWidget::Rounded 0 Paths Save Files Browse... Save directory: Specify individual files for saves EEPROM file: SRAM file: Browse... Browse... CEN64 Files Browse... Browse... Browse... PIF IPL file: ROM catalog: CEN64 executable: Browse... 64DD IPL file: Qt::Vertical 20 40 16777215 120 ROM Directories 16777215 80 CEN64-Qt will search for all .z64, .n64, .ndd, and .zip files in these directories 16777215 80 Add... Remove Table Qt::Horizontal 40 20 Qt::Vertical 20 40 Qt::Horizontal 40 20 20 0 Image: 160 250 160 300 16777215 80 ... Qt::UpArrow ... Qt::DownArrow 160 250 160 300 16777215 80 ... Qt::RightArrow ... Qt::LeftArrow Current Columns: Stretch First Column Available Columns: Grid ROM Label QLayout::SetMinAndMaxSize Show Label: 150 0 150 16777215 Label Text: Label Color: 100 16777215 Qt::Horizontal 40 20 Qt::Vertical 20 40 Other Browse... Custom Background: Sorting: Descending 150 16777215 ROM Image Qt::Horizontal 40 20 0 0 0 0 Shadow Inactive Color: Shadow Active Color: Columns: Image Size: 100 16777215 100 16777215 1 20 100 16777215 false 100 16777215 List Qt::Horizontal 40 20 20 0 First Item as Header Current Items: 16777215 80 ... Qt::RightArrow ... Qt::LeftArrow 160 250 16777215 80 ... Qt::UpArrow ... Qt::DownArrow 160 250 Available Items: Display Cover Image Image Size: Descending Sorting: 130 16777215 Qt::Horizontal 40 20 Qt::Vertical 20 40 Other 10 10 150 0 Additional Parameters: Requires catalog file 330 0 Download Game Information (thegamesdb.net): Output to Console: Use to pass additional parameters to CEN64 Qt::Vertical 20 40 Qt::Horizontal 40 20 buttonBox tabWidget cen64Path pifPath ddPath catalogPath cen64Button pifButton ddButton catalogButton romList romAddButton romRemoveButton savesPath savesButton saveOption eepromPath sramPath eepromButton sramButton tableAvailableList tableAddButton tableRemoveButton tableCurrentList tableSortDownButton tableSortUpButton tableSizeBox tableStretchOption gridSizeBox columnCountBox shadowInactiveBox shadowActiveBox labelOption labelTextBox labelColorBox backgroundPath backgroundButton gridSortBox gridDescendingOption listAvailableList listAddButton listRemoveButton listCurrentList listSortDownButton listSortUpButton listCoverOption listHeaderOption listSizeBox listSortBox listDescendingOption downloadOption outputOption parametersLine cen64-qt-20150915-alpha/src/thegamesdbscrapper.cpp000066400000000000000000000243321257603330000215470ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "thegamesdbscrapper.h" TheGamesDBScrapper::TheGamesDBScrapper(QWidget *parent, bool force) : QObject(parent) { this->parent = parent; this->force = force; this->keepGoing = true; } void TheGamesDBScrapper::deleteGameInfo(QString fileName, QString identifier) { QString text; text = QString("NOTE: If you are deleting this game's information because the game doesn't exist ") + "on TheGamesDB and CEN64-Qt pulled the information for different game, it's better " + "to create an account on TheGamesDB and add the " + "game so other users can benefit as well." + "

" + "This will cause CEN64-Qt to not update the information for this game until you " + "force it with \"Download/Update Info...\"" + "

" + "Delete the current information for " + fileName + "?"; int answer = QMessageBox::question(parent, tr("Delete Game Information"), text, QMessageBox::Yes | QMessageBox::No); if (answer == QMessageBox::Yes) { QString gameCache = getDataLocation() + "/cache/" + identifier.toLower(); QString dataFile = gameCache + "/data.xml"; QFile file(dataFile); // Remove game information file.open(QIODevice::WriteOnly); QTextStream stream(&file); stream << "NULL"; file.close(); // Remove cover image QString coverFile = gameCache + "/boxart-front."; QFile coverJPG(coverFile + "jpg"); QFile coverPNG(coverFile + "png"); if (coverJPG.exists()) coverJPG.remove(); if (coverPNG.exists()) coverPNG.remove(); coverJPG.open(QIODevice::WriteOnly); QTextStream streamImage(&coverJPG); streamImage << ""; coverJPG.close(); } } void TheGamesDBScrapper::downloadGameInfo(QString identifier, QString searchName, QString gameID) { if (keepGoing && identifier != "") { if (force) parent->setEnabled(false); bool updated = false; QString gameCache = getDataLocation() + "/cache/" + identifier.toLower(); QDir cache(gameCache); if (!cache.exists()) { cache.mkpath(gameCache); } //Get game XML info from thegamesdb.net QString dataFile = gameCache + "/data.xml"; QFile file(dataFile); if (!file.exists() || file.size() == 0 || force) { QUrl url; //Remove [!], (U), etc. from GoodName for searching searchName.remove(QRegExp("\\W*(\\(|\\[).+(\\)|\\])\\W*")); //Few game specific hacks //TODO: Contact thegamesdb.net and see if these can be fixed on their end if (searchName == "Legend of Zelda, The - Majora's Mask") searchName = "Majora's Mask"; else if (searchName == "Legend of Zelda, The - Ocarina of Time - Master Quest") searchName = "Master Quest"; else if (searchName.toLower() == "f-zero x") gameID = "10836"; //If user submits gameID, use that if (gameID != "") url.setUrl("http://thegamesdb.net/api/GetGame.php?id=" + gameID + "&platform=Nintendo 64"); else url.setUrl("http://thegamesdb.net/api/GetGame.php?name=" + searchName + "&platform=Nintendo 64"); QString dom = getUrlContents(url); QDomDocument xml; xml.setContent(dom); QDomNode node = xml.elementsByTagName("Data").at(0).firstChildElement("Game"); int count = 0, found = 0; while(!node.isNull()) { QDomElement element = node.firstChildElement("GameTitle").toElement(); if (force) { //from user dialog QDomElement date = node.firstChildElement("ReleaseDate").toElement(); QString check = "Game: " + element.text(); check.remove(QRegExp(QString("[^A-Za-z 0-9 \\.,\\?'""!@#\\$%\\^&\\*\\") + "(\\)-_=\\+;:<>\\/\\\\|\\}\\{\\[\\]`~]*")); if (date.text() != "") check += "\nReleased on: " + date.text(); check += "\n\nDoes this look correct?"; int answer = QMessageBox::question(parent, QObject::tr("Game Information Download"), check, QMessageBox::Yes | QMessageBox::No); if (answer == QMessageBox::Yes) { found = count; updated = true; break; } } else { //We only want one game, so search for a perfect match in the GameTitle element. //Otherwise this will default to 0 (the first game found) if(element.text() == searchName) found = count; } node = node.nextSibling(); count++; } if (!force || updated) { file.open(QIODevice::WriteOnly); QTextStream stream(&file); QDomNodeList gameList = xml.elementsByTagName("Game"); gameList.at(found).save(stream, QDomNode::EncodingFromDocument); file.close(); } if (force && !updated) { QString message; if (count == 0) message = QObject::tr("No results found."); else message = QObject::tr("No more results found."); QMessageBox::information(parent, QObject::tr("Game Information Download"), message); } } //Get front cover QString boxartURL = ""; QString boxartExt = ""; QString coverFile = gameCache + "/boxart-front."; QFile coverJPG(coverFile + "jpg"); QFile coverPNG(coverFile + "png"); if ((!coverJPG.exists() && !coverPNG.exists()) || (force && updated)) { file.open(QIODevice::ReadOnly); QString dom = file.readAll(); file.close(); QDomDocument xml; xml.setContent(dom); QDomNode node = xml.elementsByTagName("Game").at(0).firstChildElement("Images").firstChild(); while(!node.isNull()) { QDomElement element = node.toElement(); if(element.tagName() == "boxart" && element.attribute("side") == "front") boxartURL = element.attribute("thumb"); node = node.nextSibling(); } if (boxartURL != "") { QUrl url("http://thegamesdb.net/banners/" + boxartURL); //Check to save as JPG or PNG boxartExt = QFileInfo(boxartURL).completeSuffix().toLower(); QFile cover(coverFile + boxartExt); cover.open(QIODevice::WriteOnly); cover.write(getUrlContents(url)); cover.close(); } } if (updated) QMessageBox::information(parent, QObject::tr("Game Information Download"), QObject::tr("Download Complete!")); if (force) parent->setEnabled(true); } } QByteArray TheGamesDBScrapper::getUrlContents(QUrl url) { QNetworkAccessManager *manager = new QNetworkAccessManager; QNetworkRequest request; request.setUrl(url); request.setRawHeader("User-Agent", "CEN64-Qt"); QNetworkReply *reply = manager->get(request); QTimer timer; timer.setSingleShot(true); QEventLoop loop; connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); timer.start(10000); loop.exec(); if(timer.isActive()) { //Got reply timer.stop(); if(reply->error() > 0) showError(reply->errorString()); else return reply->readAll(); } else //Request timed out showError("Request timed out. Check your network settings."); return QByteArray(); } void TheGamesDBScrapper::showError(QString error) { QString question = "\n\nContinue scraping information?"; if (force) QMessageBox::information(parent, tr("Network Error"), error); else { int answer = QMessageBox::question(parent, tr("Network Error"), error + question, QMessageBox::Yes | QMessageBox::No); if (answer == QMessageBox::No) keepGoing = false; } } cen64-qt-20150915-alpha/src/thegamesdbscrapper.h000066400000000000000000000041761257603330000212200ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef THEGAMESDBSCRAPPER_H #define THEGAMESDBSCRAPPER_H #include #include "common.h" #include "global.h" class TheGamesDBScrapper : public QObject { Q_OBJECT public: explicit TheGamesDBScrapper(QWidget *parent = 0, bool force = false); void deleteGameInfo(QString fileName, QString identifier); void downloadGameInfo(QString identifier, QString searchName, QString gameID = ""); private: QByteArray getUrlContents(QUrl url); void showError(QString error); bool force; bool keepGoing; QWidget *parent; }; #endif // THEGAMESDBSCRAPPER_H cen64-qt-20150915-alpha/src/treewidgetitem.cpp000066400000000000000000000047021257603330000207250ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "treewidgetitem.h" //Reimplemented QTreeWidgetItem operator to sort based on both integers and text bool TreeWidgetItem::operator< (const QTreeWidgetItem &other) const { int column = treeWidget()->sortColumn(); if (data(column, Qt::UserRole).toString() != "") { if (data(column, Qt::UserRole).toString().contains(QRegExp("[^\\d]+"))) { QString firstText = data(column, Qt::UserRole).toString(); QString otherText = other.data(column, Qt::UserRole).toString(); return firstText < otherText; } else { int firstNumber = data(column, Qt::UserRole).toInt(); int otherNumber = other.data(column, Qt::UserRole).toInt(); return firstNumber < otherNumber; } } else { QString firstText = text(column); QString otherText = other.text(column); return firstText < otherText; } } cen64-qt-20150915-alpha/src/treewidgetitem.h000066400000000000000000000035261257603330000203750ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef TREEWIDGETITEM_H #define TREEWIDGETITEM_H #include class TreeWidgetItem : public QTreeWidgetItem { public: TreeWidgetItem(QTreeWidget *parent) : QTreeWidgetItem(parent) {} bool operator< (const QTreeWidgetItem &other) const; }; #endif // TREEWIDGETITEM_H cen64-qt-20150915-alpha/src/v64converter.cpp000066400000000000000000000072561257603330000202610ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #include "v64converter.h" V64Converter::V64Converter(QString romPath, QWidget *parent) : QObject(parent) { QDir romDir(romPath); QString v64File = QFileDialog::getOpenFileName(parent, tr("Open v64 File"), romPath, tr("V64 ROMs (*.v64 *.n64);;All Files (*)")); if (v64File != "") { QString defaultFileName = QFileInfo(v64File).completeBaseName() + ".z64"; QString defaultFile = romDir.absoluteFilePath(defaultFileName); QString saveFile = QFileDialog::getSaveFileName(parent, tr("Save z64 File"), defaultFile, tr("Z64 ROMs (*.z64);;All Files (*)")); if (saveFile != "") runConverter(v64File, saveFile, parent); } } void V64Converter::runConverter(QString v64File, QString saveFile, QWidget *parent) { QFile v64(v64File); v64.open(QIODevice::ReadOnly); QString v64Check(v64.read(4).toHex()), message; if (v64Check != "37804012") { if (v64Check == "80371240") message = "\"" + QFileInfo(v64).fileName() + "\" already in z64 format!"; else message = "\"" + QFileInfo(v64).fileName() + "\" is not a valid .v64 file!"; QMessageBox::warning(parent, tr("CEN64-Qt Converter"), message); } else { v64.seek(0); QFile z64(saveFile); z64.open(QIODevice::WriteOnly); QByteArray data; QByteArray flipped; while (!v64.atEnd()) { data = v64.read(1024); for (int i = 0; i < data.size(); i+=2) { //Check to see if only one byte remaining (though byte count should always be even) if (i + 1 == data.size()) flipped.append(data[i]); else { flipped.append(data[i + 1]); flipped.append(data[i]); } } z64.write(flipped); flipped.truncate(0); } z64.close(); QMessageBox::information(parent, tr("CEN64-Qt Converter"), tr("Conversion complete!")); } v64.close(); } cen64-qt-20150915-alpha/src/v64converter.h000066400000000000000000000036251257603330000177220ustar00rootroot00000000000000/*** * Copyright (c) 2013, Dan Hasting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***/ #ifndef V64CONVERTER_H #define V64CONVERTER_H #include #include #include class V64Converter : public QObject { Q_OBJECT public: explicit V64Converter(QString romPath, QWidget *parent = 0); private: void runConverter(QString v64File, QString saveFile, QWidget *parent = 0); }; #endif // V64CONVERTER_H cen64-qt-20150915-alpha/windows/000077500000000000000000000000001257603330000160775ustar00rootroot00000000000000cen64-qt-20150915-alpha/windows/cen64.ico000066400000000000000000002040761257603330000175230ustar00rootroot00000000000000 (( #.#.      2K]deeeeeeeeeeeeeeeeeeeeeeeeeee]E0J\deeeeeeeeeeeeeeeeeeeeeeeeeecV6-NU8AVH# )MMMkRRR___^^^]]]]]]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]]]]]]]]]]]]]]]]]]]]]]]]]]ZZZ666\ 'CCCgTTT]]]^^^]]]]]]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]]\\\PPP> +++5eee```QQQ%%%Ewww{```\\\???e  3ddd222===0005 /bbb===eeek ~~~RRRwX $$$222>(ttt=&FFF { UUU,,,){{{O * TTTVVVV$$$+yyyS lllR%%%qqq@KKKF...$$$|||%VVV$$$+yyyT &&&͓}zzzzzzzzzzzzzzzzzzzzzzzzzzvЛ}zzzzzzzzzzzzzzzzzzzzyyyyyzCVVV$$$+yyyT 5558 sss S ;;;4ooo$$$_ VVV$$$+yyyT SSS***mx111AAA} $E[`aaaaaaaaaaaaaaaaaaaaa_Q2VVV$$$+yyyT xxxA I$ttt]]][[[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZYYYYYYYYYYYYYYYYYYYYYYYYYYYXXXXXXXXXVVVZZZ; WWW%%%+yyyT ((()))(((2222 ###555:  iaaa222+11-5 +3*|||S BBB<<<<<<<<^^^`""HHHKQ ///PPPOOOOOOVVV6DDDDDDCCCLLL>AAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>=========<<<<<<<<<<<<;;;;;;<<<:::FFF^ {{{888888888SSS:rrrWWWxHHH  ...//////+++J cccddddddiiiM WWWWWWWWW[[[GGGVFwwwPPPQQQPPPPPPQQQOOOOOOOOONNNNNNNNNNNNMMMMMMMMMMMMLLLLLLLLLLLLKKKKKKKKKKKKIII```)LLLLLLLLLPPPiiiSlllgggvNNN CCCCCCCCC???<ʯtttttttttsss{)˟kkkllllllkkk0 2نɔǕǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖǖΗZ``````___]]]J###hhhqqq9&&&VVVUNNNINNN%%%3jjj"""vvv/QQQOWWWWWWWWWccc]]]+Siiiccceeedddooo777n2 @uuuppppppqqqpppEEEu7 rpppsssssssssvvv###r>0&#)@MMA*$&)*ChhhkkkkkkkkkifffgggPPPPPPPPPQQQlllYYYo_[ZZZZZZZZZZZZZZZZZZZZZZZZYS=dddzzz[[[\\\\\\]]]nnniiira\ZZZZZZZZZZZZZZZZZZZZZZZZYM./yyyggghhhhhhhhhtttVVVp`[ZZ]]ZZZ[byqqqooopppppplllB ј<<<=========<<>>@@@AAAAAAAAAAAAAAA@@@@@@AAAAAA333---DDDDDDDDDDDDGGGGGGGGGHHHHHHHHHDDD3 =LLLuuu> 2^^^ CCCW1! JOOO,,,------............/////////$$$!!!333333333333333444444444444555C:ddd ,/FFFjIII +%KYRwqtϽзЮЪwϦm͠e̜\ɕ\ɕ\ɖa˚kΠrΣ~ҫЮҵҾŵroqBQJ &$%~kS:cWWW !!!!!!CAAAfff'''J3LdsytqrvgSȎ[ڟxvԧdYyYvNjK{d?iUBkW,H;.H<1J>.K>CkXAkWSm[v`}cuϥvޭW֛Cҏ;ЌTڜZԛdĕy♯gkiw111uaaa333eee, $l%%%HI[s $"[]\cuވ߶q߫^ןIΏO͑|ٮӞ۾ԳЪرܿw٭]ՠ>΍vDЏ_sj$&%777{k$ 3X |!j|˱yݯ'{0Ƀ\ԝ좲L    bKϓ>А?ғ&~w߯x5  /^ۊڴ/ǁ2̇=َ̋  )PlsuuuuusiP( AiujEؘgإTݦJ؜3ˇLˎxoGtuuƧW՚7΋*ɂ޽0(všsǡtǣuɥwʧx̪yͫzͭy̬ůT\Yu-JyӬtɣpğϰ(/߷\cAӕ>Ίf~r)DNIkƨS֚7ώ;Бlئ֑U/ 7Ή ouz΄шԍ ֑"ٕ!ږqakhdY yw rBӒ.N]ڥkDԘooF֛Tݦ3̈ݾ"4Kϒqv|ˁφъ"Ր%ؔ(ۘ+ݝ-ߠ+xݺ9j̀~yIח@&f۩wKמ޶8Ds۬^e7Ѝ{˥] ΢qty~/Ӑc߮dgqO,12Z>RKmaprrrrrrrXZYЄ́|Kٛ~;=NڡmMٟ"z Hٞ[$}v$ lv{LONZ_^Gz~6|5|5tlo?37@ؿ׽ռպӷѵгԳш΄~#ˁzã r;dȽ?΍[C՗HϑÔ`Z߬ zh-  nxˁxU Ω8985752/,)%ݚ"ٔ֏!ӌχˁz ox LMnpzuѭ4͉FךHҕ۲]iT֝ii>ѓfѝ$(&V0  oy ̈́W{lUΫ<=;63/,ߟ(ܚ$ד"ԎЈ̂|t| Rsc2ʅ9ώKҖ޷zl^֟SܥYߪ7ύJˎpT:'  pz ͅat}4+ſ=?>BDAAv!ԏщ̓ʀ{LË/ʄ.ʄݲɤ %Ϲo۫4ύAԖ9͉SʐɷoonufYR pzˀto'$% ! WYՎщ΃M۟(X߲dףIГ=̋,D΍g٣ٸ pzˀχ!ӌ"֑$ږ'ޜ-48;<\AA=/AYԍщ̓N۟/ۯOxܬ oyφ Ҍ$֑'ٗ,ޝ/36:[) =;8B0_ӌЈ̂M۞/ nxˁxz|w#H861R/;6ltӊ·ˀLڝ/ lvˁVyjW;NF0>PJ*PJ+9KD) rH20,ߟ`a`ч΄Lٛ/ it~Uyi]9-ߠ*ܛג@BAЅ́|Jؙ/fqzxG+'''''% %ۘ(ږ$֒'֑́~yIח/דl msJԘfpmZ CLI#֑!ӎЉ$Њ{uGՕ/4UE$Bʉ kos8Ԑ^ڥ^٦a۩bܫdޮe߰gpohk4LfЈ΄ˀ|wrFӒ/ȡt kpuy~̂΅щ Ҍ"ԏ.ݙzlq9Ɓ.ю{ws mCя,ɗ?ʉpqty|ʀ̓υш)ג|, }vr n jDΌfkso!yʴׯ֯ׯױױױ׷Z άլ֫װ֚' /84?8?b000?p8?0?????pp xx<?cen64-qt-20150915-alpha/windows/icon.rc000066400000000000000000000000471257603330000173560ustar00rootroot00000000000000IDI_ICON1 ICON DISCARDABLE "cen64.ico"