I am trying to write a binary bot for battle.net.
I started to look at some converted VB sources, and I tried to copy selected bits of code over at a time. Did not take me long to discover I was going no where fast.
Basically, I just want some basic pointers about where to start in terms of writting a binary bot.. I do not want to use CSB (I can't anyway) or anything like it.
I have:
Basic TCP/IP experience (I can buffer the CHAT protocol)
Advance Understanding of arrays, variables, constants, OOP aspects, etc.
I don't:
Any experience with battle.net binary connections
Any idea what the best way to "hash" is
Any idea what protocol battle.net or how to parse it.
Thanks in advance guys!
Hmm. If it's in Java, JavaOp2 has some really nice hashing functions and such, and is probably a good base to learn off of.
If it's in VB, I'm no longer good at programming (sad huh? :() so I cannot help you much.
Also, check out http://bnetdocs.valhallalegends.com as it will answer most of your questions.
You guys reply so fast its not even funny...
Thanks for the thoughts.
I am programming in REALbasic (RB).
I will definitely take a look at iago's hashing methods and see if I can port them (manually, of course.)
I think bnetdocs might be a tad bit over my head, at the moment. I have no idea what a "word" or "dword" is, I know what a byte is, but I have no idea how to implement any of them into a string.
Also, when they refer to "length" they mean bytes, not characters, right?
The binary Battle.net protocol is well-documented at BnetDocs (http://bnetdocs.valhallalegends.com/content.php). Battle.net's protocol is an Application-layer protocol on top of standard TCP/IP.
I assume "RB" means "RealBasic." You should be more clear about that in the future. ;)
I highly recommend you do not look at other peoples' source code. Especially VB source code. Generally, VB programmers don't write good code and then make it public (I'm not saying this is true about people here... necessarily...), and you'll have problems especially if you just try to convert it. Instead, focus on making a bot by breaking it into tasks that you need to handle:
1.) Be able to read from and write to a network stream. This can be handled by a control or object of your own choosing, but ultimately, if you're using Windows, you'll have to incorporate the Winsock API; for non-Windows development, you'll want to use the platform-specific socket libraries (most likely the basic Berkeley sockets implementation). It would be wise to encapsulate this into some kind of class -- I believe classes can be instantiated more than once, as well. Plus, your classes can hide how the receive and send data from the parts of your program that use the class, so you could have something like this (if RB allows conditional compilation):
Public Sub Send(ByVal data As DataBuffer)
#If Windows
' do Windows-specific calls like send() here.
#ElseIf Linux
' do Linux-specific calls here.
#ElseIf MacOSX
' do Mac OS-X specific calls here.
#EndIf
End Sub
2.) Be able to manage threads, if RB supports them. Windows controls only allow updating on the thread that created the controls, and so you'll need to ensure that, if you're using multiple threads, you're only updating the controls on the proper thread.
3.) Understand the events appropriate to Battle.net. Events are not necessary for every Server->Client message, and some S->C messages define multiple events (SID_CHATEVENT is one such message).
To get yourself up-and-running somewhat quikly, I would suggest using BNLS (http://www.valhallalegends.com/yoni/bnlsprotocolspec.txt) to get started. Buy an extra CD key for $5 if it makes you feel better, and use an account that you don't care about the password for. It's another protocol to learn, but the BNLS logon sequence is fairly straightforward if you can read through the protocol specification.
You may not like CSB, but if you're an OOP-aware programmer, you should appreciate its application. It does a good job of encapsulating and shielding the end-user from the intracacies of Battle.net, which is what a good component is supposed to do.
Hope that helps.
[edit]
To address other concerns:
BnetDocs has descriptions about the types of data (http://bnetdocs.valhallalegends.com/content.php?Section=d&id=4) used in Battle.net. WORDs are 16-bit unsigned integers, and DWORDs are 32-bit unsigned integers. You should also understand what signed and unsigned, as well has hex and binary representations (http://forum.valhallalegends.com/phpbbs/index.php?topic=6435.0) are. Endian-ness (http://forum.valhallalegends.com/phpbbs/index.php?topic=12211.msg120721#msg120721) too.
RealBasic eh? Good luck with that!
(As for posting quick, I just happened to visit the forums the same time you posted this!)
Not sure what a WORD or a DWORD is? Well, have no fear, BnetDocs has most of that information (including what length is (bytes)) here! (http://bnetdocs.valhallalegends.com/content.php?Section=d&id=4)
Somehow I also forgot to mention that BNCSUtil (http://bncsutil.ionws.com/) is also available for local hashing (somewhat silly, since I made the .NET version of it). The COM parts of MBNCSUtil (http://www.jinxbot.net/mbncsutil) (.NET BNCSUtil more or less) also work with Windows clients, if RB supports COM.
Quote from: MyndFyrex86] link=topic=2517.msg23969#msg23969 date=1125364920]
The binary Battle.net protocol is well-documented at BnetDocs (http://bnetdocs.valhallalegends.com/content.php). Battle.net's protocol is an Application-layer protocol on top of standard TCP/IP.
I assume "RB" means "RealBasic." You should be more clear about that in the future. ;)
Got that. I did state what RB meant in my above post
Quote
I highly recommend you do not look at other peoples' source code. Especially VB source code. Generally, VB programmers don't write good code and then make it public (I'm not saying this is true about people here... necessarily...), and you'll have problems especially if you just try to convert it.
I noticed.. I stopped trying when I realized I was "going no where fast".
Quote
Instead, focus on making a bot by breaking it into tasks that you need to handle:
1.) Be able to read from and write to a network stream. This can be handled by a control or object of your own choosing, but ultimately, if you're using Windows, you'll have to incorporate the Winsock API; for non-Windows development, you'll want to use the platform-specific socket libraries (most likely the basic Berkeley sockets implementation). It would be wise to encapsulate this into some kind of class -- I believe classes can be instantiated more than once, as well. Plus, your classes can hide how the receive and send data from the parts of your program that use the class, so you could have something like this (if RB allows conditional compilation):
Public Sub Send(ByVal data As DataBuffer)
#If Windows
' do Windows-specific calls like send() here.
#ElseIf Linux
' do Linux-specific calls here.
#ElseIf MacOSX
' do Mac OS-X specific calls here.
#EndIf
End Sub
REALbasic's TCPSocket, is cross-platform, so I do not need to re-write it per OS.
Quote
2.) Be able to manage threads, if RB supports them. Windows controls only allow updating on the thread that created the controls, and so you'll need to ensure that, if you're using multiple threads, you're only updating the controls on the proper thread.
I know how to use threads, but I see no need for one. I can use timers if I want to check something every X seconds, or constantly. But I only need to respond when I get data, I am connected, there is an error, etc., right?
Quote
3.) Understand the events appropriate to Battle.net. Events are not necessary for every Server->Client message, and some S->C messages define multiple events (SID_CHATEVENT is one such message).
Ya.. I have a good understanding about which packets to send, what data should be in them, etc. The problems I am having involve parsing incoming packets and sending outgoing packets.
Quote
To get yourself up-and-running somewhat quikly, I would suggest using BNLS (http://www.valhallalegends.com/yoni/bnlsprotocolspec.txt) to get started. Buy an extra CD key for $5 if it makes you feel better, and use an account that you don't care about the password for. It's another protocol to learn, but the BNLS logon sequence is fairly straightforward if you can read through the protocol specification.
Ewww.... BNLS! ;) . I think I might, but I have other ways of running all the things BNLS can do locally, and I think BNLS steals keys...
Quote
You may not like CSB, but if you're an OOP-aware programmer, you should appreciate its application. It does a good job of encapsulating and shielding the end-user from the intracacies of Battle.net, which is what a good component is supposed to do.
If you have a way to use CSB with REALbasic, let me know. Its a good way to figure things out. (Not really, but w/e ;) )
Quote
Hope that helps.
[edit]
To address other concerns:
BnetDocs has descriptions about the types of data (http://bnetdocs.valhallalegends.com/content.php?Section=d&id=4) used in Battle.net. WORDs are 16-bit unsigned integers, and DWORDs are 32-bit unsigned integers. You should also understand what signed and unsigned, as well has hex and binary representations (http://forum.valhallalegends.com/phpbbs/index.php?topic=6435.0) are. Endian-ness (http://forum.valhallalegends.com/phpbbs/index.php?topic=12211.msg120721#msg120721) too.
Yep, thanks.
Here is some code I wrote up fast for WORDs and DWORDS:
Function MakeWORD, data as string, returns string:
Dim tmp as String
Dim a as String
Dim B as String
DIM varMakeWORD as String
tmp = Right("0000" + hex(Data), 4)
a = Mid(tmp, 1, 2)
B = Mid(tmp, 3, 2)
varMakeWORD=Chr( Val("&H" + B) )
varMakeWORD=MakeWORD + Chr( Val("&H" + a) )
Return varMakeWORD
Function MakeFWORD, data as integer, returns string:
Dim tmp as String
Dim a as String
Dim B as String
Dim c as String
Dim D as String
DIM varMakeDWORD as String
tmp = Right("00000000" + hex(Data), 8)
a = Mid(tmp, 1, 2)
B = Mid(tmp, 3, 2)
c = Mid(tmp, 5, 2)
D = Mid(tmp, 7, 2)
varMakeDWORD=Chr(Val("&H" + D))
varMakeDWORD=MakeDWORD + Chr(Val("&H" + c))
varMakeDWORD=MakeDWORD + Chr(Val("&H" + B))
varMakeDWORD=MakeDWORD + Chr(Val("&H" + a))
Return varMakeDWORD
Correct me if I am wrong, please.
[edit]
I have used BNCSUtil, and was planning on it.
Oh ya, one more:
Function ApplyHeaders, MessageID as Integer:
subpacket = chr(&HFF) + chr(MessageID) + MakeWord(LenB(subpacket) + 2)
// Add 2 because a WORD is to bytes.
subpacket is the packet data.
Correct me if I am wrong!
Quote from: Ryan Marcus on August 29, 2005, 09:44:30 PM
I know how to use threads, but I see no need for one. I can use timers if I want to check something every X seconds, or constantly. But I only need to respond when I get data, I am connected, there is an error, etc., right?
Polling is a suboptimal way of waiting for data. If you can put one thread into a blocking recv() or Receive() call, and then do other stuff in your main thread, you're way ahead of the game. Threads can communicate to each other via events or callbacks, which is much more efficient than polling, and pretty much the way a blocking recv() call is intended to work.
Quote from: Ryan Marcus on August 29, 2005, 09:44:30 PM
Ewww.... BNLS! ;) . I think I might, but I have other ways of running all the things BNLS can do locally, and I think BNLS steals keys...
Nah, BNLS doesn't steal keys, but be aware that anyone else looking at your internet connection can steal your keys and passwords. :)
Quote from: Ryan Marcus on August 29, 2005, 09:44:30 PM
If you have a way to use CSB with REALbasic, let me know. Its a good way to figure things out. (Not really, but w/e ;) )
Nah, I'm not suggesting you
use CSB, just don't bash it like most experienced programmers. It is an eloquent solution and a good exercise in modular programming. Most people's problem with CSB stems from the stream of morons who don't understand how to program who also think they can use it.
I'm not experienced enough in Basic to comment on your code. However, allow me to make a suggestion about handling incoming data that will make your life a jillion times easier.
Take a look at this class (http://cvs.sourceforge.net/viewcvs.py/jinxbot/Jinx/Jinx.Core/Net/DataReader.cs?rev=1.1&view=markup). It accepts a byte array during creation, and then acts as if that byte array was a stream.
Essentially, if you want to read a DWORD, it acts as if you have a pointer and you're casting it to a DWORD (that's the function of the .NET BitConverter class, which is used heavily in this code). For example (this is C#), I have:
public int ReadDword()
{
int i = BitConverter.ToInt32(m_data, m_pos);
m_pos += 4;
return i;
}
I could have expressed this equivalently as:
public unsafe int ReadDword()
{
int i = 0;
fixed (byte *pArray = &m_data)
{
pArray += m_pos;
i = (int*)pArray++;
m_pos += 4;
}
return i;
}
However, due to performance costs, I stuck with the managed version. ;)
For example, though, I might do something like this:
private void ParseBNCS(DataReader reader, short length, BncsMessage id)
{
switch (id)
{
case BncsMessage.SID_AUTH_INFO:
int logonType = reader.ReadDword();
int serverToken = reader.ReadDword();
int udpValue = reader.ReadDword();
DateTime mpqTime = DateTime.FromFileTime( reader.ReadQword() );
string ix86filename = reader.ReadNTString();
string crValueString = reader.ReadNTString();
ProcSidAuthInfo(logonType, serverToken, udpValue, mpqTime, ix86filename, crValueString);
break;
case default:
// inform the system of an unsupported message ID.
break;
}
}
Hopefully you can read that well enough to see that it would significantly help you to do something like that.
Sure can. This right:
Dim tmp as String
Dim a as String
Dim B as String
Dim c as String
Dim D as String
DIM varGetDWORD as Long
tmp = Hex(Data)
a = Mid(tmp, 1, 2)
B = Mid(tmp, 3, 2)
c = Mid(tmp, 5, 2)
D = Mid(tmp, 7, 2)
tmp = D + c + B + a
varGetDWORD=Val("&H" + tmp)
Return varGetDWORD
Gimme a sec, I'll post my buffer and debuffer. They're written for VB, and RemoveNTString is messy, but they should work nicely with little effort.
http://www.javaop.com/~joe/VB6/clsBuffer.cls
Usage:
Dim Buffer as New clsBuffer
With Buffer
.InsertByte 1
.PushRaw
'Call insert subs for 0x50 components
.PushBNCS &H50
.Flush frmMain.sckBnet 'Pass a socket to send it from
End With
http://www.javaop.com/~joe/VB6/clsDebuffer.cls
Usage:
Public Sub Parse(Data as String)
Dim Debuffer as New clsDebuffer
With Debuffer
.Buffer = Data
.RemoveVoid 1
PacketID = .RemoveByte(1)
.RemoveVoid 2 'This is the length WORD, if you need it
Select Case PacketID
'Yeah. That.
End Select
End Sub
QuoteFunction ApplyHeaders, MessageID as Integer
You want to pass MessageID as Byte (see my packetbuffer above) because if you pass an integer bigger than a byte, say, 257, you'll get a runtime error when you cast it to a byte using Chr().
QuoteI think bnetdocs might be a tad bit over my head, at the moment. I have no idea what a "word" or "dword" is
http://www.javaop.com/~joe/datatypes/
I knew I wrote that for a reason. =p
QuoteI highly recommend you do not look at other peoples' source code. Especially VB source code. Generally, VB programmers don't write good code and then make it public
Although I'm terrified to suggest LoRd[nK] over myself, his BBBB code is about as clean as VisualBasic can get. I'm not sure if its all finished and stuff, but it's rather good. -shutter-. Anyhow, c0Ld-chaos (the site where he was hosted) had its domain expire, but it might be back now. Newby, do you know where to get a copy?
Quote from: Dishfoot on August 30, 2005, 02:05:24 AM
Gimme a sec, I'll post my buffer and debuffer. They're written for VB, and RemoveNTString is messy, but they should work nicely with little effort.
http://www.javaop.com/~joe/VB6/clsBuffer.cls
Usage:
Dim Buffer as New clsBuffer
With Buffer
.InsertByte 1
.PushRaw
'Call insert subs for 0x50 components
.PushBNCS &H50
.Flush frmMain.sckBnet 'Pass a socket to send it from
End With
I already have a working buffer, thanks. I will post it sometime...
Quotehttp://www.javaop.com/~joe/VB6/clsDebuffer.cls
Usage:
Public Sub Parse(Data as String)
Dim Debuffer as New clsDebuffer
With Debuffer
.Buffer = Data
.RemoveVoid 1
PacketID = .RemoveByte(1)
.RemoveVoid 2 'This is the length WORD, if you need it
Select Case PacketID
'Yeah. That.
End Select
End Sub
Dude.... THANK YOU!
QuoteQuoteFunction ApplyHeaders, MessageID as Integer
You want to pass MessageID as Byte (see my packetbuffer above) because if you pass an integer bigger than a byte, say, 257, you'll get a runtime error when you cast it to a byte using Chr().
REALbasic has no byte data type. I will only pass integers under 257, and besides, the highest I need to go is &H82.
QuoteQuoteI think bnetdocs might be a tad bit over my head, at the moment. I have no idea what a "word" or "dword" is
http://www.javaop.com/~joe/datatypes/
I knew I wrote that for a reason. =p
Thank you once more!
QuoteQuoteI highly recommend you do not look at other peoples' source code. Especially VB source code. Generally, VB programmers don't write good code and then make it public
Although I'm terrified to suggest LoRd[nK] over myself, his BBBB code is about as clean as VisualBasic can get. I'm not sure if its all finished and stuff, but it's rather good. -shutter-. Anyhow, c0Ld-chaos (the site where he was hosted) had its domain expire, but it might be back now. Newby, do you know where to get a copy?
I have way to many source codes already... I have ported VB bots successfully (they will run and connect on mac), I just want to write one myself ;).
EDIT: De-murdified the quote blocks. -Joe
I de-murdified your quote blocks. =p
You're welcome, many times over. Feel free to IM me (information to the left) if you have any questions.
Quote from: Ryan Marcus on August 30, 2005, 08:19:32 AM
REALbasic has no byte data type. I will only pass integers under 257, and besides, the highest I need to go is &H82.
Byte values are only valid under 255. A byte is 8 bits, which can represent 0 to 2
8 - 1. 2
8 - 1 = 255.
Joe, I hope you corrected your data types document. The last time you talked about it, half the stuff in it was wrong. And you're really just recreating the BnetDocs data types stuff anyway.
Quote from: MyndFyrex86] link=topic=2517.msg24082#msg24082 date=1125419705]
Quote from: Ryan Marcus on August 30, 2005, 08:19:32 AM
REALbasic has no byte data type. I will only pass integers under 257, and besides, the highest I need to go is &H82.
Byte values are only valid under 255. A byte is 8 bits, which can represent 0 to 28 - 1. 28 - 1 = 255.
Joe, I hope you corrected your data types document. The last time you talked about it, half the stuff in it was wrong. And you're really just recreating the BnetDocs data types stuff anyway.
Sorry, met to say 255... Thanks.
Quote from: Dishfoot on August 30, 2005, 02:05:24 AM
Gimme a sec, I'll post my buffer and debuffer. They're written for VB, and RemoveNTString is messy, but they should work nicely with little effort.
http://www.javaop.com/~joe/VB6/clsBuffer.cls
Usage:
Dim Buffer as New clsBuffer
With Buffer
.InsertByte 1
.PushRaw
'Call insert subs for 0x50 components
.PushBNCS &H50
.Flush frmMain.sckBnet 'Pass a socket to send it from
End With
http://www.javaop.com/~joe/VB6/clsDebuffer.cls
Usage:
Public Sub Parse(Data as String)
Dim Debuffer as New clsDebuffer
With Debuffer
.Buffer = Data
.RemoveVoid 1
PacketID = .RemoveByte(1)
.RemoveVoid 2 'This is the length WORD, if you need it
Select Case PacketID
'Yeah. That.
End Select
End Sub
QuoteFunction ApplyHeaders, MessageID as Integer
You want to pass MessageID as Byte (see my packetbuffer above) because if you pass an integer bigger than a byte, say, 257, you'll get a runtime error when you cast it to a byte using Chr().
QuoteI think bnetdocs might be a tad bit over my head, at the moment. I have no idea what a "word" or "dword" is
http://www.javaop.com/~joe/datatypes/
I knew I wrote that for a reason. =p
QuoteI highly recommend you do not look at other peoples' source code. Especially VB source code. Generally, VB programmers don't write good code and then make it public
Although I'm terrified to suggest LoRd[nK] over myself, his BBBB code is about as clean as VisualBasic can get. I'm not sure if its all finished and stuff, but it's rather good. -shutter-. Anyhow, c0Ld-chaos (the site where he was hosted) had its domain expire, but it might be back now. Newby, do you know where to get a copy?
Sorry for the double post... Modify is going really slow..
You forgot to include your GetWORD and GetDWORD methods.. Any chance I could get those?
This is the buffer I am currently using, hope it helps:Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private databuff As String
Private datalen As Integer
Private epos As Integer
Private isOutbuff As Boolean
Public Event buffError(Number As Integer, Description As String, Routine As String)
Private Sub Class_Initialize()
Call Me.Clear
End Sub
Public Sub SetOutBuff()
isOutbuff = True
End Sub
Public Sub Clear()
databuff = ""
datalen = 0
epos = 1
End Sub
Public Sub LoadBuffer(ByVal s_Data As String)
On Error GoTo Handler
Call Me.Clear
databuff = s_Data
datalen = Len(s_Data)
On Error GoTo 0
Exit Sub
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "LoadBuffer()")
End If
End Sub
Public Sub Setepos(place As Integer)
If place > 0 And place < Len(databuff) Then epos = place
End Sub
Public Function Getepos() As Integer
Getepos = epos
End Function
Public Sub SendPacket(socket As CSocket, PID As Byte)
socket.SendData Chr(&HCF) & Chr(PID)
socket.SendData MakeDBYTE(datalen + 4)
socket.SendData databuff
Call Clear
End Sub
Public Sub SendPacket2(socket As CSocket, PID As Byte, cbuff As clsBuffer)
socket.SendData Chr(&HCF) & Chr(PID)
socket.SendData MakeDBYTE(Len(cbuff.getBuffer()) + 4)
socket.SendData cbuff.getBuffer()
Call Clear
End Sub
Public Sub InsertSTRING(ByVal s_Data As String)
On Error GoTo Handler
datalen = datalen + Len(s_Data) + 1
databuff = Left(databuff, datalen) & s_Data & Chr(0)
On Error GoTo 0
Exit Sub
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "InsertSTRING()")
End If
End Sub
Public Sub InsertBYTE(ByVal b_Data As Byte)
On Error GoTo Handler
databuff = databuff & Chr(b_Data)
datalen = datalen + 1
On Error GoTo 0
Exit Sub
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "InsertBYTE()")
End If
End Sub
Public Sub InsertDBYTE(ByVal db_Data As Integer)
On Error GoTo Handler
databuff = databuff & MakeDBYTE(db_Data)
datalen = datalen + 2
On Error GoTo 0
Exit Sub
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "InsertDBYTE()")
End If
End Sub
Public Sub InsertWORD(ByVal w_Data As Long)
On Error GoTo Handler
databuff = databuff & MakeWORD(w_Data)
datalen = datalen + 4
On Error GoTo 0
Exit Sub
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "InsertWORD()")
End If
End Sub
Public Function getBuffer() As String
On Error GoTo Handler
If datalen = 0 Then Exit Function
getBuffer = Left(databuff, datalen)
On Error GoTo 0
Exit Function
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "getBuffer()")
End If
End Function
Public Function ExtractSTRING() As String
Dim ret As String
ret = Mid(databuff, epos, InStr(epos, databuff, Chr(&H0)))
ret = Left(ret, InStr(1, ret, Chr(&H0)))
epos = epos + Len(ret)
ExtractSTRING = ret
End Function
Public Function ExtractBYTE() As String
Dim ret As String
ret = Mid(databuff, epos, 1)
epos = epos + 1
ExtractBYTE = ret
End Function
Public Function ExtractDBYTE() As String
Dim ret As String
ret = Mid(databuff, epos, 2)
epos = epos + 2
ExtractDBYTE = ret
End Function
Public Function ExtractWORD() As String
Dim ret As String
ret = Mid(databuff, epos, 4)
epos = epos + 4
ExtractWORD = ret
End Function
Public Function ExtractDATA(LENGTH As Long) As String
Dim ret As String
ret = Mid(databuff, epos, LENGTH)
epos = epos + LENGTH
ExtractDATA = ret
End Function
Private Function MakeWORD(Value As Long) As String
On Error GoTo Handler
Dim Result As String * 4
CopyMemory ByVal Result, Value, 4
MakeWORD = Result
On Error GoTo 0
Exit Function
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "MakeWORD()")
End If
End Function
Private Function MakeDBYTE(Value As Integer) As String
On Error GoTo Handler
Dim Result As String * 2
CopyMemory ByVal Result, Value, 2
MakeDBYTE = Result
On Error GoTo 0
Exit Function
Handler:
If isOutbuff Then
RaiseEvent buffError(Err.Number, Err.Description, "MakeDBYTE()")
End If
End Function
Public Function GetByteAsString(var As String) As String
Dim k As Long
Dim ret As String
k = Asc(Left(var, 1))
If k < 0 Or k > 255 Then
GetByteAsString = "[error]"
Exit Function
End If
ret = Hex(k)
ret = IIf(Len(ret) = 1, "0", "") & ret
GetByteAsString = "0x" & ret
End Function
Well, mine use copymemory or cpymem or whatever you want to call it, a Win32 API. You probably won't want to use that. Regaurdless, here (http://www.javaop.com/~joe/VB6/modWORD.bas) they are.
These can easily be written without copymemory, but seeing as how it VB instead of C(++) or whatever they wrote the API in, its a *tad* slower. I've found not to mind it. I'll write these for you, but I'm off to school in a few minutes. I'll catch ya when I get home.
EDIT -
R.a.B.B.i.T, unless you go back into the buffer to dig something out again, I find it much quicker (not compiled, but to write) if you just kill the front of the buffer instead of moving along it with a position marker.
Well I use that so I can have multiple things use the same data without duplicating the buffer several times. Do what you will.
Quote from: Joex86] link=topic=2517.msg24652#msg24652 date=1125661186]
Well, mine use copymemory or cpymem or whatever you want to call it, a Win32 API. You probably won't want to use that. Regaurdless, here (http://www.javaop.com/~joe/VB6/modWORD.bas) they are.
These can easily be written without copymemory, but seeing as how it VB instead of C(++) or whatever they wrote the API in, its a *tad* slower. I've found not to mind it. I'll write these for you, but I'm off to school in a few minutes. I'll catch ya when I get home.
EDIT -
R.a.B.B.i.T, unless you go back into the buffer to dig something out again, I find it much quiker (not compiled, but to write) if you just kill the front of the buffer instead of moving along it with a position marker.
RtlMoveMemory, or
CopyMemory as it's been called since Visual Basic supported the use of API calls, is much faster than any Visual Basic-made clone.
I know that. Statistics are great. However, look on the reality side. What end user is really going to sit there and count the miliseconds used by your MakeDWORD method? Unless you do it about 1000 times over, nobody will notice.
Disclaimer:
I didn't actually test it 1000 times. It was an estimate.
And that's exactly why you'll never become a good programmer.
Quote from: Joex86] link=topic=2517.msg24830#msg24830 date=1125779297]
I know that. Statistics are great. However, look on the reality side. What end user is really going to sit there and count the miliseconds used by your MakeDWORD method? Unless you do it about 1000 times over, nobody will notice.
Disclaimer:
I didn't actually test it 1000 times. It was an estimate.
API calls were added to VB for a reason, Joe.