Develop and Download Open Source Software

Browse CVS Repository

Contents of /enbanfukusyaya/EnbanFukusyaYa/DriveAccess/copydisc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.70 - (show annotations) (download) (as text)
Mon Nov 1 14:34:11 2010 UTC (13 years, 5 months ago) by bananajinn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.69: +19 -7 lines
File MIME type: text/x-csrc
*** empty log message ***

1 /**
2 * @file copydisc.c
3 * @brief 円盤を複写
4 * @author BananaJinn
5 * @version $Id: copydisc.c,v 1.69 2010/09/05 16:15:22 bananajinn Exp $
6 * 円盤複写屋
7 * Copyright (C) 2004-2006 BananaJinn<banana@mxh.mesh.ne.jp>.
8 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <time.h>
14 #if defined(WIN32)
15 # include <io.h>
16 # define snprintf _snprintf
17 #else
18 # include <pwd.h>
19 # include <unistd.h>
20 #endif
21 #include "mem.h"
22 #include "aspi.h"
23 #include "struct.h"
24 #include "cmd.h"
25 #include "ui.h"
26 #include "copydisc.h"
27 #include "cmdlog.h"
28 #include "netserver.h"
29 #include "text.h"
30 #include "log.h"
31 #include "discinfo.h"
32 #include "offsetiso.h"
33 #include "ebstring.h"
34 #include "cuesheet.h"
35
36 static DWORD g_SpeedData[10];
37 static int g_NumSpeedData=0;
38 static int g_MaxSpeedData=sizeof(g_SpeedData)/sizeof(DWORD);
39
40 /**
41 * 進捗速度データ初期化
42 */
43 static void InitSpeedData()
44 {
45 g_NumSpeedData=0;
46 }
47
48 /**
49 * 進捗速度と残り時間等を表示する
50 * @param[in] lba 現在記録アドレス
51 * @param[in] rest_blocks 残りブロック数
52 * @param[in] total_rest 全体の残り
53 * @param[in] src 読取装置構造体
54 * @param[in] dst 書込装置構造体
55 */
56 static void DispSpeed(DWORD lba, DWORD rest_blocks, DWORD total_rest,
57 CMDDRIVE *src, CMDDRIVE *dst)
58 {
59 double blocks_per_sec;
60 double curr_speed;
61 char *info = NULL;
62 DWORD rest_time;
63 int ret;
64 double buffer_capacity;
65
66 if(g_NumSpeedData >= g_MaxSpeedData){
67 memmove(&g_SpeedData[0], &g_SpeedData[1],
68 (g_MaxSpeedData-1)*sizeof(DWORD));
69 g_NumSpeedData--;
70 }
71 g_SpeedData[g_NumSpeedData] = lba;
72 g_NumSpeedData++;
73
74 if(g_NumSpeedData <= 1){
75 return;
76 }
77 blocks_per_sec = (double)(lba-g_SpeedData[0])/(g_NumSpeedData-1);
78 if(GetOption()->flags & OPFLG_DVD){
79 curr_speed = blocks_per_sec*2048/1024.0/1385;
80 }
81 else if(GetOption()->flags & OPFLG_BD){
82 curr_speed = blocks_per_sec*2048/1024.0/4495;
83 }
84 else{
85 curr_speed = blocks_per_sec*2352/1000.0/176.4;
86 }
87
88 info = EbStringNewWithFormat(MSG_SPEED_ /* "%.1fx"*/, curr_speed);
89 /* 残り時間計算(現在トラック) */
90 rest_time = (DWORD)(0.5+rest_blocks/blocks_per_sec);
91 info = EbStringAppendWithFormat(info,
92 MSG_REMAINS_ /*" remains=%d:%02d"*/,
93 (int)(rest_time/60), (int)(rest_time%60));
94 if(total_rest > 0){
95 /* 残り時間計算(全体) */
96 rest_time = (DWORD)(0.5+total_rest/blocks_per_sec);
97 info = EbStringAppendWithFormat(info,
98 MSG_TOTAL_REMAINS_ /*" toral_remains=%d:%02d"*/,
99 (int)(rest_time/60),
100 (int)(rest_time%60));
101 }
102
103 if(REALDRIVE(dst)){
104 ret = SendReadBufferCapacity(dst, 0);
105 if(ret == RET_OK){
106 buffer_capacity = 100-
107 100.0*Get4bytes(dst->data_buf+8)/Get4bytes(dst->data_buf+4);
108 info = EbStringAppendWithFormat(info,
109 MSG_BUFFER_ /* " buffer=%.1f%%" */,
110 buffer_capacity);
111 }
112 }
113 UIDispInfo(info);
114 if(src->type == CMDDRVTYPE_NET){
115 NAUIDispInfo(&src->u.net, info);
116 }
117 EbStringFree(info);
118 }
119
120
121 /**
122 * DVD-RW/+RWをフォーマット
123 * @param[in] drive 書込装置構造体
124 * @param[in] type フォーマットタイプ
125 * @param[in] size フォーマットサイズ
126 * @retval RET_OK 正常終了
127 * @retval RET_NG エラー
128 */
129 static int FormatDVD(CMDDRIVE *drive, BYTE type, DWORD size)
130 {
131 int ret;
132 WORD len, offset;
133 struct _FORMATCAPA_HEADER *fch;
134 struct _FORMATLIST_HEADER *fh;
135 struct _FORMATDESC *fd, fcd;
136 const char *message;
137
138 if(!REALDRIVE(drive))
139 return RET_OK;
140
141 /* Format Descriptor を得る */
142 ret = SendReadFormatCapacities(drive);
143 if(ret!=RET_OK){
144 DispCommandError(drive);
145 return ret;
146 }
147 fch = (struct _FORMATCAPA_HEADER *)drive->data_buf;
148 len = fch->list_len;
149 offset = sizeof(struct _FORMATCAPA_HEADER) + sizeof(struct _FORMATCURMAXDESC);
150 for(; offset<len; offset += sizeof(struct _FORMATDESC)){
151 fd = (struct _FORMATDESC *)(drive->data_buf + offset);
152 if(fd->format_type==type){
153 memcpy(&fcd, fd, sizeof(struct _FORMATDESC));
154 break;
155 }
156 }
157 if(offset>=len){
158 return RET_NG;
159 }
160
161 fh = (struct _FORMATLIST_HEADER *)drive->data_buf;
162 fd = (struct _FORMATDESC *)(drive->data_buf+sizeof(struct _FORMATLIST_HEADER));
163 memset(fh, 0, sizeof(struct _FORMATLIST_HEADER));
164 memcpy(fd, &fcd, sizeof(struct _FORMATDESC));
165 fh->fov = 1;
166 fh->immed = 1;
167 Set2bytes(fh->fmtdesc_len, sizeof(struct _FORMATDESC));
168 if(Get4bytes(fd->num_blocks) > size)
169 Set4bytes(fd->num_blocks, size);
170 len = sizeof(struct _FORMATLIST_HEADER) + sizeof(struct _FORMATDESC);
171 ret = SendFormatUnit(drive, 1, 0, FUFC_OTHER, len);
172 if(ret!=RET_OK){
173 DispCommandError(drive);
174 return ret;
175 }
176
177 if(type==FDFT_DVDQUICK || type==FDFT_DVDQUICKADD || type==FDFT_DVDQUICKGROW)
178 message = MSG_MIN_FORMAT; /* 高速初期化 */
179 else
180 message = MSG_FORMATTING; /* 初期化 */
181 ret = WaitProgress(drive, message, FALSE);
182 if(ret!=RET_OK){
183 if(ret==RET_CMDERR)
184 DispCommandError(drive);
185 return ret;
186 }
187
188 return RET_OK;
189 }
190
191 /**
192 * 必要があればフォーマット
193 * @param[in] drive 書込装置構造体
194 * @retval RET_OK 正常終了
195 * @retval RET_NG エラー
196 */
197 static int Formatting(CMDDRIVE *drive)
198 {
199 int ret;
200 struct _DISCINFO *di;
201 BYTE format_type = 0;
202
203 if(!REALDRIVE(drive)){
204 return RET_OK;
205 }
206
207 switch(drive->disc_type){
208 case DT_DVDPRW:
209 format_type = FDFT_DVDPRW;
210 break;
211 case DT_BDRE:
212 format_type = FDFT_BDRESPARE;
213 break;
214 }
215
216 if(format_type == 0){
217 return RET_OK;
218 }
219
220 ret = SendReadDiscInfo(drive);
221 if(ret!=RET_OK){
222 DispCommandError(drive);
223 return ret;
224 }
225
226 di = (struct _DISCINFO *)drive->data_buf;
227 if(di->bgformat_stat != BGFSTAT_NOTFORMATTED){
228 return RET_OK;
229 }
230
231 ret = FormatDVD(drive, format_type, 0xffffffff);
232 if(ret!=RET_OK){
233 return ret;
234 }
235
236 return RET_OK;
237 }
238
239 /**
240 * 必要があればディスク消去
241 * @param[in] drive 書込装置構造体
242 * @retval RET_OK 正常終了
243 * @retval RET_NG エラー
244 */
245 static int Blanking(CMDDRIVE *drive)
246 {
247 int ret;
248 struct _DISCINFO *di;
249
250 if(!REALDRIVE(drive)){
251 return RET_OK;
252 }
253
254 if(drive->disc_type==DT_DVDRWS || drive->disc_type==DT_DVDRWO){
255 if(GetOption()->dao==FALSE){
256 /* QuickFormat するので Blank 不要 */
257 return RET_OK;
258 }
259 }
260 if(drive->disc_type==DT_BDRE){
261 /* QuickFormat */
262 return RET_OK;
263 }
264 if(drive->disc_type==DT_DVDPRW){
265 /* これも不要 */
266 return RET_OK;
267 }
268 ret = SendReadDiscInfo(drive);
269 if(ret!=RET_OK){
270 DispCommandError(drive);
271 return ret;
272 }
273
274 di = (struct _DISCINFO *)drive->data_buf;
275 if(di->disc_status==DISCSTAT_EMPTY){
276 return RET_OK;
277 }
278 if(di->erasable==0){
279 /* "記録ディスクがブランクではないので複写できません。" */
280 UIDispMessage(MSG_NOT_BLANK, UIDMT_ERROR);
281 return RET_NG;
282 }
283
284 /* "記録ディスクがブランクではありません。高速消去しますか?" */
285 ret = UIDispMessage(MSG_NOT_BLANK_QUICK_BLANK, UIDMT_QUESTION);
286 if(ret==UIDMRET_CANCEL){
287 return RET_ABORT;
288 }
289
290 ret = BlankDisc(drive, 1);
291 if(ret!=RET_OK){
292 if(ret==RET_CMDERR){
293 DispCommandError(drive);
294 }
295 return ret;
296 }
297
298 return RET_OK;
299 }
300
301 /**
302 * 記録可能サイズ(ブロック数)を取得
303 * @param[in] drive 書込装置構造体
304 * @param[out] size_ret 記録可能サイズ
305 * @retval RET_OK 正常終了
306 * @retval RET_NG エラー
307 */
308 static int GetWritableSize(CMDDRIVE *drive, DWORD *size_ret)
309 {
310 int ret;
311 WORD track_num;
312 struct _DISCINFO *di;
313 struct _TRACKINFO *ti;
314
315 *size_ret = 0UL;
316 if(!REALDRIVE(drive))
317 return RET_OK;
318
319 ret = SendReadDiscInfo(drive);
320 if(ret!=RET_OK){
321 DispCommandError(drive);
322 return ret;
323 }
324 di = (struct _DISCINFO *)drive->data_buf;
325 track_num = (WORD)di->last_track_ls_msb<<8 | di->last_track_ls_lsb;
326 ret = SendReadTrackInfo(drive, track_num);
327 if(ret!=RET_OK){
328 DispCommandError(drive);
329 return ret;
330 }
331 ti = (struct _TRACKINFO *)drive->data_buf;
332 *size_ret = Get4bytes(ti->free_blocks);
333
334 return RET_OK;
335 }
336
337
338 /**
339 * セッションを閉じる
340 * @param[in] drive 書込装置構造体配列
341 * @param[in] num_drv 書込装置構造体数
342 * @retval RET_OK 正常終了
343 * @retval RET_NG エラー
344 */
345 static int CloseSession(CMDDRIVE *drive, int num_drv)
346 {
347 int ret;
348 int index;
349
350 if(!REALDRIVE(&drive[0])){
351 return RET_OK;
352 }
353
354 for(index=0; index<num_drv; index++){
355 if(drive[index].disc_type == DT_BDRE ||
356 drive[index].disc_type == DT_BDR ||
357 drive[index].disc_type == DT_DVDPR ||
358 drive[index].disc_type == DT_DVDPRW){
359 continue;
360 }
361 ret = SendCloseTrackSession(&drive[index], 1, CTST_CLOSESESSION, 0);
362 if(ret!=RET_OK){
363 DispCommandError(&drive[index]);
364 return ret;
365 }
366 }
367
368 index=num_drv-1;
369 ret = WaitProgress(&drive[index], MSG_CLOSE_SESSION/*"セッション閉め"*/, FALSE);
370 if(ret!=RET_OK){
371 if(ret==RET_CMDERR)
372 DispCommandError(&drive[index]);
373 return ret;
374 }
375
376 return RET_OK;
377 }
378
379 /**
380 * トラックを閉じる
381 * @param[in] drive 書込装置構造体配列
382 * @param[in] num_drv 書込装置構造体数
383 * @param[in] track_num トラック番号
384 * @retval RET_OK 正常終了
385 * @retval RET_NG エラー
386 */
387 static int ExecCloseTrack(CMDDRIVE *drive, int num_drv, WORD track_num)
388 {
389 int ret;
390 int index;
391
392 if(!REALDRIVE(&drive[0]))
393 return RET_OK;
394
395 for(index=0; index<num_drv; index++){
396 ret = SendCloseTrackSession(&drive[index], 1, CTST_CLOSETRACK, track_num);
397 if(ret!=RET_OK){
398 DispCommandError(&drive[index]);
399 return ret;
400 }
401 }
402
403 index = num_drv-1;
404 ret = WaitProgress(&drive[index], MSG_CLOSE_TRACK/*"トラック閉め"*/, FALSE);
405 if(ret!=RET_OK){
406 if(ret==RET_CMDERR)
407 DispCommandError(&drive[index]);
408 return ret;
409 }
410
411 return RET_OK;
412 }
413
414 /**
415 * 同期(Synchronize Cache)
416 * @param[in] drive 書込装置構造体
417 * @retval RET_OK 正常終了
418 * @retval RET_NG エラー
419 */
420 static int SyncCache(CMDDRIVE *drive)
421 {
422 int ret;
423
424 if(!REALDRIVE(drive))
425 return RET_OK;
426
427 ret = SendSynchronizeCache(drive, 1);
428 if(ret!=RET_OK){
429 DispCommandError(drive);
430 return ret;
431 }
432
433 ret = WaitProgress(drive, NULL, FALSE);
434 if(ret!=RET_OK){
435 if(ret==RET_CMDERR)
436 DispCommandError(drive);
437 return ret;
438 }
439
440 return RET_OK;
441 }
442
443 /**
444 * リザーブトラック
445 * @param[in] drive 書込装置構造体
446 * @param[in] size リザーブサイズ(ブロック数)
447 * @retval RET_OK 正常終了
448 * @retval RET_NG エラー
449 */
450 static int ReserveTrack(CMDDRIVE *drive, DWORD size)
451 {
452 int ret;
453
454 if(!REALDRIVE(drive))
455 return RET_OK;
456
457 DebugLog("Reserve Track/RZone. size=0x%08lx\n", size);
458 ret = SendReserveTrack(drive, size);
459 if(ret!=RET_OK){
460 DispCommandError(drive);
461 return ret;
462 }
463
464 return RET_OK;
465 }
466
467
468 /**
469 * 記録モード(WriteParametersPage(05h))設定
470 * @param[in] drive 書込装置構造体
471 * @param[in] discinfo ディスク情報
472 * @param[in] track_num トラック番号
473 * @retval RET_OK 正常終了
474 * @retval RET_NG エラー
475 */
476 static int SetWriteParametersPage(CMDDRIVE *drive, CPDISCINFO *discinfo,
477 WORD track_num, BOOL sao)
478 {
479 CPTRACKINFO *cpti;
480 struct _MODEPAGE05 *mp05;
481 WORD sess_num;
482 int ret;
483
484 if(!REALDRIVE(drive))
485 return RET_OK;
486
487 if(track_num==0)
488 track_num=1;
489 cpti = &discinfo->trackinfo[track_num-1];
490 sess_num = SESSION_NUMBER(&cpti->trackinfo);
491
492 /* 現在値を取得して必要な部分だけを書き換える */
493 ret = SendModeSense(drive, MSPC_CURRENT, 5);
494 if(ret!=RET_OK){
495 DispCommandError(drive);
496 return ret;
497 }
498 mp05 = (struct _MODEPAGE05 *)(drive->data_buf +
499 (drive->cmd_type==CMDDRVCTYPE_ATAPI ? 8 : 16));
500 if(drive->disc_type != DT_BDR &&
501 drive->disc_type != DT_BDRE){
502 if(DT_DVD_FAMILY(drive->disc_type)){
503 mp05->write_type = MP05WT_PACKET;
504 mp05->track_mode = MP05TM_DATA;
505 mp05->dbtype = MP05DBT_MODE1;
506 }
507 else{
508 mp05->track_mode = cpti->trackinfo.track_mode;
509 if(IS_TRACKMODE_DATA(mp05->track_mode)){
510 mp05->dbtype = cpti->mode2 ? MP05DBT_MIX : MP05DBT_MODE1;
511 mp05->write_type = cpti->trackinfo.packet ? MP05WT_PACKET : MP05WT_TAO;
512 }
513 else{
514 mp05->dbtype = MP05DBT_CDDA_2352;
515 mp05->write_type = MP05WT_TAO;
516 Set2bytes(mp05->audio_pause_len, cpti->pause_len);
517 }
518 }
519
520 mp05->BUFE = GetOption()->bufe;
521 mp05->test_write = GetOption()->test_write;
522 if(discinfo->sessions == sess_num){
523 /* 最終セッション時 */
524 mp05->multi_session = discinfo->disc_stat==DISCSTAT_COMPLETE ? 0 : 3;
525 }
526 else{
527 mp05->multi_session = 3;
528 }
529 mp05->fp = cpti->trackinfo.fp;
530 mp05->copy = cpti->trackinfo.copy;
531 mp05->session_format = discinfo->disc_type;
532 memcpy(mp05->packet_size, cpti->trackinfo.packet_size, 4);
533
534 if(sao){
535 mp05->write_type = MP05WT_SAO;
536 mp05->track_mode = MP05TM_DATA;
537 mp05->fp = 0;
538 Set4bytes(mp05->packet_size, 0UL);
539 }
540
541 /* MCN */
542 if(strlen((char *)discinfo->media_catalog_number)>0){
543 memcpy(mp05->media_cat_number, discinfo->media_catalog_number, 13);
544 mp05->mc_val = 1;
545 }
546 else{
547 memset(mp05->media_cat_number, 0, 13);
548 mp05->mc_val = 0;
549 }
550 /* ISRC */
551 if(strlen((char *)cpti->isrc)>0){
552 memcpy(mp05->ISRC, cpti->isrc, 12);
553 mp05->tc_val = 1;
554 }
555 else{
556 memset(mp05->ISRC, 0, 12);
557 mp05->tc_val = 0;
558 }
559 }
560
561 ret = SendModeSelect(drive, 5);
562 if(ret!=RET_OK){
563 DispCommandError(drive);
564 return ret;
565 }
566
567 return RET_OK;
568 }
569
570
571 /**
572 * VariablePacketのパケット長を取得する
573 * @param[in] drive 読取装置構造体
574 * @param[in] lba パケット開始アドレス
575 * @param[out] size_ret パケットサイズ(ブロック数)
576 * @retval RET_OK 正常終了
577 * @retval RET_NG エラー
578 */
579 static int GetVPSize(CMDDRIVE *drive, DWORD lba, DWORD *size_ret)
580 {
581 BYTE tmp[4];
582 DWORD start_lba;
583 DWORD len;
584 int ret;
585
586 if(!REALDRIVE(drive)){
587 if(drive->type == CMDDRVTYPE_ISO || drive->type == CMDDRVTYPE_MKISOFS){
588 return RET_OK;
589 }
590 else{
591 ret = ReadImageFile(&drive->u.image, tmp, 4, TRUE);
592 if(ret!=RET_OK)
593 return ret;
594 *size_ret = Get4bytes(tmp);
595 }
596 }
597 else{
598 start_lba = lba;
599 len = drive->bufsize / 2352;
600 ret=RET_OK;
601 while(TRUE){
602 while(TRUE){
603 if(UICheckAbort())
604 return RET_ABORT;
605 ret = SendReadCD(drive, lba, len);
606 if(ret!=RET_OK)
607 break;
608 lba += len;
609 }
610 if(len==1)
611 break;
612 len=1;
613 }
614 *size_ret = lba - start_lba;
615 }
616
617 return RET_OK;
618 }
619
620 /**
621 * VariablePacketのパケット長を設定(イメージファイルの場合のみ)
622 * @param[in] drive 書込装置構造体
623 * @param[in] size パケット長(ブロック数)
624 * @retval RET_OK 正常終了
625 * @retval RET_NG エラー
626 */
627 static int SetVPSize(CMDDRIVE *drive, DWORD size)
628 {
629 BYTE tmp[4];
630 int ret;
631
632 if(!REALDRIVE(drive)){
633 if(drive->type == CMDDRVTYPE_ISO || drive->type == CMDDRVTYPE_MKISOFS){
634 return RET_OK;
635 }
636 else{
637 Set4bytes(tmp, size);
638 ret = WriteImageFile(&drive->u.image, tmp, 4, TRUE);
639 if(ret!=RET_OK)
640 return ret;
641 }
642 }
643
644 return RET_OK;
645 }
646
647
648 /**
649 * @brief READリトライ回数設定(ModePage01h)
650 * @param[in] drive 対象ドライブ
651 * @param[in] count 設定するリトライ回数
652 * @param[out] current 設定前のリトライ回数
653 * @retval RET_OK 正常終了
654 * @retval RET_CMDERR コマンドエラー
655 * @retval RET_NG エラー
656 */
657 static int SetReadRetryCount(CMDDRIVE *drive, BYTE count, BYTE *current)
658 {
659 int ret;
660 struct _MODEPAGE01 *mp01;
661 ret = SendModeSense(drive, MSPC_CURRENT, 1);
662 if(ret != RET_OK){
663 return ret;
664 }
665 mp01 = (struct _MODEPAGE01 *)
666 (drive->data_buf + (drive->cmd_type==CMDDRVCTYPE_ATAPI ? 8 : 16));
667 if(current != NULL){
668 *current = mp01->rd_retry_count;
669 }
670 mp01->rd_retry_count = count;
671 ret = SendModeSelect(drive, 1);
672 if(ret != RET_OK){
673 return ret;
674 }
675
676 return RET_OK;
677 }
678
679 /**
680 * @brief READ実行
681 * @param[in] src 読み込みドライブ
682 * @param[in] lba 開始LBA
683 * @param[in] blocksize ブロックサイズ
684 * @param[in] len 読み込みブロック数
685 * @param[in] long_read LONGREADするかどうか
686 * @param[in] long_read_size LONGREAD時のサイズ
687 * @retval RET_OK 正常終了
688 * @retval RET_CMDERR コマンドエラー
689 * @retval RET_NG エラー
690 */
691 static int ExecRead(CMDDRIVE *src, DWORD lba, DWORD blocksize, DWORD len,
692 BOOL long_read, DWORD long_read_size)
693 {
694 int ret;
695 BYTE *sp, *dp;
696 DWORD cnt;
697
698 /* Read */
699 if(!REALDRIVE(src)){
700 if(src->type == CMDDRVTYPE_MKISOFS){
701 ret = MIFRead(&src->u.mkisofs, src->data_buf, blocksize*len);
702 }
703 else{
704 ret = ReadImageFile(&src->u.image, src->data_buf, blocksize*len,
705 (src->type==CMDDRVTYPE_IMAGE) ? TRUE:FALSE);
706 }
707 if(ret!=RET_OK)
708 return ret;
709 }
710 else{
711 if(long_read){
712 if(long_read_size){
713 /* LONGREAD送信 */
714 if(blocksize==2048){
715 ret = SendLongRead12(src, lba, (WORD)len, len*blocksize,
716 long_read_size);
717 }
718 else{
719 ret = SendLongReadCD(src, lba, len, long_read_size);
720 }
721 if(ret!=RET_OK){
722 return ret;
723 }
724 }
725 /* LONGREAD結果受信 */
726 if(blocksize==2048){
727 ret = SendLongRead12(src, lba, (WORD)len, len*blocksize, 0);
728 }
729 else{
730 ret = SendLongReadCD(src, lba, len, 0);
731 }
732 if(ret!=RET_OK){
733 return ret;
734 }
735 }
736 else{
737 /* 通常READ */
738 if(blocksize==2048){
739 ret = SendRead10(src, lba, (WORD)len, len*blocksize);
740 }
741 else{
742 ret = SendReadCD(src, lba, len);
743 }
744
745 if(ret!=RET_OK){
746 return ret;
747 }
748 }
749
750 if(blocksize==2332){
751 /* ReadCDで bs=2352 で読んだけれども、
752 必要なのは 2332 なのでバッファを詰める */
753 sp = dp = src->data_buf;
754 sp += 16; /* sync 16bytes */
755 for(cnt=0; cnt<len; cnt++){
756 memmove(dp, sp, 2332);
757 sp += 2352;
758 dp += 2332;
759 }
760 }
761 else if(blocksize==2336){
762 /* 2336 にバッファを詰める */
763 sp = dp = src->data_buf;
764 sp += 16; /* sync 16bytes */
765 for(cnt=0; cnt<len; cnt++){
766 memmove(dp, sp, 2336);
767 sp += 2352;
768 dp += 2336;
769 }
770 }
771 }
772
773 return RET_OK;
774 }
775
776
777 /**
778 * 指定アドレスの読取と記録を実行
779 * @param[in] src 読取装置構造体
780 * @param[in] dst 書込装置構造体配列
781 * @param[in] num_dst 書込装置構造体配列数
782 * @param[in] lba アドレス
783 * @param[in] blocksize 1ブロックのサイズ(バイト数)
784 * @param[in] len 読取&記録ブロック数
785 * @param[in] long_read ネットドライブのLONGREADを有効にするかどうか
786 * @param[in] long_read_size LONGREADを有効にする場合のサイズ
787 * @param[in] readin Lead-inかどうか
788 * @retval RET_OK 正常終了
789 * @retval RET_NG エラー
790 * @note blocksize は 2048/2332/2336/2352 だけ動作する。
791 * それ以外は対応していない。
792 */
793 static int ExecReadWrite(CMDDRIVE *src, CMDDRIVE *dst, int num_dst,
794 DWORD lba, DWORD blocksize, DWORD len,
795 BOOL long_read, DWORD long_read_size,
796 BOOL leadin, BOOL zerodata)
797 {
798 int ret=RET_OK;
799 int index;
800 int retry=0;
801 char *info = NULL;
802 BYTE rdretry_keep=0;
803 DWORD offset = 0;
804
805 if(zerodata){
806 memset(src->data_buf, 0, len*blocksize);
807 }
808 else{
809 if(GetOption()->outside){
810 offset = GetOffset();
811 }
812 for(retry=0; retry<=32; retry++){
813 if(retry > 0){
814 if(rdretry_keep == 0){
815 /* ドライブのREADリトライ回数を増やす */
816 ret = SetReadRetryCount(src, 0xff, &rdretry_keep);
817 if(ret != RET_OK){
818 rdretry_keep=0;
819 }
820 }
821 if((retry&1)==0 && lba>0){
822 if((retry&3)==0 && lba>16){
823 ExecRead(src, (lba-offset)/16*16-16, blocksize, 1, FALSE, 0);
824 }
825 else{
826 ExecRead(src, lba-offset-1, blocksize, 1, FALSE, 0);
827 }
828 }
829 if(retry>=16 && (retry&3)==0){
830 /* 再スピンアップさせてみたりする */
831 UIDispInfo(MSG_SPINUP/*"再回転"*/);
832 if(UICheckAbort()){
833 ret = RET_ABORT;
834 break;
835 }
836 SendStartStop(src, 1, 0, 0);
837 #ifdef WIN32
838 Sleep(1000);
839 #else
840 sleep(1);
841 #endif
842 }
843 info = EbStringNewWithFormat(
844 MSG_RETRY_ /*"再読込回数:%d"*/, retry);
845 UIDispInfo(info);
846 info = EbStringFree(info);
847 if(UICheckAbort()){
848 ret = RET_ABORT;
849 break;
850 }
851 }
852 ret = ExecRead(src, lba-offset, blocksize, len, long_read,
853 long_read_size);
854 if(ret==RET_OK){
855 break;
856 }
857 else if(ret!=RET_CMDERR){
858 break;
859 }
860 }
861 if(rdretry_keep > 0){
862 /* ドライブのREADリトライ回数設定を戻す */
863 SetReadRetryCount(src, rdretry_keep, NULL);
864 }
865 if(ret!=RET_OK){
866 DispCommandError(src);
867 return ret;
868 }
869 }
870
871 if(GetOption()->outside){
872 ret = OffsetISO(src->data_buf, lba, blocksize, len);
873 if(ret != RET_OK){
874 return ret;
875 }
876 }
877
878 /* Write */
879 if(!REALDRIVE(&dst[0])){
880 if(!zerodata){
881 ret = WriteImageFile(&dst->u.image, dst->data_buf, len*blocksize,
882 (dst->type==CMDDRVTYPE_IMAGE) ? TRUE:FALSE);
883 if(ret!=RET_OK)
884 return ret;
885 }
886 }
887 else{
888 if(leadin && (num_dst>1)){
889 /*
890 * SAOでLead-in記録開始する場合、複数記録装置で同時に
891 * Lead-inを記録開始するようにする。
892 */
893 BOOL *started = (BOOL *)MemNew(sizeof(BOOL)*num_dst);
894 int start_count=0;
895 if(started==NULL){
896 return RET_MEMERR;
897 }
898 memset(started, 0, sizeof(BOOL)*num_dst);
899 while(start_count<num_dst){
900 for(index=0; index<num_dst; index++){
901 if(started[index]){
902 continue;
903 }
904 ret = SendWrite10(&dst[index], lba, (WORD)len, len*blocksize,
905 FALSE);
906 if(ret==RET_CMDERR){
907 if((SD_SENSEKEY(&dst[index])==0x02) &&
908 (SD_ASC(&dst[index])==0x04) &&
909 (SD_ASCQ(&dst[index])==0x08)){
910 continue;
911 }
912 }
913 if(ret!=RET_OK){
914 DispCommandError(&dst[index]);
915 MemFree(started);
916 return ret;
917 }
918 started[index] = TRUE;
919 start_count++;
920 }
921 }
922 MemFree(started);
923 }
924 else{
925 /* Lead-in記録開始などは意識せずに普通に記録 */
926 for(index=0; index<num_dst; index++){
927 ret = SendWrite10(&dst[index], lba, (WORD)len, len*blocksize, TRUE);
928 if(ret!=RET_OK){
929 DispCommandError(&dst[index]);
930 return ret;
931 }
932 }
933
934 }
935 }
936
937 return RET_OK;
938 }
939
940
941 /**
942 * トラックの開始
943 * @param[in] drive 書込装置構造体
944 * @param[in] discinfo ディスク情報
945 * @param[in] track_num トラック番号
946 * @retval RET_OK 正常終了
947 * @retval RET_NG エラー
948 */
949 static int OpenTrack(CMDDRIVE *drive, CPDISCINFO *discinfo, WORD track_num)
950 {
951 int ret;
952
953 if(REALDRIVE(drive)){
954 if(DT_CD_FAMILY(drive->disc_type)){
955 ret = SetWriteParametersPage(drive, discinfo, track_num,
956 !discinfo->trackinfo[track_num-1].tao );
957 if(ret!=RET_OK)
958 return ret;
959 }
960 else{
961 if(drive->disc_type==DT_DVDR ||
962 drive->disc_type==DT_DVDRWS || drive->disc_type==DT_DVDRWO){
963 /* DVD-R/-RW */
964 if(drive->disc_type!=DT_DVDR && GetOption()->dao==FALSE){
965 ret = FormatDVD(drive,
966 (BYTE)(track_num==1 ? FDFT_DVDQUICK : FDFT_DVDQUICKADD),
967 0x00000000);
968 }
969 else{
970 ret = SetWriteParametersPage(drive, discinfo, track_num,
971 GetOption()->dao);
972 }
973 if(ret!=RET_OK)
974 return ret;
975 }
976 }
977 }
978
979 return RET_OK;
980 }
981
982
983 /**
984 * トラックを閉じる
985 * @param[in] drive 書込装置構造体
986 * @param[in] discinfo ディスク情報
987 * @param[in] track_num トラック番号
988 * @retval RET_OK 正常終了
989 * @retval RET_NG エラー
990 */
991 static int CloseTrack(CMDDRIVE *drive, int num_drv,
992 CPDISCINFO *discinfo, WORD track_num)
993 {
994 CPTRACKINFO *cpti;
995 int ret;
996
997 if(REALDRIVE(&drive[0])){
998 cpti = &discinfo->trackinfo[track_num-1];
999 if(cpti->trackinfo.packet && cpti->trackinfo.nwa_valid==0 &&
1000 Get4bytes(cpti->trackinfo.free_blocks)==0 &&
1001 drive[0].disc_type!=DT_DVDRWS &&
1002 drive[0].disc_type!=DT_DVDRWO &&
1003 GetOption()->dao==FALSE){
1004 ret = ExecCloseTrack(drive, num_drv, track_num);
1005 if(ret!=RET_OK)
1006 return ret;
1007 }
1008 }
1009
1010 return RET_OK;
1011 }
1012
1013 /**
1014 * CD-TEXT情報のデータをバッファに作成する
1015 * @param[out] buf 格納するバッファ
1016 * @param[in] fillsize 作成するサイズ(バイト数)
1017 * @param[in] cdtext CD-TEXT情報
1018 * @param[in] cdtext_size CD-TEXT情報バイト数
1019 * @param[in] cdtext_offset 参照開始オフセット(前回の続きを行う際に必要)
1020 * @retval RET_OK 正常終了
1021 * @retval RET_NG エラー
1022 */
1023 static void MakeCDTextBuffer(BYTE *buf, DWORD fillsize,
1024 BYTE *cdtext, DWORD cdtext_size, DWORD *cdtext_offset)
1025 {
1026 DWORD cdtext_restsize;
1027 DWORD copysize;
1028
1029 while(fillsize>0){
1030 cdtext_restsize = cdtext_size - (*cdtext_offset);
1031 if(fillsize < cdtext_restsize){
1032 copysize = fillsize;
1033 }
1034 else{
1035 copysize = cdtext_restsize;
1036 }
1037
1038 memcpy(buf, cdtext+(*cdtext_offset), copysize);
1039 buf += copysize;
1040 fillsize -= copysize;
1041 *cdtext_offset += copysize;
1042 if(*cdtext_offset >= cdtext_size)
1043 *cdtext_offset = 0;
1044 }
1045 }
1046
1047 /*
1048 * このCRCの計算はサッパリ解りません。
1049 * crc.h に書いてある通り、cdrecord 2.0 からパクってきてます。
1050 */
1051 #define LOCAL
1052 #define UInt16_t WORD
1053 #include "crc.h"
1054 static void CalcCDTextCRC(CPDISCINFO *discinfo)
1055 {
1056 int i, j;
1057 WORD crc;
1058
1059 for(i=0; i<discinfo->cdtext_size; i+=18){
1060 crc = 0;
1061 for(j=0; j<16; j++){
1062 crc = (crc<<BPB) ^ crctab[(crc>>(BPW-BPB)) ^ discinfo->cdtext[i+j]];
1063 }
1064 crc = crc ^ 0xFFFF;
1065 discinfo->cdtext[i+16] = (BYTE)(crc>>8);
1066 discinfo->cdtext[i+17] = (BYTE)(crc);
1067 }
1068 }
1069
1070
1071 /**
1072 * CD-TEXT記録
1073 * @param[in] drive 書込装置構造体配列
1074 * @param[in] num_drv 書込装置構造体配列数
1075 * @param[in] discinfo ディスク情報
1076 * @retval RET_OK 正常終了
1077 * @retval RET_NG エラー
1078 */
1079 static int WriteCDText(CMDDRIVE *drive, int num_drv, CPDISCINFO *discinfo)
1080 {
1081 int ret = RET_OK;
1082 struct _DISCINFO *di;
1083 DWORD lba;
1084 DWORD rest_blocks, total_blocks, len, deflen;
1085 BYTE *converted_cdtext=NULL;
1086 DWORD converted_cdtext_size;
1087 DWORD cdtext_offset=0;
1088 long t1, t2;
1089 DWORD i;
1090 DWORD *leadin_start;
1091 DWORD max_leadin;
1092 int index;
1093
1094 if(!REALDRIVE(&drive[0]))
1095 return RET_OK;
1096
1097 leadin_start = (DWORD *)MemNew(sizeof(DWORD)*num_drv);
1098 if(leadin_start == NULL){
1099 return RET_MEMERR;
1100 }
1101 /* Lead-in開始時間を取得 */
1102 max_leadin = 0;
1103 for(index=0; index<num_drv; index++){
1104 ret = SendReadDiscInfo(&drive[index]);
1105 if(ret!=RET_OK){
1106 DispCommandError(&drive[index]);
1107 MemFree(leadin_start);
1108 return ret;
1109 }
1110 di = (struct _DISCINFO *)drive[index].data_buf;
1111 leadin_start[index] = MSF2LBA(di->last_lead_in[1],
1112 di->last_lead_in[2],
1113 di->last_lead_in[3], FALSE);
1114 if(max_leadin < leadin_start[index]){
1115 max_leadin = leadin_start[index];
1116 }
1117 }
1118 /*
1119 * 挿入されているディスクの中で、一番Lead-in開始時間が
1120 * 遅いものに合わせる。
1121 */
1122 for(index=0; index<num_drv; index++){
1123 len = (drive[index].bufsize-1)/96;
1124 lba = leadin_start[index];
1125 rest_blocks = (DWORD)(max_leadin-lba);
1126 memset(drive[index].data_buf, 0, drive[index].bufsize);
1127 while(rest_blocks > 0){
1128 if(len > rest_blocks){
1129 len = rest_blocks;
1130 }
1131 ret = SendWrite10(&drive[index], lba, (WORD)len, len*96, TRUE);
1132 if(ret!=RET_OK){
1133 DispCommandError(&drive[index]);
1134 MemFree(leadin_start);
1135 return ret;
1136 }
1137 rest_blocks -= len;
1138 lba += len;
1139 }
1140 }
1141 MemFree(leadin_start);
1142
1143 /* CD-TEXTデータ作成 */
1144 CalcCDTextCRC(discinfo);
1145 converted_cdtext_size = (discinfo->cdtext_size * 4+2)/3;
1146 converted_cdtext = MemNew(converted_cdtext_size);
1147 if(converted_cdtext==NULL)
1148 return RET_MEMERR;
1149 for(i=0; i<converted_cdtext_size/4; i++){
1150 /* 8bit 6bit
1151 * aaaaaaaa 00aaaaaa
1152 * bbbbbbbb => 00aabbbb
1153 * cccccccc 00bbbbcc
1154 * 00cccccc
1155 */
1156 converted_cdtext[i*4+0] = (discinfo->cdtext[i*3+0]>>2) & 0x3f;
1157 converted_cdtext[i*4+1] = ((discinfo->cdtext[i*3+0]<<4) & 0x30) |
1158 ((discinfo->cdtext[i*3+1]>>4) & 0x0f);
1159 converted_cdtext[i*4+2] = ((discinfo->cdtext[i*3+1]<<2) & 0x3c) |
1160 ((discinfo->cdtext[i*3+2]>>6) & 0x03);
1161 converted_cdtext[i*4+3] = (discinfo->cdtext[i*3+2]>>0) & 0x3f;
1162 }
1163
1164 lba = max_leadin;
1165 rest_blocks = total_blocks = (DWORD)(-150-lba);
1166
1167 /*
1168 * 1度に転送できるブロック数を計算(1ブロック=96bytes)
1169 * 但し、全ドライブのバッファサイズが同じとする。
1170 */
1171 deflen = (drive->bufsize-1)/96;
1172
1173 /* 画面表示 */
1174 UIMeter2Initialize("CD-TEXT");
1175 if(drive->type==CMDDRVTYPE_NET){
1176 NAUIMeter2Initialize(&drive->u.net, "CD-TEXT");
1177 }
1178 t1 = t2 = time(NULL);
1179
1180 while(rest_blocks>0){
1181 t2 = time(NULL);
1182 if(t1!=t2){
1183 UIMeter2Update((float)(total_blocks-rest_blocks)*100/total_blocks);
1184 if(drive->type==CMDDRVTYPE_NET){
1185 NAUIMeter2Update(&drive->u.net,
1186 (float)(total_blocks-rest_blocks)*100/total_blocks);
1187 }
1188 t1=t2;
1189 }
1190 if(UICheckAbort()){
1191 ret = RET_ABORT;
1192 break;
1193 }
1194
1195 len = deflen < rest_blocks ? deflen : rest_blocks;
1196 for(index=0; index<num_drv; index++){
1197 MakeCDTextBuffer(drive[index].data_buf, len*96,
1198 converted_cdtext, converted_cdtext_size, &cdtext_offset);
1199 ret = SendWrite10(&drive[index], lba, (WORD)len, len*96, TRUE);
1200 if(ret!=RET_OK){
1201 DispCommandError(&drive[index]);
1202 break;
1203 }
1204 }
1205 if(ret!=RET_OK){
1206 break;
1207 }
1208 lba += len;
1209 rest_blocks -= len;
1210 }
1211
1212 MemFree(converted_cdtext);
1213
1214 return ret;
1215 }
1216
1217
1218 /**
1219 * 読み書きのループ
1220 * @param[in] src 読取装置構造体
1221 * @param[in] dst 書込装置構造体配列
1222 * @param[in] num_dst 書込装置構造体配列数
1223 * @param[in] lba 開始アドレス
1224 * @param[in] blocks 処理ブロック数
1225 * @param[in] deflen デフォルト転送単位(ブロック数)
1226 * @param[in] blocksize ブロックサイズ(バイト数)
1227 * @param[in] vp_track VariablePacketかどうか
1228 * @param[in] discinfo ディスク情報
1229 * @param[in] sao Session at once かどうか
1230 * @param[in] leadin Lead-in の記録かどうか
1231 * @retval RET_OK 正常終了
1232 * @retval RET_NG エラー
1233 */
1234 static int WriteLoop(CMDDRIVE *src, CMDDRIVE *dst, int num_dst,
1235 DWORD lba, DWORD blocks, DWORD deflen,
1236 DWORD blocksize, BOOL vp_track, CPDISCINFO *discinfo,
1237 BOOL sao, BOOL leadin, BOOL zerodata)
1238 {
1239 int ret;
1240 DWORD rest_blocks, total_blocks, len;
1241 DWORD long_read_rest=0;
1242 DWORD long_read_size=0;
1243 BOOL long_read=FALSE;
1244 BOOL long_read_now=FALSE;
1245 long t1, t2;
1246 float percent_total;
1247 int index;
1248
1249 InitSpeedData();
1250 rest_blocks = total_blocks = blocks;
1251
1252 if(src->type == CMDDRVTYPE_NET){
1253 /* LONG READ する */
1254 long_read_size = (0x00ffffffUL/deflen)*deflen;
1255 long_read = TRUE;
1256 }
1257
1258 t1 = t2 = time(NULL);
1259 ret = RET_OK;
1260 while(rest_blocks>0 && ret==RET_OK){
1261 if(vp_track){
1262 ret = GetVPSize(src, lba, &blocks);
1263 if(ret!=RET_OK)
1264 break;
1265 for(index=0; index<num_dst; index++){
1266 ret = SetVPSize(&dst[index], blocks);
1267 if(ret!=RET_OK)
1268 break;
1269 }
1270 if(ret!=RET_OK)
1271 break;
1272 }
1273 else
1274 blocks = rest_blocks;
1275
1276 while(blocks>0){
1277 t2 = time(NULL);
1278 if(t1!=t2){
1279 percent_total = (float)lba*100/discinfo->last_addr;
1280 if(GetOption()->on_the_fly==FALSE)
1281 percent_total = percent_total/2 +
1282 (dst->type!=CMDDRVTYPE_IMAGE ? 50 : 0);
1283 UIMeter1Update(percent_total);
1284 UIMeter2Update((float)(total_blocks-rest_blocks)*100/total_blocks);
1285 if(src->type==CMDDRVTYPE_NET){
1286 NAUIMeter1Update(&src->u.net, percent_total);
1287 NAUIMeter2Update(&src->u.net,
1288 (float)(total_blocks-rest_blocks)*100/total_blocks);
1289 }
1290 /* 速度、残り時間を表示 */
1291 DispSpeed(lba, rest_blocks,
1292 discinfo->tracks != 1 ? (discinfo->last_addr-lba) : 0,
1293 src, dst);
1294 t1=t2;
1295 }
1296 if(UICheckAbort()){
1297 ret = RET_ABORT;
1298 break;
1299 }
1300 len = deflen>blocks ? blocks : deflen;
1301 if(long_read && !zerodata){
1302 long_read_now = FALSE;
1303 if(long_read_rest == 0){
1304 /* LONGREAD送信 */
1305 long_read_now = TRUE;
1306 if(long_read_size > blocks){
1307 long_read_size = blocks;
1308 }
1309 long_read_rest = long_read_size;
1310 }
1311 }
1312 ret = ExecReadWrite(src, dst, num_dst, lba, blocksize, len,
1313 long_read, (long_read_now ? long_read_size : 0),
1314 leadin, zerodata);
1315 if(ret!=RET_OK)
1316 break;
1317 lba += len;
1318 blocks -= len;
1319 rest_blocks -= len;
1320 if(long_read){
1321 long_read_rest -= len;
1322 }
1323 }
1324
1325 percent_total = (float)lba*100/discinfo->last_addr;
1326 if(GetOption()->on_the_fly==FALSE)
1327 percent_total = percent_total/2 +
1328 (dst->type!=CMDDRVTYPE_IMAGE ? 50 : 0);
1329 UIMeter1Update(percent_total);
1330 UIMeter2Update((float)(total_blocks-rest_blocks)*100/total_blocks);
1331 if(src->type==CMDDRVTYPE_NET){
1332 NAUIMeter1Update(&src->u.net, percent_total);
1333 NAUIMeter2Update(&src->u.net,
1334 (float)(total_blocks-rest_blocks)*100/total_blocks);
1335 }
1336 if(ret==RET_OK){
1337 if(!sao){
1338 for(index=0; index<num_dst; index++){
1339 ret = SyncCache(&dst[index]);
1340 if(ret!=RET_OK)
1341 break;
1342 }
1343 }
1344 }
1345
1346 if(vp_track){
1347 lba += 7;
1348 if(rest_blocks>7)
1349 rest_blocks -= 7;
1350 if(rest_blocks<7)
1351 rest_blocks=0;
1352 }
1353 }
1354
1355 UIDispInfo("");
1356 if(src->type==CMDDRVTYPE_NET){
1357 NAUIDispInfo(&src->u.net, "");
1358 }
1359 return ret;
1360 }
1361
1362 /**
1363 * 1トラックの複写
1364 * @param[in] src 読取装置構造体
1365 * @param[in] dst 書込装置構造体配列
1366 * @param[in] num_dst 書込装置構造体配列数
1367 * @param[in] discinfo ディスク情報
1368 * @param[in] track_num トラック番号
1369 * @retval RET_OK 正常終了
1370 * @retval RET_NG エラー
1371 */
1372 static int CopyTrack(CMDDRIVE *src, CMDDRIVE *dst, int num_dst,
1373 CPDISCINFO *discinfo, WORD track_num)
1374 {
1375 int ret;
1376 BOOL vp_track=FALSE;
1377 CPTRACKINFO *cpti = &discinfo->trackinfo[track_num-1];
1378 DWORD len;
1379 DWORD blocksize;
1380 DWORD blocks;
1381 DWORD lba;
1382 char *msgbuf = NULL;
1383 int index;
1384
1385 /* VariablePacketかどうか */
1386 if(cpti->trackinfo.packet && Get4bytes(cpti->trackinfo.packet_size)==0)
1387 vp_track=TRUE;
1388 /* 記録ブロック数 */
1389 if(cpti->trackinfo.nwa_valid){
1390 blocks = Get4bytes(cpti->trackinfo.next_writable_addr) -
1391 Get4bytes(cpti->trackinfo.track_start);
1392 }
1393 else{
1394 blocks = Get4bytes(cpti->trackinfo.track_size) -
1395 Get4bytes(cpti->trackinfo.free_blocks);
1396 }
1397 /* ブロックサイズ */
1398 if(DT_DVD_FAMILY(dst->disc_type)){
1399 blocksize = 2048;
1400 /* 1回に転送するブロック数 */
1401 len = 16;
1402 }
1403 else{
1404 if(IS_TRACKMODE_DATA(cpti->trackinfo.track_mode)){
1405 blocksize = cpti->mode2 ? 2332 : 2048;
1406 }
1407 else{
1408 blocksize = 2352;
1409 }
1410 /* 1回に転送できるブロック数 */
1411 if(REALDRIVE(src)){
1412 len = src->bufsize / (blocksize==2048 ? 2048 : 2352);
1413 }
1414 else if(REALDRIVE(&dst[0])){
1415 len = dst->bufsize / (blocksize==2048 ? 2048 : 2352);
1416 }
1417 else{
1418 len = 16;
1419 }
1420 }
1421 if(blocksize*len >= 0x10000){
1422 /* wnaspi32.dll では 64KB 転送できないらしいので */
1423 len = 0xffff/blocksize;
1424 }
1425
1426 /* 記録アドレス */
1427 lba = Get4bytes(cpti->trackinfo.track_start);
1428
1429 for(index=0; index<num_dst; index++){
1430 ret = OpenTrack(&dst[index], discinfo, track_num);
1431 if(ret!=RET_OK)
1432 return ret;
1433 }
1434
1435 /* 画面表示 */
1436 msgbuf = EbStringNewWithFormat(MSG_TRACK_ /*"トラック%d"*/, track_num);
1437 UIMeter2Initialize(msgbuf);
1438 if(src->type==CMDDRVTYPE_NET){
1439 NAUIMeter2Initialize(&src->u.net, msgbuf);
1440 }
1441 msgbuf = EbStringFree(msgbuf);
1442
1443 if(Get4bytes(cpti->trackinfo.free_blocks) > 0){
1444 for(index=0; index<num_dst; index++){
1445 ret = ReserveTrack(&dst[index],
1446 Get4bytes(cpti->trackinfo.track_size));
1447 if(ret!=RET_OK)
1448 return ret;
1449 }
1450 }
1451
1452 if(GetOption()->outside
1453 && (discinfo->outside_offset > 0)
1454 && (track_num == 1)){
1455 /* ダミー1stトラックの記録 */
1456 ret = WriteLoop(src, dst, num_dst, lba, blocks, len, blocksize,
1457 vp_track, discinfo, FALSE, FALSE, TRUE);
1458 }
1459 else{
1460 ret = WriteLoop(src, dst, num_dst, lba, blocks, len, blocksize,
1461 vp_track, discinfo, FALSE, FALSE, FALSE);
1462 }
1463 if(ret!=RET_OK){
1464 /* エラーの場合は、SyncCacheして終了 */
1465 for(index=0; index<num_dst; index++){
1466 SyncCache(&dst[index]);
1467 }
1468 }
1469 else{
1470 ret = CloseTrack(dst, num_dst, discinfo, track_num);
1471 }
1472
1473 return ret;
1474 }
1475
1476
1477 /**
1478 * 1セッション複写
1479 * @param[in] src 読取装置構造体
1480 * @param[in] dst 書込装置構造体配列
1481 * @param[in] num_dst 書込装置構造体配列数
1482 * @param[in] discinfo ディスク情報
1483 * @param[out] track_num_ret 次のトラック番号
1484 * @retval RET_OK 正常終了
1485 * @retval RET_NG エラー
1486 */
1487 static int CopySession(CMDDRIVE *src, CMDDRIVE *dst, int num_dst,
1488 CPDISCINFO *discinfo,
1489 WORD *track_num_ret)
1490 {
1491 int ret=RET_OK;
1492 WORD track_num = *track_num_ret;
1493 struct _CUESHEET *cs=NULL, *csp;
1494 int num_cs = 0;
1495 BOOL done=FALSE;
1496 DWORD lba, blocks;
1497 DWORD translen, blocksize;
1498 char *msgbuf = NULL;
1499 int index;
1500 BOOL leadin=FALSE;
1501
1502 for(index=0; index<num_dst; index++){
1503 if(cs!=NULL){
1504 MemFree(cs);
1505 cs=NULL;
1506 }
1507 ret = SetWriteParametersPage(&dst[index], discinfo, track_num, TRUE);
1508 if(ret!=RET_OK)
1509 return ret;
1510
1511 ret = CreateCueSheet(&dst[index], discinfo, track_num,
1512 &cs, &num_cs, TRUE);
1513 if(ret!=RET_OK)
1514 return ret;
1515
1516 if(REALDRIVE(&dst[index])){
1517 ret = SendSendCueSheet(&dst[index], cs,
1518 num_cs*sizeof(struct _CUESHEET));
1519 if(ret!=RET_OK){
1520 MemFree(cs);
1521 cs = NULL;
1522 if(!(track_num==1 && discinfo->cdtext_size>0)){
1523 DispCommandError(&dst[index]);
1524 return ret;
1525 }
1526 /* CD-TEXTを無効にしてリトライ */
1527 ret = CreateCueSheet(&dst[index], discinfo, track_num,
1528 &cs, &num_cs, FALSE);
1529 if(ret!=RET_OK)
1530 return ret;
1531 ret = SendSendCueSheet(&dst[index], &cs,
1532 num_cs*sizeof(struct _CUESHEET));
1533 if(ret!=RET_OK){
1534 MemFree(cs);
1535 cs = NULL;
1536 DispCommandError(&dst[index]);
1537 return ret;
1538 }
1539 }
1540 }
1541 }
1542
1543 for(csp=cs; !done; csp++){
1544 if((csp->ctladr & 0x0f)!=CSADR_NORMAL)
1545 continue;
1546 if(csp->tno==0xaa){
1547 done=TRUE;
1548 continue;
1549 }
1550 if(csp->dataform==0x24 || csp->dataform==0x14 || csp->dataform==0x01){
1551 /* データ転送ナシ */
1552 if(csp->dataform==0x01){
1553 if(REALDRIVE(dst)){
1554 UIDispInfo(MSG_WRITING_LEAD_IN /*"内側記録中"*/);
1555 leadin = TRUE;
1556 }
1557 }
1558 continue;
1559 }
1560 if(csp->dataform==0x41){
1561 /* CD-TEXT */
1562 if(REALDRIVE(dst)){
1563 UIDispInfo(MSG_WRITING_CDTEXT /*"CD-TEXT記録中"*/);
1564 }
1565 ret = WriteCDText(dst, num_dst, discinfo);
1566 if(ret!=RET_OK)
1567 break;
1568 continue;
1569 }
1570 lba = MSF2LBA(csp->min, csp->sec, csp->frame, FALSE);
1571 #if 1
1572 if(csp->index==0){
1573 blocks = MSF2LBA((csp+1)->min, (csp+1)->sec, (csp+1)->frame, FALSE) -lba;
1574 }
1575 else{
1576 blocks = Get4bytes(discinfo->trackinfo[csp->tno-1].trackinfo.track_size);
1577 }
1578 #else /* CueSheetから求める場合は、ISRCを無視して有効なMSGを検索する必要がある */
1579 blocks = MSF2LBA((csp+1)->min, (csp+1)->sec, (csp+1)->frame, FALSE) - lba;
1580 #endif
1581 switch(csp->dataform){
1582 case 0x20:
1583 blocksize = 2336;
1584 break;
1585 case 0x10:
1586 blocksize = 2048;
1587 break;
1588 default:
1589 blocksize = 2352;
1590 }
1591 if(REALDRIVE(src))
1592 translen = src->bufsize / (blocksize==2048 ? 2048 : 2352);
1593 else
1594 translen = dst[0].bufsize / (blocksize==2048 ? 2048 : 2352);
1595 if(blocksize*translen >= 0x10000){
1596 /* wnaspi32.dll では 64KB 転送できないらしいので */
1597 translen = 0xffff / (blocksize==2048 ? 2048 : 2352);
1598 }
1599
1600 /* 画面表示 */
1601 msgbuf = EbStringNewWithFormat(MSG_TRACK_ /*"トラック%d"*/, csp->tno);
1602 UIMeter2Initialize(msgbuf);
1603 if(src->type==CMDDRVTYPE_NET){
1604 NAUIMeter2Initialize(&src->u.net, msgbuf);
1605 }
1606 msgbuf = EbStringFree(msgbuf);
1607
1608 if(GetOption()->outside
1609 && (discinfo->outside_offset > 0)
1610 && (track_num == 1)
1611 && !leadin
1612 && csp->index == 1){
1613 /* ダミー1stトラックの記録 */
1614 ret = WriteLoop(src, dst, num_dst,
1615 lba, blocks, translen, blocksize,
1616 FALSE, discinfo, TRUE, FALSE, TRUE);
1617 }
1618 else{
1619 ret = WriteLoop(src, dst, num_dst,
1620 lba, blocks, translen, blocksize,
1621 FALSE, discinfo, TRUE, leadin,
1622 (csp->index==0));
1623 }
1624 if(ret!=RET_OK){
1625 break;
1626 }
1627 *track_num_ret = csp->tno;
1628 leadin = FALSE;
1629 }
1630
1631 for(index=0; index<num_dst; index++){
1632 SyncCache(&dst[index]);
1633 }
1634
1635 (*track_num_ret)++;
1636
1637 MemFree(cs);
1638 return ret;
1639 }
1640
1641
1642 /**
1643 * DAO(Disc at once)で複写
1644 * @param[in] src 読取装置構造体
1645 * @param[in] dst 書込装置構造体配列
1646 * @param[in] num_dst 書込装置構造体配列数
1647 * @param[in] discinfo ディスク情報
1648 * @retval RET_OK 正常終了
1649 * @retval RET_NG エラー
1650 */
1651 static int CopyDAO(CMDDRIVE *src, CMDDRIVE *dst, int num_dst,
1652 CPDISCINFO *discinfo)
1653 {
1654 int disc_type;
1655 int ret;
1656 int index;
1657
1658 if(!REALDRIVE(src) && !REALDRIVE(&dst[0]))
1659 return RET_NG;
1660
1661 if(REALDRIVE(src))
1662 disc_type = src->disc_type;
1663 else
1664 disc_type = dst[0].disc_type;
1665
1666 if(DT_CD_FAMILY(disc_type)){
1667 /* もはやここには来ない */
1668 UIDispMessage(MSG_CANT_WRITE_CD_DAO
1669 /*"残念ながら、CD の DAO はできません。"*/,
1670 UIDMT_ERROR);
1671 return RET_ABORT;
1672 }
1673 else{
1674 /* DVD-R/-RW */
1675 for(index=0; index<num_dst; index++){
1676 ret = SetWriteParametersPage(&dst[index], discinfo, 1,
1677 GetOption()->dao);
1678 if(ret!=RET_OK)
1679 return ret;
1680 ret = ReserveTrack(&dst[index],
1681 Get4bytes(discinfo->trackinfo[0].trackinfo.track_size));
1682 if(ret!=RET_OK)
1683 return ret;
1684 }
1685
1686 ret = CopyTrack(src, dst, num_dst, discinfo, 1);
1687 if(ret!=RET_OK)
1688 return ret;
1689 }
1690
1691 return RET_OK;
1692 }
1693
1694
1695 /**
1696 * ISOオフセット計算
1697 * @param[in] discinfo ディスク情報
1698 * @param[in] dst 書込装置構造体配列
1699 * @param[in] num_dst 書込装置構造体配列数
1700 * @note 計算結果はdiscinfo->outside_offsetに格納する。
1701 */
1702 static void CalcOffset(CPDISCINFO *discinfo, CMDDRIVE *dst, int num_dst)
1703 {
1704 int index;
1705 int ret;
1706 DWORD last_lout_min = 0xffffffff;
1707 DWORD last_lout;
1708 DWORD run_out = 2;
1709
1710 discinfo->outside_offset = 0;
1711
1712 if(discinfo->sessions != 1){
1713 return;
1714 }
1715 if(discinfo->tracks != 1){
1716 return;
1717 }
1718 if(!IS_TRACKMODE_DATA(discinfo->trackinfo[0].trackinfo.track_mode)){
1719 return;
1720 }
1721
1722 for(index=0; index<num_dst; index++){
1723 ret = GetWritableSize(&dst[index], &last_lout);
1724 if(ret == RET_OK){
1725 if(last_lout < last_lout_min){
1726 last_lout_min = last_lout;
1727 }
1728 }
1729 }
1730
1731 if(last_lout_min == 0xffffffff){
1732 return;
1733 }
1734
1735 /*
1736 * 1stSession Lead-out が 60秒?(60*75ブロック)
1737 * 2nsSession Lead-in が 90秒?(90*75ブロック)
1738 * pre-gap が 2秒(2*75ブロック)
1739 * 1stTrack(ダミー)が最低 4秒(4*75ブロック)
1740 */
1741 if(last_lout_min < discinfo->last_addr +run_out +156*75){
1742 return;
1743 }
1744
1745 discinfo->outside_offset = last_lout_min - discinfo->last_addr;
1746 DebugLog("offset=0x%08lX\n", discinfo->outside_offset);
1747 DebugLog("last_lout_min = 0x%08lX\n", last_lout_min);
1748 DebugLog("last_addr = 0x%08lX\n", discinfo->last_addr);
1749
1750 /* ダミーの1stトラックをディスク情報に追加 */
1751 discinfo->trackinfo =
1752 (CPTRACKINFO *)MemResize(discinfo->trackinfo, sizeof(CPTRACKINFO)*2);
1753 if(discinfo->trackinfo == NULL){
1754 discinfo->outside_offset = 0;
1755 return;
1756 }
1757 memmove(discinfo->trackinfo+1, discinfo->trackinfo+0,
1758 sizeof(CPTRACKINFO));
1759 discinfo->trackinfo[1].trackinfo.track_number_lsb = 2;
1760 discinfo->trackinfo[1].trackinfo.session_number_lsb = 2;
1761 Set4bytes(discinfo->trackinfo[1].trackinfo.track_start,
1762 Get4bytes(discinfo->trackinfo[1].trackinfo.track_start)
1763 +discinfo->outside_offset);
1764
1765 Set4bytes(discinfo->trackinfo[0].trackinfo.track_size,
1766 discinfo->outside_offset-run_out-152*75);
1767
1768 /* ディスク情報更新 */
1769 discinfo->last_addr += discinfo->outside_offset;
1770 discinfo->sessions = 2;
1771 discinfo->tracks = 2;
1772 }
1773
1774
1775 /**
1776 * 複写の実行
1777 * @param[in] src 読取装置構造体
1778 * @param[in] dst 書込装置構造体配列
1779 * @param[in] num_dst 書込装置構造体配列数
1780 * @retval RET_OK 正常終了
1781 * @retval RET_NG エラー
1782 */
1783 static int ExecCopy(CMDDRIVE *src, CMDDRIVE *dst, int num_dst)
1784 {
1785 int ret;
1786 CPDISCINFO discinfo;
1787 DWORD free_size;
1788 WORD track_num;
1789 WORD sess_num;
1790 CPTRACKINFO *cpti;
1791 BOOL sao=FALSE;
1792 int index;
1793
1794 for(index=0; index<num_dst; index++){
1795 /* 記録しようとするディスクがBLANKでなければBLANK実行 */
1796 ret = Blanking(&dst[index]);
1797 if(ret!=RET_OK)
1798 return ret;
1799 /* 記録メディアが DVD+RW で、未フォーマットならフォーマット開始 */
1800 ret = Formatting(&dst[index]);
1801 if(ret!=RET_OK)
1802 return ret;
1803 }
1804
1805 /* ソースディスクの情報を得る(ReadDiscInfo. & ReadTrackInfo.) */
1806 ret = GetDiscInformation(src, &discinfo);
1807 if(ret!=RET_OK)
1808 return ret;
1809
1810 if(discinfo.last_addr==0){
1811 UIDispMessage(MSG_SOURCE_IS_BLANK
1812 /*"複写元ディスクはブランクです。複写できません。"*/,
1813 UIDMT_INFORMATION);
1814 MemFree(discinfo.trackinfo);
1815 MemFree(discinfo.cdtext);
1816 return RET_ABORT;
1817 }
1818
1819 /* 記録側が仮想ドライブなら、イメージファイルにディスク情報を出力 */
1820 if(num_dst==1){
1821 ret = SetDiscInformation(&dst[0], &discinfo);
1822 if(ret!=RET_OK){
1823 MemFree(discinfo.trackinfo);
1824 MemFree(discinfo.cdtext);
1825 return ret;
1826 }
1827 }
1828
1829 for(index=0; index<num_dst; index++){
1830 if(REALDRIVE(&dst[index])){
1831 if(dst[index].disc_type!=DT_DVDRWO &&
1832 dst[index].disc_type!=DT_DVDRWS &&
1833 dst[index].disc_type!=DT_DVDPRW &&
1834 dst[index].disc_type!=DT_BDRE){
1835 /* DVD-RW/+RW でない場合だけ、容量チェック */
1836 /* WriteParametersPage設定によってフリーブロック数が
1837 影響されてしまう為 */
1838 ret = SetWriteParametersPage(&dst[index], &discinfo, 1,
1839 !discinfo.trackinfo[0].tao );
1840 if(ret!=RET_OK){
1841 MemFree(discinfo.trackinfo);
1842 MemFree(discinfo.cdtext);
1843 return ret;
1844 }
1845
1846 /* 記録ディスクの空き容量を得る */
1847 ret = GetWritableSize(&dst[index], &free_size);
1848 if(ret!=RET_OK){
1849 MemFree(discinfo.trackinfo);
1850 MemFree(discinfo.cdtext);
1851 return ret;
1852 }
1853 if(free_size < discinfo.last_addr){
1854 ret = UIDispMessage(MSG_CAPACITY_IS_INSUFFICIENT
1855 /*"記録ディスク容量が不足しています。\n無視して続行しますか?"*/,
1856 UIDMT_QUESTION);
1857 if(ret==UIDMRET_CANCEL){
1858 MemFree(discinfo.trackinfo);
1859 MemFree(discinfo.cdtext);
1860 return RET_ABORT;
1861 }
1862 }
1863 }
1864
1865 if(dst[0].disc_type!=DT_DVDR &&
1866 dst[0].disc_type!=DT_DVDRWO &&
1867 dst[0].disc_type!=DT_DVDRWS &&
1868 dst[0].disc_type!=DT_BDR){
1869 /* DVD-R/-RW,BD-R 以外は DAO 無効 */
1870 DebugLog("DAO disabled.\n");
1871 GetOption()->dao = FALSE;
1872 }
1873 }
1874 }
1875
1876 /* ISO外側記録のずらしブロック数を計算 */
1877 if(GetOption()->outside){
1878 if(REALDRIVE(&dst[0])){
1879 CalcOffset(&discinfo, dst, num_dst);
1880 SetOffset(discinfo.outside_offset);
1881 }
1882 }
1883
1884 /* 読込速度設定 */
1885 ret = SetSpeed(src, GetOption()->read_speed, 0);
1886 if(ret!=RET_OK){
1887 MemFree(discinfo.trackinfo);
1888 MemFree(discinfo.cdtext);
1889 SetOffset(0);
1890 return ret;
1891 }
1892
1893 for(index=0; index<num_dst; index++){
1894 /* 記録速度設定 */
1895 ret = SetSpeed(&dst[index],
1896 GetOption()->write_speed,
1897 GetOption()->write_speed);
1898 if(ret!=RET_OK){
1899 MemFree(discinfo.trackinfo);
1900 MemFree(discinfo.cdtext);
1901 SetOffset(0);
1902 return ret;
1903 }
1904 }
1905
1906 if(GetOption()->dao){
1907 DebugLog("DAO writing.\n");
1908 ret = CopyDAO(src, dst, num_dst, &discinfo);
1909 if(ret!=RET_OK){
1910 MemFree(discinfo.trackinfo);
1911 MemFree(discinfo.cdtext);
1912 SetOffset(0);
1913 return ret;
1914 }
1915 }
1916 else{
1917 track_num=1;
1918 for(sess_num=1; sess_num<=discinfo.sessions; sess_num++){
1919 if(track_num > discinfo.tracks)
1920 break;
1921 if(track_num==discinfo.tracks &&
1922 discinfo.trackinfo[track_num-1].trackinfo.blank){
1923 /* 最終トラックでBLANKなら何もせず終了 */
1924 break;
1925 }
1926 if((discinfo.trackinfo[track_num-1].tao==FALSE) &&
1927 DT_CD_FAMILY(dst[0].disc_type)){
1928 DebugLog("SAO writing.\n");
1929 /* SAO記録 */
1930 sao = TRUE;
1931 ret = CopySession(src, dst, num_dst, &discinfo, &track_num);
1932 if(ret!=RET_OK){
1933 MemFree(discinfo.trackinfo);
1934 MemFree(discinfo.cdtext);
1935 SetOffset(0);
1936 return ret;
1937 }
1938 continue;
1939 }
1940
1941 /* TAO記録 */
1942 DebugLog("TAO writing.\n");
1943 sao = FALSE;
1944 for(; track_num <= discinfo.tracks; track_num++){
1945 cpti = &discinfo.trackinfo[track_num-1];
1946 if(sess_num != SESSION_NUMBER(&cpti->trackinfo)){
1947 /* このセッションは終了 */
1948 ret = CloseSession(dst, num_dst);
1949 if(ret!=RET_OK){
1950 MemFree(discinfo.trackinfo);
1951 MemFree(discinfo.cdtext);
1952 SetOffset(0);
1953 return ret;
1954 }
1955 break;
1956 }
1957 if(track_num==discinfo.tracks &&
1958 discinfo.trackinfo[track_num-1].trackinfo.blank){
1959 /* 最終トラックでBLANKなら何もせず終了 */
1960 break;;
1961 }
1962
1963 ret = CopyTrack(src, dst, num_dst, &discinfo, track_num);
1964 if(ret!=RET_OK){
1965 MemFree(discinfo.trackinfo);
1966 MemFree(discinfo.cdtext);
1967 SetOffset(0);
1968 return ret;
1969 }
1970 }
1971 }
1972
1973 if(discinfo.last_sess_stat==SESSSTAT_COMPLETE && sao==FALSE){
1974 ret = CloseSession(dst, num_dst);
1975 if(ret!=RET_OK){
1976 MemFree(discinfo.trackinfo);
1977 MemFree(discinfo.cdtext);
1978 SetOffset(0);
1979 return ret;
1980 }
1981 }
1982 }
1983
1984 MemFree(discinfo.trackinfo);
1985 MemFree(discinfo.cdtext);
1986 SetOffset(0);
1987
1988 return RET_OK;
1989 }
1990
1991
1992
1993 /**
1994 * 後処理
1995 * @param[in] retcode 実行結果コード
1996 * @param[in] src 読取装置構造体
1997 * @param[in] dst 書込装置構造体配列
1998 * @param[in] num_dst 書込装置構造体配列数
1999 */
2000 void PostProcess(int retcode, CMDDRIVE *src, CMDDRIVE *dstp, int num_dst)
2001 {
2002 int ret;
2003 int index;
2004 BOOL socket_error = FALSE;
2005
2006 if(retcode==RET_SOCKET){
2007 if(src->type==CMDDRVTYPE_NET)
2008 socket_error = DispSocketError(&src->u.net, retcode);
2009 else
2010 socket_error = DispSocketError(&dstp->u.net, retcode);
2011 }
2012
2013 if(src->type == CMDDRVTYPE_NET){
2014 if(retcode==RET_OK){
2015 NASendComplete(&src->u.net);
2016 }
2017 else if(retcode==RET_ABORT){
2018 NASendAbort(&src->u.net);
2019 }
2020 FreeSOCKCB(&src->u.net);
2021 }
2022 if(dstp->type == CMDDRVTYPE_NET){
2023 if(retcode==RET_OK){
2024 NASendComplete(&dstp->u.net);
2025 }
2026 else if(retcode==RET_ABORT){
2027 NASendAbort(&dstp->u.net);
2028 }
2029 FreeSOCKCB(&dstp->u.net);
2030 }
2031
2032 if(socket_error==FALSE){
2033 if(retcode==RET_ABORT){
2034 UIDispMessage(MSG_ABORTED/*"中断されました。"*/, UIDMT_INFORMATION);
2035 }
2036 else if(retcode==RET_OK){
2037 if(!REALDRIVE(src) && !REALDRIVE(dstp)){
2038 UIDispMessage(MSG_COMPLETE_SUCCESS
2039 /*"正常に終了しました。"*/,
2040 UIDMT_INFORMATION);
2041 }
2042 else{
2043 for(index=0; index<num_dst; index++){
2044 SendStartStop(&dstp[index], 1, 0, 0); /* SpinDown */
2045 }
2046 ret = UIDispMessage(MSG_COMPLETE_SUCCESS_AND_EJECT
2047 /*"正常に終了しました。排出しますか?"*/,
2048 UIDMT_QUESTION);
2049 if(ret==UIDMRET_OK){
2050 for(index=0; index<num_dst; index++){
2051 OpenTrayImmediate(&dstp[index]);
2052 }
2053 OpenTray(src);
2054 }
2055 }
2056 }
2057 else{
2058 if(!REALDRIVE(src) && !REALDRIVE(dstp)){
2059 UIDispMessage(MSG_ERROR_OCCURRED
2060 /* "エラーが発生しました。" */,
2061 UIDMT_ERROR);
2062 }
2063 else{
2064 ret = UIDispMessage(MSG_ERROR_OCCURRED_CMDLOG
2065 /*"エラーが発生しました。コマンドログを生成しますか?"*/,
2066 UIDMT_QUESTION);
2067 if(ret==UIDMRET_OK){
2068 CreateLog(src, dstp, num_dst);
2069 }
2070 }
2071 }
2072 }
2073 }
2074
2075 /**
2076 * ディスクタイプ名称の取得
2077 * @param[in] disc_type ディスクタイプコード
2078 * @return 名称を返す
2079 */
2080 static const char *GetDiscTypeName(BYTE disc_type)
2081 {
2082 const char *name = "UNKNOWN";
2083 switch(disc_type){
2084 case DT_CDROM: name = "CD-ROM"; break;
2085 case DT_CDR: name = "CD-R"; break;
2086 case DT_CDRW: name = "CD-RW"; break;
2087 case DT_DVDROM: name = "DVD-ROM"; break;
2088 case DT_DVDR: name = "DVD-R"; break;
2089 case DT_DVDRAM: name = "DVD-RAM"; break;
2090 case DT_DVDRWO: name = "DVD-RW"; break;
2091 case DT_DVDRWS: name = "DVD-RW"; break;
2092 case DT_DVDRDL: name = "DVD-R DL"; break;
2093 case DT_DVDRDLJ: name = "DVD-R DL"; break;
2094 case DT_DVDRWDL: name = "DVD-RW DL"; break;
2095 case DT_DVDPRW: name = "DVD+RW"; break;
2096 case DT_DVDPR: name = "DVD+R"; break;
2097 case DT_DVDPRWDL: name = "DVD+RW DL"; break;
2098 case DT_DVDPRDL: name = "DVD+R DL"; break;
2099 case DT_BDROM: name = "BD-ROM"; break;
2100 case DT_BDR: name = "BD-R"; break;
2101 case DT_BDRR: name = "BD-RR"; break;
2102 case DT_BDRE: name = "BD-RE"; break;
2103 }
2104 return name;
2105 }
2106
2107
2108 /**
2109 * 読取装置の準備
2110 * @param[in] reader 読取装置ID
2111 * @param[out] drive ドライブ構造体
2112 * @param[in] data_buf データバッファ
2113 * @param[in] bufsize データバッファサイズ
2114 * @retval RET_OK 正常終了
2115 * @retval RET_NG エラー
2116 */
2117 static int OpenReader(DRIVEID *reader, CMDDRIVE *drive,
2118 BYTE *data_buf, int bufsize)
2119 {
2120 int ret;
2121
2122 if(reader->hid == HID_VIRTUAL){
2123 if(reader->tid == CMDDRVTYPE_MKISOFS){
2124 /* フォルダからのISOイメージ */
2125 ret = OpenMkisofsDevice(drive, data_buf, bufsize);
2126 if(ret != RET_OK){
2127 return ret;
2128 }
2129 }
2130 else if(reader->tid == CMDDRVTYPE_ISO){
2131 /* ISOイメージ */
2132 ret = OpenISOImageDevice(drive, TRUE, data_buf, bufsize);
2133 if(ret != RET_OK){
2134 return ret;
2135 }
2136 }
2137 else if(reader->tid == CMDDRVTYPE_IMAGE){
2138 /* オリジナルイメージ */
2139 ret = OpenEnbanImageDevice(drive, TRUE, data_buf, bufsize);
2140 if(ret != RET_OK){
2141 return ret;
2142 }
2143 }
2144 else if(reader->tid == CMDDRVTYPE_NET){
2145 /* ネットワーク接続された装置 */
2146 ret = OpenNetDevice(drive, FALSE, data_buf, bufsize);
2147 if(ret != RET_OK){
2148 return ret;
2149 }
2150 }
2151 else{
2152 return RET_NG;
2153 }
2154 }
2155 else{
2156 /* 通常のデバイス */
2157 ret = OpenDevice(drive, reader->hid, reader->tid, TRUE, TRUE,
2158 data_buf, bufsize);
2159 if(ret != RET_OK){
2160 return ret;
2161 }
2162 }
2163 return RET_OK;
2164 }
2165
2166
2167 /**
2168 * 読取装置の後片付け
2169 * @param[in/out] drive ドライブ構造体
2170 */
2171 static void CloseReader(CMDDRIVE *drive)
2172 {
2173 CloseDevice(drive);
2174 }
2175
2176
2177 /**
2178 * 書込装置の準備
2179 * @param[in] writer 書込装置ID配列
2180 * @param[in] num_writer 書込装置数
2181 * @param[out] drive ドライブ構造体
2182 * @param[out] num_writable_drive 書込可能ドライブ数
2183 * @param[in] data_buf データバッファ
2184 * @param[in] bufsize データバッファサイズ
2185 * @retval RET_OK 正常終了
2186 * @retval RET_NG エラー
2187 */
2188 static int OpenWriter(DRIVEID *writer, int num_writer,
2189 CMDDRIVE *drive, int *num_writable_drive,
2190 BYTE *data_buf, int bufsize)
2191 {
2192 int index;
2193 int ret;
2194 CMDDRIVE tmpdrive;
2195
2196 if(writer->hid == HID_VIRTUAL){
2197 memset(&tmpdrive, 0, sizeof(tmpdrive));
2198 if(writer->tid == CMDDRVTYPE_ISO){
2199 /* ISOイメージ */
2200 ret = OpenISOImageDevice(&tmpdrive, FALSE, data_buf, bufsize);
2201 if(ret != RET_OK){
2202 return ret;
2203 }
2204 }
2205 else if(writer->tid == CMDDRVTYPE_IMAGE){
2206 /* オリジナルイメージ */
2207 ret = OpenEnbanImageDevice(&tmpdrive, FALSE, data_buf, bufsize);
2208 if(ret != RET_OK){
2209 return ret;
2210 }
2211 }
2212 else if(writer->tid == CMDDRVTYPE_NET){
2213 /* ネットワーク接続された装置 */
2214 ret = OpenNetDevice(&tmpdrive, TRUE, data_buf, bufsize);
2215 if(ret != RET_OK){
2216 return ret;
2217 }
2218 }
2219 else{
2220 return RET_NG;
2221 }
2222 memcpy(&drive[0], &tmpdrive, sizeof(CMDDRIVE));
2223 *num_writable_drive = 1;
2224 }
2225 else{
2226 /* 通常のデバイス */
2227 for(index=0; index<num_writer; index++){
2228 memset(&tmpdrive, 0, sizeof(tmpdrive));
2229 ret = OpenDevice(&tmpdrive, writer[index].hid, writer[index].tid,
2230 FALSE, (num_writer==1), data_buf, bufsize);
2231 if(ret != RET_OK){
2232 continue;
2233 }
2234 DebugLog("Writer[%d] DiscType=%s(%02X)\n", index,
2235 GetDiscTypeName(tmpdrive.disc_type), tmpdrive.disc_type);
2236 memcpy(&drive[*num_writable_drive], &tmpdrive, sizeof(CMDDRIVE));
2237 (*num_writable_drive)++;
2238 }
2239 if(*num_writable_drive == 0){
2240 return RET_NG;
2241 }
2242 }
2243
2244 return RET_OK;
2245 }
2246
2247
2248 /**
2249 * 書込装置の後片付け
2250 * @param[in/out] drive ドライブ構造体配列
2251 * @param[in] num_drive ドライブ構造体配列数
2252 */
2253 static void CloseWriter(CMDDRIVE *drive, int num_drive)
2254 {
2255 int index;
2256
2257 for(index=0; index<num_drive; index++){
2258 CloseDevice(&drive[index]);
2259 }
2260 }
2261
2262 /**
2263 * 円盤を複写
2264 * @param[in] reader 読取装置ID
2265 * @param[in] writer 書込装置ID配列
2266 * @param[in] num_writer 書込装置数
2267 * @retval RET_OK 正常終了
2268 * @retval RET_NG エラー
2269 */
2270 int CopyDisc(DRIVEID *reader, DRIVEID *writer, int num_writer)
2271 {
2272 BOOL bSameDrive=FALSE;
2273 BOOL bDVD=FALSE;
2274 CMDDRIVE src, virtual_drv, *dstp=NULL;
2275 int ret;
2276 OPTIONS *option;
2277 int index;
2278 int num_writable_drive=0;
2279 int disc_type;
2280 BYTE *data_buf;
2281 int bufsize;
2282 char tmpfile[_MAX_PATH];
2283
2284 MemDebugStart();
2285
2286 memset(&src, 0, sizeof(src));
2287 memset(&virtual_drv, 0, sizeof(virtual_drv));
2288
2289 UICheckAbort();
2290
2291 if(reader->hid != HID_VIRTUAL && writer->hid != HID_VIRTUAL){
2292 if(reader->hid == writer->hid &&
2293 reader->tid == writer->tid){
2294 bSameDrive = TRUE;
2295 }
2296 }
2297
2298 if(!bSameDrive){
2299 dstp = (CMDDRIVE *)MemNew(num_writer*sizeof(CMDDRIVE));
2300 if(dstp==NULL){
2301 UIDispMessage(MSG_MEM_ALLOC_ERROR
2302 /*"メモリ確保に失敗しました。"*/, UIDMT_ERROR);
2303 MemDumpLeaks();
2304 MemDebugEnd();
2305 return RET_NG;
2306 }
2307 memset(dstp, 0, num_writer*sizeof(CMDDRIVE));
2308 }
2309 bufsize = 0x10000;
2310 data_buf = (BYTE *)MemNew(bufsize);
2311 if(data_buf==NULL){
2312 UIDispMessage(MSG_MEM_ALLOC_ERROR
2313 /*"メモリ確保に失敗しました。"*/, UIDMT_ERROR);
2314 MemFree(dstp);
2315 MemDumpLeaks();
2316 MemDebugEnd();
2317 return RET_NG;
2318 }
2319
2320 /* 読取装置のオープン */
2321 ret = OpenReader(reader, &src, data_buf, bufsize);
2322 if(ret!=RET_OK){
2323 MemFree(dstp);
2324 MemFree(data_buf);
2325 MemDumpLeaks();
2326 MemDebugEnd();
2327 return ret;
2328 }
2329 disc_type = src.disc_type;
2330
2331 /* 書込装置のオープン */
2332 if(bSameDrive){
2333 ret = SetOption(&src, &src, src.disc_type);
2334 if(ret!=RET_OK){
2335 CloseReader(&src);
2336 MemFree(dstp);
2337 MemFree(data_buf);
2338 MemDumpLeaks();
2339 MemDebugEnd();
2340 return ret;
2341 }
2342 num_writable_drive = 1;
2343 }
2344 else{
2345 ret = OpenWriter(writer, num_writer, dstp, &num_writable_drive,
2346 data_buf, bufsize);
2347 if(ret != RET_OK){
2348 CloseReader(&src);
2349 MemFree(dstp);
2350 MemFree(data_buf);
2351 MemDumpLeaks();
2352 MemDebugEnd();
2353 return ret;
2354 }
2355
2356 if((writer->hid == HID_VIRTUAL) &&
2357 (writer->tid == CMDDRVTYPE_NET)){
2358 /* ネットワーク接続された装置の場合 */
2359 /* サーバモード待機 */
2360 ret = WaitingNetCmd(&dstp[0], &src);
2361 PostProcess(ret, &src, &dstp[0], num_writable_drive);
2362 CloseReader(&src);
2363 CloseWriter(dstp, num_writable_drive);
2364 MemFree(dstp);
2365 MemFree(data_buf);
2366 MemDumpLeaks();
2367 MemDebugEnd();
2368 return ret;
2369 }
2370
2371 if(disc_type==DT_UNKNOWN){
2372 disc_type = dstp[0].disc_type;
2373 }
2374
2375 ret = SetOption(&src, &dstp[0], disc_type);
2376 if(ret!=RET_OK){
2377 CloseReader(&src);
2378 CloseWriter(dstp, num_writable_drive);
2379 MemFree(dstp);
2380 MemFree(data_buf);
2381 MemDumpLeaks();
2382 MemDebugEnd();
2383 return ret;
2384 }
2385 }
2386
2387 /* 一時ファイル名決定 */
2388 strcpy(tmpfile, GetOption()->temppath);
2389 if(strlen(tmpfile)+1+7+1>=sizeof(tmpfile)){
2390 MemDumpLeaks();
2391 MemDebugEnd();
2392 return RET_NG;
2393 }
2394 #ifdef WIN32
2395 if(strlen(tmpfile)>0){
2396 if(tmpfile[strlen(tmpfile)-1]=='\\')
2397 strcat(tmpfile, "tmp.img");
2398 else
2399 strcat(tmpfile, "\\tmp.img");
2400 }
2401 else
2402 strcat(tmpfile, "\\tmp.img");
2403 #else
2404 strcat(tmpfile, "/tmp.img");
2405 #endif
2406
2407 UIMeter1Initialize(MSG_TOTAL /*"全体"*/);
2408 if(src.type==CMDDRVTYPE_NET){
2409 NAUIMeter1Initialize(&src.u.net, MSG_TOTAL /*"全体"*/);
2410 }
2411
2412 option = GetOption();
2413 if(option->on_the_fly){
2414 /* On-The-Fly書き込み */
2415 bDVD = DT_DVD_FAMILY(disc_type);
2416 for(index=0; index<num_writable_drive; index++){
2417 if(!REALDRIVE(&dstp[index])){
2418 dstp[index].disc_type = disc_type;
2419 }
2420 else if((bDVD != DT_DVD_FAMILY(dstp[index].disc_type)) &&
2421 REALDRIVE(&src)){
2422 UIDispMessage(MSG_CANT_COPY_DIFFERENT_TYPE
2423 /*"CD から DVD や、DVD から CD にはコピーできません。"*/,
2424 UIDMT_ERROR);
2425 CloseReader(&src);
2426 CloseWriter(dstp, num_writable_drive);
2427 MemFree(dstp);
2428 MemFree(data_buf);
2429 MemDumpLeaks();
2430 MemDebugEnd();
2431 return RET_NG;
2432 }
2433 }
2434 ret = ExecCopy(&src, dstp, num_writable_drive);
2435 PostProcess(ret, &src, dstp, num_writable_drive);
2436 CloseReader(&src);
2437 CloseWriter(dstp, num_writable_drive);
2438 MemFree(dstp);
2439 MemFree(data_buf);
2440 }
2441 else{
2442 /* 一時ファイル経由 */
2443 ret = OpenTempImageDevice(&virtual_drv, FALSE, data_buf, bufsize, tmpfile);
2444 if(ret!=RET_OK){
2445 CloseReader(&src);
2446 if(!bSameDrive){
2447 CloseWriter(dstp, num_writable_drive);
2448 }
2449 MemFree(dstp);
2450 MemFree(data_buf);
2451 MemDumpLeaks();
2452 MemDebugEnd();
2453 return ret;
2454 }
2455
2456 virtual_drv.disc_type = src.disc_type;
2457
2458 ret = ExecCopy(&src, &virtual_drv, 1); /* DISC => Image file */
2459 if(ret==RET_OK){
2460 OpenTray(&src);
2461 if(src.type == CMDDRVTYPE_NET){
2462 NASendComplete(&src.u.net);
2463 }
2464 }
2465 else{
2466 PostProcess(ret, &src, &virtual_drv, 1);
2467 }
2468 if(bSameDrive){
2469 dstp = &src;
2470 }
2471 else{
2472 CloseReader(&src);
2473 }
2474 CloseDevice(&virtual_drv);
2475 if(ret!=RET_OK){ /* ExecCopyの戻り値確認 */
2476 RemoveImageFile(tmpfile);
2477 CloseWriter(dstp, num_writable_drive);
2478 if(!bSameDrive){
2479 MemFree(dstp);
2480 }
2481 MemFree(data_buf);
2482 MemDumpLeaks();
2483 MemDebugEnd();
2484 return ret;
2485 }
2486
2487 ret = OpenTempImageDevice(&virtual_drv, TRUE, data_buf, bufsize, tmpfile);
2488 if(ret!=RET_OK){
2489 CloseWriter(dstp, num_writable_drive);
2490 if(!bSameDrive){
2491 MemFree(dstp);
2492 }
2493 MemFree(data_buf);
2494 MemDumpLeaks();
2495 MemDebugEnd();
2496 return ret;
2497 }
2498 if(bSameDrive){
2499 /* ディスク挿入待ち */
2500 ret = GetDiscType(&dstp[0], &dstp[0].disc_type, TRUE);
2501 if(ret!=RET_OK){
2502 PostProcess(ret, &virtual_drv, dstp, num_writable_drive);
2503 CloseDevice(&virtual_drv);
2504 RemoveImageFile(tmpfile);
2505 CloseWriter(dstp, num_writable_drive);
2506 if(!bSameDrive){
2507 MemFree(dstp);
2508 }
2509 MemFree(data_buf);
2510 MemDumpLeaks();
2511 MemDebugEnd();
2512 return ret;
2513 }
2514 }
2515
2516 /* Image file => DISC */
2517 ret = ExecCopy(&virtual_drv, dstp, num_writable_drive);
2518 PostProcess(ret, &virtual_drv, dstp, num_writable_drive);
2519 CloseDevice(&virtual_drv);
2520 RemoveImageFile(tmpfile);
2521 CloseWriter(dstp, num_writable_drive);
2522 if(!bSameDrive){
2523 MemFree(dstp);
2524 }
2525 MemFree(data_buf);
2526 }
2527
2528 MemDumpLeaks();
2529 MemDebugEnd();
2530 return ret;
2531 }
2532

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26