-
Notifications
You must be signed in to change notification settings - Fork 3
/
N64-Dump.abp
843 lines (663 loc) · 21.3 KB
/
N64-Dump.abp
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
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
'Todo
'- SE
'- CRCをチェック、カートリッジ接触チェック
'- このチェックが通ったらSaveタイプ判定
'- ダンプ終わったらDat-OMaticのCRCと比較
/* FT232H, MCP23S17を用いたN64吸出しプログラム [for ActiveBasic v4]
* RGBA_CRT 2016-2017 [rgba3crt1p@gmail.com]
* <<< 実験コード・未リファクタリング >>>>
*
* reference materials:
* http://n64.icequake.net/mirror/www.crazynation.org/N64/
* https://github.com/sanni/cartreader/
* FTDI Documents
* http://www.hdl.co.jp/USB/mpsse_spi/
*
* connection::
* ADBus-SPI <-> MCP23S17
* ADBus4~7 <-> N64 /WE /RE ALE_L ALE_H
* ACBus0~7 <-> N64 LoByte
* MCP23S17-GPIOA <-> N64 HiByte
* MCP23S17-GPIOB <-> N64 EEP_CLK /RESET S_DAT
*/
/*
todo: verify, error check, refactor, check blank before write, unlock only command, erace on program
*/
#console
#include "D2XX.sbp"
#include <RGBALib.sbp>
Const IO_BUFFERSIZE = 1024*32
Const USB_BUFFER_SIZE = 1024*6
Const FT_USB_LATENCY = 1 ' 1~254
Const CART_BASEADR_SRAM = &H08000000
Const CART_BASEADR_ROM = &H10000000
Const NUS_DUMP_BUFFER_SIZE = &H200 '512バイトずつアドレス指定が必要なのでこれが最大
'http://www.zophar.net/fileuploads/2/10655uytsm/N64ops03.txt
Const NUS_ROM_HEADER_SIZE = &H40
Const NUS_TITLE_LEN = 20
Type NUS_ROM_HEADER_RAW
Initial_Reg As Word
isCompress As Byte '12h = uncomplessed 13 = complessed
uk1[4] As Byte
EntryPoint As DWord
uk2 As DWord
CRC1 As DWord
CRC2 As DWord
uk3[1] As DWord
Title[NUS_TITLE_LEN-1] As Byte
uk4[6] As Byte
GameID[3] As Byte
Version As Byte
End Type
' 色々正規化されたヘッダ
' ActiveBasicにunionが無いのが悲しい
Type NUS_ROM_HEADER
Raw As NUS_ROM_HEADER_RAW
Title[NUS_TITLE_LEN] As Byte
GameID_str[4] As Byte
CicType As Long
RomSize As DWord
RomSizeReason As BytePtr
End Type
#include "N64.idx"
'Global vars
Dim dwAB As DWord
Dim hFT As FT_HANDLE
Dim DevIdx As Long
Dim outbuf[IO_BUFFERSIZE] As Byte, c As DWord
Dim slowMode As BOOL
Main()
End
Sub Main()
Print " - N64 ROM DUMPER with FT232H v1.2 - PROGRAMMED BY RGBA_CRT 2016-2023"
Print
DevIdx = ListUpFTDI_Devices()
print DevIdx
if DevIdx<1 then
end
else if DevIdx = 1 then
DevIdx = 0
else
Input "slect device [num] > ", DevIdx
endif
'device open
FT_Open(DevIdx, hFT)
if hFT = 0 then
Print "Could not open Device."
Sleep(3000)
End
else
Print ex"Open OK\n"
endif
if NUS_InitRomAccess(hFT) <> TRUE then Print "err":ExitFunction
InitSPI()
NUS_InitPorts()
FTDI_SendCommand()
Dim biosPath As String
Dim op As DWord, header As NUS_ROM_HEADER
Dim adrStr As String, adr As DWord
Dim FileName[MAX_PATH] As Byte, i As Long
Dim save_type As NUS_SAVE_TYPE
Dim SaveBE As String, SaveLE As String
' EnterSlowMode()
' IntelFhash_WriteFile(CART_BASEADR_ROM, "controller_pak.n64")
' IntelFhash_WriteFile(CART_BASEADR_ROM, "YOSHI STORY.z64")
*ROM_INFO
input "[INSERT CART AND PRESS ENTER]", DevIdx
flush()
FillMemory(VarPtr(header), sizeof(NUS_ROM_HEADER), &HDD)
header.RomSizeReason = "ERR"
GetRomInfo(VarPtr(header))
if header.Title[0] = ex"\xFF" then lstrcpy(header.Title, "[CART CONNECT ERR]")
PrintRomInfo(VarPtr(header))
*SEL_OP
Print ex"[SELECT OPERATION]\n\t1.DUMP FULL ROM\n\t2.INPUT ROM SIZE AND DUMP\n\t3.SRAM DUMP [TEST]\n\t4.ROM VIEWER\n\t5.EXIT"
input "> ", op
Print
flush()
MakeRomFileName(FileName, MAX_PATH, VarPtr(header))
Select Case op
Case 1
lstrcat(FileName, ".z64")
DumpFullRom(FileName, header.RomSize)
Case 2
lstrcat(FileName, ".z64")
Input ex"Input ROM size (ex:8MB)\n > ", adrStr
rcAsciiToInt(adrStr, VarPtr(adr), 0, TRUE)
printf(ex"Size: %dMB\n", adr/1024/1024 As DWord)
if DumpFullRom(FileName, adr) <> TRUE then Print " [Error]":Goto *EXIT_PROGRAM
Case 3
N64PowerON()
FTDI_SendCommand()
save_type = SloveSaveType()
printf(ex"SaveType: %s\n", GetSaveTypeLabel(save_type))
if save_type = NUS_SAVE_UNKNOWN or save_type = NUS_SAVE_NONE then
printf(ex"dump save abort.\n")
else if save_type = NUS_SAVE_EEPROM then
SaveLE = FileName+MakeStr(".eep")
SaveBE = FileName+MakeStr(".eeprom")
if DumpEEPROM_File(SaveLE) = TRUE then
CopyFile(SaveLE, SaveBE, FALSE)
printf(ex"Saved EEPROM dump for Ares to \q%s\q\n", SaveBE)
printf(ex"Saved EEPROM dump for PJ64 to \q%s\q\n", SaveLE)
endif
else
Dim ltsave_ext As BytePtr
if save_type = NUS_SAVE_SRAM then
adr = 32*1024 As DWord
ltsave_ext = ".sra"
else if save_type = NUS_SAVE_SRAMx3 then
adr = 32*1024*3 As DWord
ltsave_ext = ".sra"
else if save_type = NUS_SAVE_FLASH_BYTE or save_type = NUS_SAVE_FLASH_WORD then
adr = 128*1024 As DWord
ltsave_ext = ".fla"
SaveFlash_CmdReadEnable()
else
debug
adr = 128*1024 As DWord
endif
printf(ex"Size = %dKB : %d bytes : 0x%X : %dKbits\n\n",
adr/1024,
adr,
adr,
adr*8/1024
)
SaveBE = FileName+MakeStr(".sav")
SaveLE = FileName+MakeStr(ltsave_ext)
'DumpFullRom(SaveBE, adr, CART_BASEADR_SRAM)
DumpSramFile(SaveBE, adr, save_type, CART_BASEADR_SRAM)
printf(ex"Saved sram dump for Ares to \q%s\q\n", SaveBE)
ConvertLittleEndian(SaveBE, SaveLE)
printf(ex"Saved sram dump for PJ64 to \q%s\q\n", SaveLE)
endif
N64PowerOFF()
Case 24
lstrcat(FileName, "_debug.sra")
'Input ex"Input sram size (ex:32KB)\n > ", adrStr
adrStr = "128KB"
rcAsciiToInt(adrStr, VarPtr(adr), 0, TRUE)
printf(ex"Size = %dKB : %d bytes : 0x%X\n",
adr/1024,
adr,
adr
)
'問答無用でFlashRamを有効にする。レジスタの位置にかぶる大きさのSRAMがないので大丈夫のはず
SaveFlash_CmdReadEnable()
DumpFullRom("temp-sram.raw", adr, CART_BASEADR_SRAM)
ConvertLittleEndian("temp-sram.raw", FileName)
printf(ex"Saved sram dump to \q%s\q", FileName)
Case 4
Do
testDump(adr)
Input ex"[ENTER:Continue][1:InputAdr][2:Reload][3:Exit]\n> ", op
if op = 0 then
adr + = TEST_DUMP_BLOCK_SIZE
else if op = 1 then
Input ex"Address : ", adrStr
rcAsciiToInt(adrStr, VarPtr(adr), 0, TRUE)
else if op = 2 then
else
ExitDo
endif
Loop
Case 5
Goto *EXIT_PROGRAM
Case 6
EnterSlowMode()
Case 7
ReadCFI()
Case 8
GS_Dump()
Case 9
op = GS_GetFlashId()
printf(ex"ID = %08X\n", op)
if op = GS_FLASH_ID then
printf(ex"id match.\n")
else
printf(ex"id unmatch.\n")
endif
Case 10
Input ex"EraseFlash(1/0)\n", op
if op = 1 then
GS_EraseFlash()
printf(ex"erased!\n")
endif
Case 11
input "bios path> ", biosPath
GS_WriteFromFile(StrPtr(biosPath))
'GS_WriteFromFile("doc\GS\GS3.3.z64")
Case 12
EnterSlowMode()
IntelFhash_Erase(CART_BASEADR_ROM + 0)
IntelFhash_Erase(CART_BASEADR_ROM + &H2000000)
Case 13
EnterSlowMode()
N64PowerON()
IntelFhash_ChipErase(CART_BASEADR_ROM)
IntelFhash_ChipErase(CART_BASEADR_ROM + &H2000000)
N64PowerOFF()
Case 14
EnterSlowMode()
N64PowerON()
IntelFhash_Reset(CART_BASEADR_ROM)
IntelFhash_Reset(CART_BASEADR_ROM + &H2000000)
N64PowerOFF()
Case 15
EnterSlowMode()
Input ex"[WRITE] path> : ", adrStr
IntelFhash_WriteFile(CART_BASEADR_ROM, adrStr)
Case 20
N64PowerON()
Case 21
N64PowerOFF()
Case 31
EnterSlowMode()
N64PowerON()
IntelFhash_Erase(CART_BASEADR_ROM + 0)
N64PowerOFF()
Case 32
EnterSlowMode()
N64PowerON()
IntelFhash_Erase(CART_BASEADR_ROM + &H2000000)
N64PowerOFF()
Case 40
N64PowerON()
SaveFlash_printID()
N64PowerOFF()
Case 41
N64PowerON()
SaveFlash_printID()
SaveFlash_CmdReadEnable()
N64PowerOFF()
Case 42
N64PowerON()
save_type = SloveSaveType()
printf(ex"SaveType: %s\n", GetSaveTypeLabel(save_type))
N64PowerOFF()
Case 43
ConvertLittleEndian("A", "B")
Case 61
EnterSlowMode()
N64PowerON()
IntelFhash_Test(CART_BASEADR_ROM + 0)
N64PowerOFF()
Case 62
Input ex"romspeed> : ", op
Print "romspeed: ", op
SetRomSpeed(op)
Case 16
NUS_Reset()
Case 63
EnterSlowMode()
N64PowerON()
FTDI_SendCommand()
IntelFlash_SetReadConfigRegister(CART_BASEADR_ROM)
flash_printID(CART_BASEADR_ROM)
N64PowerOFF()
case 80
N64PowerON()
if NUS_InitJoybusAccess(hFT, NUS_JOYBUS_CONTROLLER) <> TRUE then Print "err":end
do
'Joybus Controller test
Dim jret As NUS_JOYBUS_ERR, decbuf[4] As Byte
Dim info As NUS_JoybusDeviceInfo
jret = NUS_JoybusGetDeviceInfo(VarPtr(info))
if jret <> NUS_JOYBUS_OK then printf(ex"Joybus error: %s\n", NUS_JoybusErrorText(jret)):ExitDo
printf(ex"Joybus Device: [%04x]%s status = %02x\t\n", info.id, NUS_JoybusDeviceText(info.id), info.status)
jret = NUS_JoybusGetControllerInput(decbuf, 4)
if jret <> NUS_JOYBUS_OK then printf(ex"Joybus error: %s\n", NUS_JoybusErrorText(jret)):ExitDo
Dump(decbuf, 4)
Dim BUTTON_LABEL = "><v^SZBArlduRL?*" As BytePtr
For i = 0 to 15
if (GetWord(decbuf) >> i ) And 1 then
printf("%c ", BUTTON_LABEL[i])
else
printf(" ")
endif
Next i
printf(ex"%4d %4d\n", (decbuf[2]<<24) As Long >> 24, (decbuf[3]<<24) As Long >> 24)
ConsoleReturnLine()
ConsoleLocateRelative(0, -4)
Sleep(50)
Loop
NUS_InitRomAccess(hFT)
N64PowerOFF()
case 81
N64PowerON()
if NUS_InitJoybusAccess(hFT, NUS_JOYBUS_EEPROM) <> TRUE then Print "err":end
'EEPROM test
Dim eepbuf[8] As Byte, block As Long
' Dim info As NUS_JoybusDeviceInfo
jret = NUS_JoybusGetDeviceInfo(VarPtr(info))
if jret <> NUS_JOYBUS_OK then printf(ex"Joybus error: %s\n", NUS_JoybusErrorText(jret))
printf(ex"Joybus Device: [%04x]%s status = %02x\t\n", info.id, NUS_JoybusDeviceText(info.id), info.status)
if info.id = NUS_JB_DEV_ID_EEPROM_4K then
block = 4*1024/8/8
else if info.id = NUS_JB_DEV_ID_EEPROM_16K then
block = 16*1024/8/8
else
printf(ex"Dump save error: Unknown EEPROM type.\n")
endif
Dim eepsave As File
eepsave.openFile("test.eep", GENERIC_WRITE)
for i = 0 To block-1
jret = NUS_JoybusReadEEPROM(eepbuf, i)
if jret <> NUS_JOYBUS_OK then
printf(ex"Joybus error: %s\n", NUS_JoybusErrorText(jret))
ExitFor
endif
Dump(eepbuf, 8, i*8)
eepsave.write(eepbuf, 8)
Next i
eepsave.close()
NUS_InitRomAccess(hFT)
N64PowerOFF()
case 82
N64PowerON()
case 1204
'SPFlash_Test()
Input ex"[WRITE] path> : ", adrStr
SPFlash_WriteFile(StrPtr(adrStr))
End Select
Print ex"\n\n"
Goto *ROM_INFO
*EXIT_PROGRAM
N64PowerOFF()
FT_Close(hFT)
Print "END"
End Sub
Sub NotifySound()
MessageBeep(-1)
End Sub
Sub EnterSlowMode()
Print "Slow Mode Eneble"
memcpy(outbuf+c, ex"\x85\x97\x8c\x8A\x86\x03\x00", 7) : c+ = 7 'SlowSpeed For FlashCart
slowMode = TRUE
End Sub
Sub SetRomSpeed(speed As Word)
Print "Slow Mode Eneble"
memcpy(outbuf+c, ex"\x85\x97\x8c\x8A\x86\x00\x00", 7) : c+ = 7 'OverSpeed
'slowMode = TRUE
outbuf[c-1] = speed>>8
outbuf[c-2] = speed And &HFF
Dump(outbuf+c-7, 7)
End Sub
Sub flush()
Dim ftStatus As Long, bufsize As DWord, buf As BytePtr, dwAB As DWord
ftStatus = ftStatus or FT_GetQueueStatus(hFT, bufsize) ' Get the number of bytes in the FT2232H receive buffer
buf = calloc(bufsize)
if bufsize>0 then Print bufsize
if (ftStatus = FT_OK) And (bufsize > 0) then _
FT_Read(hFT, buf, bufsize, dwAB) 'Read out the data from FT2232H receive buffer
free(buf)
End Sub
Function DumpFullRom(fileName As BytePtr, RomSize As DWord)(BaseAddress As DWord) As Long
Dim out As File , inbuf As BytePtr, inSize As DWord
Dim reqAdr = &H0 As DWord
if BaseAddress = 0 then
BaseAddress = CART_BASEADR_ROM
else if BaseAddress = &HFFFFFFFF then
BaseAddress = &H00000000
endif
inbuf = calloc(NUS_DUMP_BUFFER_SIZE)
if out.openFile(fileName, GENERIC_WRITE) = FALSE then
Print "Failed to create file."
ExitFunction
endif
flush()
N64PowerON()
NUS_SetAddress(BaseAddress)
if FTDI_SendCommand() <> FT_OK then Goto *DFR_EXIT
printf(ex"output file name: %s\n", fileName)
printf(ex"dumping ROM...\n")
Dim time As DWord, lt As DWord, retry As DWord
time = GetTickCount()
Do
' Byte Address
NUS_SetAddress(BaseAddress + reqAdr)
NUS_readRequest(NUS_DUMP_BUFFER_SIZE>>1)
if FTDI_SendCommand() <> FT_OK then Goto *DFR_EXIT
if FT_Read(hFT, inbuf, NUS_DUMP_BUFFER_SIZE, inSize) <> FT_OK then Goto *DFR_EXIT
if inSize <> NUS_DUMP_BUFFER_SIZE then
printf(ex"receive size error.\n")
retry++
if retry>5 then Goto *DFR_EXIT
Continue
endif
out.write(inbuf, inSize)
reqAdr+ = inSize
if reqAdr Mod (&H5000*2) = 0 then
ConsoleReturnLine()
printf(ex"Address = 0x%08X ... %d.%d%% [%d KB/s] ", reqAdr, (reqAdr/RomSize)*100, ((reqAdr/RomSize) * 1000) Mod 10, reqAdr/(GetTickCount()-time))
if GetKeyState(VK_ESCAPE) And &H80 then Print ex"\n[ESC]Cancelled by user.":Goto *DFR_EXIT
endif
' if reqAdr Mod &H100000 = 0 then Sleep(200)
if reqAdr >= RomSize then ExitDo
Loop
lt = GetTickCount()-time
printf(ex"\nDump Successfull !\nTime:%dms = %ds = %dmin\n", lt, lt/1000, lt/1000/60)
DumpFullRom = TRUE
*DFR_EXIT
free(inbuf)
Dim hash_buf As BytePtr
hash_buf = calloc(1024*1024)
out.setFilePtr(&H1000)
out.read(hash_buf, &H100000)
printf(ex"head hash = 0x%08X\n",crc32.GetHash(hash_buf, &HFFFFF))
free(hash_buf)
out.close()
N64PowerOFF()
FT_Purge(hFT, FT_PURGE_RX or FT_PURGE_TX)
NotifySound()
End Function
'大体のエミュのセーブデータの形式がリトルエンディアン(DWord)
Function ConvertLittleEndian(fname As BytePtr, outname As BytePtr) As Long
Dim out As File, in As File, buf As *DWord, size As DWord, i As DWord
in.openFile(fname, GENERIC_READ)
size = in.length()
buf = calloc(size+12)
in.read(buf, size)
in.close()
For i = 0 To size/4-1
ChangeEndianDW(buf[i])
Next i
out.openFile(outname, GENERIC_WRITE)
out.write(buf, size)
out.close()
free(buf)
End Function
Sub GetRawHeader(header As *NUS_ROM_HEADER_RAW)
Dim inbuf[NUS_ROM_HEADER_SIZE] As Byte
NUS_SetAddress(CART_BASEADR_ROM)
NUS_readRequest(NUS_ROM_HEADER_SIZE/2)
if FTDI_SendCommand() <> FT_OK then Print "Connection err.":Goto *PRI_EXIT
if FT_Read(hFT, inbuf, NUS_ROM_HEADER_SIZE, dwAB) <> FT_OK then Goto *PRI_EXIT
memcpy(header, inbuf, sizeof(NUS_ROM_HEADER))
*PRI_EXIT
End Sub
Sub GetRomInfo(header As *NUS_ROM_HEADER)
N64PowerON()
'RAW header
GetRawHeader(VarPtr(header->Raw))
' Title
memcpy(header->Title, header->Raw.Title, NUS_TITLE_LEN)
header->Title[NUS_TITLE_LEN] = 0
Dim i As Long
For i = NUS_TITLE_LEN To 0 Step -1
'スペース埋めを解除
if header->Title[i] > &H20 then
ExitFor
endif
header->Title[i] = 0
Next i
'CIC
header->CicType = NUS_GetCicType(hFT)
'Game ID(strings)
memcpy(header->GameID_str, header->Raw.GameID, 4)
header->GameID_str[4] = 0
'ROM Size
header->RomSize = SloveRomSize(VarPtr(header->RomSizeReason))
N64PowerOFF()
End Sub
Sub PrintRomInfo(header As *NUS_ROM_HEADER)
Dim isCompress As BytePtr
if header->Raw.isCompress = &H13 then
isCompress = "Yes"
else
isCompress = "No"
endif
ChangeEndianDW(header->Raw.CRC1)
ChangeEndianDW(header->Raw.CRC2)
ChangeEndianDW(header->Raw.EntryPoint)
printf(ex"N64 ROM Infomation\n\tTitle : %s \n\tGameID : NUS-%s \n\tVersion : 1.%d\n\tCIC Type : %s\n\tCRC1 : 0x%08X\n\tCRC2 : 0x%08X\n\tEntryPtr : 0x%08X\n\tCompress : %s\n",
header->Title,
header->GameID_str,
header->Raw.Version,
CicLabelTable[header->CicType],
header->Raw.CRC1, header->Raw.CRC2,
header->Raw.EntryPoint,
isCompress
)
printf(ex"\tROM Size : %d MB (%dMbit) [推定] ::: %s \n\n",
header->RomSize/(1024*1024),
header->RomSize/(1024*1024/8),
header->RomSizeReason
)
End Sub
Const NUS_SLOVE_SAMPLE_SIZE1 = &H80
Const NUS_SLOVE_SAMPLE_SIZE2 = &H10
Const NUS_SLOVE_FF_FILL_HASH = &H652D544C ' SampleSize変わるたびに更新必要
Const NUS_SLOVE_00_FILL_HASH = &HC2A8FA9D ' SampleSize変わるたびに更新必要
Const HASH3_OFFSET = 512*1024 ' ロボットポンコッツ64 NUS-NR7Jにおいて0x1000000がちょうど00データのためずらした位置の再読み込みが必要
Function NUS_ReadDataSingle(buffer As BytePtr, address As DWord, size As DWord) As BOOL
if size>NUS_DUMP_BUFFER_SIZE then exitfunction
NUS_SetAddress(address)
NUS_readRequest(size>>1)
if FTDI_SendCommand() <> FT_OK then ExitFunction
if FT_Read(hFT, buffer, size, dwAB) <> FT_OK then ExitFunction
NUS_ReadDataSingle = TRUE
End Function
Function NUS_ReadData(buffer As BytePtr, address As DWord, size As DWord)(blockSize As DWord) As BOOL
if blockSize = 0 then
blockSize = NUS_DUMP_BUFFER_SIZE
endif
Dim i As DWord, offset = 0 As DWord, readSize As DWord, loop_num As DWord
loop_num = (size/blockSize) As DWord
if size Mod blockSize then loop_num+ = 1
'printf(ex"READ DATA adr = %p sizse = %p blockSizse = %p loopn = %d\n", address, size, blockSize, loop_num)
For i = 0 To loop_num-1
offset = i*blockSize
if i <> loop_num then
readSize = blockSize
else
readSize = size Mod blockSize
endif
' printf(ex" - %d %d\n", i, readSize)
if NUS_ReadDataSingle(buffer + offset, address+offset, readSize) <> TRUE then Exitfunction
Next i
NUS_ReadData = TRUE
End Function
Function NUS_GetHash(address As DWord, size As DWord)(blockSize As DWord) As DWord
Dim buf[NUS_DUMP_BUFFER_SIZE] As Byte
if NUS_ReadData(buf, address, size, blockSize) <> TRUE then ExitFunction
' FillMemory(buf, size, &H00)
NUS_GetHash = crc32.GetHash(buf, size)
'Dump(buf, size)
End Function
'ROMサイズを推測する
Function SloveRomSize(reason As *BytePtr) As DWord
Dim i As Long
Dim sloveAddress As DWord
Dim headerHash As DWord, lastHash As DWord, hash As DWord, hash2 As DWord, hash3 As DWord
Const slovePatternCount = 8
Dim slovePattern[slovePatternCount] = [
0, 4, 8, 12, 16, 32, 40, 48, 64,
] As Byte
reason[0]=NULL
N64PowerON()
#ifdef _DEBUG
printf(ex"ROM SLOVE: 00_FILL=%08X FF_FILL=%08X \n", NUS_SLOVE_00_FILL_HASH, NUS_SLOVE_FF_FILL_HASH)
#endif
For i = 0 To slovePatternCount
' READ
sloveAddress = CART_BASEADR_ROM + (slovePattern[i] * 1024*1024)
'データ不定領域の判定のため、1回の転送ブロックサイズを変えた2回の読み出しをする
' Ref: https://twitter.com/HelicopterP64/status/1608976626125275137
hash = NUS_GetHash(sloveAddress, NUS_SLOVE_SAMPLE_SIZE1, NUS_SLOVE_SAMPLE_SIZE1)
hash2 = NUS_GetHash(sloveAddress, NUS_SLOVE_SAMPLE_SIZE1, NUS_SLOVE_SAMPLE_SIZE2)
hash3 = NUS_GetHash(sloveAddress + HASH3_OFFSET, NUS_SLOVE_SAMPLE_SIZE1, NUS_SLOVE_SAMPLE_SIZE1)
#ifdef _DEBUG
printf(ex" === %3dMB === adr:%08X hash1:%08X hash2:%08X hash3:%08X \n", slovePattern[i], sloveAddress, hash, hash2, hash3)
#endif
if hash <> hash2 then
reason[0] = "detect unstable area"
ExitFor
endif
if (hash = NUS_SLOVE_FF_FILL_HASH) AND (hash3 = hash) then
reason[0] = "detect 0xFF fill"
ExitFor
endif
if (hash = NUS_SLOVE_00_FILL_HASH) AND (hash3 = hash) then
reason[0] = "detect 0x00 fill"
ExitFor
endif
if i = 0 then
' MEMORY HEADER
headerHash = hash
else
' COMPARE HEADER
if headerHash = hash then reason[0] = "detect header":ExitFor
if lastHash = hash then reason[0] = "detect repeat": ExitFor
endif
lastHash = hash
Next i
' if i Mod 4 <> 0 then i+ = 4-(i Mod 4)
SloveRomSize = sloveAddress - CART_BASEADR_ROM
*SRS_EXIT
N64PowerOFF()
'free(header)
'free(inbuf )
if reason[0] = NULL then reason[0] = "max ROM size"
End Function
Function isFilled(adr As BytePtr, size As DWord, checkByte As Byte) As Long
Dim i As Long
For i = 0 To size-1
if adr[i] <> checkByte then ExitFunction
Next
isFilled = TRUE
End Function
Function compareBin(data1 As BytePtr, data2 As BytePtr, size As DWord) As Long
Dim i As Long
For i = 0 To size-1
if data1[i] <> data2[i] then ExitFunction
Next
compareBin = TRUE
End Function
Sub PrintBuffer()
printf(ex"[output buffer : %d/%d -> %d%%]", c, IO_BUFFERSIZE, c/IO_BUFFERSIZE*100)
End Sub
Const TEST_DUMP_BLOCK_SIZE = &H100
Sub testDump(Adr As DWord)
N64PowerON()
NUS_SetAddress(NUS_GS_HEADER_OFFSET + Adr)
NUS_readRequest(TEST_DUMP_BLOCK_SIZE/2)
Dim inbuf[TEST_DUMP_BLOCK_SIZE] As Byte, inSize As DWord
FTDI_SendCommand()
FT_Read(hFT, inbuf, TEST_DUMP_BLOCK_SIZE, inSize)
Dump(inbuf, TEST_DUMP_BLOCK_SIZE, CART_BASEADR_ROM + Adr)
N64PowerOFF()
' Sleep(1000)
End Sub
Function MakeRomFileName(buf As BytePtr, buflen As DWord, header As *NUS_ROM_HEADER) As Long
Dim rom_title[MAX_PATH] As Byte
Dim ver As Long
ver = 10 + (header->Raw.Version) As Long
Dim region As Char
region = header->Raw.GameID[3]
if region=0 then region=GetByte("-")
wsprintf(rom_title, "%s (%c) (V%d.%d)",
header->Title, header->Raw.GameID[3], ver / 10, ver Mod 10)
memcpy(buf, rom_title, buflen-1)
buf[buflen-1] = 0
End Function