|
Post by hydrophilic on Aug 22, 2014 5:51:58 GMT
Now that is very interesting... it seems you first read it into a byte array, with ReadAllBytes, but then convert it into a (unicode!) string called 'compressTarget' and then iterate through that as if it were an ASCII/ANSI string (using Mid and Len, but without any B suffix). Well if it works, great.
I have VisualBASIC v6 and VisualBASIC.NET, but these are older (pre-2010) versions, so I don't think if I tested that code I could give any reliable feedback... but from a generic point of view, I did see one thing you might want to change...
If processPointer > endOfProcess Then If Len(raw) = 0 Then outputString = outputString & Chr(0) Exit Do End If outputString = outputString & Chr(Len(raw) * 4) & raw & Chr(0) Exit Do End If
Although that is probably okay when using only Raw packets, a more general approach that should work with any/all packet types might be coded like this:
If processPointer > endOfProcess Then If Len(raw) > 0 Then outputString = outputString & Chr(Len(raw) * 4) & raw End If outputString = outputString & Chr(0) Exit Do End If
Hopefully you can see that both versions produce the same the output with only Raw packets, but the second version should be easier to expand to include other types like RLE/Copy (just change the IF into IF...ELSE IF...ELSE IF) and always end with '& Chr(0)'. I'm speaking from experience (although my video encoder is in C, hopefully you agree the same principles apply in almost any language).
Anyway, keep up the good work. I think once you get RLE working correctly, (also easy to verify) you should see by looking at your code how to implement Copy (of course near/far versions would need to be slightly different). In that case, it should be easy to verify it produces CORRECT output, but quite difficult to verify it produces OPTIMAL output. Although it would be nice, there is no strict requirement to produce OPTIMAL output (unless maybe you want to sell a guaranteed version?)... in other words, as long it produces GOOD (near optimal) output, that should be just fine (obviously my opinion, more demanding lurkers might say otherwise).
Deleted junk characters here...
|
|
|
Post by VDC 8x2 on Aug 22, 2014 8:25:29 GMT
working rle now. needs some cleanup still before going on to next part.
Module Module1
Sub Main() Dim outputString As String = "" Dim packetSize As Integer = 0 Dim starting() As Byte = {0} Dim stringCount As Integer Dim historyPointer As Integer Dim processPointer As Integer Dim futurePointer As Integer Dim endOfProcess As Integer Dim raw As String = "" Dim compressTarget As String = "" Dim anyCompression As Boolean Dim count As Integer
Dim bytes = My.Computer.FileSystem.ReadAllBytes("D:/Emulation/drive10/testdata.prg") 'convert array into our workstring For index = 0 To bytes.GetUpperBound(0) compressTarget = compressTarget & Chr(bytes(index)) Next historyPointer = 0 processPointer = 1 futurePointer = 256
endOfProcess = Len(compressTarget) Do stringCount = 1 anyCompression = False Do If Mid(compressTarget, processPointer, 1) = Mid(compressTarget, processPointer + stringCount, 1) Then stringCount = stringCount + 1 anyCompression = True If stringCount = futurePointer Then Exit Do End If Else Exit Do End If Loop If anyCompression = True Then If Len(raw) <> 0 Then outputString = outputString & Chr(Len(raw) * 4) & raw raw = "" End If If stringCount = 256 Then outputString = outputString & Chr(2) & Mid(compressTarget, processPointer, 1) Else If stringCount > 64 Then stringCount = 64 End If outputString = outputString & Chr((stringCount - 1) * 4 + 2) & Mid(compressTarget, processPointer, 1) End If processPointer = processPointer + stringCount If processPointer > endOfProcess Then outputString = outputString & Chr(0) Exit Do End If End If If anyCompression = False Then raw = raw & Mid(compressTarget, processPointer, 1) processPointer = processPointer + 1 If Len(raw) = 63 Then outputString = outputString & Chr(63 * 4) & raw raw = "" End If If processPointer > endOfProcess Then If Len(raw) = 0 Then outputString = outputString & Chr(0) Exit Do End If outputString = outputString & Chr(Len(raw) * 4) & raw & Chr(0) Exit Do End If End If If processPointer + futurePointer > endOfProcess Then futurePointer = futurePointer - (processPointer + futurePointer - endOfProcess) End If If futurePointer = 0 Then outputString = outputString & Chr(0) Exit Do End If Loop Dim outputFile(Len(outputString)) As Byte For count = 1 To Len(outputString) outputFile(count) = Asc(Mid(outputString, count, 1)) Next My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", starting, False) My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", outputFile, True) End Sub
End Module
|
|
|
Post by hydrophilic on Aug 22, 2014 10:20:07 GMT
Thanks for sharing! Have you checked this is actually produces valid Raw/RLE code ?
I must admit, some of it seems strange, but upon examination it seems correct... (I could try testing myself, but not sure the results would be applicable to your verision of VB). It still pisses me off that MS would break compatibility with itself! Just as stupid as CBM v7 incompatible with v4.7... it is not neccessary, yet some dumbass programmed it anyway.
Obviouslly (hopefully), I am not the supervisor of such programmers (otherwise there would be many dead bodies to discard...)
|
|
|
Post by VDC 8x2 on Aug 22, 2014 15:33:58 GMT
The codes are valid to my decoder. So many bodies, so little time to hide them.
|
|
|
Post by VDC 8x2 on Aug 22, 2014 17:27:49 GMT
on a bsaved graphic1,1 screen, it has compressed it down to 91 bytes. I was just testing best case with the rle/raw.
|
|
|
Post by hydrophilic on Aug 23, 2014 10:12:23 GMT
Great to hear that hear RLE is verified working. Personally, I would try to clean up / simplify the code before moving on to Copy. Well you could just move on to Copy, and once you get it working it should be rather obvious how you can "optimize" the code to deal with either RLE/Copy in a generic/effecient manner. Ummm, yeah, there are multiple ways to develope a "sophisticated" piece of software... the end result is all that really matters: 1. Does it do the job ? 2. Does it do it always do it correctly? 3. Is it effecient? 4. Is it easy to use?
Feel free to re-order those... in particular #4 should be much higher in the list from a practical/human/user point of view... in fact, I think many software publishers use that formula!!! In other words, they often put human usability last... which is just plain wrong in my opinion, and why I have little respect for modern software. (In general... sometimes you find a gem that is extremely user friendly.)
|
|
|
Post by VDC 8x2 on Aug 24, 2014 4:11:13 GMT
So far, the program is showing correct compression codes.
Mirror copy version:
Module Module1
Sub Main() Dim outputString As String = "" Dim packetSize As Integer = 0 Dim starting() As Byte = {0} Dim stringCount As Integer Dim historyPointer As Integer = 0 Dim processPointer As Integer = 1 Dim futurePointer As Integer = 256 Dim endOfProcess As Integer Dim raw As String = "" Dim compressTarget As String = "" Dim anyCompression As Integer Dim count As Integer
Dim bytes = My.Computer.FileSystem.ReadAllBytes("D:/Emulation/drive10/testdata.prg") 'convert array into our workstring For index = 0 To bytes.GetUpperBound(0) compressTarget = compressTarget & Chr(bytes(index)) Next endOfProcess = Len(compressTarget) Do stringCount = 1 anyCompression = 0 If historyPointer > 257 Then If futurePointer = 256 Then stringCount = futurePointer If Mid(compressTarget, processPointer - 257, stringCount) = Mid(compressTarget, processPointer + 256, stringCount) Then anyCompression = 2 End If End If End If If anyCompression = 0 Then If historyPointer > 65 Then If futurePointer > 63 Then stringCount = 64 Else stringCount = futurePointer End If Do If Mid(compressTarget, processPointer - stringCount - 1, stringCount) = Mid(compressTarget, processPointer + stringCount, stringCount) Then anyCompression = 2 Exit Do Else stringCount = stringCount - 1 If stringCount = 1 Then Exit Do End If End If Loop End If End If If anyCompression = 0 Then Do If Mid(compressTarget, processPointer, 1) = Mid(compressTarget, processPointer + stringCount, 1) Then stringCount = stringCount + 1 anyCompression = 1 If stringCount = futurePointer Then Exit Do End If Else Exit Do End If Loop End If If anyCompression > 0 Then If Len(raw) <> 0 Then outputString = outputString & Chr(Len(raw) * 4) & raw raw = "" End If End If If anyCompression = 2 Then If stringCount = 256 Then outputString = outputString & Chr(1) Else outputString = outputString & Chr((stringCount - 1) * 4 + 1) End If End If If anyCompression = 1 Then If stringCount = 256 Then outputString = outputString & Chr(2) & Mid(compressTarget, processPointer, 1) Else If stringCount > 64 Then stringCount = 64 End If outputString = outputString & Chr((stringCount - 1) * 4 + 2) & Mid(compressTarget, processPointer, 1) End If End If If anyCompression = 0 Then raw = raw & Mid(compressTarget, processPointer, 1) If Len(raw) = 63 Then outputString = outputString & Chr(63 * 4) & raw raw = "" End If If Len(raw) = futurePointer Then outputString = outputString & Chr(Len(raw) * 4) & raw raw = "" End If End If
historyPointer = historyPointer + stringCount If historyPointer > 2048 Then historyPointer = 2048 End If processPointer = processPointer + stringCount If processPointer + futurePointer > endOfProcess Then futurePointer = futurePointer - (processPointer + futurePointer - endOfProcess) End If If futurePointer = 0 Then outputString = outputString & Chr(0) Exit Do End If Loop Dim outputFile(Len(outputString)) As Byte For count = 1 To Len(outputString) outputFile(count) = Asc(Mid(outputString, count, 1)) Next My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", starting, False) My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", outputFile, True)
End Sub
End Module
|
|
|
Post by hydrophilic on Aug 24, 2014 6:35:49 GMT
Glad that you got it working! You might want to add some REMs for everyone's benefit, especially yourself a year from now I think I understand it... so first it does three checks, first a 'big' copy of 256, then a 'normal' copy of 64 or less, then (if both those fail), a check for RLE. Next it just acts on the discovery... it outputs a 'big' or 'normal' copy packet (anyCompression=2), or an RLE packet (anyCompression=1), or else it just builds up a raw packet (anyCompression=0). Well that is my generic understanding... of course along the way you have to (virtually) write out packets (advance pointers), and watch for the end-of-file... and other such annoying details which make programming a chore. And of course at the end you write out the CBM load address and (really write) all the packets (outputFile) to the target file (outputData.prg). Anyway, if you are confident it is encoding and decoding correctly, you can start testing some real images to see what type of compression you get. I would be very interested to know what you get. My video encoder uses very similar technique, and on VIC-II images it typically gets 50% or more... but that is due to the nature of video (a lot of data is redundant anyway) and also the sloppy / approximate image generation that I use (the approximation or "lossy" encoding improves compression). Because you aren't doing lossy compression I imagine compression would only be around 25% ~ 33% for reasonably complex images... in other words, a compression of 50% or more wouldn't normally happen unless the image was extremely "boring". This is just a guess (based on "new scenes" in my VIC-II videos), but I would really love to hear what you get! I imagine there are major differences in how data compresses between the VIC and VDC images. So, keep us posted.
|
|
|
Post by VDC 8x2 on Aug 24, 2014 16:02:47 GMT
I'll make sure to add REMs for our benefit.
I still need to encode far copy then I can start the testing of images.
the main difference between vdc and VIC-II is the straight line on each line of the graphic picture. vic-II doing the byte 7 other bytes then next byte in the line.
I am thinking the vdc graphic images should compress more then vic-II.
|
|
|
Post by VDC 8x2 on Aug 25, 2014 3:20:13 GMT
Here is the working code with Big far copy.
Need to find a way to have rle short and small far copy compete. I think that would help relieve situations where it is rle 2 rle 2 ect. If small far copy is bigger run then the rle, it should win.
Module Module1
Sub Main() Dim outputString As String = "" Dim starting() As Byte = {0} Dim highByte As Integer Dim lowByte As Integer Dim stringCount As UInteger Dim historyPointer As Integer = 0 Dim processPointer As Integer = 1 Dim futurePointer As UInteger = 256 Dim endOfProcess As Integer Dim farSize As Integer Dim raw As String = "" Dim compressTarget As String = "" Dim anyCompression As Integer
Dim bytes = My.Computer.FileSystem.ReadAllBytes("D:/Emulation/drive10/testdata.prg") 'convert array into our workstring For index = 0 To bytes.GetUpperBound(0) compressTarget = compressTarget & Chr(bytes(index)) Next endOfProcess = Len(compressTarget) 'start of the encoding loop Do stringCount = 1 anyCompression = 0 'big copy mirror If historyPointer > 257 Then If futurePointer = 256 Then stringCount = futurePointer If Mid(compressTarget, processPointer - 257, stringCount) = Mid(compressTarget, processPointer + 256, stringCount) Then anyCompression = 2 End If End If End If '64 mirror copy If anyCompression = 0 Then If historyPointer > 65 Then If futurePointer > 63 Then stringCount = 64 Else stringCount = futurePointer End If Do If Mid(compressTarget, processPointer - stringCount - 1, stringCount) = Mid(compressTarget, processPointer + stringCount, stringCount) Then anyCompression = 2 Exit Do Else stringCount = stringCount - 1 If stringCount = 1 Then Exit Do End If End If Loop End If End If '64k far copy If anyCompression = 0 Then 'has to be 64 bytes or more in the future and history buffer for this to work If futurePointer > 63 And historyPointer > 65 Then stringCount = historyPointer farSize = 64 Do If Mid(compressTarget, processPointer - stringCount, farSize) = Mid(compressTarget, processPointer, farSize) Then anyCompression = 3 Exit Do Else stringCount = stringCount - 1 If stringCount < 65 Then 'nothing found so set stringCount for the next check stringCount = 1 Exit Do End If End If Loop End If End If 'rle copy for 256 or 64 bytes If anyCompression = 0 Then Do If Mid(compressTarget, processPointer, 1) = Mid(compressTarget, processPointer + stringCount, 1) Then stringCount = stringCount + 1 anyCompression = 1 If stringCount = futurePointer Then Exit Do End If Else Exit Do End If Loop End If 'if any compression happened then flush raw buffer If anyCompression > 0 Then If Len(raw) <> 0 Then outputString = outputString & Chr(Len(raw) * 4) & raw raw = "" End If End If 'process 64 byte far copy If anyCompression = 3 Then If farSize = 64 Then highByte = (stringCount And 2016) / 8 + 3 'hhhlllxx with xx = 11 lowByte = (stringCount And 31) * 8 'lllllsss with sss = 000 for 64bytes outputString = outputString & Chr(highByte) & Chr(lowByte) stringCount = farSize End If End If 'process mirror packet If anyCompression = 2 Then If stringCount = 256 Then outputString = outputString & Chr(1) Else outputString = outputString & Chr((stringCount - 1) * 4 + 1) End If End If 'process rle packet If anyCompression = 1 Then If stringCount = 256 Then outputString = outputString & Chr(2) & Mid(compressTarget, processPointer, 1) Else If stringCount > 64 Then stringCount = 64 End If outputString = outputString & Chr((stringCount - 1) * 4 + 2) & Mid(compressTarget, processPointer, 1) End If End If If anyCompression = 0 Then raw = raw & Mid(compressTarget, processPointer, 1) 'if raw has reached 63 bytes then flush the buffer to output and clear If Len(raw) = 63 Then outputString = outputString & Chr(63 * 4) & raw raw = "" End If End If
historyPointer = historyPointer + stringCount If historyPointer > 2048 Then historyPointer = 2048 End If processPointer = processPointer + stringCount If processPointer + futurePointer > endOfProcess Then futurePointer = futurePointer - (processPointer + futurePointer - endOfProcess) End If If futurePointer = 0 Then 'if any raw left in buffer then flush out before ending If Len(raw) <> 0 Then outputString = outputString & Chr(Len(raw) * 4) & raw raw = "" End If outputString = outputString & Chr(0) Exit Do End If Loop Dim outputFile(Len(outputString)) As Byte For index = 1 To Len(outputString) outputFile(index) = Asc(Mid(outputString, index, 1)) Next My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", starting, False) My.Computer.FileSystem.WriteAllBytes("D:/Emulation/drive10/outputData.prg", outputFile, True)
End Sub
End Module
|
|