├── TUITool
├── TUITool.exe
├── TUITool.ico
├── TUITool.res
├── romnames.db
├── sqlite3.dll
├── libeay32.dll
├── ssleay32.dll
├── tool
├── gamelist.sh
└── gamelist.js
├── TUITool.lpr
├── README.md
├── TUITool.lpi
├── i18n
├── TUITool.pot
├── i18n.po
└── i18n.en.po
├── mainform.lrj
├── TUITool.lps
├── mainform.lfm
└── mainform.pas
/TUITool:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/TUITool
--------------------------------------------------------------------------------
/TUITool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/TUITool.exe
--------------------------------------------------------------------------------
/TUITool.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/TUITool.ico
--------------------------------------------------------------------------------
/TUITool.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/TUITool.res
--------------------------------------------------------------------------------
/romnames.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/romnames.db
--------------------------------------------------------------------------------
/sqlite3.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/sqlite3.dll
--------------------------------------------------------------------------------
/libeay32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/libeay32.dll
--------------------------------------------------------------------------------
/ssleay32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryusatgat/trimuitool/HEAD/ssleay32.dll
--------------------------------------------------------------------------------
/tool/gamelist.sh:
--------------------------------------------------------------------------------
1 | #for i in `ls */gamelist.xml`
2 | #do
3 | # echo processing $i ...
4 | # node gamelist.js $i
5 | #done
6 |
7 | for i in `ls */gamelist_en.xml`
8 | do
9 | echo processing $i ...
10 | node gamelist.js $i 1
11 | done
12 |
--------------------------------------------------------------------------------
/TUITool.lpr:
--------------------------------------------------------------------------------
1 | program TUITool;
2 |
3 | {$mode objfpc}{$H+}
4 |
5 | uses
6 | {$IFDEF UNIX}
7 | cthreads,
8 | {$ENDIF}
9 | {$IFDEF HASAMIGA}
10 | athreads,
11 | {$ENDIF}
12 | Interfaces, // this includes the LCL widgetset
13 | Forms, memdslaz, lazcontrols, MainForm
14 | { you can add units after this };
15 |
16 | {$R *.res}
17 |
18 | begin
19 | RequireDerivedFormResource:=True;
20 | Application.Title:='TrimUI Tool';
21 | Application.Scaled:=True;
22 | Application.Initialize;
23 | Application.CreateForm(TFormMain, FormMain);
24 | Application.Run;
25 | end.
26 |
27 |
--------------------------------------------------------------------------------
/tool/gamelist.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const xml2js = require('xml2js');
4 | const sqlite3 = require('sqlite3').verbose();
5 |
6 | const parser = new xml2js.Parser();
7 | const db = new sqlite3.Database('./romnames.db');
8 |
9 | if (process.argv.length == 4) {
10 | db.serialize(function() {
11 | const stmt = db.prepare('UPDATE romnames SET name = ? WHERE system = ? AND shortname = ?');
12 | fs.readFile(process.argv[2], function(err, data) {
13 | parser.parseString(data, function(err, result) {
14 | for (const game of result.gameList.game) {
15 | stmt.run(game.name[0], path.dirname(process.argv[2]), path.parse(game.path[0]).filename);
16 | }
17 | stmt.finalize();
18 | db.close();
19 | });
20 | });
21 | });
22 | } else if (process.argv.length == 3) {
23 | db.run('CREATE TABLE IF NOT EXISTS romnames(system varchar2, shortname varchar2, name varchar2, ename varchar2)');
24 |
25 | db.serialize(function() {
26 | const stmt = db.prepare('INSERT INTO romnames(system, shortname, name, ename) VALUES (?, ?, ?, ?)');
27 | fs.readFile(process.argv[2], function(err, data) {
28 | parser.parseString(data, function(err, result) {
29 | for (const game of result.gameList.game) {
30 | stmt.run(path.dirname(process.argv[2]), path.parse(game.path[0]).filename, game.name[0], path.parse(game.path[0])).filename;
31 | }
32 | stmt.finalize();
33 | db.close();
34 | });
35 | });
36 | });
37 | }
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TrimUI Smart Pro Tool
2 |
3 | 
4 |
5 |
6 | ## Getting ready to use
7 | 1. Turn off the TSP main unit completely. (Setting > System > Power off).
8 | 2. Remove the SD card from the unit and connect it to the PC. (The drive must be recognized)
9 | 3. Run the TRIMUI.exe file to bring up the screen. (The reference position will be set automatically)
10 | 4. If the reference position is not set automatically, press the ... button to select the SD card drive.
11 | 5. When the emulators are listed, they are ready for normal use. Please select the emulator you want to work with.
12 |
13 | ## To add a rom
14 | 1. Select the location where you want to add the rom. (Folder in the bottom left corner, no need to select a subfolder)
15 | 2. Right-click and select Add Rom or select Add Rom from the File menu.
16 | 3. Select the rom you want to add and click the Open button to add it to the list.
17 | 4. If you want to add all the roms that exist in the current emulator's rom folder, click the Regenerate Cache button. (If the Rom shortened filename is checked, it will automatically import the full name)
18 |
19 | ## Image Scraping
20 | 1. To scrape a screenshot, select the rom name from the list and click the Scrape button.
21 | 2. If "shortname" is checked in the details, only one will be scraped, and if it is unchecked, four will be scraped. (Rom shortened filename is an arcade filename, so don't uncheck it, and if you want to scrape more, enter a search term to search in the scrape search term and scrape it to get 4 images unconditionally)
22 | - Emulators with Rom shortened filename checked will get images from adb.arcadeitalia.net, and other emulators will get images from yahoo.com. You may get strange images, so choose the one you like the most. If you don't like all of them, please enter another search term in the scrape search box and press the scrape button.
23 | 3. Additionally, you can click on the scraped images to replace them with your own.
24 | 4. You can search and download your own images in a web browser and drag the files to TRIMUI Tool to add them.
25 | 5. Scrape All Emulators from the Scraper menu will scrape all the roms present in the rom (except if the images already exist), press ESC if you want to cancel the scraping.
26 |
27 | ## Rename Rom
28 | 1. Select a specific Rom from the Rom list and click it once again with the mouse or press F2 after selecting it to rename it.
29 | 2. You can also rename it in Korean and the changes will be saved to the SD card immediately. (The filename will not be changed.)
30 | 3. If you want to change the file name, please change the file name of the rom in Explorer and then click Generate cache.
31 |
32 | ## Create a subfolder
33 | 1. Right-click on the folder icon in the bottom left corner and click New folder.
34 | 2. Enter a name for the folder and click OK.
35 | 3. You can drag a rom from the parent folder to the folder (the rom from the physical SD card will be moved to the folder).
36 |
37 | ## Managing gamelist.xml
38 | 1. Clicking "Create a game list using gamelist.xml" from the XML menu will generate a list from the contents of gamelist.xml. (It will also recognize folder tags and save subfolder information.)
39 | 2. Clicking "Generate gamelist.xml" from the XML menu will save the contents of the current list as a gamelist.xml file and specify the gamelist entries in the details.
40 |
41 | ## TIP. What is "Generate cache"?
42 | 1. TSP stock OS creates and uses cache files of sqlite3 DB internally. Because of this, simply copying a rom file to an SD card will not be recognized.
43 | 2. TRIMUI Tool manages file lists and images by modifying this cache.
44 | 3. Therefore, if you click Refresh Roms in the TSP internal menu, the changed rom name will be changed to the original filename.
45 | 4. Please do not use the Refresh Roms function on TSP when managing the list with TRIMUI Tool.
46 |
--------------------------------------------------------------------------------
/TUITool.lpi:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | -
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | -
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 | -
115 |
116 |
117 | -
118 |
119 |
120 | -
121 |
122 |
123 | -
124 |
125 |
126 | -
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | -
169 |
170 |
171 | -
172 |
173 |
174 | -
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/i18n/TUITool.pot:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr "Content-Type: text/plain; charset=UTF-8"
3 |
4 | #: mainform.i18n_added
5 | msgid "추가되었습니다"
6 | msgstr ""
7 |
8 | #: mainform.i18n_canceledscrape
9 | msgid "스크랩이 취소되었습니다"
10 | msgstr ""
11 |
12 | #: mainform.i18n_confirm
13 | msgid "확인"
14 | msgstr ""
15 |
16 | #: mainform.i18n_created
17 | msgid "생성되었습니다"
18 | msgstr ""
19 |
20 | #: mainform.i18n_deleteconfirm
21 | msgid "롬 파일을 삭제합니다. 계속 하시겠습니까?"
22 | msgstr ""
23 |
24 | #: mainform.i18n_deleted
25 | msgid "삭제되었습니다"
26 | msgstr ""
27 |
28 | #: mainform.i18n_deletedirconfirm
29 | msgid "폴더를 삭제합니다. 계속 하시겠습니까?"
30 | msgstr ""
31 |
32 | #: mainform.i18n_direxists
33 | msgid "폴더가 존재합니다"
34 | msgstr ""
35 |
36 | #: mainform.i18n_dirnotfound
37 | msgid "폴더를 찾을 수 없습니다"
38 | msgstr ""
39 |
40 | #: mainform.i18n_donescrape
41 | msgid "스크랩이 완료되었습니다"
42 | msgstr ""
43 |
44 | #: mainform.i18n_erroroccured
45 | msgid "오류가 발생하였습니다"
46 | msgstr ""
47 |
48 | #: mainform.i18n_fileexists
49 | msgid "파일이 존재합니다"
50 | msgstr ""
51 |
52 | #: mainform.i18n_filenotfound
53 | msgid "파일을 찾을 수 없습니다"
54 | msgstr ""
55 |
56 | #: mainform.i18n_gamelistconfirm
57 | msgid "캐시로부터 gamelist.xml 파일을 새로 생성합니다. 계속 하시겠습니까?"
58 | msgstr ""
59 |
60 | #: mainform.i18n_gencache
61 | msgid "캐시를 생성하고 있습니다..."
62 | msgstr ""
63 |
64 | #: mainform.i18n_inputdirname
65 | msgid "폴더명을 입력하세요"
66 | msgstr ""
67 |
68 | #: mainform.i18n_makedir
69 | msgid "폴더생성"
70 | msgstr ""
71 |
72 | #: mainform.i18n_noselemul
73 | msgid "선택된 에뮬레이터가 없습니다"
74 | msgstr ""
75 |
76 | #: mainform.i18n_processing
77 | msgid "처리중입니다"
78 | msgstr ""
79 |
80 | #: mainform.i18n_recacheconfirm
81 | msgid "캐시 파일을 재생성합니다. 계속 하시겠습니까?"
82 | msgstr ""
83 |
84 | #: mainform.i18n_romfrom
85 | msgid "롬 한글정보 출처: 텐타클팀(http://cafe.naver.com/raspigamer)"
86 | msgstr ""
87 |
88 | #: mainform.i18n_romnotselected
89 | msgid "롬을 먼저 선택해주세요"
90 | msgstr ""
91 |
92 | #: mainform.i18n_saved
93 | msgid "저장되었습니다"
94 | msgstr ""
95 |
96 | #: mainform.i18n_scrapestarted
97 | msgid " 스크랩이 시작되었습니다"
98 | msgstr ""
99 |
100 | #: tformmain.acabout.caption
101 | msgid "TrimUI 정보(&A)"
102 | msgstr ""
103 |
104 | #: tformmain.acaddrom.caption
105 | msgid "롬추가(&N)"
106 | msgstr ""
107 |
108 | #: tformmain.acbuildgamelist.caption
109 | msgid "&Gamelist.xml 생성"
110 | msgstr ""
111 |
112 | #: tformmain.accancelscrape.caption
113 | msgid "스크랩 취소(&C)"
114 | msgstr ""
115 |
116 | #: tformmain.acchangeimage.caption
117 | msgid "이미지 변경(&I)"
118 | msgstr ""
119 |
120 | #: tformmain.acdelete.caption
121 | msgid "삭제(&D)"
122 | msgstr ""
123 |
124 | #: tformmain.acdetectbasepath.caption
125 | msgid "기준위치 자동인식"
126 | msgstr ""
127 |
128 | #: tformmain.acexit.caption
129 | msgid "종료(&X)"
130 | msgstr ""
131 |
132 | #: tformmain.acgeneratecache.caption
133 | msgid "캐시 재생성(&C)"
134 | msgstr ""
135 |
136 | #: tformmain.acgithub.caption
137 | msgid "&Github"
138 | msgstr ""
139 |
140 | #: tformmain.acmkdir.caption
141 | msgid "폴더 생성(&F)"
142 | msgstr ""
143 |
144 | #: tformmain.acopenbasepath.caption
145 | msgid "기준위치 열기"
146 | msgstr ""
147 |
148 | #: tformmain.acopenimagepos.caption
149 | msgid "이미지 위치 열기(&O)"
150 | msgstr ""
151 |
152 | #: tformmain.acrefresh.caption
153 | msgid "새로 고침"
154 | msgstr ""
155 |
156 | #: tformmain.acrename.caption
157 | msgid "이름 바꾸기(&R)"
158 | msgstr ""
159 |
160 | #: tformmain.acrescrapeall.caption
161 | msgid "모두 스크랩(&A)"
162 | msgstr ""
163 |
164 | #: tformmain.acrmdir.caption
165 | msgid "폴더 삭제(&D)"
166 | msgstr ""
167 |
168 | #: tformmain.acsaveemuinfo.caption
169 | msgid "상세정보 저장(&V)"
170 | msgstr ""
171 |
172 | #: tformmain.acscrape.caption
173 | msgctxt "tformmain.acscrape.caption"
174 | msgid "스크랩(&S)"
175 | msgstr ""
176 |
177 | #: tformmain.acscrapemissing.caption
178 | msgid "누락 항목 스크랩(&M)"
179 | msgstr ""
180 |
181 | #: tformmain.btautodetect.caption
182 | msgid "!"
183 | msgstr ""
184 |
185 | #: tformmain.btopen.caption
186 | msgid "..."
187 | msgstr ""
188 |
189 | #: tformmain.btrefresh.caption
190 | msgid "⟳"
191 | msgstr ""
192 |
193 | #: tformmain.caption
194 | msgid "TrimUI Tool v0.9"
195 | msgstr ""
196 |
197 | #: tformmain.ckhidebios.caption
198 | msgid "바이오스숨기기"
199 | msgstr ""
200 |
201 | #: tformmain.ckshortname.caption
202 | msgid "롬 단축파일명"
203 | msgstr ""
204 |
205 | #: tformmain.ckuseswap.caption
206 | msgid "스왑 사용"
207 | msgstr ""
208 |
209 | #: tformmain.edsearch.hint
210 | msgid "스크래핑 시 해당 키워드를 통해 검색합니다"
211 | msgstr ""
212 |
213 | #: tformmain.groupbox1.caption
214 | msgid "상세정보"
215 | msgstr ""
216 |
217 | #: tformmain.label1.caption
218 | msgid "기준위치"
219 | msgstr ""
220 |
221 | #: tformmain.label2.caption
222 | msgid "에뮬레이터"
223 | msgstr ""
224 |
225 | #: tformmain.label3.caption
226 | msgid "스크랩검색어"
227 | msgstr ""
228 |
229 | #: tformmain.label4.caption
230 | msgid "레이블"
231 | msgstr ""
232 |
233 | #: tformmain.label5.caption
234 | msgid "롬 경로"
235 | msgstr ""
236 |
237 | #: tformmain.label6.caption
238 | msgctxt "tformmain.label6.caption"
239 | msgid "이미지 경로"
240 | msgstr ""
241 |
242 | #: tformmain.label7.caption
243 | msgid "확장자 목록"
244 | msgstr ""
245 |
246 | #: tformmain.label8.caption
247 | msgid "gamelist"
248 | msgstr ""
249 |
250 | #: tformmain.label9.caption
251 | msgid "아이콘"
252 | msgstr ""
253 |
254 | #: tformmain.listview.columns[0].caption
255 | msgid "롬이름"
256 | msgstr ""
257 |
258 | #: tformmain.listview.columns[1].caption
259 | msgctxt "tformmain.listview.columns[1].caption"
260 | msgid "이미지 경로"
261 | msgstr ""
262 |
263 | #: tformmain.listview.columns[2].caption
264 | msgid "롬파일명"
265 | msgstr ""
266 |
267 | #: tformmain.listview.columns[3].caption
268 | msgid "롬경로"
269 | msgstr ""
270 |
271 | #: tformmain.menuitem20.caption
272 | msgid "TrimUI Tool 정보(&A)"
273 | msgstr ""
274 |
275 | #: tformmain.menuitem23.caption
276 | msgid "언어(Language)"
277 | msgstr ""
278 |
279 | #: tformmain.menuitem4.caption
280 | msgid "파일(&F)"
281 | msgstr ""
282 |
283 | #: tformmain.menuitem5.caption
284 | msgid "도움말(&H)"
285 | msgstr ""
286 |
287 | #: tformmain.menuitem9.caption
288 | msgctxt "tformmain.menuitem9.caption"
289 | msgid "스크랩(&S)"
290 | msgstr ""
291 |
292 | #: tformmain.mnlangeng.caption
293 | msgid "&English(영어)"
294 | msgstr ""
295 |
296 | #: tformmain.mnlangeng.hint
297 | msgid "EN"
298 | msgstr ""
299 |
300 | #: tformmain.mnlangkor.caption
301 | msgid "한국어(&Korean)"
302 | msgstr ""
303 |
304 | #: tformmain.mnlangkor.hint
305 | msgid "KO"
306 | msgstr ""
307 |
308 |
--------------------------------------------------------------------------------
/i18n/i18n.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: \n"
4 | "POT-Creation-Date: \n"
5 | "PO-Revision-Date: \n"
6 | "Last-Translator: \n"
7 | "Language-Team: \n"
8 | "Language: ko\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "X-Generator: Poedit 3.4.4\n"
13 |
14 | #: mainform.i18n_added
15 | msgid "추가되었습니다"
16 | msgstr "추가되었습니다"
17 |
18 | #: mainform.i18n_canceledscrape
19 | msgid "스크랩이 취소되었습니다"
20 | msgstr "스크랩이 취소되었습니다"
21 |
22 | #: mainform.i18n_confirm
23 | msgid "확인"
24 | msgstr "확인"
25 |
26 | #: mainform.i18n_created
27 | msgid "생성되었습니다"
28 | msgstr "생성되었습니다"
29 |
30 | #: mainform.i18n_deleteconfirm
31 | msgid "롬 파일을 삭제합니다. 계속 하시겠습니까?"
32 | msgstr "롬 파일을 삭제합니다. 계속 하시겠습니까?"
33 |
34 | #: mainform.i18n_deleted
35 | msgid "삭제되었습니다"
36 | msgstr "삭제되었습니다"
37 |
38 | #: mainform.i18n_deletedirconfirm
39 | msgid "폴더를 삭제합니다. 계속 하시겠습니까?"
40 | msgstr "롬 파일을 삭제합니다. 계속 하시겠습니까?"
41 |
42 | #: mainform.i18n_direxists
43 | msgid "폴더가 존재합니다"
44 | msgstr "파일이 존재합니다"
45 |
46 | #: mainform.i18n_dirnotfound
47 | msgid "폴더를 찾을 수 없습니다"
48 | msgstr "디렉터리를 찾을 수 없습니다"
49 |
50 | #: mainform.i18n_donescrape
51 | msgid "스크랩이 완료되었습니다"
52 | msgstr "스크랩이 완료되었습니다"
53 |
54 | #: mainform.i18n_erroroccured
55 | msgid "오류가 발생하였습니다"
56 | msgstr "오류가 발생하였습니다"
57 |
58 | #: mainform.i18n_fileexists
59 | msgid "파일이 존재합니다"
60 | msgstr "파일이 존재합니다"
61 |
62 | #: mainform.i18n_filenotfound
63 | msgid "파일을 찾을 수 없습니다"
64 | msgstr "파일을 찾을 수 없습니다"
65 |
66 | #: mainform.i18n_gamelistconfirm
67 | msgid "캐시로부터 gamelist.xml 파일을 새로 생성합니다. 계속 하시겠습니까?"
68 | msgstr "캐시로부터 gamelist.xml 파일을 새로 생성합니다. 계속 하시겠습니까?"
69 |
70 | #: mainform.i18n_gencache
71 | msgid "캐시를 생성하고 있습니다..."
72 | msgstr "캐시를 생성하고 있습니다..."
73 |
74 | #: mainform.i18n_inputdirname
75 | msgid "폴더명을 입력하세요"
76 | msgstr "폴더명을 입력하세요"
77 |
78 | #: mainform.i18n_makedir
79 | msgid "폴더생성"
80 | msgstr "폴더생성"
81 |
82 | #: mainform.i18n_noselemul
83 | msgid "선택된 에뮬레이터가 없습니다"
84 | msgstr "선택된 에뮬레이터가 없습니다"
85 |
86 | #: mainform.i18n_processing
87 | msgid "처리중입니다"
88 | msgstr "처리중입니다"
89 |
90 | #: mainform.i18n_recacheconfirm
91 | msgid "캐시 파일을 재생성합니다. 계속 하시겠습니까?"
92 | msgstr "캐시 파일을 재생성합니다. 계속 하시겠습니까?"
93 |
94 | #: mainform.i18n_romfrom
95 | msgid "롬 한글정보 출처: 텐타클팀(http://cafe.naver.com/raspigamer)"
96 | msgstr "롬 한글정보 출처: 텐타클팀(http://cafe.naver.com/raspigamer)"
97 |
98 | #: mainform.i18n_romnotselected
99 | msgid "롬을 먼저 선택해주세요"
100 | msgstr "롬을 먼저 선택해주세요"
101 |
102 | #: mainform.i18n_saved
103 | msgid "저장되었습니다"
104 | msgstr "저장되었습니다"
105 |
106 | #: mainform.i18n_scrapestarted
107 | msgid " 스크랩이 시작되었습니다"
108 | msgstr " 스크랩이 시작되었습니다"
109 |
110 | #: tformmain.acabout.caption
111 | msgid "TrimUI 정보(&A)"
112 | msgstr "TrimUI 정보(&A)"
113 |
114 | #: tformmain.acaddrom.caption
115 | msgid "롬추가(&N)"
116 | msgstr "롬추가(&N)"
117 |
118 | #: tformmain.acbuildgamelist.caption
119 | msgid "&Gamelist.xml 생성"
120 | msgstr "&Gamelist.xml 생성"
121 |
122 | #: tformmain.accancelscrape.caption
123 | msgid "스크랩 취소(&C)"
124 | msgstr "스크랩 취소(&C)"
125 |
126 | #: tformmain.acchangeimage.caption
127 | msgid "이미지 변경(&I)"
128 | msgstr "이미지 변경(&I)"
129 |
130 | #: tformmain.acdelete.caption
131 | msgid "삭제(&D)"
132 | msgstr "삭제(&D)"
133 |
134 | #: tformmain.acdetectbasepath.caption
135 | msgid "기준위치 자동인식"
136 | msgstr "기준위치 자동인식"
137 |
138 | #: tformmain.acexit.caption
139 | msgid "종료(&X)"
140 | msgstr "종료(&X)"
141 |
142 | #: tformmain.acgeneratecache.caption
143 | msgid "캐시 재생성(&C)"
144 | msgstr "캐시 재생성(&C)"
145 |
146 | #: tformmain.acgithub.caption
147 | msgid "&Github"
148 | msgstr "&Github"
149 |
150 | #: tformmain.acmkdir.caption
151 | msgid "폴더 생성(&F)"
152 | msgstr "폴더 생성(&F)"
153 |
154 | #: tformmain.acopenbasepath.caption
155 | msgid "기준위치 열기"
156 | msgstr "기준위치 열기"
157 |
158 | #: tformmain.acopenimagepos.caption
159 | msgid "이미지 위치 열기(&O)"
160 | msgstr "이미지 위치 열기(&O)"
161 |
162 | #: tformmain.acrefresh.caption
163 | msgid "새로 고침"
164 | msgstr "새로 고침"
165 |
166 | #: tformmain.acrename.caption
167 | msgid "이름 바꾸기(&R)"
168 | msgstr "이름 바꾸기(&R)"
169 |
170 | #: tformmain.acrescrapeall.caption
171 | msgid "모두 스크랩(&A)"
172 | msgstr "모두 스크랩(&A)"
173 |
174 | #: tformmain.acrmdir.caption
175 | msgid "폴더 삭제(&D)"
176 | msgstr "폴더 삭제(&D)"
177 |
178 | #: tformmain.acsaveemuinfo.caption
179 | msgid "상세정보 저장(&V)"
180 | msgstr "상세정보 저장(&V)"
181 |
182 | #: tformmain.acscrape.caption
183 | msgctxt "tformmain.acscrape.caption"
184 | msgid "스크랩(&S)"
185 | msgstr "스크랩(&S)"
186 |
187 | #: tformmain.acscrapemissing.caption
188 | msgid "누락 항목 스크랩(&M)"
189 | msgstr "누락 항목 스크랩(&M)"
190 |
191 | #: tformmain.btautodetect.caption
192 | msgid "!"
193 | msgstr "!"
194 |
195 | #: tformmain.btopen.caption
196 | msgid "..."
197 | msgstr "..."
198 |
199 | #: tformmain.btrefresh.caption
200 | msgid "⟳"
201 | msgstr "⟳"
202 |
203 | #: tformmain.caption
204 | msgid "TrimUI Tool v0.9"
205 | msgstr "TrimUI Tool v0.9"
206 |
207 | #: tformmain.ckhidebios.caption
208 | msgid "바이오스숨기기"
209 | msgstr "바이오스숨기기"
210 |
211 | #: tformmain.ckshortname.caption
212 | msgid "롬 단축파일명"
213 | msgstr "롬 단축파일명"
214 |
215 | #: tformmain.ckuseswap.caption
216 | msgid "스왑 사용"
217 | msgstr "스왑 사용"
218 |
219 | #: tformmain.edsearch.hint
220 | msgid "스크래핑 시 해당 키워드를 통해 검색합니다"
221 | msgstr "스크래핑 시 해당 키워드를 통해 검색합니다"
222 |
223 | #: tformmain.groupbox1.caption
224 | msgid "상세정보"
225 | msgstr "상세정보"
226 |
227 | #: tformmain.label1.caption
228 | msgid "기준위치"
229 | msgstr "기준위치"
230 |
231 | #: tformmain.label2.caption
232 | msgid "에뮬레이터"
233 | msgstr "에뮬레이터"
234 |
235 | #: tformmain.label3.caption
236 | msgid "스크랩검색어"
237 | msgstr "스크랩검색어"
238 |
239 | #: tformmain.label4.caption
240 | msgid "레이블"
241 | msgstr "레이블"
242 |
243 | #: tformmain.label5.caption
244 | msgid "롬 경로"
245 | msgstr "롬 경로"
246 |
247 | #: tformmain.label6.caption
248 | msgctxt "tformmain.label6.caption"
249 | msgid "이미지 경로"
250 | msgstr "이미지 경로"
251 |
252 | #: tformmain.label7.caption
253 | msgid "확장자 목록"
254 | msgstr "확장자 목록"
255 |
256 | #: tformmain.label8.caption
257 | msgid "gamelist"
258 | msgstr "gamelist"
259 |
260 | #: tformmain.label9.caption
261 | msgid "아이콘"
262 | msgstr "아이콘"
263 |
264 | #: tformmain.listview.columns[0].caption
265 | msgid "롬이름"
266 | msgstr "롬이름"
267 |
268 | #: tformmain.listview.columns[1].caption
269 | msgctxt "tformmain.listview.columns[1].caption"
270 | msgid "이미지 경로"
271 | msgstr "이미지 경로"
272 |
273 | #: tformmain.listview.columns[2].caption
274 | msgid "롬파일명"
275 | msgstr "롬파일명"
276 |
277 | #: tformmain.listview.columns[3].caption
278 | msgid "롬경로"
279 | msgstr "롬경로"
280 |
281 | #: tformmain.menuitem20.caption
282 | msgid "TrimUI Tool 정보(&A)"
283 | msgstr "TrimUI Tool 정보(&A)"
284 |
285 | #: tformmain.menuitem23.caption
286 | msgid "언어(Language)"
287 | msgstr "언어(Language)"
288 |
289 | #: tformmain.menuitem4.caption
290 | msgid "파일(&F)"
291 | msgstr "파일(&F)"
292 |
293 | #: tformmain.menuitem5.caption
294 | msgid "도움말(&H)"
295 | msgstr "도움말(&H)"
296 |
297 | #: tformmain.menuitem9.caption
298 | msgctxt "tformmain.menuitem9.caption"
299 | msgid "스크랩(&S)"
300 | msgstr "스크랩(&S)"
301 |
302 | #: tformmain.mnlangeng.caption
303 | msgid "&English(영어)"
304 | msgstr "&English(영어)"
305 |
306 | #: tformmain.mnlangeng.hint
307 | msgid "EN"
308 | msgstr ""
309 |
310 | #: tformmain.mnlangkor.caption
311 | msgid "한국어(&Korean)"
312 | msgstr "한국어(&Korean)"
313 |
314 | #: tformmain.mnlangkor.hint
315 | msgid "KO"
316 | msgstr "KO"
317 |
318 | #~ msgid "en"
319 | #~ msgstr "en"
320 |
--------------------------------------------------------------------------------
/i18n/i18n.en.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: \n"
4 | "POT-Creation-Date: \n"
5 | "PO-Revision-Date: 2024-07-07 11:45+0900\n"
6 | "Last-Translator: \n"
7 | "Language-Team: \n"
8 | "Language: en\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "X-Generator: Poedit 3.4.4\n"
13 | "X-Poedit-Basepath: .\n"
14 |
15 | #: mainform.i18n_added
16 | msgid "추가되었습니다"
17 | msgstr "Added"
18 |
19 | #: mainform.i18n_canceledscrape
20 | msgid "스크랩이 취소되었습니다"
21 | msgstr "Canceled scraping"
22 |
23 | #: mainform.i18n_confirm
24 | msgid "확인"
25 | msgstr "Confirm"
26 |
27 | #: mainform.i18n_created
28 | msgid "생성되었습니다"
29 | msgstr "Generated"
30 |
31 | #: mainform.i18n_deleteconfirm
32 | msgid "롬 파일을 삭제합니다. 계속 하시겠습니까?"
33 | msgstr "Delete the ROM file. Do you want to continue?"
34 |
35 | #: mainform.i18n_deleted
36 | msgid "삭제되었습니다"
37 | msgstr "Deleted"
38 |
39 | #: mainform.i18n_deletedirconfirm
40 | msgid "폴더를 삭제합니다. 계속 하시겠습니까?"
41 | msgstr "Delete the folder. Do you want to continue?"
42 |
43 | #: mainform.i18n_direxists
44 | msgid "폴더가 존재합니다"
45 | msgstr "Folder exists"
46 |
47 | #: mainform.i18n_dirnotfound
48 | msgid "폴더를 찾을 수 없습니다"
49 | msgstr "Folder not found"
50 |
51 | #: mainform.i18n_donescrape
52 | msgid "스크랩이 완료되었습니다"
53 | msgstr "Scraping is complete"
54 |
55 | #: mainform.i18n_erroroccured
56 | msgid "오류가 발생하였습니다"
57 | msgstr "An error occurred"
58 |
59 | #: mainform.i18n_fileexists
60 | msgid "파일이 존재합니다"
61 | msgstr "File exists"
62 |
63 | #: mainform.i18n_filenotfound
64 | msgid "파일을 찾을 수 없습니다"
65 | msgstr "File not found"
66 |
67 | #: mainform.i18n_gamelistconfirm
68 | msgid ""
69 | "캐시로부터 gamelist.xml 파일을 새로 생성합니다. 계속 하시겠습니까?"
70 | msgstr ""
71 | "Create a new gamelist.xml file from the cache. Do you want to continue?"
72 |
73 | #: mainform.i18n_gencache
74 | msgid "캐시를 생성하고 있습니다..."
75 | msgstr "Creating a cache..."
76 |
77 | #: mainform.i18n_inputdirname
78 | msgid "폴더명을 입력하세요"
79 | msgstr "Enter the folder name"
80 |
81 | #: mainform.i18n_makedir
82 | msgid "폴더생성"
83 | msgstr "New folder"
84 |
85 | #: mainform.i18n_noselemul
86 | msgid "선택된 에뮬레이터가 없습니다"
87 | msgstr "There is no emulator selected"
88 |
89 | #: mainform.i18n_processing
90 | msgid "처리중입니다"
91 | msgstr "Processing"
92 |
93 | #: mainform.i18n_recacheconfirm
94 | msgid "캐시 파일을 재생성합니다. 계속 하시겠습니까?"
95 | msgstr "Regenerate cache file. Do you want to continue?"
96 |
97 | #: mainform.i18n_romfrom
98 | msgid "롬 한글정보 출처: 텐타클팀(http://cafe.naver.com/raspigamer)"
99 | msgstr ""
100 | "Source of ROM Korean information: Tentacle Team (http://cafe.naver.com/"
101 | "raspigamer)"
102 |
103 | #: mainform.i18n_romnotselected
104 | msgid "롬을 먼저 선택해주세요"
105 | msgstr "Please select the ROM first"
106 |
107 | #: mainform.i18n_saved
108 | msgid "저장되었습니다"
109 | msgstr "Saved"
110 |
111 | #: mainform.i18n_scrapestarted
112 | msgid " 스크랩이 시작되었습니다"
113 | msgstr " The scraping has begun"
114 |
115 | #: tformmain.acabout.caption
116 | msgid "TrimUI 정보(&A)"
117 | msgstr "About TUI Tool"
118 |
119 | #: tformmain.acaddrom.caption
120 | msgid "롬추가(&N)"
121 | msgstr "Add rom"
122 |
123 | #: tformmain.acbuildgamelist.caption
124 | msgid "&Gamelist.xml 생성"
125 | msgstr "&Generate Gamelist.xml"
126 |
127 | #: tformmain.accancelscrape.caption
128 | msgid "스크랩 취소(&C)"
129 | msgstr "&Cancel scraping"
130 |
131 | #: tformmain.acchangeimage.caption
132 | msgid "이미지 변경(&I)"
133 | msgstr "Change &Image"
134 |
135 | #: tformmain.acdelete.caption
136 | msgid "삭제(&D)"
137 | msgstr "&Delete"
138 |
139 | #: tformmain.acdetectbasepath.caption
140 | msgid "기준위치 자동인식"
141 | msgstr "Detect"
142 |
143 | #: tformmain.acexit.caption
144 | msgid "종료(&X)"
145 | msgstr "E&xit"
146 |
147 | #: tformmain.acgeneratecache.caption
148 | msgid "캐시 재생성(&C)"
149 | msgstr "Generate &cache"
150 |
151 | #: tformmain.acgithub.caption
152 | msgid "&Github"
153 | msgstr "&Github"
154 |
155 | #: tformmain.acmkdir.caption
156 | msgid "폴더 생성(&F)"
157 | msgstr "&New folder"
158 |
159 | #: tformmain.acopenbasepath.caption
160 | msgid "기준위치 열기"
161 | msgstr "Open"
162 |
163 | #: tformmain.acopenimagepos.caption
164 | msgid "이미지 위치 열기(&O)"
165 | msgstr "&Open Image Folder"
166 |
167 | #: tformmain.acrefresh.caption
168 | msgid "새로 고침"
169 | msgstr "Refresh"
170 |
171 | #: tformmain.acrename.caption
172 | msgid "이름 바꾸기(&R)"
173 | msgstr "&Rename"
174 |
175 | #: tformmain.acrescrapeall.caption
176 | msgid "모두 스크랩(&A)"
177 | msgstr "Scrape &all"
178 |
179 | #: tformmain.acrmdir.caption
180 | msgid "폴더 삭제(&D)"
181 | msgstr "&Delete folder"
182 |
183 | #: tformmain.acsaveemuinfo.caption
184 | msgid "상세정보 저장(&V)"
185 | msgstr "Sa&ve details"
186 |
187 | #: tformmain.acscrape.caption
188 | msgctxt "tformmain.acscrape.caption"
189 | msgid "스크랩(&S)"
190 | msgstr "&Scrape"
191 |
192 | #: tformmain.acscrapemissing.caption
193 | msgid "누락 항목 스크랩(&M)"
194 | msgstr "Scrape &missing"
195 |
196 | #: tformmain.btautodetect.caption
197 | msgid "!"
198 | msgstr "!"
199 |
200 | #: tformmain.btopen.caption
201 | msgid "..."
202 | msgstr "..."
203 |
204 | #: tformmain.btrefresh.caption
205 | msgid "⟳"
206 | msgstr "⟳"
207 |
208 | #: tformmain.caption
209 | msgid "TrimUI Tool v0.9"
210 | msgstr "TrimUI Tool v0.9"
211 |
212 | #: tformmain.ckhidebios.caption
213 | msgid "바이오스숨기기"
214 | msgstr "Hide bios"
215 |
216 | #: tformmain.ckshortname.caption
217 | msgid "롬 단축파일명"
218 | msgstr "Shortname"
219 |
220 | #: tformmain.ckuseswap.caption
221 | msgid "스왑 사용"
222 | msgstr "Use swap"
223 |
224 | #: tformmain.edsearch.hint
225 | msgid "스크래핑 시 해당 키워드를 통해 검색합니다"
226 | msgstr "Search with keyword when scraping"
227 |
228 | #: tformmain.groupbox1.caption
229 | msgid "상세정보"
230 | msgstr "Details"
231 |
232 | #: tformmain.label1.caption
233 | msgid "기준위치"
234 | msgstr "Base path"
235 |
236 | #: tformmain.label2.caption
237 | msgid "에뮬레이터"
238 | msgstr "Emulator"
239 |
240 | #: tformmain.label3.caption
241 | msgid "스크랩검색어"
242 | msgstr "Search word"
243 |
244 | #: tformmain.label4.caption
245 | msgid "레이블"
246 | msgstr "Label"
247 |
248 | #: tformmain.label5.caption
249 | msgid "롬 경로"
250 | msgstr "Rom path"
251 |
252 | #: tformmain.label6.caption
253 | msgctxt "tformmain.label6.caption"
254 | msgid "이미지 경로"
255 | msgstr "Image path"
256 |
257 | #: tformmain.label7.caption
258 | msgid "확장자 목록"
259 | msgstr "Extensions"
260 |
261 | #: tformmain.label8.caption
262 | msgid "gamelist"
263 | msgstr "gamelist"
264 |
265 | #: tformmain.label9.caption
266 | msgid "아이콘"
267 | msgstr "Icon"
268 |
269 | #: tformmain.listview.columns[0].caption
270 | msgid "롬이름"
271 | msgstr "Rom name"
272 |
273 | #: tformmain.listview.columns[1].caption
274 | msgctxt "tformmain.listview.columns[1].caption"
275 | msgid "이미지 경로"
276 | msgstr "Image path"
277 |
278 | #: tformmain.listview.columns[2].caption
279 | msgid "롬파일명"
280 | msgstr "Rom filename"
281 |
282 | #: tformmain.listview.columns[3].caption
283 | msgid "롬경로"
284 | msgstr "Rom path"
285 |
286 | #: tformmain.menuitem20.caption
287 | msgid "TrimUI Tool 정보(&A)"
288 | msgstr "About TUI Tool"
289 |
290 | #: tformmain.menuitem23.caption
291 | msgid "언어(Language)"
292 | msgstr "&Language"
293 |
294 | #: tformmain.menuitem4.caption
295 | msgid "파일(&F)"
296 | msgstr "&File"
297 |
298 | #: tformmain.menuitem5.caption
299 | msgid "도움말(&H)"
300 | msgstr "&Help"
301 |
302 | #: tformmain.menuitem9.caption
303 | msgctxt "tformmain.menuitem9.caption"
304 | msgid "스크랩(&S)"
305 | msgstr "&Scrape"
306 |
307 | #: tformmain.mnlangeng.caption
308 | msgid "&English(영어)"
309 | msgstr "&English"
310 |
311 | #: tformmain.mnlangeng.hint
312 | msgid "EN"
313 | msgstr ""
314 |
315 | #: tformmain.mnlangkor.caption
316 | msgid "한국어(&Korean)"
317 | msgstr "&Korean"
318 |
319 | #: tformmain.mnlangkor.hint
320 | msgid "KO"
321 | msgstr ""
322 |
--------------------------------------------------------------------------------
/mainform.lrj:
--------------------------------------------------------------------------------
1 | {"version":1,"strings":[
2 | {"hash":127367094,"name":"tformmain.caption","sourcebytes":[84,114,105,109,85,73,32,84,111,111,108,32,118,48,46,57,54],"value":"TrimUI Tool v0.96"},
3 | {"hash":142165976,"name":"tformmain.ckforcepng.caption","sourcebytes":[234,176,149,236,160,156,32,112,110,103,32,235,179,128,237,153,152],"value":"\uAC15\uC81C png \uBCC0\uD658"},
4 | {"hash":38331112,"name":"tformmain.label1.caption","sourcebytes":[234,184,176,236,164,128,236,156,132,236,185,152],"value":"\uAE30\uC900\uC704\uCE58"},
5 | {"hash":12558,"name":"tformmain.btopen.caption","sourcebytes":[46,46,46],"value":"..."},
6 | {"hash":60579,"name":"tformmain.btrefresh.caption","sourcebytes":[226,159,179],"value":"\u27F3"},
7 | {"hash":172119648,"name":"tformmain.label2.caption","sourcebytes":[236,151,144,235,174,172,235,160,136,236,157,180,237,132,176],"value":"\uC5D0\uBBAC\uB808\uC774\uD130"},
8 | {"hash":157693556,"name":"tformmain.label3.caption","sourcebytes":[236,138,164,237,129,172,235,158,169,234,178,128,236,131,137,236,150,180],"value":"\uC2A4\uD06C\uB7A9\uAC80\uC0C9\uC5B4"},
9 | {"hash":147718036,"name":"tformmain.edsearch.hint","sourcebytes":[236,138,164,237,129,172,235,158,152,237,149,145,32,236,139,156,32,237,149,180,235,139,185,32,237,130,164,236,155,140,235,147,156,235,165,188,32,237,134,181,237,149,180,32,234,178,128,236,131,137,237,149,169,235,139,136,235,139,164],"value":"\uC2A4\uD06C\uB798\uD551 \uC2DC \uD574\uB2F9 \uD0A4\uC6CC\uB4DC\uB97C \uD1B5\uD574 \uAC80\uC0C9\uD569\uB2C8\uB2E4"},
10 | {"hash":33,"name":"tformmain.btautodetect.caption","sourcebytes":[33],"value":"!"},
11 | {"hash":170279908,"name":"tformmain.groupbox1.caption","sourcebytes":[236,131,129,236,132,184,236,160,149,235,179,180],"value":"\uC0C1\uC138\uC815\uBCF4"},
12 | {"hash":124380292,"name":"tformmain.label4.caption","sourcebytes":[235,160,136,236,157,180,235,184,148],"value":"\uB808\uC774\uBE14"},
13 | {"hash":257162828,"name":"tformmain.label5.caption","sourcebytes":[235,161,172,32,234,178,189,235,161,156],"value":"\uB86C \uACBD\uB85C"},
14 | {"hash":166249404,"name":"tformmain.label6.caption","sourcebytes":[236,157,180,235,175,184,236,167,128,32,234,178,189,235,161,156],"value":"\uC774\uBBF8\uC9C0 \uACBD\uB85C"},
15 | {"hash":262899493,"name":"tformmain.ckshortname.caption","sourcebytes":[235,161,172,32,235,139,168,236,182,149,237,140,140,236,157,188,235,170,133],"value":"\uB86C \uB2E8\uCD95\uD30C\uC77C\uBA85"},
16 | {"hash":92095984,"name":"tformmain.ckhidebios.caption","sourcebytes":[235,176,148,236,157,180,236,152,164,236,138,164,236,136,168,234,184,176,234,184,176],"value":"\uBC14\uC774\uC624\uC2A4\uC228\uAE30\uAE30"},
17 | {"hash":165302733,"name":"tformmain.label7.caption","sourcebytes":[237,153,149,236,158,165,236,158,144,32,235,170,169,235,161,157],"value":"\uD655\uC7A5\uC790 \uBAA9\uB85D"},
18 | {"hash":138163828,"name":"tformmain.label8.caption","sourcebytes":[103,97,109,101,108,105,115,116],"value":"gamelist"},
19 | {"hash":203479177,"name":"tformmain.ckuseswap.caption","sourcebytes":[236,138,164,236,153,145,32,236,130,172,236,154,169],"value":"\uC2A4\uC651 \uC0AC\uC6A9"},
20 | {"hash":57271176,"name":"tformmain.label9.caption","sourcebytes":[236,149,132,236,157,180,236,189,152],"value":"\uC544\uC774\uCF58"},
21 | {"hash":191488036,"name":"tformmain.listview.columns[0].caption","sourcebytes":[235,161,172,236,157,180,235,166,132],"value":"\uB86C\uC774\uB984"},
22 | {"hash":166249404,"name":"tformmain.listview.columns[1].caption","sourcebytes":[236,157,180,235,175,184,236,167,128,32,234,178,189,235,161,156],"value":"\uC774\uBBF8\uC9C0 \uACBD\uB85C"},
23 | {"hash":102048885,"name":"tformmain.listview.columns[2].caption","sourcebytes":[235,161,172,237,140,140,236,157,188,235,170,133],"value":"\uB86C\uD30C\uC77C\uBA85"},
24 | {"hash":190730348,"name":"tformmain.listview.columns[3].caption","sourcebytes":[235,161,172,234,178,189,235,161,156],"value":"\uB86C\uACBD\uB85C"},
25 | {"hash":52791353,"name":"tformmain.acscrape.caption","sourcebytes":[236,138,164,237,129,172,235,158,152,237,149,145,40,38,83,41],"value":"\uC2A4\uD06C\uB798\uD551(&S)"},
26 | {"hash":160947737,"name":"tformmain.acrescrapeall.caption","sourcebytes":[235,170,168,235,145,144,32,236,138,164,237,129,172,235,158,152,237,149,145,40,38,65,41],"value":"\uBAA8\uB450 \uC2A4\uD06C\uB798\uD551(&A)"},
27 | {"hash":119690809,"name":"tformmain.acscrapemissing.caption","sourcebytes":[235,136,132,235,157,189,32,237,149,173,235,170,169,32,236,138,164,237,129,172,235,158,152,237,149,145,40,38,77,41],"value":"\uB204\uB77D \uD56D\uBAA9 \uC2A4\uD06C\uB798\uD551(&M)"},
28 | {"hash":193620297,"name":"tformmain.acrename.caption","sourcebytes":[236,157,180,235,166,132,32,235,176,148,234,190,184,234,184,176,40,38,82,41],"value":"\uC774\uB984 \uBC14\uAFB8\uAE30(&R)"},
29 | {"hash":110225321,"name":"tformmain.acdelete.caption","sourcebytes":[236,130,173,236,160,156,40,38,68,41],"value":"\uC0AD\uC81C(&D)"},
30 | {"hash":112456249,"name":"tformmain.accancelscrape.caption","sourcebytes":[236,138,164,237,129,172,235,158,152,237,149,145,32,236,183,168,236,134,140,40,38,67,41],"value":"\uC2A4\uD06C\uB798\uD551 \uCDE8\uC18C(&C)"},
31 | {"hash":63339337,"name":"tformmain.acchangeimage.caption","sourcebytes":[236,157,180,235,175,184,236,167,128,32,235,179,128,234,178,189,40,38,73,41],"value":"\uC774\uBBF8\uC9C0 \uBCC0\uACBD(&I)"},
32 | {"hash":117446921,"name":"tformmain.acopenimagepos.caption","sourcebytes":[236,157,180,235,175,184,236,167,128,32,236,156,132,236,185,152,32,236,151,180,234,184,176,40,38,79,41],"value":"\uC774\uBBF8\uC9C0 \uC704\uCE58 \uC5F4\uAE30(&O)"},
33 | {"hash":206219113,"name":"tformmain.acsaveemuinfo.caption","sourcebytes":[236,131,129,236,132,184,236,160,149,235,179,180,32,236,160,128,236,158,165,40,38,86,41],"value":"\uC0C1\uC138\uC815\uBCF4 \uC800\uC7A5(&V)"},
34 | {"hash":180066001,"name":"tformmain.acbuildgamelist.caption","sourcebytes":[38,103,97,109,101,108,105,115,116,46,120,109,108,32,236,131,157,236,132,177],"value":"&gamelist.xml \uC0DD\uC131"},
35 | {"hash":194694696,"name":"tformmain.acrefresh.caption","sourcebytes":[236,131,136,235,161,156,32,234,179,160,236,185,168],"value":"\uC0C8\uB85C \uACE0\uCE68"},
36 | {"hash":230869853,"name":"tformmain.acdetectbasepath.caption","sourcebytes":[234,184,176,236,164,128,236,156,132,236,185,152,32,236,158,144,235,143,153,236,157,184,236,139,157],"value":"\uAE30\uC900\uC704\uCE58 \uC790\uB3D9\uC778\uC2DD"},
37 | {"hash":200088752,"name":"tformmain.acopenbasepath.caption","sourcebytes":[234,184,176,236,164,128,236,156,132,236,185,152,32,236,151,180,234,184,176],"value":"\uAE30\uC900\uC704\uCE58 \uC5F4\uAE30"},
38 | {"hash":95535337,"name":"tformmain.acexit.caption","sourcebytes":[236,162,133,235,163,140,40,38,88,41],"value":"\uC885\uB8CC(&X)"},
39 | {"hash":56861833,"name":"tformmain.acgeneratecache.caption","sourcebytes":[236,186,144,236,139,156,32,236,158,172,236,131,157,236,132,177,40,38,67,41],"value":"\uCE90\uC2DC \uC7AC\uC0DD\uC131(&C)"},
40 | {"hash":251678745,"name":"tformmain.acabout.caption","sourcebytes":[84,114,105,109,85,73,32,236,160,149,235,179,180,40,38,65,41],"value":"TrimUI \uC815\uBCF4(&A)"},
41 | {"hash":4795369,"name":"tformmain.acaddrom.caption","sourcebytes":[235,161,172,236,182,148,234,176,128,40,38,78,41],"value":"\uB86C\uCD94\uAC00(&N)"},
42 | {"hash":40479625,"name":"tformmain.acmkdir.caption","sourcebytes":[237,143,180,235,141,148,32,236,131,157,236,132,177,40,38,70,41],"value":"\uD3F4\uB354 \uC0DD\uC131(&F)"},
43 | {"hash":182497170,"name":"tformmain.acgithub.caption","sourcebytes":[38,71,105,116,104,117,98],"value":"&Github"},
44 | {"hash":306025,"name":"tformmain.acrmdir.caption","sourcebytes":[237,143,180,235,141,148,32,236,130,173,236,160,156,40,38,68,41],"value":"\uD3F4\uB354 \uC0AD\uC81C(&D)"},
45 | {"hash":73351257,"name":"tformmain.acscanext.caption","sourcebytes":[237,153,149,236,158,165,236,158,144,32,236,138,164,236,186,148,40,38,69,41],"value":"\uD655\uC7A5\uC790 \uC2A4\uCE94(&E)"},
46 | {"hash":8648729,"name":"tformmain.acscrapetotal.caption","sourcebytes":[236,160,132,236,178,180,32,236,151,144,235,174,172,235,160,136,236,157,180,237,132,176,32,236,138,164,237,129,172,235,158,152,237,149,145,40,38,84,41],"value":"\uC804\uCCB4 \uC5D0\uBBAC\uB808\uC774\uD130 \uC2A4\uD06C\uB798\uD551(&T)"},
47 | {"hash":229835009,"name":"tformmain.accachefromxml.caption","sourcebytes":[103,97,109,101,108,105,115,116,46,120,109,108,32,236,157,132,32,236,157,180,236,154,169,237,149,180,236,132,156,32,234,178,140,236,158,132,32,235,170,169,235,161,157,32,236,131,157,236,132,177],"value":"gamelist.xml \uC744 \uC774\uC6A9\uD574\uC11C \uAC8C\uC784 \uBAA9\uB85D \uC0DD\uC131"},
48 | {"hash":109170489,"name":"tformmain.mnfile.caption","sourcebytes":[237,140,140,236,157,188,40,38,70,41],"value":"\uD30C\uC77C(&F)"},
49 | {"hash":21530681,"name":"tformmain.mnscrape.caption","sourcebytes":[236,138,164,237,129,172,235,158,152,237,141,188,40,38,83,41],"value":"\uC2A4\uD06C\uB798\uD37C(&S)"},
50 | {"hash":179484,"name":"tformmain.mnxml.caption","sourcebytes":[38,88,77,76],"value":"&XML"},
51 | {"hash":49466729,"name":"tformmain.mnlanguage.caption","sourcebytes":[236,150,184,236,150,180,40,76,97,110,103,117,97,103,101,41],"value":"\uC5B8\uC5B4(Language)"},
52 | {"hash":86404281,"name":"tformmain.mnlangkor.caption","sourcebytes":[237,149,156,234,181,173,236,150,180,40,38,75,111,114,101,97,110,41],"value":"\uD55C\uAD6D\uC5B4(&Korean)"},
53 | {"hash":1279,"name":"tformmain.mnlangkor.hint","sourcebytes":[75,79],"value":"KO"},
54 | {"hash":205420121,"name":"tformmain.mnlangeng.caption","sourcebytes":[38,69,110,103,108,105,115,104,40,236,152,129,236,150,180,41],"value":"&English(\uC601\uC5B4)"},
55 | {"hash":1182,"name":"tformmain.mnlangeng.hint","sourcebytes":[69,78],"value":"EN"},
56 | {"hash":42060169,"name":"tformmain.mnhelp.caption","sourcebytes":[235,143,132,236,155,128,235,167,144,40,38,72,41],"value":"\uB3C4\uC6C0\uB9D0(&H)"},
57 | {"hash":26682457,"name":"tformmain.menuitem20.caption","sourcebytes":[84,114,105,109,85,73,32,84,111,111,108,32,236,160,149,235,179,180,40,38,65,41],"value":"TrimUI Tool \uC815\uBCF4(&A)"}
58 | ]}
59 |
--------------------------------------------------------------------------------
/TUITool.lps:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 | -
393 |
394 |
395 | -
396 |
397 |
398 | -
399 |
400 |
401 |
402 |
403 |
404 |
--------------------------------------------------------------------------------
/mainform.lfm:
--------------------------------------------------------------------------------
1 | object FormMain: TFormMain
2 | Left = 993
3 | Height = 673
4 | Top = 141
5 | Width = 918
6 | AllowDropFiles = True
7 | Caption = 'TrimUI Tool v0.96'
8 | ClientHeight = 673
9 | ClientWidth = 918
10 | Menu = MainMenu
11 | OnClose = FormClose
12 | OnCreate = FormCreate
13 | OnDestroy = FormDestroy
14 | OnDropFiles = FormDropFiles
15 | OnShow = FormShow
16 | LCLVersion = '3.4.0.0'
17 | object pnImage: TPanel
18 | Left = 692
19 | Height = 573
20 | Top = 0
21 | Width = 226
22 | Align = alRight
23 | BevelOuter = bvNone
24 | ClientHeight = 573
25 | ClientWidth = 226
26 | TabOrder = 1
27 | object Image: TImage
28 | Left = 13
29 | Height = 290
30 | Top = 38
31 | Width = 200
32 | Center = True
33 | ParentShowHint = False
34 | PopupMenu = pmImage
35 | Proportional = True
36 | ShowHint = True
37 | end
38 | object NoImage: TImage
39 | Left = 27
40 | Height = 171
41 | Top = 98
42 | Width = 172
43 | Picture.Data = {
44 | 1754506F727461626C654E6574776F726B47726170686963D016000089504E47
45 | 0D0A1A0A0000000D49484452000000AC000000AB0806000000FB347760000000
46 | 017352474200AECE1CE90000000467414D410000B18F0BFC6105000000097048
47 | 597300000EC300000EC301C76FA8640000166549444154785EED9D3FACDEB615
48 | C5B314488106F0D0C153E10219820E41462F453D1A28827A343A65F4566FF152
49 | 78ABC774CB98A5C01B3D66F418204B468F1E337AF4F8F5FCDE93623DBE4B8A94
50 | 7845EAFB7480637F4F7F288A3ABCBCBC24A54F4E07F2F1F6EDE9F4E6CDE9F4F2
51 | E56D3E7E7C3A3D7A34CF172F6E9FF7FAF5E9F4D34F43E20772700836C4FBF737
52 | A2FCE1878F62FCEA2B95948ACA930F1E7C14F577DFDDE4E1D75F874C1D18A192
53 | BA707CF8703AFDF8E38D501E3EBC2BA4D6FCE28BD3E9D9B3D3E9EAEA10B0A012
54 | B9408CCD3A16CD1249CFC4DA3F7F7EE34ED01A5C1854021702ACE837DF9C4EF7
55 | EEDD15C19EF9E4C98DFB424B7101D01D9F317EF9E5A639BD7FFFEE833E377EFA
56 | E9E9F4F4E98DE53D63E84ECF0CEFDEDD34F7F87ED683BD045241A9A8671881D0
57 | DD9D09102A4DBEF5002F99F8E9F8EC6702DDD1CE41B38F1F673DAC831F8970F1
58 | E3770EDDC94E710875198932ECD8CFD51DEC0C8C361D425D4F84BB438BAB9CEF
59 | 04C41C09EE5B857F7039A9FC3B1A90508E770046792E2134D58A84C45EBDDA45
60 | 2C57B9ED1834FF8CE55B857CB03E090576EE2628971D829A4EF34FCDB70AF6A0
61 | 2F3B761394BBCE8055DD6276D4C13419C2EED0DA2A671D8131F1731BEBDF3B69
62 | E93AF26D95A30E40811CA354FD9269978C247600E5A6311800B8E471FFBD9096
63 | 8F684D6328270DC1CCFAA363B52F32A9A6A18BA01C34C23108B05F126A6C245A
64 | 5DBD01F6EEAF329184B9A7E362423A8BCC884A91F1FBF178EE9F34F6DCC12492
65 | D360C583AEBC21A8957B1A0818D7537DFFFD8DE83C629394096923FA5ED795C5
66 | 886837EE8CE9AA1B81DAD8FBC360E52AD60FF1B40C9C23622C326BB77A8F4953
67 | 66C4CE3782AEB801A885BD163C731410C686855E0C2A0F1DD45EA329B836447B
68 | 3680AEE60CC44A2DB46EB41529602CE91E273453B1A8603D96E906A2D5951C81
69 | 1BD09365C5429DD30A532A5C4F4BD511AD734BA5AB380151F4E2B35269CE7935
70 | 299DB65E848BE577EC88E90A0EE8251AC0433CF365CFB7C02AD91E5663D09239
71 | 85BC94BA035AC759E9485D92504360715B77D068D51C5C2FA55C197408AC1BD8
72 | 8AC4321B04B4BB04AB085A0E4E388C8829D58A20F462657C0BD2FCF71C9A6A05
73 | 42628CCA5965B605696D2B42295602FE538B892C5C939EFF813470135A85C22A
74 | 3E1FA5560134C1AD0AE33FFF19327160163CA7169D328C4AA5D64FA95540EB90
75 | CA6161CBD0625A2706AD42DF4229AD04B38FAC0C6ECD43B4656831711EEBBE12
76 | 4A6505F08BAC8CB5E28C687FD1437AA33C87FC75C144979FE4B387E97C58D023
77 | E69CD7AF5FABDEBF3C3D7BF64C8DD5A36B7EA3CE0ADBAEAEAE16A59B052CDED6
78 | 833B58F715500A0BC143EEF1E51609D122844F744CC8873CB4423C501317A6F3
79 | AE6084E7AD7CBAA7EABD8769C4C8B154B8EAA0326C39C8832BB2E235A04A6121
80 | 7A18518931528B638285DF33E7B5004B058BB5C49286E7E692735D2CEE96833D
81 | 2B061574F60230E9C2CA484FC4B70E9012ECA7AAF925AEC112C1BE57138C350F
82 | CF2B25F7415AD5B1E5B2A585AE81CE2C0435A3D779992103D1A6040B1FD33466
83 | A254B058C5AF6459C27342DEBB77EF9AD6BE2911BE8BA5DDAA138D6BB0A0EFA0
84 | 330BC1709F95815E3911ED9C60E10F99D18652C1D2890A8F1F4945A173353D9F
85 | DF6C4BE5F939C3E01ED8CA3D6004AE103AAB00D488ADE3773538883647B0F7D5
86 | 91CC710D4A044B14203C76648EE838C63A17BA74C4C0561DB1376F860BE64167
87 | 14A0E78ED61C255A4BB05FC8BD09B7D1239F43896063AE4049478F109795C693
88 | 0AB14D13B81B2A2F5DC497851D309D91893D74B466F8C81019CD2E1DAE70FB8F
89 | 33CB6772051BB3AE88B804F8AB587F2B2D42642EA063B7457FA5A003A6A33341
90 | 015B17DB111F89E1C346B096F5421CA94E4DAE6063BE2B422EC5777AB0565A6C
91 | 770395C17B8A22F1FC4C2BABA33340E15A17DA192DC1D2C98AF5E08979C6902B
92 | 58EBB8250315807C8669412A852BB678FE99954E4766E00CAC2B8C0916D07909
93 | F741865C2DE40896CE5B780C5CD3BBB7AE8B1FEE0EEF89F999565647CEC0BB76
94 | 91D1FFFED7DE579929C182172F5EDCD98F182CD72047B0B14AB0A609B73A8EB8
95 | 2FEEA00CBCE71D64948B8E9A817726470B8670ACFD15690AF61FFFB8B9BE8030
96 | ADA801420E912358AC73780C5CE2BF8E88F9C49B80FBF30C6B6658591D950031
97 | 3E2BE15A0CC347CEA235052B4E07179885151E4314218C77E60816EB1D1E03B9
98 | C652C4C25B9B012BC8F5BC3863657544029E71577A9E5680DE51B451C1C28915
99 | B526A78461A81CC1C6425A442696C2B2B054A8CD8005F4ECD3CC58591D1181B7
100 | 754DD52427D126050B87DE36AE8125C8570C4B0FC811AC65ADE1349D52583E2C
101 | 79D914B871BAAE1B79FE11686F049EBDC2C05A99C00A55F69766050B07D15AFE
102 | 27966C0CD2E7083616254885CBE6605D17116F0ECA49D77661E27EB4D7002619
103 | D36C255683B93E1CA34D15459B25583888D6720D4671E4081658A353A5A35C23
104 | 621500BF7673E0CE553628B7689425D01E039EA1ACD2B1EF8AA2CD162C946899
105 | 736A098ECE9435D0600996B1FEF038B8C48F8D4D825913755805CF56385209B5
106 | C78067672BE86D67A192688B040B255AE61484E720622BFC650936D6F19A1BFA
107 | 0D8175B5E63C94A653159E5636E2976B4F00CF4CAC99595441B4C58285126D6A
108 | 2EEB94966081658D21E9E6880D4BCF9C592B0DD7790439F0B4B2C628A3B606F0
109 | 8CB32DB1AE53AC14ED22C18AEFFFF94FD3350819136CCCCA427CE2D472173A79
110 | 963587F8D1CDACEB084F03A70A1D425B0378C5D8167634EE608568970A165EFD
111 | ED6FFAEFEEF953C6040B52561AE1B19FF9B1E39271425FCCCB8D2D97C13D5833
112 | 0051155E5696E71C54486D9D8002B74EACC19A1D8385A25D2358F8F4CF7FD67F
113 | 77D31899122C9630E61A2CE1740E4473785AD94037DA3281D72853C4815E8505
114 | A25D2BD85FC5FBBFFFBD7EDE4D07A6040B106DCC17CD2596B559542005AF8E3A
115 | D67B026D99009FC13A692DBDE28485A25D2B58C8F1611A23E7043B82B869CECA
116 | D890F8BBDDB80121A844CA637506AEA4B64C8025B44E5ACBCC07B90805A2AD21
117 | 58F8580CD381B9820574B4F053631DAA91585462B95D5AD529F035D53155A6EB
118 | 73D229D55F03286CEBE0B5DC62D87045476C158D5EEC1220743A5A74BAB0BE90
119 | F82FDB7605AFCED7A4B2EAAF015EFEEB569D8356A2653974EBD0522FF09A3035
120 | F163F5D7000FFF15016DF93011ADF782398B87683F422E8E59466B38F163F5D7
121 | 000FFF750B772004B5FC106D3B78B905831FAB5F8297FFEA151D98C321DA76F0
122 | 8A160C7EAC7E095E1769D9693844DB065842AB5CD67298F4AE5F027F5807ADE1
123 | D6FEAB8543B46DE031BC3FACFFD32FC1A3C3D5C27FB57088767B78F8B143C74B
124 | BF048FA5DCADFC570B8768B785878B498B2DE897E0F1300931F58443B4DB81C9
125 | 305659ACE5DBB712AC63E2DDE110ED76F02867596EDE2B69EF5CC3C17C778943
126 | B4DBC0C3CD7CF54A82F5586110CCB0E90E8768FDE1D191579AAC11B677AEE182
127 | 77D76F8E43B4BEF008953E7A24C17AD48421C8DB3D5A8996E632B18EEB2CE011
128 | 2970136C4FCB37E6D04AB4B84DE72C5A269A5BF7BD862A33BEEA60EF5CC33D09
129 | 163097C26BF27A8AE72C5A8FF9297A46ACBBB077AE61620E01AFAD1C57868E4C
130 | 7D54C23A7ECA35B895D6D5D5E9CDFDFBA737CA3F7C37BD9F02BE15C734A664BB
131 | 75FC5AD1B24E8CC9DE4CFAE63DB62CA319C9DF6CE7DD05E1EB422DCC95758A77
132 | 565B9C8B6029C87019084B9C63B08E9F92C25A021E8E95DEC897A27E14F38168
133 | A5C776FDB0B940B4DC77E98246DEAD90FAA4D35C59A748C5B8053A96DA5E9B2C
134 | 8A3777AC62A236D7166CEADC14521F6B834B048B25B5D21AF993A81F3633454B
135 | 455B232C184355C1026DAF4D1FC186CDC304B505CB22BDD2B79F70FCDC9B5C5E
136 | 2EE8883D13ADB446B25F3FE29C116DEC9B62A58C611F82F558E9B8A16061E94B
137 | 2552AF0E1AF9F25FFF2AEA887D10EF89565A23D9CF71FA23CE886859616BA519
138 | 928A4899A52A640CD505EB600C776761B130E19A7E8E2941F80A4CEB5DAFD70F
139 | 80FBC82C9F2B314CC35A56FE5AD48F3403D1CE5530DE638B4F6B7D2397CE109D
140 | 32CA78B4CE31943E9B5938840B7D049BE8F5AF152CB4DEB99AFB4E00EBB59556
141 | 7ABF598C4CD186EF2AF854B45EBAF144D48F790EA22582127303B0A2252FD6E0
142 | 5D08A9EFDB5617ACCEAF4D3ECB67EE5845E72881D53C9A4D9281F0DCF1456CD3
143 | 6DF0567A33A2E51546E1F958576B3B427E2FEA8F794AB44FFEFE77FDBC9B0EE5
144 | 927AEBE112EC43B0CAA4B563159D056B85A4105E0EC237ADD09C12EA996E8377
145 | 2A4042B4AFC4F0FCEF45F6596EC1B86F8EBF88E1B9108B5BF296995C54152CF9
146 | D3F955892B783D19C3DAB98689D7A1D7106CEC4D80733159EBAB2E6CB3AE615A
147 | EC8868BF10C3F3B1AEEC439CE1BE8722FBE6F8420CCF855E2F31EE5EB02A7B72
148 | 64EF5CC344AFBD8660B12E3CB470FB5CE1861FD9C0DA826CC18240B49615C4AA
149 | B20F5A6E01CC1949FB4A0CCF1BF3EC81AA822516AFF3ABD24DB0090B504BB056
150 | E789BF633159B687D105FC595024583011EDF3E03C1836F9965B303730819F1B
151 | 9E039F7EFDF59089FAA82A588F8501E4EFFA0B80D6CE354C7C87AA966081D5BB
152 | 8FC56409BA87C78E61A062C1029DFBE1CB2F4FF783F3E0E80E8CB4DC82E450AD
153 | 18F35FAF073486FB0F513217C0AAD85639E490F3EE806884F65525F9BB9EBB6A
154 | ED5C43220F11D414AC159F340B4F08C7DDF97B84758D59C10AAFFFF7BF3BE74D
155 | DD819131B72035541B1BE625DE7B6DDD0DD15AF711A3D5692B397F4AB3CC3D96
156 | 7A63A05C26DA620522B00A65A9608135A2133E0C2C6978CCF43B59D63572046B
157 | 59F85804C0720B5243B5B117272364FD30455B223877C17A74E6E50D7C721DE4
158 | B776AE6524466815CA1AC132852EDC1F8A2D8CBDE2CB4E9B44EB1A7382B57C68
159 | 18BA03232DB7203554CB8858783CBC35521688B64470EE82F518F2C7ADBB4EDC
160 | DAB996911118AB50D6089691A0707F18930D875EC36FBD5AD79813AC15A578F4
161 | 873FD86521C6DC82D8506DCC2520E6AB1F1F39116D89E072054BF890B248F14E
162 | BF0163A573AB93F8FBF5053CDEE9191902AC2D58F0503E73780C1D0BC0FFE1BE
163 | 7038738960AD6B3EF8D39FAE454BF36F9151AEF09CD8502D61AFF05868BA1186
164 | 7B3082B2B2D2C9156CEAD94441F9EADCEA54ABA87F05F962E6016B18B9510FC1
165 | 52C3C363701540187BC562842815AC65D5973235546BCDFE6290827D7718116D
166 | 13C112D6D4B95539C49FF54BF0086D05CDF2080FC1E28F86FEE428CCD01DB046
167 | 894A056BF9CD6B18EBA8617DADE3A333BE0CD13611AC8701244D41BF047ACCD6
168 | 416B59A15072040B48233C2E8CBD22EA31F63A45A960E7267F973236546B75D4
169 | 20B1DFE8BCDA40B44D044B9448E756E5D062EA97E0318C068D20BE97602D5F35
170 | B4AE84A12C9408D6FABA37C4F5E09C5BFCF6DBD34B899B51AD91D14F2689FA71
171 | 8B88D21A98808CB0E987CD89683717AC97968630A47E0DF0A815C6CD7A0916CC
172 | 7DF32AF6ADAB12C15A33BBB0B851D063C63DD17190D5B3E1F9303654FB9D681D
173 | 0FB1CCD1D5B883683717AC87FF0A87FCEAD7000FBF83420BE029D8D432124415
174 | 9B67902B58E69F5AB1D7304C76078168ADD95DA9A1DA982F0BE9B431AB0BF7E1
175 | B7410591A1DD1FFEF8C7D3E3BFFEF5D6F12373059B13D61A793D3FD763C060A2
176 | 23FD35C0AB660CE1A5119E82B546B446B24A36865CC15AD1083886D092988816
177 | 6B6AA5131BAAC535B0666EAD61AE604BF8EEE79F7DBE9536D187FE1AE0E57B04
178 | 62F4142C88ADD56762480CB982B58E63D42C1B885669C4DC82D4502DA1AF98FF
179 | BB842E82FDF7BFCDBCAFE6A42FA4BF26F0F063A97133C3A035056B4D88B162AF
180 | 53E408966B86C7C0621F8FB250A5B2DC829C55B558E7B9D5B92932E0414B5173
181 | B6D6C8777FF98B99E7D59C3C6FFD3581871F0B2735C45BB03C8830EC3437433F
182 | 47B0FC1D1E03891A1443797CF9F9E7667A39AB6A11353E2BA367561A211138D6
183 | FBED679FDDB4A411AC16ACA81F7519F483B465022F3F56057120C06069CDF22A
184 | 249DAD1FC53174C64C2FB69911045AD1846817C3EB0B888131D39609BCFC5898
185 | B08A178B8AA22D626DD1721F84F6AC6BAD6510CBD796005E174EF4D22F1AE720
186 | 5AAF9619062393DA12C0635E01A4F3650C8B1E10F62C5A4FEB4A9904D0D6005E
187 | 13BAE16165E3D8AB683DADEB6455C8086D35E0F136187858D934F6285A2FEB4A
188 | 9E288F00DA63C063C5E3C8C3CAA6B127D17AAC071C1919EED61E0358418F2136
189 | 7858D979EC41B4E471323FA23A23C3DDDA1381D720022C1D1DBA44F42E5A4FDF
190 | D5983435427B23F034F73067C2C8A5A3956869055323789E2D3034E6718CD0DE
191 | 08282C2F871AD29C708D036950469EAD5D8C29D1F2610FEB9C1A9C7119754402
192 | 9E661F92FE813CE0465965E8494BB4FC6D1D5B8B339D721D9180B7959DA94D07
193 | 02B4162D7AF07825C0C80C3DE8A819785BD963624C195A8AD66B82CBC88C90A7
194 | 8E9A81B795850927FB808116A2FDDDEFECEDB598D9DAEAC80C785B5918592078
195 | 208216A2F564644573081D99812DAC2CF1BF630A6219CE49B49903163A32135B
196 | 5859E63050390EE4E31C449BF8FE6D081D9D0984E43914379240F98132EC59B4
197 | 8591229D510046A7AC8BD6260FE04019F62ADAC258BCCE2884E728C79447E4A0
198 | 1C7B13ED82D14E9D5508CC3766DCCA406D263E337920823D8976C17C129DB500
199 | 5B74C04616361907843D88B6A0A33585CE5C80AD3A60238F49DFE5E859B4851D
200 | AD2974F6426CD5011B498D3C425E65A01F6095656BAE70F574F60A6C5D20CC3B
201 | E0FD5407F2D19B683347B462500A2B8188AC8C79115764617372B1E845B4AC24
202 | 58697094CA4A9001326265D08B0CE3C626171FB0D15AB4F8ADBC426025945205
203 | F0999BAD425D53D2193BFCDA7CB4146DF0CAA1A5504A95B065A86B4AE61F1C93
204 | 66E641C56E1539E0BA95A0D42AA2C5DA23888B307C4AFE8001A66E7ACFB68B91
205 | 150A155B41A5581193D7A23721D78E7C32F42281CFD862D5ED482A49E5D64FA9
206 | 56468B4E58489AA04B8E2460D178A95F8B7EC5C89297721440293B805AD5AA09
207 | 1A4981E1575F5AA78CCE4DEBB2A7A238457194BA13A85D88C6BAA12D491EE81D
208 | 9FF380039592CAD9BA651BE9B8DC49A93B82E1DB96CDD294089766F29C5C8551
209 | A8AD2DEA94CE33EC74056778BFF26809999760BC7B7437A063C9DBFD7A68C1A6
210 | A4257386AEB201F0AB7AB1B453F2C079F07B882CD02F4010BD34FB2137102BD0
211 | 9536024E786F16614A84C0C8192D422FFE2E2E154268192ACCE18613ED75B50D
212 | D14B472C878CA0E1F352D1B6123002650084D8698F2D5248F2B8B16BA5AB6E0C
213 | 9AB65E9BB5147938CC4CC3FFC5EA61891158A9983967B49CB823A4B9974A3C25
214 | 796E300149576E001E72EFCDDC1A321CE9F59D881E88581D060572A0AB3702A2
215 | 6D35F7E0E07252191B4E36520E1A039FCD2A9883FD1177A8718754B9E8008495
216 | F6E8D75E0AF1DF2BCD675D0BE5A6131C2E429FC405A8B052A01694A3CE404C6F
217 | 0F219D4B20518CCE260F29571D821EE83947117A2773133A1DBA56EE3A061DB2
218 | 3DC628F74C46FB1A77AC52500E3B07B3ABE89D5A857BB01E891B378AAD964039
219 | DD09181DF2FC82C9A592E6BF9308400E94E31D810EC0E126D463E7CDBF05E57A
220 | 87A090198B3F845B4E2230AC796B385AB506BA831DE3106E3E112A1675E72B2E
221 | 7427670084DBDB52915E48653EA3A541BAA333023E2E030F47E7ECA60CF0F777
222 | E6A3CE417776A6603811CB724973146861189DDA41786A297497178071D1DE39
223 | BA0CF8A6C4A91D9756F704DDF18581074BE763CF43BFB41AF4F4899F9E59933F
224 | 07DDFD058387CD9839D6B767BF9796012B8A40771A8EAA0595C681DF404F1A01
225 | 132A63AD550B11234EAE4D2B4007B2A3A97D3D4025746016746258708790698A
226 | 11145CB26E8B4A309ECFFC5FD2A49230F47C6006A7D3FF0176F1E564B5BA5487
227 | 0000000049454E44AE426082
228 | }
229 | Visible = False
230 | end
231 | object Image1: TImage
232 | Cursor = crHandPoint
233 | Left = 13
234 | Height = 114
235 | Top = 334
236 | Width = 96
237 | Center = True
238 | OnClick = Image1Click
239 | ParentShowHint = False
240 | PopupMenu = pmImage
241 | Proportional = True
242 | ShowHint = True
243 | end
244 | object Image2: TImage
245 | Cursor = crHandPoint
246 | Left = 117
247 | Height = 114
248 | Top = 334
249 | Width = 96
250 | Center = True
251 | OnClick = Image1Click
252 | ParentShowHint = False
253 | PopupMenu = pmImage
254 | Proportional = True
255 | ShowHint = True
256 | end
257 | object Image3: TImage
258 | Cursor = crHandPoint
259 | Left = 13
260 | Height = 114
261 | Top = 454
262 | Width = 96
263 | Center = True
264 | OnClick = Image1Click
265 | ParentShowHint = False
266 | PopupMenu = pmImage
267 | Proportional = True
268 | ShowHint = True
269 | end
270 | object Image4: TImage
271 | Cursor = crHandPoint
272 | Left = 117
273 | Height = 114
274 | Top = 454
275 | Width = 96
276 | Center = True
277 | OnClick = Image1Click
278 | ParentShowHint = False
279 | PopupMenu = pmImage
280 | Proportional = True
281 | ShowHint = True
282 | end
283 | object ckForcePng: TCheckBox
284 | Left = 13
285 | Height = 24
286 | Top = 8
287 | Width = 200
288 | AutoSize = False
289 | Caption = '강제 png 변환'
290 | Checked = True
291 | State = cbChecked
292 | TabOrder = 0
293 | end
294 | end
295 | object Panel3: TPanel
296 | Left = 0
297 | Height = 573
298 | Top = 0
299 | Width = 692
300 | Align = alClient
301 | ClientHeight = 573
302 | ClientWidth = 692
303 | TabOrder = 0
304 | object Panel4: TPanel
305 | Left = 1
306 | Height = 264
307 | Top = 1
308 | Width = 690
309 | Align = alTop
310 | BevelOuter = bvNone
311 | ClientHeight = 264
312 | ClientWidth = 690
313 | TabOrder = 0
314 | object Label1: TLabel
315 | Left = 12
316 | Height = 18
317 | Top = 17
318 | Width = 72
319 | Alignment = taRightJustify
320 | AutoSize = False
321 | Caption = '기준위치'
322 | end
323 | object edBasePath: TEdit
324 | Left = 88
325 | Height = 23
326 | Top = 12
327 | Width = 200
328 | TabOrder = 0
329 | end
330 | object btOpen: TButton
331 | Left = 314
332 | Height = 25
333 | Top = 12
334 | Width = 26
335 | Action = acOpenBasePath
336 | Caption = '...'
337 | Font.Color = clWindowText
338 | Font.Height = -16
339 | Font.Name = '맑은 고딕'
340 | ParentFont = False
341 | ParentShowHint = False
342 | ShowHint = True
343 | TabOrder = 2
344 | OnClick = btOpenClick
345 | end
346 | object btRefresh: TButton
347 | Left = 339
348 | Height = 25
349 | Top = 12
350 | Width = 26
351 | Action = acRefresh
352 | Caption = '⟳'
353 | Font.Color = clWindowText
354 | Font.Height = -16
355 | Font.Name = '맑은 고딕'
356 | ParentFont = False
357 | ParentShowHint = False
358 | ShowHint = True
359 | TabOrder = 3
360 | end
361 | object Label2: TLabel
362 | Left = 399
363 | Height = 18
364 | Top = 17
365 | Width = 76
366 | Alignment = taRightJustify
367 | AutoSize = False
368 | Caption = '에뮬레이터'
369 | end
370 | object cboEmulator: TComboBox
371 | Left = 480
372 | Height = 23
373 | Top = 12
374 | Width = 136
375 | ItemHeight = 15
376 | Style = csDropDownList
377 | TabOrder = 4
378 | OnChange = cboEmulatorChange
379 | end
380 | object Label3: TLabel
381 | Left = 43
382 | Height = 12
383 | Top = 230
384 | Width = 72
385 | Alignment = taRightJustify
386 | Caption = '스크랩검색어'
387 | end
388 | object edSearch: TEdit
389 | Left = 120
390 | Height = 23
391 | Hint = '스크래핑 시 해당 키워드를 통해 검색합니다'
392 | Top = 225
393 | Width = 112
394 | ParentShowHint = False
395 | ShowHint = True
396 | TabOrder = 5
397 | OnKeyPress = edSearchKeyPress
398 | end
399 | object btScrape: TButton
400 | Left = 239
401 | Height = 34
402 | Top = 224
403 | Width = 76
404 | Action = acScrape
405 | TabOrder = 6
406 | end
407 | object btAutoDetect: TButton
408 | Left = 289
409 | Height = 25
410 | Top = 12
411 | Width = 26
412 | Action = acDetectBasePath
413 | Caption = '!'
414 | Font.Color = clWindowText
415 | Font.Height = -16
416 | Font.Name = '맑은 고딕'
417 | ParentFont = False
418 | ParentShowHint = False
419 | ShowHint = True
420 | TabOrder = 1
421 | end
422 | object GroupBox1: TGroupBox
423 | Left = 24
424 | Height = 171
425 | Top = 48
426 | Width = 608
427 | Caption = '상세정보'
428 | ClientHeight = 154
429 | ClientWidth = 604
430 | TabOrder = 7
431 | object Label4: TLabel
432 | Left = 16
433 | Height = 18
434 | Top = 4
435 | Width = 72
436 | Alignment = taRightJustify
437 | AutoSize = False
438 | Caption = '레이블'
439 | end
440 | object Label5: TLabel
441 | Left = 8
442 | Height = 18
443 | Top = 45
444 | Width = 80
445 | Alignment = taRightJustify
446 | AutoSize = False
447 | Caption = '롬 경로'
448 | end
449 | object Label6: TLabel
450 | Left = 303
451 | Height = 18
452 | Top = 44
453 | Width = 88
454 | Alignment = taRightJustify
455 | AutoSize = False
456 | Caption = '이미지 경로'
457 | end
458 | object ckShortname: TCheckBox
459 | Left = 115
460 | Height = 19
461 | Top = 116
462 | Width = 94
463 | Caption = '롬 단축파일명'
464 | TabOrder = 7
465 | end
466 | object edImagePath: TEdit
467 | Left = 400
468 | Height = 23
469 | Top = 38
470 | Width = 193
471 | TabOrder = 3
472 | end
473 | object edRomPath: TEdit
474 | Left = 96
475 | Height = 23
476 | Top = 38
477 | Width = 193
478 | TabOrder = 2
479 | end
480 | object edLabel: TEdit
481 | Left = 96
482 | Height = 23
483 | Top = -2
484 | Width = 193
485 | DoubleBuffered = True
486 | ParentDoubleBuffered = False
487 | TabOrder = 0
488 | end
489 | object ckHideBios: TCheckBox
490 | Left = 219
491 | Height = 19
492 | Top = 116
493 | Width = 102
494 | Caption = '바이오스숨기기'
495 | TabOrder = 8
496 | end
497 | object edGamelist: TEdit
498 | Left = 400
499 | Height = 23
500 | Top = 78
501 | Width = 193
502 | TabOrder = 5
503 | end
504 | object Label7: TLabel
505 | Left = 8
506 | Height = 18
507 | Top = 82
508 | Width = 80
509 | Alignment = taRightJustify
510 | AutoSize = False
511 | Caption = '확장자 목록'
512 | end
513 | object Label8: TLabel
514 | Left = 312
515 | Height = 18
516 | Top = 82
517 | Width = 79
518 | Alignment = taRightJustify
519 | AutoSize = False
520 | Caption = 'gamelist'
521 | end
522 | object edExtList: TEdit
523 | Left = 96
524 | Height = 23
525 | Top = 78
526 | Width = 193
527 | TabOrder = 4
528 | end
529 | object ckUseSwap: TCheckBox
530 | Left = 16
531 | Height = 19
532 | Top = 116
533 | Width = 70
534 | Caption = '스왑 사용'
535 | TabOrder = 6
536 | end
537 | object Label9: TLabel
538 | Left = 312
539 | Height = 18
540 | Top = 4
541 | Width = 79
542 | Alignment = taRightJustify
543 | AutoSize = False
544 | Caption = '아이콘'
545 | end
546 | object edIcon: TEdit
547 | Left = 400
548 | Height = 23
549 | Top = -2
550 | Width = 193
551 | TabOrder = 1
552 | end
553 | object btSaveEmuInfo: TButton
554 | Left = 470
555 | Height = 34
556 | Top = 109
557 | Width = 123
558 | Action = acSaveEmuInfo
559 | TabOrder = 9
560 | end
561 | object btScanExt: TButton
562 | Left = 328
563 | Height = 34
564 | Top = 109
565 | Width = 136
566 | Action = acScanExt
567 | TabOrder = 10
568 | end
569 | end
570 | object btGenerateCache: TButton
571 | Left = 477
572 | Height = 34
573 | Top = 224
574 | Width = 139
575 | Action = acGenerateCache
576 | ParentShowHint = False
577 | ShowHint = True
578 | TabOrder = 8
579 | end
580 | end
581 | object Panel1: TPanel
582 | Left = 1
583 | Height = 307
584 | Top = 265
585 | Width = 690
586 | Align = alClient
587 | ClientHeight = 307
588 | ClientWidth = 690
589 | TabOrder = 1
590 | object TreeView: TTreeView
591 | Left = 1
592 | Height = 305
593 | Top = 1
594 | Width = 137
595 | Align = alLeft
596 | AutoExpand = True
597 | Images = ImageList
598 | PopupMenu = pmDir
599 | RowSelect = True
600 | TabOrder = 0
601 | OnChange = TreeViewChange
602 | OnDragDrop = TreeViewDragDrop
603 | OnDragOver = TreeViewDragOver
604 | OnEdited = TreeViewEdited
605 | Options = [tvoAutoExpand, tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoRowSelect, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
606 | end
607 | object ListView: TListView
608 | Left = 143
609 | Height = 305
610 | Top = 1
611 | Width = 546
612 | Align = alClient
613 | AutoSortIndicator = True
614 | BorderStyle = bsNone
615 | Columns = <
616 | item
617 | Caption = '롬이름'
618 | Width = 200
619 | end
620 | item
621 | Caption = '이미지 경로'
622 | Visible = False
623 | Width = 1
624 | end
625 | item
626 | Caption = '롬파일명'
627 | Width = 100
628 | end
629 | item
630 | Caption = '롬경로'
631 | Width = 377
632 | end>
633 | DragMode = dmAutomatic
634 | GridLines = True
635 | HideSelection = False
636 | MultiSelect = True
637 | ParentFont = False
638 | PopupMenu = pmPopup
639 | RowSelect = True
640 | SmallImages = ImageList
641 | SortColumn = 0
642 | SortType = stText
643 | TabOrder = 1
644 | ViewStyle = vsReport
645 | OnCustomDrawItem = ListViewCustomDrawItem
646 | OnEdited = ListViewEdited
647 | OnSelectItem = ListViewSelectItem
648 | end
649 | object Splitter1: TSplitter
650 | Left = 138
651 | Height = 305
652 | Top = 1
653 | Width = 5
654 | end
655 | end
656 | end
657 | object mmLog: TMemo
658 | Left = 0
659 | Height = 80
660 | Top = 573
661 | Width = 918
662 | Align = alBottom
663 | Color = clBlack
664 | Font.Color = clLime
665 | ParentFont = False
666 | ReadOnly = True
667 | ScrollBars = ssAutoBoth
668 | TabOrder = 2
669 | end
670 | object pbInfo: TProgressBar
671 | Left = 0
672 | Height = 20
673 | Top = 653
674 | Width = 918
675 | Align = alBottom
676 | ParentShowHint = False
677 | ShowHint = True
678 | TabOrder = 3
679 | Visible = False
680 | BarShowText = True
681 | end
682 | object ActionList: TActionList
683 | Left = 108
684 | Top = 363
685 | object acScrape: TAction
686 | Caption = '스크래핑(&S)'
687 | OnExecute = acScrapeExecute
688 | end
689 | object acRescrapeAll: TAction
690 | Caption = '모두 스크래핑(&A)'
691 | Visible = False
692 | end
693 | object acScrapeMissing: TAction
694 | Caption = '누락 항목 스크래핑(&M)'
695 | OnExecute = acScrapeMissingExecute
696 | end
697 | object acRename: TAction
698 | Caption = '이름 바꾸기(&R)'
699 | OnExecute = acRenameExecute
700 | ShortCut = 113
701 | end
702 | object acDelete: TAction
703 | Caption = '삭제(&D)'
704 | OnExecute = acDeleteExecute
705 | ShortCut = 32814
706 | end
707 | object acCancelScrape: TAction
708 | Caption = '스크래핑 취소(&C)'
709 | OnExecute = acCancelScrapeExecute
710 | ShortCut = 27
711 | end
712 | object acChangeImage: TAction
713 | Caption = '이미지 변경(&I)'
714 | OnExecute = acChangeImageExecute
715 | end
716 | object acOpenImagePos: TAction
717 | Caption = '이미지 위치 열기(&O)'
718 | OnExecute = acOpenImagePosExecute
719 | end
720 | object acSaveEmuInfo: TAction
721 | Caption = '상세정보 저장(&V)'
722 | OnExecute = acSaveEmuInfoExecute
723 | end
724 | object acBuildGamelist: TAction
725 | Caption = '&gamelist.xml 생성'
726 | OnExecute = acBuildGamelistExecute
727 | end
728 | object acRefresh: TAction
729 | Caption = '새로 고침'
730 | OnExecute = acRefreshExecute
731 | ShortCut = 116
732 | end
733 | object acDetectBasePath: TAction
734 | Caption = '기준위치 자동인식'
735 | OnExecute = acDetectBasePathExecute
736 | end
737 | object acOpenBasePath: TAction
738 | Caption = '기준위치 열기'
739 | OnExecute = acOpenBasePathExecute
740 | ShortCut = 16463
741 | end
742 | object acExit: TAction
743 | Caption = '종료(&X)'
744 | OnExecute = acExitExecute
745 | end
746 | object acGenerateCache: TAction
747 | Caption = '캐시 재생성(&C)'
748 | OnExecute = acGenerateCacheExecute
749 | end
750 | object acAbout: TAction
751 | Caption = 'TrimUI 정보(&A)'
752 | OnExecute = acAboutExecute
753 | end
754 | object acAddRom: TAction
755 | Caption = '롬추가(&N)'
756 | OnExecute = acAddRomExecute
757 | end
758 | object acMkDir: TAction
759 | Caption = '폴더 생성(&F)'
760 | OnExecute = acMkDirExecute
761 | end
762 | object acGithub: TAction
763 | Caption = '&Github'
764 | OnExecute = acGithubExecute
765 | end
766 | object acRmDir: TAction
767 | Caption = '폴더 삭제(&D)'
768 | OnExecute = acRmDirExecute
769 | end
770 | object acScanExt: TAction
771 | Caption = '확장자 스캔(&E)'
772 | OnExecute = acScanExtExecute
773 | end
774 | object acScrapeTotal: TAction
775 | Caption = '전체 에뮬레이터 스크래핑(&T)'
776 | OnExecute = acScrapeTotalExecute
777 | end
778 | object acCacheFromXml: TAction
779 | Caption = 'gamelist.xml 을 이용해서 게임 목록 생성'
780 | OnExecute = acCacheFromXmlExecute
781 | end
782 | end
783 | object pmPopup: TPopupMenu
784 | Left = 220
785 | Top = 363
786 | object pmScrape: TMenuItem
787 | Action = acScrape
788 | end
789 | object Scrapemissing1: TMenuItem
790 | Action = acScrapeMissing
791 | end
792 | object RescrapeAll1: TMenuItem
793 | Action = acRescrapeAll
794 | end
795 | object MenuItem32: TMenuItem
796 | Action = acScrapeTotal
797 | end
798 | object Separator4: TMenuItem
799 | Caption = '-'
800 | end
801 | object MenuItem22: TMenuItem
802 | Action = acAddRom
803 | end
804 | object Rename1: TMenuItem
805 | Action = acRename
806 | end
807 | object MenuItem1: TMenuItem
808 | Action = acChangeImage
809 | end
810 | object Delete1: TMenuItem
811 | Action = acDelete
812 | end
813 | object N1: TMenuItem
814 | Caption = '-'
815 | end
816 | object C1: TMenuItem
817 | Action = acCancelScrape
818 | end
819 | end
820 | object SQLite3Connection: TSQLite3Connection
821 | Connected = False
822 | LoginPrompt = False
823 | KeepConnection = False
824 | Transaction = SQLTransaction
825 | CharSet = 'utf8'
826 | AlwaysUseBigint = False
827 | Left = 220
828 | Top = 304
829 | end
830 | object SQLQuery: TSQLQuery
831 | FieldDefs = <>
832 | Database = SQLite3Connection
833 | Transaction = SQLTransaction
834 | SQL.Strings = (
835 | ''
836 | )
837 | Options = [sqoAutoCommit]
838 | Params = <>
839 | Macros = <>
840 | Left = 220
841 | Top = 427
842 | end
843 | object SQLTransaction: TSQLTransaction
844 | Active = False
845 | Database = SQLite3Connection
846 | Left = 109
847 | Top = 427
848 | end
849 | object SQLite3Name: TSQLite3Connection
850 | Connected = False
851 | LoginPrompt = False
852 | KeepConnection = False
853 | Transaction = SQLTransactionName
854 | CharSet = 'utf8'
855 | OpenFlags = [sofReadWrite]
856 | AlwaysUseBigint = False
857 | Left = 109
858 | Top = 304
859 | end
860 | object SQLName: TSQLQuery
861 | FieldDefs = <>
862 | Database = SQLite3Name
863 | Transaction = SQLTransactionName
864 | SQL.Strings = (
865 | ''
866 | )
867 | Options = [sqoAutoCommit]
868 | Params = <>
869 | Macros = <>
870 | Left = 168
871 | Top = 427
872 | end
873 | object SQLTransactionName: TSQLTransaction
874 | Active = False
875 | Database = SQLite3Name
876 | Left = 64
877 | Top = 427
878 | end
879 | object pmImage: TPopupMenu
880 | Left = 256
881 | Top = 363
882 | object MenuItem2: TMenuItem
883 | Action = acChangeImage
884 | end
885 | object MenuItem3: TMenuItem
886 | Action = acOpenImagePos
887 | end
888 | end
889 | object MainMenu: TMainMenu
890 | Left = 45
891 | Top = 363
892 | object mnFile: TMenuItem
893 | Caption = '파일(&F)'
894 | object MenuItem7: TMenuItem
895 | Action = acDetectBasePath
896 | end
897 | object MenuItem6: TMenuItem
898 | Action = acOpenBasePath
899 | end
900 | object MenuItem19: TMenuItem
901 | Action = acRefresh
902 | end
903 | object Separator2: TMenuItem
904 | Caption = '-'
905 | end
906 | object MenuItem21: TMenuItem
907 | Action = acAddRom
908 | end
909 | object MenuItem26: TMenuItem
910 | Action = acMkDir
911 | end
912 | object MenuItem30: TMenuItem
913 | Action = acRmDir
914 | end
915 | object MenuItem12: TMenuItem
916 | Action = acSaveEmuInfo
917 | end
918 | object MenuItem13: TMenuItem
919 | Action = acRename
920 | end
921 | object MenuItem15: TMenuItem
922 | Action = acGenerateCache
923 | end
924 | object Separator1: TMenuItem
925 | Caption = '-'
926 | end
927 | object MenuItem8: TMenuItem
928 | Action = acExit
929 | end
930 | end
931 | object mnScrape: TMenuItem
932 | Caption = '스크래퍼(&S)'
933 | object MenuItem10: TMenuItem
934 | Action = acScrape
935 | end
936 | object MenuItem11: TMenuItem
937 | Action = acScrapeMissing
938 | end
939 | object MenuItem31: TMenuItem
940 | Action = acScrapeTotal
941 | end
942 | object MenuItem16: TMenuItem
943 | Action = acCancelScrape
944 | end
945 | object Separator3: TMenuItem
946 | Caption = '-'
947 | end
948 | object MenuItem17: TMenuItem
949 | Action = acChangeImage
950 | end
951 | object MenuItem18: TMenuItem
952 | Action = acOpenImagePos
953 | end
954 | end
955 | object mnXML: TMenuItem
956 | Caption = '&XML'
957 | object MenuItem4: TMenuItem
958 | Action = acCacheFromXml
959 | end
960 | object MenuItem5: TMenuItem
961 | Action = acBuildGamelist
962 | end
963 | end
964 | object mnLanguage: TMenuItem
965 | Caption = '언어(Language)'
966 | object mnLangKor: TMenuItem
967 | Caption = '한국어(&Korean)'
968 | Checked = True
969 | GroupIndex = 1
970 | Hint = 'KO'
971 | OnClick = mnLangKorClick
972 | end
973 | object mnLangEng: TMenuItem
974 | Caption = '&English(영어)'
975 | GroupIndex = 1
976 | Hint = 'EN'
977 | OnClick = mnLangKorClick
978 | end
979 | end
980 | object mnHelp: TMenuItem
981 | Caption = '도움말(&H)'
982 | object MenuItem20: TMenuItem
983 | Action = acAbout
984 | Caption = 'TrimUI Tool 정보(&A)'
985 | end
986 | object MenuItem28: TMenuItem
987 | Action = acGithub
988 | end
989 | end
990 | end
991 | object ImageList: TImageList
992 | Left = 328
993 | Top = 304
994 | Bitmap = {
995 | 4C7A060000001000000010000000DD0400000000000078DAED985F6CD35514C7
996 | 6F3ADD984EC714980F688428236A4974119EFDF360221A338D18D107B7325F84
997 | 80F26062A2461F30445F244CE1417D80487F5D496420FFD99F32B6C41253DA6E
998 | CB9658C75AB4125666BBA66BBB1ECFF7F6F7EB7EFCF66BD73F23406293937B7F
999 | E79CCFBDE79C7B7FF7B6252241B750FC0EF1994F1109165225015DB1BCF457C4
1000 | 03B9F1B8CFBA886EBC4222FDCA8D5D1BA7427EB6C858CD64F63688FF7FBE323E
1001 | 52C1FA47E816BFBF77E8FB1FD1AF4139EBB698BCBB4BDC53E63E08A31DB28B17
1002 | B9ED2B25068D91E3D8C5973E87F8A2A41C54468DC3C56BF6428935908CCA4751
1003 | 836259B55E51B5A57273CFBD8365E6AEF1E5E68EBE5711E972DEFB52EA7533C5
1004 | EA8AEF6AEA8DA51EEF8911047DE88AE5D7B27FEFF50CB9A324057DAB6B3AA98D
1005 | 5748D6F64E47D16A6CA9A28D53219F2926D63C52095B94ACEB8B51C7789486A7
1006 | A7C817BB4A43B108EDF9738AAC7DC5B1BFFD1BA5DD6127ADF7D9C87A71133D35
1007 | F01A7D3ABA970623930B8EB1773CCB367B5BC9EADE44C1449856773F470F9FDC
1008 | 401F5FDA4DDF06220579C4BCDE6F936CD3858D383369E5890DD478C44A2B9C6B
1009 | C8733D5C9047BEEB2EBE25E7D57FC663135477B0917E9FBC5C90F773AD90EFEA
1010 | EEE7E5BCF834385649F6DE1F1BC813F98BD6F464F7A079FE53B256C817316BF3
1011 | 56FF5047DBFA77D29E3F26930BBC1FB5FF24AE793FF1ED4A20DFBA038D54F753
1012 | 036D776D4F84E3610FEC45BC63B55713D7BEB912FF3B188806C2A15828C8ECD7
1013 | AC5F7233CE0345115510DD5917C86733FD3EA088763E5BF79BDE95AC87BD103F
1014 | F28BB88F9990EF907856CFFB3BC5D3DCBFE25644FD3CEE7361C1B86307C4FDEA
1015 | 99DCC6E7F3A0AF53BC22CF5BB47671DE6B17ADB0C34FC6C19CC623368C0F76F8
1016 | A068667B9CC5C5BAE368591F1F3A249E811D7E32478D57E592229A59DFEFCDB2
1017 | 6F1BBE276D869ED97EF815A8DFABB85FCC6CCCF77B1D62A3C97D1430DC2FC7F3
1018 | DC5B270C7E81793E6AAD4A99FF86FC956CFE5CEB770CECBB5C9B69D3FC0DF547
1019 | 9DE1CBB5388F5CC0E0396FFD0DEBCF369BDF2E06102BF264E6655F760DDB4CD7
1020 | BFD2FDB788FBBFD2F70F2204355455CDBC61B1A43EB458923BD067DDD222B815
1021 | 96AAE4FEAABB92296E492FAAEE7BF6596ECA56CF3C595D930AD62C49CEDAB6A4
1022 | E9D8AF191A1B2329478F65083AD8D86702BEC679C1363E944A9F399BA150884C
1023 | E5F4990CC1478E216899C6735CFB3036ECF0EBEE9E3F86A63B792A43D535C959
1024 | 66BE53E75E8ADCB6B4A7A5FDECB98CCCB7FDFD748E451F3AD8F0FC5E6B1AF548
1025 | 325B2FEBCC36E46BF447ABEF6BF6AEA3D939986DE135DA89FEE8E88DF16EDD96
1026 | CED55E8B4D13F84A9B25F5911413FE83AD733CE60E06E76C23231A2FF7C6EBA5
1027 | C67FA46B2E7EAD7E6DB6F2EA57C1FA75E8F6CF72EC09EC8D53A7F3EF1FB0D9FD
1028 | 93BCCCCC8326FB770263B7B6A5658EA829047DC40C5B969D7922CFFBB30CFB0A
1029 | B999BC3FD07518E7CD334E7D766F2477A86BD4A2D5EA76930AFEFBA0C5FEFF06
1030 | 67E30545D4F2DDF326DA85CE4A238FDF647C471CF63BC561D63BF5BFD1F8DC7E
1031 | 045288E7FBA685EFCF4EE9EF149D7856D9C778DC0108FA85E6C7BCFAF9877F16
1032 | 8FCADF9BCCE9FB46DEE3142B3D8A58A5CF9F9F9B8C736AB1A0D578F73E71373F
1033 | F7707F50F3D5FB99DC71D2965B4387F84A7EE79A635ECAC7EAC7D0ED01C5A03F
1034 | 578835D64FFFFFD19DB277174BFE03F97B604E
1035 | }
1036 | end
1037 | object pmDir: TPopupMenu
1038 | Left = 160
1039 | Top = 368
1040 | object MenuItem24: TMenuItem
1041 | Action = acAddRom
1042 | end
1043 | object MenuItem25: TMenuItem
1044 | Action = acMkDir
1045 | end
1046 | object MenuItem29: TMenuItem
1047 | Action = acRmDir
1048 | end
1049 | object MenuItem27: TMenuItem
1050 | Action = acRename
1051 | end
1052 | end
1053 | end
1054 |
--------------------------------------------------------------------------------
/mainform.pas:
--------------------------------------------------------------------------------
1 | unit MainForm;
2 |
3 | {$mode objfpc}{$H+}
4 |
5 | interface
6 |
7 | uses
8 | Classes, SysUtils, DB, dbf, SQLite3Conn, SQLDB, Forms, Controls, Graphics,
9 | Dialogs, ExtCtrls, ComCtrls, StdCtrls, ActnList, Menus, DBGrids, Buttons,
10 | fpjson, jsonparser, jsonConf, openssl, opensslsockets, fphttpclient, DOM,
11 | XMLRead, XMLWrite, xmltextreader, simpleipc, LazFileUtils, LCLTranslator,
12 | RegExpr, httpprotocol, LCLType, process, dynlibs, fileutil, Translations,
13 | LResources, ShellCtrls, StrUtils, lclintf;
14 |
15 | const
16 | BASE_PATH = '/mnt/SDCARD';
17 |
18 | type
19 | TEmuConfig = record
20 | Caption: String;
21 | Icon: String;
22 | System: String;
23 | EmuPath: String;
24 | RomPath: String;
25 | ImgPath: String;
26 | CachePath: String;
27 | Shortname: Boolean;
28 | UseSwap: Boolean;
29 | HideBios: Boolean;
30 | Gamelist: String;
31 | ExtList: String;
32 | end;
33 |
34 | PScrapeInfo = ^TScrapeInfo;
35 | TScrapeInfo = record
36 | System, Key, ImagePath, SearchStr, Gamelist, ImageBase, EmuPath: String;
37 | IsShortname, IsForce, ForcePng: Boolean;
38 | end;
39 |
40 | { TQueueThread }
41 |
42 | TQueueThread = class(TThread)
43 | private
44 | HttpClient: TFPHttpClient;
45 | Image: TImage;
46 | class var BasePath: String;
47 | class var IPCClient: TSimpleIPCClient;
48 | class var ScrapeList: TList;
49 | class var Count, TotalCount: Integer;
50 | public
51 | constructor Create(CreateSuspended: boolean);
52 | destructor Destroy; override;
53 | procedure Execute; override;
54 | class procedure SetBasePath(Path: String); static;
55 | class procedure CancelScrape; static;
56 | class procedure Put(ScrapeInfo: TScrapeInfo); static;
57 | function Get(var ScrapeInfo: TScrapeInfo): Boolean;
58 | procedure Scrape(ScrapeInfo: TScrapeInfo; IsArcade: Boolean);
59 | class procedure WriteLog(Log: String); static;
60 | end;
61 |
62 | { TFormMain }
63 |
64 | TFormMain = class(TForm)
65 | acCacheFromXml: TAction;
66 | acCancelScrape: TAction;
67 | acDelete: TAction;
68 | acRename: TAction;
69 | acRescrapeAll: TAction;
70 | acScrape: TAction;
71 | acScrapeMissing: TAction;
72 | acChangeImage: TAction;
73 | acOpenImagePos: TAction;
74 | acSaveEmuInfo: TAction;
75 | acBuildGamelist: TAction;
76 | acRefresh: TAction;
77 | acDetectBasePath: TAction;
78 | acOpenBasePath: TAction;
79 | acExit: TAction;
80 | acGenerateCache: TAction;
81 | acAbout: TAction;
82 | acAddRom: TAction;
83 | acMkDir: TAction;
84 | acGithub: TAction;
85 | acRmDir: TAction;
86 | acScanExt: TAction;
87 | acScrapeTotal: TAction;
88 | ActionList: TActionList;
89 | btGenerateCache: TButton;
90 | btOpen: TButton;
91 | btAutoDetect: TButton;
92 | btRefresh: TButton;
93 | btScanExt: TButton;
94 | btScrape: TButton;
95 | btSaveEmuInfo: TButton;
96 | C1: TMenuItem;
97 | cboEmulator: TComboBox;
98 | ckForcePng: TCheckBox;
99 | ckHideBios: TCheckBox;
100 | ckShortname: TCheckBox;
101 | ckUseSwap: TCheckBox;
102 | Delete1: TMenuItem;
103 | edBasePath: TEdit;
104 | edLabel: TEdit;
105 | edRomPath: TEdit;
106 | edImagePath: TEdit;
107 | edExtList: TEdit;
108 | edGamelist: TEdit;
109 | edIcon: TEdit;
110 | edSearch: TEdit;
111 | GroupBox1: TGroupBox;
112 | Image: TImage;
113 | Image1: TImage;
114 | Image2: TImage;
115 | Image3: TImage;
116 | Image4: TImage;
117 | ImageList: TImageList;
118 | Label1: TLabel;
119 | Label2: TLabel;
120 | Label3: TLabel;
121 | Label4: TLabel;
122 | Label5: TLabel;
123 | Label6: TLabel;
124 | Label7: TLabel;
125 | Label8: TLabel;
126 | Label9: TLabel;
127 | ListView: TListView;
128 | MainMenu: TMainMenu;
129 | MenuItem1: TMenuItem;
130 | MenuItem10: TMenuItem;
131 | MenuItem11: TMenuItem;
132 | MenuItem12: TMenuItem;
133 | MenuItem13: TMenuItem;
134 | MenuItem15: TMenuItem;
135 | MenuItem16: TMenuItem;
136 | MenuItem17: TMenuItem;
137 | MenuItem18: TMenuItem;
138 | MenuItem19: TMenuItem;
139 | MenuItem20: TMenuItem;
140 | MenuItem21: TMenuItem;
141 | MenuItem22: TMenuItem;
142 | MenuItem4: TMenuItem;
143 | MenuItem5: TMenuItem;
144 | mnLanguage: TMenuItem;
145 | MenuItem24: TMenuItem;
146 | MenuItem25: TMenuItem;
147 | MenuItem26: TMenuItem;
148 | MenuItem27: TMenuItem;
149 | MenuItem28: TMenuItem;
150 | MenuItem29: TMenuItem;
151 | MenuItem30: TMenuItem;
152 | MenuItem31: TMenuItem;
153 | MenuItem32: TMenuItem;
154 | mnXML: TMenuItem;
155 | mnLangKor: TMenuItem;
156 | mnLangEng: TMenuItem;
157 | Panel1: TPanel;
158 | pmDir: TPopupMenu;
159 | pbInfo: TProgressBar;
160 | Separator4: TMenuItem;
161 | Separator3: TMenuItem;
162 | Separator2: TMenuItem;
163 | MenuItem2: TMenuItem;
164 | MenuItem3: TMenuItem;
165 | mnFile: TMenuItem;
166 | mnHelp: TMenuItem;
167 | MenuItem6: TMenuItem;
168 | MenuItem7: TMenuItem;
169 | MenuItem8: TMenuItem;
170 | mnScrape: TMenuItem;
171 | Separator1: TMenuItem;
172 | mmLog: TMemo;
173 | N1: TMenuItem;
174 | NoImage: TImage;
175 | pnImage: TPanel;
176 | Panel3: TPanel;
177 | Panel4: TPanel;
178 | pmScrape: TMenuItem;
179 | pmPopup: TPopupMenu;
180 | pmImage: TPopupMenu;
181 | Rename1: TMenuItem;
182 | RescrapeAll1: TMenuItem;
183 | Scrapemissing1: TMenuItem;
184 | Splitter1: TSplitter;
185 | SQLite3Connection: TSQLite3Connection;
186 | SQLite3Name: TSQLite3Connection;
187 | SQLQuery: TSQLQuery;
188 | SQLName: TSQLQuery;
189 | SQLTransaction: TSQLTransaction;
190 | SQLTransactionName: TSQLTransaction;
191 | TreeView: TTreeView;
192 | procedure acAboutExecute(Sender: TObject);
193 | procedure acAddRomExecute(Sender: TObject);
194 | procedure acBuildGamelistExecute(Sender: TObject);
195 | procedure acCacheFromXmlExecute(Sender: TObject);
196 | procedure acCancelScrapeExecute(Sender: TObject);
197 | procedure acChangeImageExecute(Sender: TObject);
198 | procedure acDeleteExecute(Sender: TObject);
199 | procedure acDetectBasePathExecute(Sender: TObject);
200 | procedure acExitExecute(Sender: TObject);
201 | procedure acGenerateCacheExecute(Sender: TObject);
202 | procedure acGithubExecute(Sender: TObject);
203 | procedure acMkDirExecute(Sender: TObject);
204 | procedure acOpenBasePathExecute(Sender: TObject);
205 | procedure acOpenImagePosExecute(Sender: TObject);
206 | procedure acRefreshExecute(Sender: TObject);
207 | procedure acRenameExecute(Sender: TObject);
208 | procedure acRmDirExecute(Sender: TObject);
209 | procedure acSaveEmuInfoExecute(Sender: TObject);
210 | procedure acScanExtExecute(Sender: TObject);
211 | procedure acScrapeExecute(Sender: TObject);
212 | procedure acScrapeMissingExecute(Sender: TObject);
213 | procedure acScrapeTotalExecute(Sender: TObject);
214 | procedure btOpenClick(Sender: TObject);
215 | procedure cboEmulatorChange(Sender: TObject);
216 | procedure edSearchKeyPress(Sender: TObject; var Key: char);
217 | procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
218 | procedure FormCreate(Sender: TObject);
219 | procedure FormDestroy(Sender: TObject);
220 | procedure FormDropFiles(Sender: TObject; const FileNames: array of string);
221 | procedure FormShow(Sender: TObject);
222 | procedure Image1Click(Sender: TObject);
223 | procedure ListViewCustomDrawItem(Sender: TCustomListView; Item: TListItem;
224 | {%H-}State: TCustomDrawState; var {%H-}DefaultDraw: Boolean);
225 | procedure ListViewEdited(Sender: TObject; Item: TListItem;
226 | var AValue: string);
227 | procedure ListViewSelectItem(Sender: TObject; Item: TListItem;
228 | Selected: Boolean);
229 | procedure mnLangKorClick(Sender: TObject);
230 | procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
231 | procedure TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
232 | procedure TreeViewDragOver(Sender, Source: TObject; {%H-}X, {%H-}Y: Integer;
233 | {%H-}State: TDragState; var Accept: Boolean);
234 | procedure TreeViewEdited(Sender: TObject; Node: TTreeNode; var S: string);
235 | private
236 | procedure AppIdle(Sender: TObject; var {%H-}Done: Boolean);
237 | public
238 | IPCServer: TSimpleIPCServer;
239 | EmuConfig: TEmuConfig;
240 | QueueThread: TQueueThread;
241 | procedure IPCServerMessage(Sender: TObject);
242 | procedure LoadEmus(BasePath: String);
243 | procedure WriteLog(Log: String);
244 | function LoadEmuConfig(System: String): Boolean;
245 | function LoadEmuInfo(System: String): Boolean;
246 | function SaveEmuConfig(System: String): Boolean;
247 | procedure BuildCache(IsDelete: Boolean=False);
248 | procedure GetSubDir;
249 | procedure GetEmuList(SubDir: String='.');
250 | function RenameTitle(Key, Tobe: String): Boolean;
251 | function RenameSubDir(Asis, Tobe: String): Boolean;
252 | function DeleteSubDir: Boolean;
253 | function InsertCache(Filename: String; SubDir: String=''): String;
254 | function UpdateCache(Key, Column, Value: String): Boolean;
255 | function DeleteCache(Key: String): Boolean;
256 | function ExecCacheSQL(Query: String; Args: Array of const): Boolean;
257 | function GetFullTitle(Title, DefaultTitle: String): String;
258 | function UpdateRomName(Key, Value: String): Boolean;
259 | procedure GenCacheFromXml(Gamelist: String);
260 | procedure ReadSettings;
261 | procedure WriteSettings;
262 | end;
263 |
264 | var
265 | FormMain: TFormMain;
266 | SystemMap: TStringList;
267 |
268 | resourcestring
269 | I18N_SCRAPESTARTED = ' 스크래핑이 시작되었습니다';
270 | I18N_ROMFROM = '롬 한글정보 출처: 텐타클팀(http://cafe.naver.com/raspigamer)';
271 | I18N_FILENOTFOUND = '파일을 찾을 수 없습니다';
272 | I18N_DIRNOTFOUND = '폴더를 찾을 수 없습니다';
273 | I18N_CANCELEDSCRAPE = '스크래핑이 취소되었습니다';
274 | I18N_CACHEFROMXML = 'gamelist.xml 파일정보로부터 캐시파일을 새로 생성합니다. 계속 하시겠습니까?';
275 | I18N_GENCACHE = '캐시를 생성하고 있습니다...';
276 | I18N_ERROROCCURED = '오류가 발생하였습니다';
277 | I18N_FILEEXISTS = '파일이 존재합니다';
278 | I18N_DIREXISTS = '폴더가 존재합니다';
279 | I18N_NOSELEMUL = '선택된 에뮬레이터가 없습니다';
280 | I18N_DONESCRAPE = '스크래핑이 완료되었습니다';
281 | I18N_ROMNOTSELECTED = '롬을 먼저 선택해주세요';
282 | I18N_SAVED = '저장되었습니다';
283 | I18N_CREATED = '생성되었습니다';
284 | I18N_PROCESSING = '처리중입니다';
285 | I18N_DELETED = '삭제되었습니다';
286 | I18N_CONFIRM = '확인';
287 | I18N_ADDED = '추가되었습니다';
288 | I18N_RECACHECONFIRM = '캐시 파일을 재생성합니다. 계속 하시겠습니까?';
289 | I18N_DELETECONFIRM = '롬 파일을 삭제합니다. 계속 하시겠습니까?';
290 | I18N_DELETEDIRCONFIRM = '폴더를 삭제합니다. 계속 하시겠습니까?';
291 | I18N_GAMELISTCONFIRM = '캐시로부터 gamelist.xml 파일을 새로 생성합니다. 계속 하시겠습니까?';
292 | I18N_MAKEDIR = '폴더생성';
293 | I18N_INPUTDIRNAME = '폴더명을 입력하세요';
294 | I18N_ADDEDEXT = '확장자가 추가되었습니다';
295 | I18N_SCRAPEALLCONFIRM = '에뮬레이터 전체 영역에 대해 누락 항목을 스크래핑합니다. 계속하시겠습니까?';
296 | I18N_DONE = '완료되었습니다';
297 |
298 | implementation
299 |
300 | {$R *.lfm}
301 |
302 | uses
303 | IniFiles;
304 |
305 | var
306 | CriticalSection: TRTLCriticalSection;
307 |
308 | function Translate(const Language: String): boolean;
309 | var
310 | Res: TResourceStream;
311 | PoStringStream: TStringStream;
312 | PoFile: TPOFile;
313 | LocalTranslator: TPOTranslator;
314 | i: Integer;
315 | begin
316 | Res := TResourceStream.Create(HInstance, 'I18N.' + Language, RT_RCDATA);
317 | PoStringStream := TStringStream.Create('');
318 | try
319 | Res.SaveToStream(PoStringStream)
320 | finally
321 | Res.Free;
322 | end;
323 |
324 | PoFile := TPOFile.Create(False);
325 | try
326 | PoFile.ReadPOText(PoStringStream.DataString);
327 | Result := TranslateResourceStrings(PoFile);
328 |
329 | LocalTranslator := TPOTranslator.Create(PoFile);
330 |
331 | if Assigned(LRSTranslator) then
332 | LRSTranslator.Free;
333 | LRSTranslator := LocalTranslator;
334 |
335 | for i := 0 to Pred(Screen.CustomFormCount) do
336 | LocalTranslator.UpdateTranslation(Screen.CustomForms[i]);
337 | for i := 0 to Pred(Screen.DataModuleCount) do
338 | LocalTranslator.UpdateTranslation(Screen.DataModules[i]);
339 | finally
340 | if Assigned(PoStringStream) then
341 | PoStringStream.Free;
342 | end;
343 | end;
344 |
345 | function SaveImage(Image: TImage; var ImagePath: String; ForcePng: Boolean): Boolean;
346 | var
347 | PngImage: TPortableNetworkGraphic;
348 | begin
349 | if Image.Picture.Graphic.Classname = 'TPortableNetworkGraphic' then
350 | begin
351 | if ExtractFileExt(ImagePath) <> '.png' then
352 | ImagePath := ExtractFileNameWithoutExt(ImagePath) + '.png'
353 | end else if Image.Picture.Graphic.Classname = 'TJpegImage' then
354 | begin
355 | if ForcePng then
356 | begin
357 | PngImage := TPortableNetworkGraphic.Create;
358 | try
359 | PngImage.Assign(Image.Picture.Bitmap);
360 | ImagePath := ExtractFileNameWithoutExt(ImagePath) + '.png';
361 | Image.Picture.Bitmap.LoadFromRawImage(PngImage.RawImage, False);
362 | finally
363 | if Assigned(PngImage) then
364 | PngImage.Free;
365 | end;
366 | end else if ExtractFileExt(ImagePath) <> '.jpg' then
367 | ImagePath := ExtractFileNameWithoutExt(ImagePath) + '.jpg'
368 | end else begin
369 | Result := False;
370 | exit;
371 | end;
372 |
373 | if FileExists(ImagePath) then
374 | SysUtils.DeleteFile(ImagePath);
375 | Image.Picture.SaveToFile(ImagePath);
376 |
377 | Result := True;
378 | end;
379 |
380 | function Win2Lin(BasePath, WinPath: String): String;
381 | begin
382 | {$IFDEF Linux}
383 | Result := StringReplace(WinPath, BasePath, BASE_PATH, [rfReplaceAll]);
384 | {$ELSE}
385 | Result := StringReplace(
386 | StringReplace(WinPath, BasePath, BASE_PATH, []), '\', '/', [rfReplaceAll]);
387 | {$ENDIF}
388 | end;
389 |
390 | function Lin2Win(BasePath, LinPath: String): String;
391 | begin
392 | {$IFDEF Linux}
393 | Result := ExpandFileName(StringReplace(LinPath, BASE_PATH, BasePath, [rfReplaceAll]));
394 | {$ELSE}
395 | Result := ExpandFileName(StringReplace(
396 | StringReplace(LinPath, BASE_PATH, BasePath, []), '/', '\', [rfReplaceAll]));
397 | {$ENDIF}
398 | end;
399 |
400 | { TQueueThread }
401 |
402 | constructor TQueueThread.Create(CreateSuspended : boolean);
403 | begin
404 | inherited Create(CreateSuspended);
405 | Image := TImage.Create(nil);
406 |
407 | EnterCriticalSection(CriticalSection);
408 | try
409 | HttpClient := TFPHTTPClient.Create(nil);
410 | if not Assigned(ScrapeList) then
411 | ScrapeList := TList.Create;
412 | if not Assigned(IPCClient) then
413 | begin
414 | IPCClient := TSimpleIPCClient.Create(nil);
415 | IPCClient.ServerID := 'WriteLog';
416 | end;
417 |
418 | Count := 0;
419 | TotalCount := 0;
420 | finally
421 | LeaveCriticalSection(CriticalSection);
422 | end;
423 | end;
424 |
425 | destructor TQueueThread.Destroy;
426 | var
427 | i: Integer;
428 | begin
429 | EnterCriticalSection(CriticalSection);
430 | try
431 | for i:=0 to ScrapeList.Count-1 do
432 | Dispose(PScrapeInfo(ScrapeList.Items[i]));
433 |
434 | if Assigned(ScrapeList) then
435 | FreeAndNil(ScrapeList);
436 | if Assigned(IPCClient) then
437 | FreeAndNil(IPCClient);
438 | finally
439 | LeaveCriticalSection(CriticalSection);
440 | end;
441 |
442 | HttpClient.Free;
443 | Image.Free;
444 | inherited Destroy;
445 | end;
446 |
447 | procedure TQueueThread.Execute;
448 | var
449 | ScrapeInfo: TScrapeInfo;
450 | begin
451 | ScrapeInfo.System := '';
452 | ScrapeInfo.SearchStr := '';
453 | ScrapeInfo.Key := '';
454 | ScrapeInfo.ImagePath := '';
455 | ScrapeInfo.IsShortname := False;
456 | ScrapeInfo.IsForce := False;
457 | ScrapeInfo.Gamelist := '';
458 | ScrapeInfo.ImageBase := '';
459 | ScrapeInfo.EmuPath := '';
460 | ScrapeInfo.ForcePng := True;
461 |
462 | while not Terminated do
463 | begin
464 | while Get(ScrapeInfo) do
465 | begin
466 | WriteLog(ScrapeInfo.SearchStr + I18N_SCRAPESTARTED);
467 | if ScrapeInfo.IsShortname then
468 | Scrape(ScrapeInfo, True)
469 | else
470 | Scrape(ScrapeInfo, False);
471 | end;
472 | Sleep(1000);
473 | end;
474 | end;
475 |
476 | class procedure TQueueThread.SetBasePath(Path: String); static;
477 | begin
478 | BasePath := Path;
479 | end;
480 |
481 | class procedure TQueueThread.CancelScrape; static;
482 | var
483 | i: Integer;
484 | begin
485 | if ScrapeList.Count > 0 then
486 | WriteLog(I18N_CANCELEDSCRAPE + ' - ' + IntToStr(ScrapeList.Count));
487 | EnterCriticalSection(CriticalSection);
488 |
489 | try
490 | for i:=0 to ScrapeList.Count-1 do
491 | Dispose(PScrapeInfo(ScrapeList.Items[i]));
492 | ScrapeList.Clear;
493 | finally
494 | LeaveCriticalSection(CriticalSection);
495 | end;
496 | end;
497 |
498 | class procedure TQueueThread.Put(ScrapeInfo: TScrapeInfo); static;
499 | var
500 | Info: PScrapeInfo;
501 | begin
502 | EnterCriticalSection(CriticalSection);
503 | try
504 | Count += 1;
505 | TotalCount += 1;
506 | New(Info);
507 | Info^ := ScrapeInfo;
508 | ScrapeList.Add(Info);
509 | finally
510 | LeaveCriticalSection(CriticalSection);
511 | end;
512 | end;
513 |
514 | function TQueueThread.Get(var ScrapeInfo: TScrapeInfo): Boolean;
515 | begin
516 | EnterCriticalSection(CriticalSection);
517 | try
518 | if ScrapeList.Count > 0 then
519 | begin
520 | ScrapeInfo := PScrapeInfo(ScrapeList[0])^;
521 | Dispose(PScrapeInfo(ScrapeList[0]));
522 | ScrapeList.Delete(0);
523 | Result := True;
524 | end else
525 | Result := False;
526 | finally
527 | LeaveCriticalSection(CriticalSection);
528 | end;
529 | end;
530 |
531 | procedure TQueueThread.Scrape(ScrapeInfo: TScrapeInfo; IsArcade: Boolean);
532 | var
533 | JsonStr, ImageUrl: String;
534 | JData : TJSONData;
535 | Stream: TStream;
536 | SysStr: String;
537 | Contents: String;
538 | RegEx: TRegExpr;
539 | ImageCount: Integer;
540 | i: Integer;
541 | function GetText(Title: String): String;
542 | var
543 | i: Integer;
544 | begin
545 | for i:=1 to Length(Title) do
546 | if Title[i] in ['(', '['] then
547 | begin
548 | Result := Copy(Title, 1, i-1);
549 | exit;
550 | end;
551 | Result := Title;
552 | end;
553 | begin
554 | if Copy(ScrapeInfo.ImageBase, 1, 1) = '/' then
555 | ScrapeInfo.ImagePath := Lin2Win(BasePath, ScrapeInfo.ImageBase + '/' + ScrapeInfo.Key)
556 | else
557 | ScrapeInfo.ImagePath := Lin2Win(BasePath, ScrapeInfo.EmuPath + '/' + ScrapeInfo.ImageBase + '/' + ScrapeInfo.Key);
558 |
559 | if not DirectoryExists(ExtractFileDir(ScrapeInfo.ImagePath)) then
560 | MkDir(ExtractFileDir(ScrapeInfo.ImagePath));
561 | if FileExists(ScrapeInfo.ImagePath) and not ScrapeInfo.IsForce then
562 | begin
563 | WriteLog(ScrapeInfo.ImagePath + ' - ' + I18N_FILEEXISTS);
564 | exit;
565 | end;
566 |
567 | EnterCriticalSection(CriticalSection);
568 | try
569 | Count -= 1;
570 | finally
571 | LeaveCriticalSection(CriticalSection);
572 | end;
573 | ImageCount := 0;
574 | Stream := TMemoryStream.Create;
575 |
576 | try
577 | try
578 | if IsArcade then
579 | begin
580 | with HttpClient do
581 | begin
582 | JsonStr := Get('http://adb.arcadeitalia.net/service_scraper.php?ajax=query_mame&game_name=' + ScrapeInfo.SearchStr);
583 |
584 | JData := GetJSON(JsonStr);
585 |
586 | if not Assigned(JData) then
587 | begin
588 | WriteLog('No data found error - ' + ScrapeInfo.SearchStr);
589 | exit;
590 | end;
591 |
592 | ImageUrl := TJsonObject(JData).FindPath('result[0].url_image_ingame').AsString;
593 | Get(ImageUrl, Stream);
594 | Stream.Seek(0, soFromBeginning);
595 | Image.Picture.LoadFromStream(Stream);
596 |
597 | if not SaveImage(Image, ScrapeInfo.ImagePath, ScrapeInfo.ForcePng) then
598 | begin
599 | WriteLog('Scraping ' + ScrapeInfo.System + ' - ' + Image.Picture.Graphic.Classname + '--> File format error');
600 | exit;
601 | end;
602 | end;
603 | end else
604 | begin
605 | SysStr := ScrapeInfo.System;
606 | if SystemMap.Values[ScrapeInfo.System] <> '' then
607 | SysStr := SystemMap.Values[ScrapeInfo.System];
608 | try
609 | EnterCriticalSection(CriticalSection);
610 | try
611 | Contents := HttpClient.Get('https://images.search.yahoo.com/search/images?p=' +
612 | HTTPEncode(StringReplace('screenshot+gamefabrique+'+GetText(ScrapeInfo.SearchStr)+'+'+SysStr, ' ', '+', [rfReplaceAll])));
613 | finally
614 | LeaveCriticalSection(CriticalSection);
615 | end;
616 | except
617 | on E :Exception do
618 | begin
619 | WriteLog(HttpClient.ResponseStatusText + ' - ' + E.Message);
620 | exit;
621 | end;
622 | end;
623 |
624 | RegEx := TRegExpr.Create('img data-src=''(https://tse\d\.mm\.bing\.net.*?)'' alt=');
625 |
626 | try
627 | if RegEx.Exec(Contents) then
628 | begin
629 | ImageUrl := RegEx.Match[1];
630 | HttpClient.Get(ImageUrl, Stream);
631 |
632 | Stream.Seek(0, soFromBeginning);
633 | Image.Picture.LoadFromStream(Stream);
634 |
635 | if not SaveImage(Image, ScrapeInfo.ImagePath, ScrapeInfo.ForcePng) then
636 | begin
637 | WriteLog('Scraping ' + ScrapeInfo.System + ' - ' + Image.Picture.Graphic.Classname + '--> File format error');
638 | exit;
639 | end;
640 |
641 | if ScrapeList.Count = 0 then
642 | begin
643 | for i:=1 to 4 do
644 | begin
645 | if RegEx.ExecNext then
646 | begin
647 | ImageUrl := RegEx.Match[1];
648 | JsonStr := ExtractFilePath(Application.ExeName) + DirectorySeparator + 'Image' + IntToStr(i) + '.jpg';
649 | HttpClient.Get(ImageUrl, JsonStr);
650 | Inc(ImageCount);
651 | end else break;
652 | end;
653 | end;
654 | end;
655 | finally
656 | RegEx.Free;
657 | end;
658 | end;
659 |
660 | WriteLog('@' + ScrapeInfo.ImagePath + '|' + ScrapeInfo.ImageBase + '|' + ScrapeInfo.Key + '|' + IntToStr(ImageCount) + '|' +
661 | IntToStr(Count) + '|' + IntToStr(TotalCount));
662 | except
663 | on E :Exception do
664 | WriteLog(ScrapeInfo.SearchStr + I18N_ERROROCCURED + ' - ' + E.Message);
665 | end;
666 | finally
667 | Stream.Free;
668 | EnterCriticalSection(CriticalSection);
669 | try
670 | if Count = 0 then
671 | TotalCount := 0;
672 | finally
673 | LeaveCriticalSection(CriticalSection);
674 | end;
675 | end;
676 | end;
677 |
678 | class procedure TQueueThread.WriteLog(Log: String); static;
679 | begin
680 | if not IPCClient.ServerRunning then
681 | exit;
682 | IPCClient.Active := True;
683 | try
684 | IPCClient.SendStringMessage(Log);
685 | finally
686 | IPCClient.Active := False;
687 | end;
688 | end;
689 |
690 | { TFormMain }
691 |
692 | procedure TFormMain.btOpenClick(Sender: TObject);
693 | begin
694 |
695 | end;
696 |
697 | procedure TFormMain.acScrapeExecute(Sender: TObject);
698 | var
699 | i: Integer;
700 | Filename: String;
701 | ScrapeInfo: TScrapeInfo;
702 | begin
703 | if ListView.Selected = nil then
704 | begin
705 | ShowMessage(I18N_ROMNOTSELECTED);
706 | exit;
707 | end;
708 |
709 | ScrapeInfo.Gamelist := EmuConfig.Gamelist;
710 | ScrapeInfo.System := EmuConfig.System;
711 | ScrapeInfo.IsShortname := (EmuConfig.Shortname)and(edSearch.Text = '');
712 | ScrapeInfo.IsForce := True;
713 | ScrapeInfo.ImageBase := edImagePath.Text;
714 | ScrapeInfo.ForcePng := ckForcePng.Checked;
715 | ScrapeInfo.EmuPath := EmuConfig.EmuPath;
716 | TQueueThread.SetBasePath(edBasePath.Text);
717 |
718 | for i:= 0 to ListView.Items.Count-1 do
719 | begin
720 | if ListView.Items[i].Selected then
721 | begin
722 | if (edSearch.Text <> '') and (ListView.SelCount=1) then
723 | ScrapeInfo.SearchStr := edSearch.Text
724 | else
725 | ScrapeInfo.SearchStr := ListView.Items[i].SubItems[1];
726 | ScrapeInfo.Key := ListView.Items[i].SubItems[1];
727 | Filename := ExtractFilename(Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[2]));
728 | ScrapeInfo.ImagePath := EmuConfig.ImgPath + DirectorySeparator + ExtractFileNameWithoutExt(Filename);
729 |
730 | TQueueThread.Put(ScrapeInfo);
731 | end;
732 | end;
733 | end;
734 |
735 | procedure TFormMain.acScrapeMissingExecute(Sender: TObject);
736 | var
737 | ScrapeInfo: TScrapeInfo;
738 | Filename: String;
739 | i: Integer;
740 | begin
741 | ScrapeInfo.Gamelist := EmuConfig.Gamelist;
742 | ScrapeInfo.System := EmuConfig.System;
743 | ScrapeInfo.IsShortname := EmuConfig.Shortname;
744 | ScrapeInfo.IsForce := True;
745 | ScrapeInfo.ImageBase := edImagePath.Text;
746 | ScrapeInfo.ForcePng := ckForcePng.Checked;
747 | ScrapeInfo.EmuPath := EmuConfig.EmuPath;
748 | TQueueThread.SetBasePath(edBasePath.Text);
749 |
750 | for i:=0 to ListView.Items.Count-1 do
751 | begin
752 | if FileExists(Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[0])) then
753 | continue;
754 | ScrapeInfo.SearchStr := ListView.Items[i].SubItems[1];
755 | ScrapeInfo.Key := ListView.Items[i].SubItems[1];
756 | Filename := ExtractFilename(Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[2]));
757 | ScrapeInfo.ImagePath := EmuConfig.ImgPath + DirectorySeparator + ExtractFileNameWithoutExt(Filename);
758 | TQueueThread.Put(ScrapeInfo);
759 | end;
760 | end;
761 |
762 | procedure TFormMain.acScrapeTotalExecute(Sender: TObject);
763 | var
764 | ScrapeInfo: TScrapeInfo;
765 | Filename: String;
766 | EmuPath, Shortname, ImagePath, Path: String;
767 | SearchRec: TSearchRec;
768 | Count: Integer;
769 | begin
770 | Count := 0;
771 | EmuPath := edBasePath.Text + DirectorySeparator + 'Emus';
772 |
773 | if not DirectoryExists(EmuPath) then
774 | begin
775 | WriteLog(EmuPath + ' - ' + I18N_DIRNOTFOUND);
776 | exit;
777 | end;
778 |
779 | if Application.MessageBox(PChar(I18N_SCRAPEALLCONFIRM),
780 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
781 | exit;
782 |
783 | cboEmulator.Enabled := False;
784 | WriteLog(I18N_SCRAPESTARTED);
785 |
786 | try
787 | if FindFirst(EmuPath + DirectorySeparator + '*', faDirectory, SearchRec) = 0 then
788 | begin
789 | repeat
790 | if Copy(SearchRec.Name, 1, 1) <> '.' then
791 | begin
792 | if not FileExists(EmuPath + DirectorySeparator + SearchRec.Name + DirectorySeparator + 'config.json') then
793 | WriteLog(EmuPath + DirectorySeparator + SearchRec.Name + DirectorySeparator + 'config.json - ' + I18N_FILENOTFOUND)
794 | else begin
795 | if LoadEmuConfig(SearchRec.Name) then
796 | begin
797 | if not DirectoryExists(EmuConfig.RomPath) then
798 | WriteLog(EmuConfig.RomPath + ' - ' + I18N_FILENOTFOUND)
799 | else begin
800 | WriteLog(I18N_PROCESSING + ' - ' + SearchRec.Name);
801 | Application.ProcessMessages;
802 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
803 | if not SQLite3Connection.Connected then
804 | SQLite3Connection.Connected := True;
805 | try
806 | ScrapeInfo.Gamelist := EmuConfig.Gamelist;
807 | ScrapeInfo.System := EmuConfig.System;
808 | ScrapeInfo.IsShortname := EmuConfig.Shortname;
809 | ScrapeInfo.IsForce := True;
810 | ScrapeInfo.ImageBase := edImagePath.Text;
811 | ScrapeInfo.ForcePng := ckForcePng.Checked;
812 | ScrapeInfo.EmuPath := EmuConfig.EmuPath;
813 | TQueueThread.SetBasePath(edBasePath.Text);
814 |
815 | SQLQuery.SQL.Text := Format('SELECT id, disp, path, imgpath, pinyin, opinyin FROM %s_roms WHERE type = 0', [EmuConfig.System]);
816 |
817 | try
818 | SQLQuery.Active := True;
819 | SQLQuery.First;
820 |
821 | while not SQLQuery.EOF do
822 | begin
823 | Shortname := SQLQuery.FieldByName('opinyin').AsString;
824 | ImagePath := SQLQuery.FieldByName('imgpath').AsString;
825 | Path := SQLQuery.FieldByName('path').AsString;
826 |
827 | if not FileExists(Lin2Win(edBasePath.Text, ImagePath)) then
828 | begin
829 | ScrapeInfo.SearchStr := Shortname;
830 | ScrapeInfo.Key := Shortname;
831 | Filename := ExtractFilename(Lin2Win(edBasePath.Text, Path));
832 | ScrapeInfo.ImagePath := EmuConfig.ImgPath + DirectorySeparator + ExtractFileNameWithoutExt(Filename);
833 | TQueueThread.Put(ScrapeInfo);
834 | Inc(Count);
835 | end;
836 |
837 | SQLQuery.Next;
838 | end;
839 | except
840 | on E :Exception do
841 | begin
842 | WriteLog(I18N_ERROROCCURED + ' - ' + EmuConfig.System + '_roms - ' + E.Message);
843 | end;
844 | end;
845 | finally
846 | SQLite3Connection.Connected := False;
847 | end;
848 | end;
849 | end;
850 | end;
851 | end;
852 | Application.ProcessMessages;
853 | until FindNext(SearchRec) <> 0;
854 |
855 | SysUtils.FindClose(SearchRec);
856 | end;
857 | finally
858 | LoadEmuConfig(cboEmulator.Text);
859 | cboEmulator.Enabled := True;
860 | end;
861 |
862 | WriteLog(I18N_DONE + ' - ' + IntToStr(Count));
863 | end;
864 |
865 | procedure TFormMain.acRenameExecute(Sender: TObject);
866 | begin
867 | if (ActiveControl is TTreeView) and Assigned(TTreeView(ActiveControl).Selected) and (TTreeView(ActiveControl).Selected.Level <> 0) then
868 | TTreeView(ActiveControl).Selected.EditText
869 | else if (ActiveControl is TListView) and Assigned(TListView(ActiveControl).Selected) then
870 | TListView(ActiveControl).Selected.EditCaption;
871 | end;
872 |
873 | procedure TFormMain.acRmDirExecute(Sender: TObject);
874 | begin
875 | DeleteSubDir;
876 | end;
877 |
878 | procedure TFormMain.acSaveEmuInfoExecute(Sender: TObject);
879 | var
880 | EmuPath: String;
881 | JConfig: TJSONConfig;
882 | begin
883 | if cboEmulator.Items.Count = 0 then
884 | exit;
885 |
886 | EmuPath := edBasePath.Text + DirectorySeparator + 'Emus' + DirectorySeparator + EmuConfig.System + DirectorySeparator + 'config.json';
887 |
888 | if not FileExists(EmuPath) then
889 | begin
890 | WriteLog(EmuPath + ' - ' + I18N_FILENOTFOUND);
891 | exit;
892 | end;
893 | JConfig := TJSONConfig.Create(nil);
894 | try
895 | try
896 | JConfig.Formatted := True;
897 | JConfig.Filename := EmuPath;
898 |
899 | JConfig.SetValue('/label', edLabel.Text);
900 | JConfig.SetValue('/icon', edIcon.Text);
901 | JConfig.SetValue('/rompath' , edRomPath.Text);
902 | if edGamelist.Text <> '' then
903 | JConfig.SetValue('/gamelist', edGamelist.Text)
904 | else
905 | JConfig.DeleteValue('/gamelist');
906 | JConfig.SetValue('/imgpath' , edImagePath.Text);
907 |
908 | JConfig.SetValue('/shortname', Ord(ckShortname.Checked));
909 | JConfig.SetValue('/hidebios', Ord(ckHideBios.Checked));
910 | JConfig.SetValue('/useswap', Ord(ckUseSwap.Checked));
911 | JConfig.SetValue('/extlist', edExtList.Text);
912 | except
913 | on E: Exception do
914 | WriteLog(EmuConfig.System + ' - config.json : ' + E.Message);
915 | end;
916 | finally
917 | WriteLog(I18N_SAVED + ' - ' + EmuPath);
918 | JConfig.Free;
919 | end;
920 |
921 | end;
922 |
923 | procedure TFormMain.acScanExtExecute(Sender: TObject);
924 | const
925 | SkipExt: array [0..10] of String =
926 | ('', 'bak', 'db', 'xml', 'txt', 'state', 'jpg', 'jpeg', 'png', 'gif', 'sh');
927 | var
928 | ExtList: String;
929 |
930 | procedure ScanExt(SubDir: String; Level: Integer; var ExtList: String);
931 | var
932 | Info: TSearchRec;
933 | Ext: String;
934 | ExtArray: TStringArray;
935 | begin
936 | if FindFirst(EmuConfig.RomPath + DirectorySeparator + SubDir + DirectorySeparator + '*' , faAnyFile, Info) = 0 then
937 | begin
938 | repeat
939 | repeat
940 | if Copy(Info.Name, 1, 1) = '.' then
941 | break;
942 |
943 | if (Level = 0) and ((Info.Attr and faDirectory) = faDirectory) then
944 | begin
945 | ScanExt(Info.Name, 1, ExtList);
946 | break;
947 | end;
948 |
949 | ExtArray := SplitString(ExtList, '|');
950 | Ext := Copy(ExtractFileExt(Utf8String(Info.Name)), 2);
951 |
952 | if not {%H-}MatchStr(Ext, ExtArray) and not {%H-}MatchStr(LowerCase(Ext), SkipExt) then
953 | begin
954 | if ExtList = '' then
955 | ExtList := Ext
956 | else
957 | ExtList := ExtList + '|' + Ext;
958 |
959 | WriteLog(I18N_ADDEDEXT + ' - ' + Ext);
960 | end;
961 | until True;
962 | until FindNext(Info) <> 0;
963 |
964 | FindClose(Info);
965 | end;
966 | end;
967 | begin
968 | ExtList := edExtList.Text;
969 | ScanExt('.', 0, ExtList);
970 | if ExtList <> edExtList.Text then
971 | begin
972 | edExtList.Text := ExtList;
973 | btSaveEmuInfo.Click;
974 | end;
975 | end;
976 |
977 | procedure TFormMain.acCancelScrapeExecute(Sender: TObject);
978 | begin
979 | TQueueThread.CancelScrape;
980 | pbInfo.Visible := False;
981 | end;
982 |
983 | procedure TFormMain.acBuildGamelistExecute(Sender: TObject);
984 | var
985 | Xml: TXMLDocument;
986 | RootNode, Node, ChildNode: TDOMNode;
987 | begin
988 | if cboEmulator.Items.Count = 0 then
989 | begin
990 | ShowMessage(I18N_NOSELEMUL);
991 | exit;
992 | end;
993 |
994 | if not FileExists(EmuConfig.CachePath) then
995 | btGenerateCache.Click;
996 |
997 | if Application.MessageBox(PChar(I18N_GAMELISTCONFIRM),
998 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
999 | exit;
1000 |
1001 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
1002 |
1003 | if not SQLite3Connection.Connected then
1004 | SQLite3Connection.Connected := True;
1005 |
1006 | Xml := TXMLDocument.Create;
1007 |
1008 | try
1009 | SQLQuery.SQL.Text := Format('SELECT disp, path, imgpath, type, pinyin, opinyin FROM %s_roms', [EmuConfig.System]);
1010 | try
1011 | SQLQuery.Active := True;
1012 | except
1013 | on E :Exception do
1014 | begin
1015 | WriteLog(I18N_ERROROCCURED + ' - ' + EmuConfig.System + '_roms - ' + E.Message);
1016 | exit;
1017 | end;
1018 | end;
1019 |
1020 | RootNode := Xml.CreateElement('gameList');
1021 | Xml.AppendChild(RootNode);
1022 |
1023 | SQLQuery.First;
1024 |
1025 | while not SQLQuery.EOF do
1026 | begin
1027 | if SQLQuery.FieldByName('type').AsInteger = 0 then
1028 | Node := Xml.CreateElement('game')
1029 | else
1030 | Node := Xml.CreateElement('folder');
1031 | RootNode.AppendChild(Node);
1032 |
1033 | ChildNode := Xml.CreateElement('name');
1034 | ChildNode.TextContent := SQLQuery.FieldByName('disp').AsUnicodeString;
1035 | Node.AppendChild(ChildNode);
1036 |
1037 | ChildNode := Xml.CreateElement('image');
1038 | ChildNode.TextContent := SQLQuery.FieldByName('imgpath').AsUnicodeString;
1039 | Node.AppendChild(ChildNode);
1040 |
1041 | if SQLQuery.FieldByName('type').AsInteger = 0 then
1042 | begin
1043 | ChildNode := Xml.CreateElement('path');
1044 | // ChildNode.TextContent := UnicodeString(StringReplace(SQLQuery.FieldByName('path').AsString, EmuConfig.EmuPath + '/', '', []));
1045 | ChildNode.TextContent := SQLQuery.FieldByName('path').AsUnicodeString;
1046 | Node.AppendChild(ChildNode);
1047 | end;
1048 |
1049 | SQLQuery.Next;
1050 | end;
1051 |
1052 | if (Trim(EmuConfig.Gamelist) = '') or (Trim(edGamelist.Text) = '') then
1053 | begin
1054 | edGamelist.Text := edRomPath.Text + '/gamelist.xml';
1055 | acSaveEmuInfo.Execute;
1056 |
1057 | EmuConfig.Gamelist := Lin2Win(edBasePath.Text, edGamelist.Text);
1058 | end;
1059 |
1060 | WriteXMLFile(Xml, EmuConfig.Gamelist);
1061 | WriteLog(EmuConfig.Gamelist + ' - ' + I18N_CREATED);
1062 | finally
1063 | if Xml <> nil then
1064 | Xml.Free;
1065 | SQLite3Connection.Connected := False;
1066 | end;
1067 | end;
1068 |
1069 | procedure TFormMain.acCacheFromXmlExecute(Sender: TObject);
1070 | begin
1071 | with TOpenDialog.Create(Self) do
1072 | try
1073 | Filter := 'gamelist file|*.xml';
1074 |
1075 | if not Execute then
1076 | exit;
1077 |
1078 | GenCacheFromXml(FileName);
1079 | finally
1080 | Free;
1081 | end;
1082 | end;
1083 |
1084 | procedure TFormMain.acAboutExecute(Sender: TObject);
1085 | begin
1086 | ShowMessage('Author: ryusatgat (https://www.ryugod.com)');
1087 | end;
1088 |
1089 | procedure TFormMain.acAddRomExecute(Sender: TObject);
1090 | var
1091 | Ext: String;
1092 | Filenames: array of String;
1093 | i: Integer;
1094 | begin
1095 | if cboEmulator.Items.Count = 0 then
1096 | begin
1097 | ShowMessage(I18N_NOSELEMUL);
1098 | exit;
1099 | end;
1100 |
1101 | Filenames := [];
1102 | Ext := '*.' + StringReplace(edExtList.Text, '|', ';*.', [rfReplaceAll]);
1103 | with TOpenDialog.Create(Self) do
1104 | try
1105 | Options := Options + [ofAllowMultiSelect];
1106 | Filter := 'Rom file|' + Ext;
1107 |
1108 | if Execute then
1109 | begin
1110 | SetLength(Filenames, Files.Count);
1111 | for i:=0 to Files.Count-1 Do
1112 | Filenames[i] := Files[i];
1113 | FormDropFiles(Self, Filenames);
1114 | end;
1115 | finally
1116 | Free;
1117 | end;
1118 | end;
1119 |
1120 | procedure TFormMain.acChangeImageExecute(Sender: TObject);
1121 | var
1122 | Key, ImageFile, WinFilename, Ext: String;
1123 | begin
1124 | if ListView.Selected = nil then
1125 | begin
1126 | ShowMessage(I18N_ROMNOTSELECTED);
1127 | exit;
1128 | end;
1129 |
1130 | with TOpenDialog.Create(Self) do
1131 | try
1132 | Filter := 'Image file|*.png;*.jpg;*.jpeg';
1133 | if Execute then
1134 | begin
1135 | Image.Picture.LoadFromFile(FileName);
1136 | Ext := ExtractFileExt(FileName);
1137 |
1138 | Key := ListView.Selected.SubItems[1];
1139 | if Copy(edImagePath.Text, 1, 1) = '/' then
1140 | ImageFile := edImagePath.Text + '/' + ExtractFileNameWithoutExt(ExtractFilename(FileName)) + Ext
1141 | else
1142 | ImageFile := EmuConfig.EmuPath + '/' + edImagePath.Text + '/' + ExtractFileNameWithoutExt(ExtractFilename(FileName)) + Ext;
1143 | WinFilename := Lin2Win(edBasePath.Text, ImageFile);
1144 | SaveImage(Image, WinFilename, ckForcePng.Checked);
1145 |
1146 | ListView.Selected.SubItems[0] := ImageFile;
1147 | UpdateCache(Key, 'imgpath', ImageFile);
1148 | end;
1149 | finally
1150 | Free;
1151 | end;
1152 | end;
1153 |
1154 | procedure TFormMain.acDeleteExecute(Sender: TObject);
1155 | var
1156 | i: Integer;
1157 | Key: String;
1158 | ImgPath, RomPath: String;
1159 | begin
1160 | if ListView.Selected = nil then
1161 | exit;
1162 | if Application.MessageBox(PChar(I18N_DELETECONFIRM),
1163 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
1164 | exit;
1165 |
1166 | for i:=ListView.Items.Count-1 downto 0 do
1167 | if ListView.Items[i].Selected then
1168 | begin
1169 | Key := ListView.Items[i].SubItems[1];
1170 | ImgPath := Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[0]);
1171 | RomPath := Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[2]);
1172 | if FileExists(ImgPath) then
1173 | begin
1174 | SysUtils.DeleteFile(ImgPath);
1175 | WriteLog(I18N_DELETED + ' - ' + ImgPath);
1176 | end;
1177 | if FileExists(RomPath) then
1178 | begin
1179 | SysUtils.DeleteFile(RomPath);
1180 | WriteLog(I18N_DELETED + ' - ' + RomPath);
1181 | end;
1182 | ListView.Items.Delete(i);
1183 | DeleteCache(Key);
1184 | end;
1185 | end;
1186 |
1187 | procedure TFormMain.acDetectBasePathExecute(Sender: TObject);
1188 | var
1189 | Drv: String;
1190 | Path: String;
1191 | {$IFDEF linux}
1192 | i: Integer;
1193 | List: TStringList;
1194 | {$ENDIF}
1195 | begin
1196 | {$IFDEF linux}
1197 | RunCommand('/bin/bash', ['-c', 'grep vfat /proc/mounts'], Drv);
1198 | List := TStringList.Create;
1199 | try
1200 | List.Delimiter := LineEnding;
1201 | List.DelimitedText := Drv;
1202 | for i:=0 to List.Count-1 do
1203 | begin
1204 | if Copy(List.Strings[i], 1, 6) = '/media' then
1205 | begin
1206 | Path := List.Strings[i];
1207 | if DirectoryExists(Path + '/Emus') then
1208 | begin
1209 | edBasePath.Text := Path;
1210 | btRefresh.Click;
1211 | break;
1212 | end;
1213 | end;
1214 | end;
1215 | finally
1216 | List.Free;
1217 | end;
1218 | {$ELSE}
1219 | for Drv in 'DEFGHIJK' do
1220 | begin
1221 | Path := Drv + ':\';
1222 |
1223 | if DirectoryExists(Path + '\Emus') then
1224 | begin
1225 | edBasePath.Text := Path;
1226 | btRefresh.Click;
1227 | break;
1228 | end;
1229 | end;
1230 | {$ENDIF}
1231 | end;
1232 |
1233 | procedure TFormMain.acExitExecute(Sender: TObject);
1234 | begin
1235 | Close;
1236 | end;
1237 |
1238 | procedure TFormMain.acGenerateCacheExecute(Sender: TObject);
1239 | begin
1240 | if Application.MessageBox(PChar(I18N_RECACHECONFIRM),
1241 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
1242 | exit;
1243 |
1244 | BuildCache(True);
1245 | cboEmulatorChange(cboEmulator);
1246 | end;
1247 |
1248 | procedure TFormMain.acGithubExecute(Sender: TObject);
1249 | begin
1250 | openURL('https://github.com/ryusatgat/trimuitool');
1251 | end;
1252 |
1253 | procedure TFormMain.acMkDirExecute(Sender: TObject);
1254 | var
1255 | Dir, Path: String;
1256 | begin
1257 | if cboEmulator.Items.Count = 0 then
1258 | begin
1259 | ShowMessage(I18N_NOSELEMUL);
1260 | exit;
1261 | end;
1262 | Dir := '';
1263 | if not InputQuery(I18N_MAKEDIR, I18N_INPUTDIRNAME, Dir) then
1264 | exit;
1265 | Path := Lin2Win(edBasePath.Text, EmuConfig.EmuPath + '/' + edRomPath.Text + '/' + Dir);
1266 |
1267 | if DirectoryExists(Path) then
1268 | begin
1269 | ShowMessage(I18N_DIREXISTS);
1270 | exit
1271 | end;
1272 |
1273 | if not CreateDir(Path) then
1274 | begin
1275 | WriteLog(Path);
1276 | ShowMessage(I18N_ERROROCCURED);
1277 | exit;
1278 | end;
1279 |
1280 | Path := EmuConfig.EmuPath + '/' + edRomPath.Text + '/' + Dir;
1281 | ExecCacheSQL('INSERT INTO %s_roms (disp, path, imgpath, type, ppath, pinyin, cpinyin, opinyin) VALUES (%s, %s, %s, 1, ''.'', '''', '''', '''')',
1282 | [EmuConfig.System, QuotedStr(Dir), QuotedStr(Path), QuotedStr(Path), QuotedStr(Dir)]);
1283 |
1284 | btRefresh.Click;
1285 | end;
1286 |
1287 | procedure TFormMain.acOpenBasePathExecute(Sender: TObject);
1288 | begin
1289 | with TSelectDirectoryDialog.Create(nil) do
1290 | try
1291 | if Execute then
1292 | begin
1293 | edBasePath.Text := FileName;
1294 | btRefresh.Click;
1295 | end;
1296 | finally
1297 | Free;
1298 | end;
1299 | end;
1300 |
1301 | procedure TFormMain.acOpenImagePosExecute(Sender: TObject);
1302 | var
1303 | OStr: String;
1304 | begin
1305 | {$IFDEF Linux}
1306 | if Image.Hint <> '' then
1307 | RunCommand('open', [Image.Hint], OStr);
1308 | {$ELSE}
1309 | RunCommand('explorer.exe', ['/select,"' + Image.Hint + '"'], OStr);
1310 | {$ENDIF}
1311 | end;
1312 |
1313 | procedure TFormMain.acRefreshExecute(Sender: TObject);
1314 | begin
1315 | LoadEmus(edBasePath.Text);
1316 | cboEmulatorChange(cboEmulator);
1317 | end;
1318 |
1319 | procedure TFormMain.cboEmulatorChange(Sender: TObject);
1320 | begin
1321 | if cboEmulator.Items.Count = 0 then
1322 | exit;
1323 |
1324 | LoadEmuConfig(cboEmulator.Text);
1325 | LoadEmuInfo(cboEmulator.Text);
1326 |
1327 | if not FileExists(EmuConfig.CachePath) then
1328 | BuildCache;
1329 | GetSubDir;
1330 | end;
1331 |
1332 | procedure TFormMain.edSearchKeyPress(Sender: TObject; var Key: char);
1333 | begin
1334 | if Key = #13 then
1335 | btScrape.Click;
1336 | end;
1337 |
1338 | procedure TFormMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
1339 | begin
1340 | WriteSettings;
1341 | TQueueThread.CancelScrape;
1342 | end;
1343 |
1344 | procedure TFormMain.FormCreate(Sender: TObject);
1345 | begin
1346 | InitCriticalSection(CriticalSection);
1347 | IPCServer := TSimpleIPCServer.Create(nil);
1348 | {$ifdef linux}
1349 | Application.OnIdle := @AppIdle;
1350 | {$endif}
1351 | IPCServer.ServerID := 'WriteLog';
1352 | IPCServer.OnMessageQueued := @IPCServerMessage;
1353 | IPCServer.Global := True;
1354 | IPCServer.StartServer;
1355 |
1356 | SystemMap := TStringList.Create;
1357 |
1358 | SystemMap.Add('DC=Sega Dreamcast');
1359 | SystemMap.Add('FC=nes');
1360 | SystemMap.Add('FDS=Famicom Disk System');
1361 | SystemMap.Add('ARCADE=arcade');
1362 | SystemMap.Add('FBNEO=arcade');
1363 | SystemMap.Add('CPS1=arcade');
1364 | SystemMap.Add('CPS2=arcade');
1365 | SystemMap.Add('CPS3=arcade');
1366 | SystemMap.Add('GB=gb');
1367 | SystemMap.Add('GBA=gba');
1368 | SystemMap.Add('GBC=gbc');
1369 | SystemMap.Add('GG=Sega Game Gear');
1370 | SystemMap.Add('GW=Nintendo Game & Watch');
1371 | SystemMap.Add('LYNX=Atari Lynx');
1372 | SystemMap.Add('MAME=arcade');
1373 | SystemMap.Add('MAME2003PLUS=arcade');
1374 | SystemMap.Add('MAME2010=arcade');
1375 | SystemMap.Add('MD=megadrive');
1376 | SystemMap.Add('MS=mastersystem');
1377 | SystemMap.Add('N64=Nintendo 64');
1378 | SystemMap.Add('NAOMI=Sega NAOMI');
1379 | SystemMap.Add('NGP=ngp');
1380 | SystemMap.Add('NEOGEO=arcade');
1381 | SystemMap.Add('OPERA=3DO');
1382 | SystemMap.Add('PCE=pcengine');
1383 | SystemMap.Add('PCECD=pcengine');
1384 | SystemMap.Add('PGM=PolyGame Master');
1385 | SystemMap.Add('PS=Sony Playstation');
1386 | SystemMap.Add('PSP=Sony PSP');
1387 | SystemMap.Add('PSPMINIS=Sony PSP Minis');
1388 | SystemMap.Add('SATURN=Sega Saturn');
1389 | SystemMap.Add('SCD=Sega CD');
1390 | SystemMap.Add('SEGA32X=sega32x');
1391 | SystemMap.Add('SFC=snes');
1392 | SystemMap.Add('SFX=SuperGrafx');
1393 | SystemMap.Add('SG1000=Sega SG-1000');
1394 | SystemMap.Add('SGB=Super Game Boy');
1395 | SystemMap.Add('VB=Nintendo Virtual Boy');
1396 | SystemMap.Add('DOS=DOSBOX');
1397 | SystemMap.Add('WS=wonderswan');
1398 |
1399 | QueueThread := TQueueThread.Create(False);
1400 | end;
1401 |
1402 | procedure TFormMain.FormDestroy(Sender: TObject);
1403 | begin
1404 | SQLName.Close;
1405 | SQLite3Name.Connected := False;
1406 |
1407 | TQueueThread.CancelScrape;
1408 | QueueThread.Terminate;
1409 | QueueThread.WaitFor;
1410 | QueueThread.Free;
1411 | IPCServer.StopServer;
1412 | IPCServer.Free;
1413 | SystemMap.Free;
1414 |
1415 | DoneCriticalSection(CriticalSection);
1416 | end;
1417 |
1418 | procedure TFormMain.FormDropFiles(Sender: TObject;
1419 | const FileNames: array of string);
1420 | var
1421 | Key, ImageFile, Ext, Filename, Fullname: String;
1422 | Path, SubDir: String;
1423 | i: Integer;
1424 | begin
1425 | if cboEmulator.Items.Count = 0 then
1426 | exit;
1427 |
1428 | for i:=0 to Length(FileNames)-1 do
1429 | begin
1430 | Ext := ExtractFileExt(FileNames[i]);
1431 | if Pos(Copy(Ext, 2), EmuConfig.ExtList) > 0 then
1432 | begin
1433 | SubDir := TreeView.Selected.Text;
1434 | Filename := ExtractFileNameWithoutExt(ExtractFileName(Filenames[i]));
1435 | Fullname := InsertCache(ExtractFileName(Filenames[i]), SubDir);
1436 | if Fullname = '' then
1437 | exit;
1438 | Path := EmuConfig.RomPath;
1439 | Path := StringReplace(Path, '..' + DirectorySeparator + '..', edBasePath.Text, [rfReplaceAll]);
1440 | if Assigned(TreeView.Selected) and (TreeView.Selected.Level > 0) then
1441 | Path := Path + DirectorySeparator + SubDir;
1442 | Path := Path + DirectorySeparator + Filename + Ext;
1443 | CopyFile(Filenames[i], Path);
1444 | WriteLog(Filenames[i] + ' --> ' + Path);
1445 | GetEmuList(TreeView.Selected.Text);
1446 | end else if Ext = '.xml' then
1447 | begin
1448 | if Application.MessageBox(PChar(I18N_CACHEFROMXML),
1449 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
1450 | exit;
1451 | GenCacheFromXml(FileNames[0]);
1452 | exit;
1453 | end else begin
1454 | if ListView.Selected = nil then
1455 | begin
1456 | ShowMessage(I18N_ROMNOTSELECTED);
1457 | exit;
1458 | end;
1459 |
1460 | case Ext of
1461 | '.jpg','.jpeg','.png':
1462 | else
1463 | exit;
1464 | end;
1465 | Ext := ExtractFileExt(FileNames[0]);
1466 | Image.Picture.LoadFromFile(FileNames[0]);
1467 | Key := ListView.Selected.SubItems[1];
1468 |
1469 | Filename := ExtractFilename(FileNames[0]);
1470 | if Copy(edImagePath.Text, 1, 1) = '/' then
1471 | ImageFile := edImagePath.Text + '/' + ExtractFileNameWithoutExt(Filename) + Ext
1472 | else
1473 | ImageFile := EmuConfig.EmuPath + '/' + edImagePath.Text + '/' + ExtractFileNameWithoutExt(FileName) + Ext;
1474 |
1475 | Filename := Lin2Win(edBasePath.Text, ImageFile);
1476 | SaveImage(Image, Filename, ckForcePng.Checked);
1477 | ListView.Selected.SubItems[0] := ImageFile;
1478 | UpdateCache(Key, 'imgpath', ImageFile);
1479 | exit;
1480 | end;
1481 | end;
1482 | end;
1483 |
1484 | procedure TFormMain.FormShow(Sender: TObject);
1485 | var
1486 | DbPath: String;
1487 | begin
1488 | WriteLog(I18N_ROMFROM);
1489 |
1490 | DbPath := ExtractFileDir(Application.ExeName) + DirectorySeparator + 'romnames.db';
1491 | if not FileExists(DbPath) then
1492 | WriteLog('romnames.db - ' + I18N_FILENOTFOUND)
1493 | else
1494 | SQLite3Name.DatabaseName := DbPath;
1495 |
1496 | btAutoDetect.Click;
1497 | ReadSettings;
1498 | end;
1499 |
1500 | procedure TFormMain.Image1Click(Sender: TObject);
1501 | var
1502 | Picture: TPicture;
1503 | begin
1504 | Picture := TPicture.Create;
1505 | try
1506 | if Assigned(TImage(Sender).Picture) then
1507 | begin
1508 | Picture.Assign(Image.Picture);
1509 | Image.Picture.Assign(TImage(Sender).Picture);
1510 | TImage(Sender).Picture.Assign(Picture);
1511 |
1512 | if Image.Hint <> '' then
1513 | begin
1514 | Image.Picture.SaveToFile(Image.Hint);
1515 | WriteLog(I18N_SAVED + ' - ' + Image.Hint);
1516 | end;
1517 | end;
1518 | finally
1519 | if Assigned(Picture) then
1520 | Picture.Free;
1521 | end;
1522 | end;
1523 |
1524 | procedure TFormMain.ListViewCustomDrawItem(Sender: TCustomListView;
1525 | Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
1526 | begin
1527 | if not FileExists(Lin2Win(edBasePath.Text, Item.SubItems[2])) then
1528 | begin
1529 | TListView(Sender).Canvas.Brush.Color := $00FF80FF;
1530 | Item.ImageIndex := 4;
1531 | end else if not FileExists(Lin2Win(edBasePath.Text, Item.SubItems[0])) then
1532 | begin
1533 | TListView(Sender).Canvas.Brush.Color := $0080FFFF;
1534 | Item.ImageIndex := 5;
1535 | end else
1536 | Item.ImageIndex := 3;
1537 | end;
1538 |
1539 | procedure TFormMain.ListViewEdited(Sender: TObject; Item: TListItem;
1540 | var AValue: string);
1541 | begin
1542 | if not RenameTitle(Item.SubItems[1], AValue) then
1543 | AValue := Item.Caption;
1544 | end;
1545 |
1546 | procedure TFormMain.ListViewSelectItem(Sender: TObject; Item: TListItem;
1547 | Selected: Boolean);
1548 | var
1549 | ImagePath: String;
1550 | begin
1551 | if not Selected then
1552 | begin
1553 | acScrape.Enabled := False;
1554 | exit;
1555 | end;
1556 | ImagePath := Lin2Win(edBasePath.Text, Item.SubItems[0]);
1557 | acScrape.Enabled := True;
1558 | Image.Hint := ImagePath;
1559 |
1560 | if FileExists(ImagePath) then
1561 | Image.Picture.LoadFromFile(ImagePath)
1562 | else
1563 | Image.Picture.Assign(NoImage.Picture);
1564 | end;
1565 |
1566 | procedure TFormMain.mnLangKorClick(Sender: TObject);
1567 | begin
1568 | mnLangKor.Checked := False;
1569 | mnLangEng.Checked := False;
1570 | TMenuItem(Sender).Checked := True;
1571 | Translate(TMenuItem(Sender).Hint);
1572 | end;
1573 |
1574 | procedure TFormMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
1575 | begin
1576 | if not Assigned(Node) then
1577 | exit;
1578 | if Node.Level = 0 then
1579 | TreeView.ReadOnly := True
1580 | else
1581 | TreeView.ReadOnly := False;
1582 | GetEmuList(Node.Text);
1583 | end;
1584 |
1585 | procedure TFormMain.TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
1586 | var
1587 | i: Integer;
1588 | Node: TTreeNode;
1589 | OldPath, Path, PPath, Filename, Shortname: String;
1590 | begin
1591 | if Source is TListView then
1592 | begin
1593 | if not Assigned(TListView(Source).Selected) then
1594 | exit;
1595 |
1596 | Node := TTreeView(Sender).GetNodeAt(X, Y);
1597 |
1598 | if Assigned(Node) and not Node.Selected then
1599 | begin
1600 | Node.ImageIndex := 0;
1601 | for i:=ListView.Items.Count-1 downto 0 do
1602 | begin
1603 | if not ListView.Items[i].Selected then
1604 | continue;
1605 | Filename := ExtractFileName(Lin2Win(edBasePath.Text, ListView.Items[i].SubItems[2]));
1606 | Shortname := ListView.Items[i].SubItems[1];
1607 | OldPath := ListView.Items[i].SubItems[2];
1608 | Path := EmuConfig.EmuPath + '/' + edRomPath.Text;
1609 | if Node.Level = 0 then
1610 | PPath := '.'
1611 | else begin
1612 | PPath := Node.Text;
1613 | Path := Path + '/' + PPath;
1614 | end;
1615 | Path := Path + '/' + Filename;
1616 |
1617 | WriteLog(OldPath + ' --> ' + Path);
1618 | RenameFile(Lin2Win(edBasePath.Text, OldPath), Lin2Win(edBasePath.Text, Path));
1619 |
1620 | ExecCacheSQL('UPDATE %s_roms SET path = %s, ppath = %s WHERE opinyin = %s',
1621 | [EmuConfig.System, QuotedStr(Path), QuotedStr(PPath), QuotedStr(Shortname)]);
1622 |
1623 | ListView.BeginUpdate;
1624 | try
1625 | ListView.Items[i].Delete;
1626 | finally
1627 | ListView.EndUpdate;
1628 | end;
1629 | end;
1630 | end;
1631 | end;
1632 | end;
1633 |
1634 | procedure TFormMain.TreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
1635 | State: TDragState; var Accept: Boolean);
1636 | var
1637 | i: Integer;
1638 | Node: TTreeNode;
1639 | begin
1640 | Accept := Source is TListView;
1641 | if Accept then
1642 | begin
1643 | Node := TTreeView(Sender).GetNodeAt(X, Y);
1644 |
1645 | for i:=0 to TTreeView(Sender).Items.Count-1 do
1646 | begin
1647 | if not TTreeView(Sender).Items[i].Selected then
1648 | TTreeView(Sender).Items[i].ImageIndex := 0;
1649 | end;
1650 | if Assigned(Node) and not Node.Selected then
1651 | begin
1652 | Node.ImageIndex := 2;
1653 | end;
1654 | end;
1655 | end;
1656 |
1657 | procedure TFormMain.TreeViewEdited(Sender: TObject; Node: TTreeNode;
1658 | var S: string);
1659 | begin
1660 | if not RenameSubDir(Node.Text, S) then
1661 | S := Node.Text
1662 | else
1663 | GetEmuList(S);
1664 | end;
1665 |
1666 | procedure TFormMain.AppIdle(Sender: TObject; var Done: Boolean);
1667 | begin
1668 | IPCServer.PeekMessage(1, True);
1669 | end;
1670 |
1671 | procedure TFormMain.IPCServerMessage(Sender: TObject);
1672 | var
1673 | ImageFile, Key: String;
1674 | StrArr: TStringArray;
1675 | i, ImageCount: Integer;
1676 | Count, TotalCount: Integer;
1677 | ImagePath, ImageBase: String;
1678 | begin
1679 | IPCServer.ReadMessage;
1680 | if (Copy(IPCServer.StringMessage, 1, 1) = '@') then
1681 | begin
1682 | try
1683 | StrArr := Copy(IPCServer.StringMessage, 2).Split('|');
1684 | ImageFile := StrArr[0];
1685 | ImageBase := Strarr[1];
1686 | Key := StrArr[2];
1687 | ImageCount := StrToInt(StrArr[3]);
1688 | Count := StrToInt(StrArr[4]);
1689 | TotalCount := StrToInt(StrArr[5]);
1690 |
1691 | if ImageCount > 0 then
1692 | begin
1693 | Image1.Picture.Clear;
1694 | Image2.Picture.Clear;
1695 | Image3.Picture.Clear;
1696 | Image4.Picture.Clear;
1697 | end;
1698 |
1699 | pbInfo.Visible := TotalCount-Count > 0;
1700 | pbInfo.Max := TotalCount;
1701 | pbInfo.Position := TotalCount - Count;
1702 | pbInfo.Caption := Format('%d / %d', [TotalCount-Count, TotalCount]);
1703 | pbInfo.Hint := pbInfo.Caption;
1704 |
1705 | EnterCriticalSection(CriticalSection);
1706 | try
1707 | for i:=1 to ImageCount do
1708 | begin
1709 | ImagePath := ExtractFilePath(Application.ExeName) + DirectorySeparator + 'Image' + IntToStr(i) + '.jpg';
1710 | case i of
1711 | 1: Image1.Picture.LoadFromFile(ImagePath);
1712 | 2: Image2.Picture.LoadFromFile(ImagePath);
1713 | 3: Image3.Picture.LoadFromFile(ImagePath);
1714 | 4: Image4.Picture.LoadFromFile(ImagePath);
1715 | end;
1716 | end;
1717 | finally
1718 | LeaveCriticalSection(CriticalSection);
1719 | end;
1720 | except
1721 | on E :Exception do
1722 | begin
1723 | WriteLog(E.Message);
1724 | exit;
1725 | end;
1726 | end;
1727 |
1728 | EnterCriticalSection(CriticalSection);
1729 | try
1730 | if FileExists(ImageFile) then
1731 | begin
1732 | Image.Picture.LoadFromFile(ImageFile);
1733 | Image.Hint := ImageFile;
1734 |
1735 | for i:=0 to ListView.Items.Count-1 do
1736 | if ListView.Items[i].SubItems[1] = Key then
1737 | begin
1738 | if Copy(edImagePath.Text, 1, 1) = '/' then
1739 | ImageFile := ImageBase + '/' + ExtractFileName(ImageFile)
1740 | else
1741 | ImageFile := EmuConfig.EmuPath + '/' + ImageBase + '/' + ExtractFileName(ImageFile);
1742 |
1743 | ListView.Items[i].SubItems[0] := ImageFile;
1744 | UpdateCache(Key, 'imgpath', ImageFile);
1745 | break;
1746 | end;
1747 | end;
1748 | finally
1749 | LeaveCriticalSection(CriticalSection);
1750 | end;
1751 |
1752 | WriteLog(Key + ' (' + pbInfo.Caption + ') - ' + I18N_DONESCRAPE);
1753 | end else
1754 | WriteLog(IPCServer.StringMessage);
1755 | end;
1756 |
1757 | procedure TFormMain.LoadEmus(BasePath: String);
1758 | var
1759 | SearchRec: TSearchRec;
1760 | EmuPath: String;
1761 | begin
1762 | EmuPath := BasePath + DirectorySeparator + 'Emus';
1763 |
1764 | if not DirectoryExists(EmuPath) then
1765 | begin
1766 | WriteLog(EmuPath + ' - ' + I18N_DIRNOTFOUND);
1767 | exit;
1768 | end;
1769 |
1770 | if cboEmulator.ItemIndex >= 0 then
1771 | cboEmulator.Tag := cboEmulator.ItemIndex;
1772 | cboEmulator.Clear;
1773 |
1774 | if FindFirst(EmuPath + DirectorySeparator + '*', faDirectory, SearchRec) = 0 then
1775 | begin
1776 | repeat
1777 | if Copy(SearchRec.Name, 1, 1) <> '.' then
1778 | begin
1779 | if not FileExists(EmuPath + DirectorySeparator + SearchRec.Name + DirectorySeparator + 'config.json') then
1780 | WriteLog(EmuPath + DirectorySeparator + SearchRec.Name + DirectorySeparator + 'config.json - ' + I18N_FILENOTFOUND)
1781 | else begin
1782 | if LoadEmuConfig(SearchRec.Name) then
1783 | begin
1784 | if not DirectoryExists(EmuConfig.RomPath) then
1785 | WriteLog(EmuConfig.RomPath + ' - ' + I18N_FILENOTFOUND)
1786 | else
1787 | cboEmulator.Items.AddStrings(SearchRec.Name);
1788 | end;
1789 | end;
1790 | end;
1791 | Application.ProcessMessages;
1792 | until FindNext(SearchRec) <> 0;
1793 |
1794 | SysUtils.FindClose(SearchRec);
1795 | end;
1796 |
1797 | if cboEmulator.Items.Count > 0 then
1798 | begin
1799 | btGenerateCache.Enabled := True;
1800 | if cboEmulator.Items.Count > cboEmulator.Tag then
1801 | cboEmulator.ItemIndex := cboEmulator.Tag
1802 | else
1803 | cboEmulator.ItemIndex := 0;
1804 | end else
1805 | btGenerateCache.Enabled := False;
1806 | end;
1807 |
1808 | procedure TFormMain.WriteLog(Log: String);
1809 | begin
1810 | mmLog.Lines.Add(Format('[%s] %s', [TimeToStr(Now), Log]));
1811 | mmLog.CaretPos := Point(0, mmLog.Lines.Count-1);
1812 | end;
1813 |
1814 | function TFormMain.LoadEmuConfig(System: String): Boolean;
1815 | var
1816 | EmuPath: String;
1817 | JConfig: TJSONConfig;
1818 | begin
1819 | EmuPath := edBasePath.Text + DirectorySeparator + 'Emus' + DirectorySeparator + System;
1820 | SetCurrentDir(EmuPath);
1821 | EmuPath := EmuPath + DirectorySeparator + 'config.json';
1822 |
1823 | if not FileExists(EmuPath) then
1824 | begin
1825 | WriteLog(EmuPath + ' - ' + I18N_FILENOTFOUND);
1826 | Result := False;
1827 | exit;
1828 | end;
1829 | JConfig := TJSONConfig.Create(nil);
1830 | try
1831 | try
1832 | JConfig.Filename := EmuPath;
1833 |
1834 | EmuConfig.RomPath := Lin2Win(edBasePath.Text, String(JConfig.GetValue('/rompath' , '../../Roms/' + System)));
1835 | EmuConfig.System := ExtractFileNameOnly(EmuConfig.RomPath);
1836 | EmuConfig.EmuPath := BASE_PATH + '/Emus/' + System;
1837 | EmuConfig.Caption:= String(JConfig.GetValue('/label', ''));
1838 | EmuConfig.Icon := String(JConfig.GetValue('/icon', ''));
1839 | EmuConfig.CachePath := EmuConfig.RomPath + DirectorySeparator + EmuConfig.System + '_cache7.db';
1840 | EmuConfig.Gamelist := Lin2Win(edBasePath.Text, String(JConfig.GetValue('/gamelist', '')));
1841 | EmuConfig.ImgPath := Lin2Win(edBasePath.Text, String(JConfig.GetValue('/imgpath' , '../Imgs/' + System)));
1842 | if Copy(EmuConfig.ImgPath, 1, 5) = '..' + DirectorySeparator + '..' then
1843 | EmuConfig.ImgPath := StringReplace(EmuConfig.ImgPath, '..' + DirectorySeparator + '..', edBasePath.Text, [rfReplaceAll]);
1844 | EmuConfig.Shortname := JConfig.GetValue('/shortname', 0) = 1;
1845 | EmuConfig.HideBios := JConfig.GetValue('/hidebios', 0) = 1;
1846 | EmuConfig.UseSwap := JConfig.GetValue('/useswap', 0) = 1;
1847 | EmuConfig.ExtList:= String(JConfig.GetValue('/extlist', 'zip'));
1848 | except
1849 | on E: Exception do
1850 | begin
1851 | WriteLog(EmuConfig.System + ' - config.json : ' + E.Message);
1852 | Result := False;
1853 | exit;
1854 | end;
1855 | end;
1856 |
1857 | finally
1858 | JConfig.Free;
1859 | end;
1860 | Result := True;
1861 | end;
1862 |
1863 | function TFormMain.LoadEmuInfo(System: String): Boolean;
1864 | var
1865 | EmuPath: String;
1866 | JConfig: TJSONConfig;
1867 | begin
1868 | EmuPath := edBasePath.Text + DirectorySeparator + 'Emus' + DirectorySeparator + System + DirectorySeparator + 'config.json';
1869 |
1870 | if not FileExists(EmuPath) then
1871 | begin
1872 | WriteLog(EmuPath + ' - ' + I18N_FILENOTFOUND);
1873 | Result := False;
1874 | exit;
1875 | end;
1876 | JConfig := TJSONConfig.Create(nil);
1877 | try
1878 | JConfig.Filename := EmuPath;
1879 |
1880 | edLabel.Text := String(JConfig.GetValue('/label', ''));
1881 | edIcon.Text := String(JConfig.GetValue('/icon', ''));
1882 | edRomPath.Text := String(JConfig.GetValue('/rompath' , '../../Roms/' + System));
1883 | edGamelist.Text := String(JConfig.GetValue('/gamelist', ''));
1884 | edImagePath.Text := String(JConfig.GetValue('/imgpath' , '../Imgs/' + System));
1885 | ckShortname.Checked := JConfig.GetValue('/shortname', 0) = 1;
1886 | ckHideBios.Checked := JConfig.GetValue('/hidebios', 0) = 1;
1887 | ckUseSwap.Checked := JConfig.GetValue('/useswap', 0) = 1;
1888 | edExtList.Text := String(JConfig.GetValue('/extlist', 'zip'));
1889 | finally
1890 | JConfig.Free;
1891 | end;
1892 | Result := True;
1893 | end;
1894 |
1895 | function TFormMain.SaveEmuConfig(System: String): Boolean;
1896 | var
1897 | EmuPath: String;
1898 | begin
1899 | EmuPath := edBasePath.Text + DirectorySeparator + 'Emus' + DirectorySeparator + System + DirectorySeparator + 'config.json';
1900 |
1901 | if not FileExists(EmuPath) then
1902 | begin
1903 | WriteLog(EmuPath + ' - ' + I18N_FILENOTFOUND);
1904 | Result := False;
1905 | exit;
1906 | end;
1907 |
1908 | Result := True;
1909 | end;
1910 |
1911 | procedure TFormMain.BuildCache(IsDelete: Boolean=False);
1912 | var
1913 | Count, AddedCount: Integer;
1914 | ExtList: TStringArray;
1915 | Path: String;
1916 |
1917 | procedure FindUpdate(SubDir: String; Level: Integer);
1918 | var
1919 | Info: TSearchRec;
1920 | Path, ImgPath, Shortname, Fullname: String;
1921 | begin
1922 | if FindFirst(EmuConfig.RomPath + DirectorySeparator + SubDir + DirectorySeparator + '*' , faAnyFile, Info) = 0 then
1923 | begin
1924 | repeat
1925 | repeat
1926 | if Copy(Info.Name, 1, 1) = '.' then
1927 | break;
1928 | if (Level = 0) and ((Info.Attr and faDirectory) = faDirectory) then
1929 | begin
1930 | FindUpdate(Info.Name, 1);
1931 | break;
1932 | end;
1933 |
1934 | if (Info.Attr and faDirectory) = faDirectory then
1935 | break;
1936 | ExtList := SplitString(EmuConfig.ExtList, '|');
1937 | if {%H-}MatchStr(Copy(ExtractFileExt(Info.Name), 2), ExtList) then
1938 | begin
1939 | Shortname := ExtractFileNameWithoutExt(ExtractFileName(UTF8String(Info.Name)));
1940 | FullName := GetFullTitle(Shortname, Shortname);
1941 | SQLQuery.SQL.Text := Format('UPDATE %s_roms SET disp = %s WHERE opinyin = %s', [EmuConfig.System, QuotedStr(FullName), QuotedStr(Shortname)]);
1942 | SQLQuery.ExecSQL;
1943 | if SQLQuery.RowsAffected = 0 then
1944 | begin
1945 | Inc(AddedCount);
1946 | Path := EmuConfig.EmuPath + '/' + edRomPath.Text + '/';
1947 | if SubDir = '' then
1948 | SubDir := '.'
1949 | else
1950 | Path := Path + SubDir + '/';
1951 | Path := Path + Shortname + ExtractFileExt(Utf8String(Info.Name));
1952 | if Copy(edImagePath.Text, 1, 1) = '/' then
1953 | ImgPath := edImagePath.Text + '/' + Shortname
1954 | else
1955 | ImgPath := EmuConfig.EmuPath + '/' + edImagePath.Text + '/' + Shortname;
1956 | if FileExists(Lin2Win(edBasePath.Text, ImgPath + '.jpg')) then
1957 | ImgPath := ImgPath + '.jpg'
1958 | else
1959 | ImgPath := ImgPath + '.png';
1960 |
1961 | SQLQuery.SQL.Text := Format('INSERT INTO %s_roms (disp, path, imgpath, type, ppath, pinyin, cpinyin, opinyin) VALUES (%s, %s, %s, 0, %s, %s, %s, %s)',
1962 | [EmuConfig.System, QuotedStr(Fullname), QuotedStr(Path), QuotedStr(ImgPath), QuotedStr(SubDir), QuotedStr(Fullname), QuotedStr(Fullname), QuotedStr(Shortname)]);
1963 | SQLQuery.ExecSQL;
1964 | end;
1965 | end;
1966 |
1967 | Inc(Count);
1968 |
1969 | if Count mod 100 = 0 then
1970 | begin
1971 | WriteLog(I18N_PROCESSING + '... ' + IntToStr(Count));
1972 | Application.ProcessMessages;
1973 | end;
1974 | until True;
1975 | until FindNext(Info) <> 0;
1976 |
1977 | FindClose(Info);
1978 | end;
1979 | end;
1980 |
1981 | begin
1982 | if IsDelete and FileExists(EmuConfig.CachePath) then
1983 | DeleteFile(EmuConfig.CachePath);
1984 |
1985 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
1986 | if not SQLite3Connection.Connected then
1987 | SQLite3Connection.Connected := True;
1988 |
1989 | WriteLog(EmuConfig.System + ' - ' + I18N_GENCACHE);
1990 | Count := 0;
1991 | AddedCount := 0;
1992 | try
1993 | SQLQuery.SQL.Text :=
1994 | Format('CREATE TABLE IF NOT EXISTS %s_roms (id INTEGER NOT NULL, disp TEXT NOT NULL, path TEXT NOT NULL, imgpath TEXT NOT NULL, type INTEGER NULL, ppath TEXT NOT NULL, pinyin TEXT NOT NULL, cpinyin TEXT NOT NULL, opinyin TEXT NOT NULL, PRIMARY KEY (id))',
1995 | [EmuConfig.System]);
1996 |
1997 | SQLQuery.ExecSQL;
1998 |
1999 | if IsDelete then
2000 | begin
2001 | SQLQuery.SQL.Text := Format('DELETE FROM %s_roms', [EmuConfig.System]);
2002 | SQLQuery.ExecSQL;
2003 | end;
2004 | FindUpdate('', 0);
2005 |
2006 | Path := EmuConfig.EmuPath + '/' + edRomPath.Text + '/';
2007 | SQLQuery.SQL.Text := Format('INSERT INTO %s_roms (disp, path, imgpath, type, ppath, pinyin, cpinyin, opinyin) SELECT DISTINCT ppath, %s||ppath, %s||ppath, 1, ''.'', '''', '''', '''' FROM %s_roms WHERE ppath <> ''.'' AND ppath NOT IN (SELECT disp FROM %s_roms WHERE type = 1)',
2008 | [EmuConfig.System, QuotedStr(Path), QuotedStr(Path), EmuConfig.System, EmuConfig.System]);
2009 | SQLQuery.ExecSQL;
2010 | finally
2011 | SQLite3Connection.Connected := False;
2012 | WriteLog(IntToStr(AddedCount) + ' - ' + I18N_ADDED);
2013 | end;
2014 | end;
2015 |
2016 | procedure TFormMain.GetSubDir;
2017 | var
2018 | RootNode: TTreeNode;
2019 | Info: TSearchRec;
2020 | begin
2021 | TreeView.BeginUpdate;
2022 | TreeView.Items.Clear;
2023 | try
2024 | RootNode := TreeView.Items.Add(nil, EmuConfig.System);
2025 | RootNode.ImageIndex := 0;
2026 | RootNode.SelectedIndex := 1;
2027 |
2028 | if FindFirst(EmuConfig.RomPath + DirectorySeparator + '*' , faDirectory, Info) = 0 then
2029 | begin
2030 | repeat
2031 | if (Copy(Info.Name, 1, 1) <> '.')and((Info.Attr and faDirectory) = faDirectory) then
2032 | with TreeView.Items.AddChild(RootNode, Info.Name) do
2033 | begin
2034 | ImageIndex := 0;
2035 | SelectedIndex := 1;
2036 | end;
2037 | until FindNext(Info) <> 0;
2038 | end;
2039 |
2040 | FindClose(Info);
2041 | finally
2042 | TreeView.EndUpdate;
2043 | TreeView.TopItem.Selected := True;
2044 | end;
2045 | end;
2046 |
2047 | procedure TFormMain.GetEmuList(SubDir: String='.');
2048 | var
2049 | Title, Shortname: String;
2050 | begin
2051 | if not Assigned(TreeView.Selected) or (TreeView.Selected.Level = 0) then
2052 | SubDir := '.';
2053 | ListView.Items.Clear;
2054 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
2055 | if not SQLite3Connection.Connected then
2056 | SQLite3Connection.Connected := True;
2057 |
2058 | ListView.BeginUpdate;
2059 | try
2060 | SQLQuery.SQL.Text := Format('SELECT id, disp, path, imgpath, pinyin, opinyin FROM %s_roms WHERE ppath = %s AND type = 0', [EmuConfig.System, QuotedStr(SubDir)]);
2061 | try
2062 | SQLQuery.Active := True;
2063 | except
2064 | on E :Exception do
2065 | begin
2066 | WriteLog(I18N_ERROROCCURED + ' - ' + EmuConfig.System + '_roms - ' + E.Message);
2067 | exit;
2068 | end;
2069 | end;
2070 | SQLQuery.First;
2071 |
2072 | while not SQLQuery.EOF do
2073 | begin
2074 | with ListView.Items.Add do
2075 | begin
2076 | ImageIndex := 3;
2077 | Shortname := SQLQuery.FieldByName('opinyin').AsString;
2078 | Title := SQLQuery.FieldByName('disp').AsString;
2079 | Caption := Title;
2080 | SubItems.Add(SQLQuery.FieldByName('imgpath').AsString);
2081 | SubItems.Add(Shortname);
2082 | SubItems.Add(SQLQuery.FieldByName('path').AsString);
2083 | end;
2084 |
2085 | SQLQuery.Next;
2086 | end;
2087 | finally
2088 | ListView.EndUpdate;
2089 | SQLite3Connection.Connected := False;
2090 | end;
2091 | end;
2092 |
2093 | function TFormMain.RenameTitle(Key, Tobe: String): Boolean;
2094 | begin
2095 | Result := False;
2096 | if (Key = Tobe) or (Tobe = '') then
2097 | exit;
2098 |
2099 | Result := UpdateCache(Key, 'disp', Tobe);
2100 | if Result then
2101 | Result := UpdateRomName(Key, Tobe);
2102 | end;
2103 |
2104 | function TFormMain.RenameSubDir(Asis, Tobe: String): Boolean;
2105 | var
2106 | TobePath, AsisPath: String;
2107 | begin
2108 | if (Asis = Tobe) or (Tobe = '') then
2109 | begin
2110 | Result := False;
2111 | exit;
2112 | end;
2113 |
2114 | AsisPath := '/' + edRomPath.Text + '/' + Asis + '/';
2115 | TobePath := '/' + edRomPath.Text + '/' + Tobe + '/';
2116 |
2117 | RenameFile(Lin2Win(edBasePath.Text, AsisPath), Lin2Win(edBasePath.Text, TobePath));
2118 | Result := ExecCacheSQL('UPDATE %s_roms SET path = REPLACE(path, %s, %s), ppath = %s WHERE ppath = %s',
2119 | [EmuConfig.System, QuotedStr(AsIsPath), QuotedStr(TobePath), QuotedStr(Tobe), QuotedStr(Asis)]);
2120 | if Result then
2121 | Result := ExecCacheSQL('UPDATE %s_roms SET disp = %s WHERE disp = %s AND type = 1',
2122 | [EmuConfig.System, QuotedStr(Tobe), QuotedStr(Asis)]);
2123 | end;
2124 |
2125 | function TFormMain.DeleteSubDir: Boolean;
2126 | var
2127 | Dir: String;
2128 | begin
2129 | Result := False;
2130 | if Application.MessageBox(PChar(I18N_DELETEDIRCONFIRM),
2131 | PChar(I18N_CONFIRM), MB_ICONQUESTION + MB_YESNO) <> IDYES then
2132 | exit;
2133 | if Assigned(TreeView.Selected) then
2134 | begin
2135 | if TreeView.Selected.Level = 0 then
2136 | exit;
2137 |
2138 | Dir := Lin2Win(edBasePath.Text, EmuConfig.EmuPath + '/' + edRomPath.Text + '/' + TreeView.Selected.Text);
2139 |
2140 | if not DirectoryExists(Dir) then
2141 | WriteLog(I18N_DIRNOTFOUND + ' - ' + Dir)
2142 | else if not DeleteDirectory(Dir, False) then
2143 | begin
2144 | WriteLog(I18N_ERROROCCURED + ' - ' + Dir);
2145 | exit;
2146 | end;
2147 | end;
2148 |
2149 | Result := ExecCacheSQL('DELETE FROM %s_roms WHERE ppath = %s AND type = 0', [EmuConfig.System, QuotedStr(TreeView.Selected.Text)]);
2150 | if Result then
2151 | Result := ExecCacheSQL('DELETE FROM %s_roms WHERE disp = %s AND type = 1', [EmuConfig.System, QuotedStr(TreeView.Selected.Text)]);
2152 |
2153 | if Result then
2154 | begin
2155 | TreeView.Selected.Delete;
2156 | TreeView.TopItem.Selected := True;
2157 | end;
2158 | end;
2159 |
2160 | function TFormMain.ExecCacheSQL(Query: String; Args: array of const): Boolean;
2161 | begin
2162 | Result := False;
2163 | if (Query = '') then
2164 | exit;
2165 |
2166 | if not SQLite3Connection.Connected then
2167 | SQLite3Connection.Connected := True;
2168 | try
2169 | SQLQuery.SQL.Text := Format(Query, Args);
2170 | try
2171 | SQLQuery.ExecSQL;
2172 | except
2173 | on E :Exception do
2174 | begin
2175 | WriteLog(I18N_ERROROCCURED + ' - ' + E.Message);
2176 | exit;
2177 | end;
2178 | end;
2179 | Result := True;
2180 | finally
2181 | SQLite3Connection.Connected := False;
2182 | end;
2183 | end;
2184 |
2185 | function TFormMain.InsertCache(Filename: String; SubDir: String=''): String;
2186 | var
2187 | Path, ImgPath, Shortname, Fullname: String;
2188 | begin
2189 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
2190 | if not SQLite3Connection.Connected then
2191 | SQLite3Connection.Connected := True;
2192 |
2193 | WriteLog(EmuConfig.System + ' - ' + I18N_GENCACHE);
2194 |
2195 | if not Assigned(TreeView.Selected) or (TreeView.Selected.Level = 0) then
2196 | SubDir := '';
2197 |
2198 | try
2199 | SQLQuery.SQL.Text :=
2200 | Format('CREATE TABLE IF NOT EXISTS %s_roms (id INTEGER NOT NULL, disp TEXT NOT NULL, path TEXT NOT NULL, imgpath TEXT NOT NULL, type INTEGER NULL, ppath TEXT NOT NULL, pinyin TEXT NOT NULL, cpinyin TEXT NOT NULL, opinyin TEXT NOT NULL, PRIMARY KEY (id))',
2201 | [EmuConfig.System]);
2202 | SQLQuery.ExecSQL;
2203 |
2204 | Shortname := ExtractFileNameWithoutExt(ExtractFilename(Filename));
2205 | Fullname := GetFullTitle(Shortname, Shortname);
2206 | Result := Fullname;
2207 | Path := EmuConfig.EmuPath + '/' + edRomPath.Text;
2208 | if SubDir = '' then
2209 | SubDir := '.'
2210 | else
2211 | Path := Path + '/' + SubDir;
2212 | Path := Path + '/' + Filename;
2213 | SQLQuery.SQL.Text := Format('UPDATE %s_roms SET disp = %s, path = %s WHERE opinyin = %s', [EmuConfig.System, QuotedStr(FullName), QuotedStr(Path), QuotedStr(Shortname)]);
2214 | SQLQuery.ExecSQL;
2215 | if SQLQuery.RowsAffected = 0 then
2216 | begin
2217 | if Copy(edImagePath.Text, 1, 1) = '/' then
2218 | ImgPath := edImagePath.Text + '/' + ExtractFileNameWithoutExt(FileName) + '.png'
2219 | else
2220 | ImgPath := EmuConfig.EmuPath + '/' + edImagePath.Text + '/' + Shortname + '.png';
2221 | SQLQuery.SQL.Text := Format('INSERT INTO %s_roms (disp, path, imgpath, type, ppath, pinyin, cpinyin, opinyin) VALUES (%s, %s, %s, 0, %s, %s, %s, %s)',
2222 | [EmuConfig.System, QuotedStr(Fullname), QuotedStr(Path), QuotedStr(ImgPath), QuotedStr(SubDir), QuotedStr(Fullname), QuotedStr(Fullname), QuotedStr(Shortname)]);
2223 | SQLQuery.ExecSQL;
2224 | end;
2225 | finally
2226 | SQLite3Connection.Connected := False;
2227 | WriteLog(Filename + ' - ' + I18N_ADDED);
2228 | end;
2229 | end;
2230 |
2231 | function TFormMain.UpdateCache(Key, Column, Value: String): Boolean;
2232 | begin
2233 | Result := ExecCacheSQL('UPDATE %s_roms SET %s = %s WHERE opinyin = %s',
2234 | [EmuConfig.System, Column, QuotedStr(Value), QuotedStr(Key)]);
2235 | end;
2236 |
2237 | function TFormMain.DeleteCache(Key: String): Boolean;
2238 | begin
2239 | Result := ExecCacheSQL('DELETE FROM %s_roms WHERE opinyin = %s', [EmuConfig.System, QuotedStr(Key)]);
2240 | end;
2241 |
2242 | function TFormMain.GetFullTitle(Title, DefaultTitle: String): String;
2243 | var
2244 | ColName: String;
2245 | begin
2246 | if mnLangKor.Checked then
2247 | ColName := 'name'
2248 | else
2249 | ColName := 'ename';
2250 | if not SQLite3Name.Connected then
2251 | begin
2252 | SQLite3Name.Connected := True;
2253 | end;
2254 | SQLName.SQL.Text := Format('SELECT name, ename FROM romnames WHERE system = %s AND shortname = %s',
2255 | [QuotedStr(SystemMap.Values[EmuConfig.System]), QuotedStr(Title)]);
2256 | SQLName.Open;
2257 |
2258 | try
2259 | SQLName.First;
2260 | if SQLName.Eof then
2261 | Result := DefaultTitle
2262 | else
2263 | Result := SQLName.FieldByName(ColName).AsString;
2264 | finally
2265 | SQLName.Close;
2266 | end;
2267 | end;
2268 |
2269 | function TFormMain.UpdateRomName(Key, Value: String): Boolean;
2270 | begin
2271 | SQLName.SQL.Text := Format('UPDATE romnames SET name = %s WHERE system = %s AND shortname = %s', [QuotedStr(Value), QuotedStr(SystemMap.Values[EmuConfig.System]), QuotedStr(Key)]);
2272 | try
2273 | SQLName.ExecSQL;
2274 | except
2275 | on E :Exception do
2276 | begin
2277 | WriteLog(I18N_ERROROCCURED + ' - ' + Value + ' - ' + E.Message);
2278 | Result := False;
2279 | exit;
2280 | end;
2281 | end;
2282 | Result := True;
2283 | end;
2284 |
2285 | procedure TFormMain.GenCacheFromXml(Gamelist: String);
2286 | var
2287 | RootNode, Node, ChildNode: TDOMNode;
2288 | Xml: TXMLDocument;
2289 | disp, path, imgpath, ppath, yin: String;
2290 | tp: Integer;
2291 | i: Integer;
2292 | begin
2293 | SQLite3Connection.DatabaseName := EmuConfig.CachePath;
2294 | if not ExecCacheSQL('DELETE FROM %s_roms', [EmuConfig.System]) then
2295 | begin
2296 | WriteLog(I18N_ERROROCCURED + ' - ' + 'DELETE FROM clause');
2297 | exit;
2298 | end;
2299 |
2300 | ReadXMLFile(Xml, gamelist);
2301 | try
2302 | RootNode := Xml.FindNode('gameList');
2303 | if RootNode = nil then
2304 | begin
2305 | WriteLog('gameList tag not found - ' + gamelist);
2306 | exit;
2307 | end;
2308 |
2309 | pbInfo.Max := RootNode.GetChildNodes.Count;
2310 | pbInfo.Visible := True;
2311 | imgpath := '';
2312 | for i:= 0 to RootNode.GetChildNodes.Count-1 do
2313 | begin
2314 | tp := Ord(RootNode.GetChildNodes.Item[i].NodeName = 'folder');
2315 | Node := RootNode.GetChildNodes.Item[i];
2316 | ChildNode := Node.FindNode('name');
2317 | disp := AnsiString(ChildNode.TextContent);
2318 | ChildNode := Node.FindNode('image');
2319 | imgpath := AnsiString(ChildNode.TextContent);
2320 |
2321 | if tp = 0 then
2322 | begin
2323 | ChildNode := Node.FindNode('path');
2324 | path := AnsiString(ChildNode.TextContent);
2325 |
2326 | ppath := ExtractFileNameOnly(ExtractFileDir(path));
2327 | if (EmuConfig.System = ppath) or (ppath= '') or (ppath = '.') or (ppath = '/.') then
2328 | ppath := '.';
2329 |
2330 | yin := disp;
2331 | end else
2332 | begin
2333 | path := edRomPath.Text;
2334 | ppath := '.';
2335 | yin := '';
2336 | end;
2337 |
2338 | if not ExecCacheSQL('INSERT INTO %s_roms (disp, path, imgpath, type, ppath, pinyin, cpinyin, opinyin) VALUES (%s, %s, %s, %d, %s, %s, %s, %s)',
2339 | [EmuConfig.System, QuotedStr(disp), QuotedStr(path), QuotedStr(imgpath), tp, QuotedStr(ppath), QuotedStr(yin), QuotedStr(yin), QuotedStr(yin)]) then
2340 | begin
2341 | WriteLog(I18N_ERROROCCURED + ' - ' + 'INSERT INTO clause - ' + disp);
2342 | exit;
2343 | end;
2344 |
2345 | pbInfo.Position := i+1;
2346 | if pbInfo.Position mod 10 = 0 then
2347 | Application.ProcessMessages;
2348 | end;
2349 |
2350 | WriteLog(I18N_DONE + ' - ' + Gamelist);
2351 | cboEmulatorChange(cboEmulator);
2352 | finally
2353 | Xml.Free;
2354 | end;
2355 | end;
2356 |
2357 | procedure TFormMain.ReadSettings;
2358 | var
2359 | IniFile, Lang: String;
2360 | begin
2361 | IniFile := ExtractFilePath(Application.ExeName) +
2362 | ExtractFileNameOnly(Application.ExeName) + '.ini';
2363 | with TIniFile.Create(IniFile) do
2364 | try
2365 | Lang := ReadString('Main', 'Lang', 'EN');
2366 | if Lang = 'EN' then
2367 | mnLangEng.Click;
2368 | finally
2369 | Free;
2370 | end;
2371 | end;
2372 |
2373 | procedure TFormMain.WriteSettings;
2374 | var
2375 | IniFile, Lang: String;
2376 | begin
2377 | IniFile := ExtractFilePath(Application.ExeName) +
2378 | ExtractFileNameOnly(Application.ExeName) + '.ini';
2379 |
2380 | if mnLangKor.Checked then
2381 | Lang := 'KO'
2382 | else
2383 | Lang := 'EN';
2384 | with TIniFile.Create(IniFile) do
2385 | try
2386 | WriteString('Main', 'Lang', Lang);
2387 | finally
2388 | Free;
2389 | end;
2390 | end;
2391 |
2392 |
2393 | end.
2394 |
--------------------------------------------------------------------------------