Not sure if this should go in the VB Programming forum. Please move it if it should.
Hdx and I are working on writing a VisualBasic CheckRevision() function. If anyone is interested in suggesting stuff or testing, or would like more information or something, feel free to ask. Here it is, as of right now.
Public Function checkRevision( _ '// This is the CheckRevision function used for 0x51.
versionString As String, _ '// Checksum Formula recieved in 0x50.
mpqNum As Integer, _ '// MPQ Number recieved in 0x50.
Product As String) As Long '// Product to use.
'START JOES CODE
'// Sample formula -- A=602362906 B=5284658 C=149279165 4 A=A+S B=B^C C=C^A A=A^B
'// TODO - Joe: Define hash codes, define files.
Dim A As Long, B As Long, C As Long, S As Long, Splt() as String, O1 as String
Dim O2 as String, Dim O3 as String
A = CLng(Mid(Splt(0), 3))
B = CLng(Mid(Splt(1), 3))
C = CLng(Mid(Splt(2), 3))
O1 = Mid(Splt(4), 4, 1)
O2 = Mid(Splt(5), 4, 1)
O2 = Mid(Splt(6), 4, 1)
'END JOES CODE
'START HDX'S CODE
A = A ^ hashCodes(mpqNum)
For I = 0 To UBound(strFiles)
intFile = FreeFile
Open strFiles(I) For Binary Access Read As #intFile
RoundedSize = CDbl((LOF(intFile) / 1024) * 1024)
For J = 0 To RoundedSize Step 4
strTmpData = Space(4)
Get #intFile, J + 1, strTmpData
S = GetDWORD(strTmpData)
Select Case op1
Case "^": A = A ^ S
Case "-": A = A - S
Case "+": A = A + S
End Select
Select Case op2
Case "^": B = B ^ C
Case "-": B = B - C
Case "+": B = B + C
End Select
Select Case op3
Case "^": C = C ^ A
Case "-": C = C - A
Case "+": C = C + A
End Select
Select Case op4
Case "^": A = A ^ B
Case "-": A = A - B
Case "+": A = A + B
End Select
Next J
Close #intFile
Next I
checkRevision = C
'// END HDX'S CODE
End Function
A couple comments, and take them with a grain of salt, as it's late and I might just be completely missing something.
1.) The Splt array seems to be unassigned. You declare it, and then immediately use it:
'Declare it:
Dim A As Long, B As Long, C As Long, S As Long, Splt() as String, O1 as String
' Use it
A = CLng(Mid(Splt(0), 3))
Is this intended? I would think it would generate a compile-time error.
2.) I can't remember, but does VB support the ^ operator? I thought it didn't support *any* symbolic bitwise operators -- I thought that appropriate bitwise operators were:
A = A And B
B = B Or C
C = C Xor S
If that's the case you'll need to revise code that uses the ^ operator. I'm too lazy to look it up right now.
Actually, the ^ operator is valid, but it means exponentiation. See this page (http://juicystudio.com/tutorial/vb/operators.asp) for more information.
3.) You repeat defining O2:
O2 = Mid(Splt(5), 4, 1)
O2 = Mid(Splt(6), 4, 1)
Not being picky, just saving you that runtime debugging frustration later :)
Otherwise I think you've got a good start.
Correct me if I'm wrong, but wouldn't:
((Integer * 1024) / 1024) return the same value as Integer..?
Quote from: UserLoser on April 15, 2005, 02:06 PM
Correct me if I'm wrong, but wouldn't:
((Integer * 1024) / 1024) return the same value as Integer..?
Assuming you didn't have overflow, yes, but I don't see that expression in his code. You want either
((Integer / 1024) * 1024)
or:
Integer - (Integer % 1024)
IIRC the second is more efficient, because integral division can take a long time.
You also might be able to get it faster by left-shifting (without carry) by 22 and then right-shifting it back 22 -- I believe that will fill the upper 22 bits with 0s and leave the remaining lower 10 bits as they were.
Or you could just bitwise AND it with 0x3ff, IIRC.
And on that note, should you just use a Long instead of a Double to hold the file size? I don't think that any of Blizz's files go bigger than 2gb -- at least, not the ones you're CheckRevisioning.
Quote from: MyndFyre on April 15, 2005, 02:15 PM
Assuming you didn't have overflow, yes, but I don't see that expression in his code. You want either
RoundedSize = CDbl((LOF(intFile) / 1024) * 1024)
According to all my tests, it returns the same value. What's the point of doing / 1024 * 1024 is what I'm wanting to know
Quote from: UserLoser on April 15, 2005, 02:25 PM
Quote from: MyndFyre on April 15, 2005, 02:15 PM
Assuming you didn't have overflow, yes, but I don't see that expression in his code. You want either
RoundedSize = CDbl((LOF(intFile) / 1024) * 1024)
According to all my tests, it returns the same value. What's the point of doing / 1024 * 1024 is what I'm wanting to know
You should do \ 1024 then * 1024...
Quote from: MyndFyre on April 15, 2005, 02:15 PM
Integer - (Integer % 1024)
IIRC the second is more efficient, because integral division can take a long time.
I'll just point out that % implies integral division.
You do save a multiplication though.
With modern processors there isn't a performance gain doing shifts in place of multiplications/divisions anymore.
I simply did this in my vb 6.0 checkrevision implementation.
' Round file size
lFileSize = Round(GetFileSize(hFile, ByVal 0&) / 1024) * 1024
I store the result in a long (which in vb 6 is 32 bits) and worked just fine.
MyndFyre, thanks for reminding me to fill Splt with stuff, and for reminding me about Xor. I'll just have to replace the ^ with Xor's, so I don't screw myself up big time.
UserLoser: I was wondering that myself. Thats in the Hdx's Code section, and I'll have to talk to him and find out what the hell he was thinking.
Quote from: OnlyMeat on April 15, 2005, 02:47 PM
' Round file size
lFileSize = Round(GetFileSize(hFile, ByVal 0&) / 1024) * 1024
I store the result in a long (which in vb 6 is 32 bits) and worked just fine.
I'm not so sure that works reliably. Maybe it just works 50% of the cases?
#1, the ((I / 1024) * 1024) was suposto round the size to the nerest MB, but I accedently did / insted of \ :/
As for the ^ This was already descused in the original topic -.- the one i started.
Also Joe, PLEASE stop taking my code and posts from one site, and posting them on another site saying its a team project between the two of us!, I mearly wanted the input of some people on Quikness forums. Not here -.- (no offence all, but I would of posted it here myself, if i wanted help from everyone here, I like smaller forums over big ones)
Now Here is the current code:
Private hashCodes(0 To 7) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef destination As Any, ByRef Source As Any, ByVal numbytes As Long)
Private Sub SetVars()
hashCodes(0) = &HE7F4CB62
hashCodes(1) = &HF6A14FFC
hashCodes(2) = &HAA5504AF
hashCodes(3) = &H871FCDC2
hashCodes(4) = &H11BF6A18
hashCodes(5) = &HC57292E6
hashCodes(6) = &H7927D27E
hashCodes(7) = &H2FEC8733
End Sub
Public Function GetDWORD(Data As String) As Long
Dim lReturn As Long
Call CopyMemory(lReturn, ByVal Data, 4)
GetDWORD = lReturn
End Function
Public Function checkRevision(ByVal versionString As String, ByRef strFiles() As String, ByVal mpqNum As Integer) As Integer
Dim tok As New clsStringTokenizer
Call tok.SetVals(versionString, Space(1))
Dim A As Long, B As Long, C As Long, S As Long
A = Val(tok.getNextToken(3))
B = Val(tok.getNextToken(3))
C = Val(tok.getNextToken(3))
tok.getNextToken
Dim Formula As String, I As Integer, intFile As Integer, RoundedSize As Double, J As Double
Dim op1 As String, op2 As String, op3 As String, op4 As String, strTmpData As String
op1 = Mid(tok.getNextToken, 4, 1)
op2 = Mid(tok.getNextToken, 4, 1)
op3 = Mid(tok.getNextToken, 4, 1)
op4 = Mid(tok.getNextToken, 4, 1)
A = A Xor hashCodes(mpqNum)
For I = 0 To UBound(strFiles)
intFile = FreeFile
Open strFiles(I) For Binary Access Read As #intFile
RoundedSize = CDbl((LOF(intFile) \ 1024) * 1024)
For J = 0 To RoundedSize Step 4
strTmpData = Space(4)
Get #intFile, J + 1, strTmpData
S = GetDWORD(strTmpData)
Select Case op1
Case "^": A = Moduls(A Xor S)
Case "-": A = Moduls(A - S)
Case "+": A = Moduls(A + S)
End Select
Select Case op2
Case "^": B = Moduls(B Xor C)
Case "-": B = Moduls(B - C)
Case "+": B = Moduls(B + C)
End Select
Select Case op3
Case "^": C = Moduls(C Xor A)
Case "-": C = Moduls(C - A)
Case "+": C = Moduls(C + A)
End Select
Select Case op4
Case "^": A = Moduls(A Xor B)
Case "-": A = Moduls(A - B)
Case "+": A = Moduls(A + B)
End Select
Next J
Close #intFile
Next I
checkRevision = C
End Function
Private Function Moduls(intOne As Long) As Long
Moduls = CLng(intOne Mod &HFFFFFFFF)
End Function
Private Sub Form_Load()
Call SetVars
Dim blah(0 To 2) As String
blah(0) = "E:\JBLS\W2BN\Warcraft II BNE.exe"
blah(2) = "E:\JBLS\W2BN\battle.snp"
blah(1) = "E:\JBLS\W2BN\storm.dll"
Call checkRevision("A=602362906 B=5284658 C=149279165 4 A=A+S B=B^C C=C^A A=A^B", blah, 3)
End Sub
Moduls() Was suggested by both Joe, Fool, And iago. As a way to prevent overflows. But it always returns zero :/
Now does the opertation thet B.net sends refer to all Bitwise opertations (Xor, Or, And, Etc...) or there mathmatical counterparts? (+, -, /, \, ^, *, etc...)
^ was explaind to mean Xor, and so could it be assumed that + means And, and - means Or? If so it always returns zero (not using Moduls()) with no overflows.
~-~(HDX)~-~
PS: This is a strait port of iago's java code.
Also who deleyted my last post. Please don't do it again. It is varry annoying. Thanks.
Quote from: Adron on April 15, 2005, 02:29 PM
Quote from: UserLoser on April 15, 2005, 02:25 PM
Quote from: MyndFyre on April 15, 2005, 02:15 PM
Assuming you didn't have overflow, yes, but I don't see that expression in his code. You want either
RoundedSize = CDbl((LOF(intFile) / 1024) * 1024)
According to all my tests, it returns the same value. What's the point of doing / 1024 * 1024 is what I'm wanting to know
You should do \ 1024 then * 1024...
That seems correct. I wanted to know why he was doing it the other way
Private Sub SetVars()
hashCodes(0) = &HE7F4CB62
hashCodes(1) = &HF6A14FFC
hashCodes(2) = &HAA5504AF
hashCodes(3) = &H871FCDC2
hashCodes(4) = &H11BF6A18
hashCodes(5) = &HC57292E6
hashCodes(6) = &H7927D27E
hashCodes(7) = &H2FEC8733
End Sub
I suggest just space-delimiting them, and then calling them using Split(Hashcodes, Space(1)(MPQNum).
Quote from: Joex86] link=topic=11286.msg108723#msg108723 date=1113617931]
Private Sub SetVars()
hashCodes(0) = &HE7F4CB62
hashCodes(1) = &HF6A14FFC
hashCodes(2) = &HAA5504AF
hashCodes(3) = &H871FCDC2
hashCodes(4) = &H11BF6A18
hashCodes(5) = &HC57292E6
hashCodes(6) = &H7927D27E
hashCodes(7) = &H2FEC8733
End Sub
I suggest just space-delimiting them, and then calling them using Split(Hashcodes, Space(1)(MPQNum).
Why!?
No initiation sub needs to be called beforehand.
CRev() Initiated..
M(A) = -5091265
M(B) = 5284658
M(C) = 15061445
M(A) = -5091265
M(A) = -5091265
M(B) = 5284658
M(C) = 15061445
M(A) = -5091265
M(A) = -5091265
M(B) = 5284658
M(C) = 15061445
M(A) = -5091265
CRev() = 15061445
GG.
I lowered the mod to &HFFFFFF, because I don't remember if it was actually &HFFFFFFFF in the first place, and it works now. Not sure if it returned the correct value, but atleast it returned.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef destination As Any, ByRef Source As Any, ByVal numbytes As Long)
Private Const HashCodes As String = "&HE7F4CB62 &HF6A14FFC &HAA5504AF " _
& "&H871FCDC2 &H11BF6A18 &HC57292E6 &H7927D27E &H2FEC8733"
Public Function GetDWORD(Data As String) As Long
Dim lReturn As Long
Call CopyMemory(lReturn, ByVal Data, 4)
GetDWORD = lReturn
End Function
Public Function checkRevision(ByVal versionString As String, ByRef strFiles() As String, ByVal mpqNum As Integer) As Currency
'// Sample formula -- A=602362906 B=5284658 C=149279165 4 A=A+S B=B^C C=C^A A=A^B
Dim I1 As Integer, I2 As Integer, ToAdd As Long
Dim A As Currency, B As Currency, C As Currency, Splt() As String, O1 As String
Dim O2 As String, O3 As String, O4 As String, sTmpData As String
Splt = Split(versionString, " ")
A = CLng(Mid(Splt(0), 3))
B = CLng(Mid(Splt(1), 3))
C = CLng(Mid(Splt(2), 3))
O1 = Mid(Splt(4), 4, 1)
O2 = Mid(Splt(5), 4, 1)
O3 = Mid(Splt(6), 4, 1)
Debug.Print "CRev() Initiated.."
A = A Xor Split(HashCodes, " ")(mpqNum - 1)
For I1 = LBound(strFiles) To UBound(strFiles)
intFile = FreeFile
Open strFiles(I) For Binary Access Read As #intFile
RoundedSize = LOF(intFile) - (LOF(intFile) Mod 4) 'RoundedSize = CDbl((LOF(intFile) \ 1024) * 1024)
For I2 = 0 To RoundedSize Step 4
strTmpData = Space(4)
Get #intFile, I2 + 1, strTmpData
ToAdd = GetDWORD(CStr(strTmpData))
Select Case op1
Case "^": A = A Xor ToAdd
Case "-": A = A - S
Case "+": A = A + S
End Select
Debug.Print "M(A) = " & M(A)
A = M(A)
Select Case op2
Case "^": B = B Xor ToAdd
Case "-": B = B - C
Case "+": B = B + C
End Select
Debug.Print "M(B) = " & M(B)
B = M(B)
Select Case op3
Case "^": C = C Xor ToAdd
Case "-": C = C - A
Case "+": C = C + A
End Select
Debug.Print "M(C) = " & M(C)
C = M(C)
Select Case op4
Case "^": A = A Xor ToAdd
Case "-": A = A - B
Case "+": A = A + B
End Select
Debug.Print "M(A) = " & M(A)
A = M(A)
Next I2
Close #intFile
Next I1
Debug.Print "CRev() = " & C
checkRevision = C
End Function
Public Function M(l As Currency) As Currency
'Dim l2 As Long
'l2 = l
'While l2 > &HFFFFFFFF
' l2 = l2 - &HFFFFFFFF
'Wend
'M = l2
'// @Above: How slow can such simple code get?
M = l Mod &HFFFFFF
End Function
Quote from: HdxBmx27 on April 15, 2005, 06:11 PM
Now does the opertation thet B.net sends refer to all Bitwise opertations (Xor, Or, And, Etc...) or there mathmatical counterparts? (+, -, /, \, ^, *, etc...)
^ was explaind to mean Xor, and so could it be assumed that + means And, and - means Or? If so it always returns zero (not using Moduls()) with no overflows.
~-~(HDX)~-~
+ is + and - is -.
Incidentally, I'm not at all confident that a floating point value (which I imagine "currency" is?) will be accurate enough to do this correctly consistantly.
And yeah, the 3 symbols used are their common usage in all real languages:
^ = xor
- = minus
+ = plus
Quote from: iago on April 16, 2005, 02:21 PM
Incidentally, I'm not at all confident that a floating point value (which I imagine "currency" is?)
Currency isn't a floating point value. It's a fixed point value.
Quote from: Adron on April 16, 2005, 03:22 PM
Quote from: iago on April 16, 2005, 02:21 PM
Incidentally, I'm not at all confident that a floating point value (which I imagine "currency" is?)
Currency isn't a floating point value. It's a fixed point value.
What's the advantage of using it, then? Isn't there a better way to get numbers that won't overflow?
Quote from: iago on April 16, 2005, 03:28 PM
What's the advantage of using it, then? Isn't there a better way to get numbers that won't overflow?
The advantage, I suppose, would be to get exact calculations with decimal point numbers where roundings don't happen in any strange way. In the old days the advantage was that fixed point numbers were much faster to use than floating point numbers.
The best way of not getting an overflow error for numbers might be to tell the compiler not to generate overflow checks.... :P
Can VB do that?
Quote from: iago on April 16, 2005, 03:47 PM
Can VB do that?
Only when you compile your code. It's listed as an optimization.
Hmm, perhaps these gentlemen should try that
That'd be a royal pain, especially in debugging (interpreted code, not compiled).
To save you all the trouble, here is the checkrevision me and NiNe wrote. Note this has only been tested with starcraft and warcraft 2.
Cost with compiled exe and all advanced optimizations turned on (0.671 seconds). Machine stats - 1 gig DDR ram, 3.06ghz P4.
[Kp edit: killed horribly long code paste, it was ruining the thread. On top of that, it was VB!]
It's a vb checkrevision thread, what do you expect duh!
Here is the download link kp erased:
http://mercury.walagata.com/w/ddjl/VB6CheckRevision.rar
To view the CCheckRevision class, here is a quick link:
http://mercury.walagata.com/w/ddjl/CCheckRevision.txt
The point is that they were doing it for a challenge, not because they wanted an implementation of it.
Ok this is funny,
they are having fun in a topic, like all users helping and in 1 second the fun can end because of an %$&%.
[Edit: The life can end like that soon or later too]