VINTAGE TIME MACHINE: graphics Cross-Compression tools for C-64 use - Page 1
Forum section: electronics / general

author: RJSV
author_rank: Super Contributor
timestamp: September 02, 2020, 11:25:54 pm
content: Hello faithfull eevblog readers / students of coding !Enclosed start outlines problems making sensible screen graphics originating tools. We have the player(s), but the tools out there show lots of limits, to be addressed here.Diagram 1, shows a Commodore screen, about 1/3 occupied by a video-like display square.Diagram 2, starts to introduce main problem area, how to compress while managing a practical 'loss' of data. Plus, what constitutes a good 'replacement' of pixel and color display (dots), for ultimate viewing.Diagram 3, that's getting into the weeds, here, a start for examining the C-64 HIRES system, where 3 colors just doesn't cover general cases.More background is contained in other thread, all focus on teaching code writing, less about the Commodore 64 specifics. But the C-64 MIGHT be brought out, again...(Who knows, blue-nose, a friend always chirped.)

author: RJSV
author_rank: Super Contributor
timestamp: September 02, 2020, 11:27:50 pm
content: (sorry about the picture omission...Have not figured out how to post multiples)

author: RJSV
author_rank: Super Contributor
timestamp: September 04, 2020, 02:33:03 am
content: Searched on 'See-64 TV' and no trademarks, I think....But then I found 'Vintage Time Machine', just as I was browsing some guitar pedal stuff! That's a pedal effects maker...shhht"We're totally screwed..." from movie: THE MILLERSOK, so being a mid-level assembly language fellow, I have now to 'muck about', in other's business: I.E. Graphics Compression.Pls see photo, concerning C-64 limited colors, in any one pixel Stamp. The green frog in the toy (hologram) served to show, where 'white' is background. The question extends beyond having a 'cross-compressor' and into the realm of replacement (pixels).You can see, the white background color patch, under the toy frog, that should ideally RED, along with the other 4 sample stamps shown.(Please refer back a couple posts for the main pict showing full screen)A pixel replacement method would find a best color, for at least putting some blue, in that empty patch.In this one diagram case, better to make that BLUE the background color, that way would have a third color, and probably solve that one case, as RED could then be employed, in that one empty patch under the frog toy.So far, I have:#1. A step, in graphics tool machine, of pre-sortingmy screen stamp's bit to color assignments, forbest frequency of duplicates. There are initially6 ways of ordering individual color assignmentsto each pixel bit-pair#2. Second step runs compression, hopefully bothin spatial terms but also across the 10 secondsof slow frame video (10 hz).#3. For playback without that color ' drop out'effect, I need some 'best replacement' strategyStep 3, of course, should probably be before compression.Now, the screen box will be 8 by 8 Tiles, so approx 16 by 16 Stamps, so that's one whole stamp set right there. With 10 per second, that could work, if each stamp repeats 10 times, approx.The 10 second time run is going to put another X10 factor in, but more confidence, using JPEG like approach, where the screen items are not excessively 'busy'.So there is the user created animation, but also a 'video sourced' type of screen. Seems like having user intervention can produce results that can be tweaked.Task right now is to get better intro on the science, Huffman codes, and frequency domain compression methods, but I don't want to clog the pipeline, with a bunch of google results...The main game is in the pixel replacement, IE 'repair'concepts, on the graphics host system."We (already) have the players" on the Commodore64 side.

author: RJSV
author_rank: Super Contributor
timestamp: September 09, 2020, 04:36:35 am
content: Making progress, on the Commodore 64 Hires color compression.Does anyone have answer to question about MATRIX multiplication ? Here is the dilemma:When multiplying two matrixes they relate in, I guess, TRANSPOSED manner, like, for example, a4 by 5 has to be mult with a 5 by 4. I get that, where the elements end up. But what about the more simple case, say 8 by 8, mult by another 8 by 8?Can't you just multiply each element by the same position element, of the second, matrix?Such as A(4,3) times B(4,3) to put into C(4,3)?(Using A(i,j) type format above).I know what matrix dot product does, each indiv i,j element times a ' scaler'.Over my head in matrix math, needed for Huffman coding, and JPEG graphical handlers.On another note, been checking out buying a C-64 !Worried more about getting a usable floppy disk drive.Is there, also, any gamer Cartridge, w a USB port ?

author: ebastler
author_rank: Super Contributor
timestamp: September 09, 2020, 05:17:52 am
content: Quote from: RJHayward on September 09, 2020, 04:36:35 amNo, that is not a matrix product at all. Every element of the product matrix C must be calculated as a dot product (scalar product) of two vectors, namely a row of matrix A times column of matrix B: C(i,j) = Sum [A(i,k) B (k,j)]https://en.wikipedia.org/wiki/Matrix_multiplication#Definition,also see the illustration:https://en.wikipedia.org/wiki/Matrix_multiplication#IllustrationQuoteI have never seen the term "dot product" applied to an operation on a matrix, only to vectors, where it is defined as a*b = Sum [a(k) b(k)]. I assume you are simply referring to the product of a matrix and a single, scalar number. That is calculated as you mention, but it is not called a "dot product" to my knowledge.

author: RJSV
author_rank: Super Contributor
timestamp: September 09, 2020, 10:58:10 am
content: Thanks, I've seen that Wikipedia before, but need to take more study...a bit confusing, plus Vectors also.I realized, was maybe thinking 'arrays' (I'm not fluent in C++ either).Thinking something like [4,2] times [1,3] = [4,6] but also plenty to study. Much of this subject showing up in 2013 timeframe. ( Other blogs don't seem to have mobile friendly format like eevblog has though)Thanks again!

author: ebastler
author_rank: Super Contributor
timestamp: September 11, 2020, 05:23:37 am
content: Quote from: RJHayward on September 09, 2020, 10:58:10 amUmm -- linear algebra and matrix multiplications are "slightly" older than that.http://people.math.harvard.edu/~knill/history/matrix/index.htmlThere is a renewed interest in highly efficient implementations on GPUs (which can do vector math in hardware); maybe the blog entries you refer to focus on that? But you should probably start with the basic operations first. Frankly, I am not sure I understand what you want to achieve here, and where matrix multiplication comes into it.

author: RJSV
author_rank: Super Contributor
timestamp: September 16, 2020, 09:23:39 pm
content: ...Made some progress, managed to eliminate / combine TILEs with STAMPs, basically by eliminating the 'go-between' stamp pointers. This is due to consideration of a substitution method, for bypassing binary weight coding, by using unweighted 'counts' of active pixels.See photo, each of three virtual 'colors' are assigned to have 5 variations (of pixel count per byte 'slice'. That fits nicely into 4 bits of compression, where original byte has 256 possible combinations using conventional binary weights, on the combinatorial range of the four pixels.After those 15 assignments, 5 for each color, there is then a 16th assignment, all zero or 4 blanks (background). Another short-cut for reducing the burden of 256 full possible involves using 5 bits, for the pixel code sub-set, very similar but involves some moderate degree of bit-packing, say 3 slices per every 2 bytes (using 15 of the 16 bits).But the 4 bit / 16 possible is easier to introduce.In 2 bytes, you have 4 nibbles, each ending up as a byte 'slice' of 4 Hires pixels.To interpret the photo diagram, each slice has a row, with a main color, by itself, and also with 2 variations of mixture, such as 'Green' with one or two 'blue' pixels in the mix. The possible variety, having all three 'colors' is skipped, as are a lot of other combinatorial varieties. The end result is one nibble, 4 bits, per full byte output (4 bit pairs written to screen RAM).That's compression approx 50 % and, while remaining ignorant of biggest task, best judgement 'repair' of pixel colors outside of the 3 active possible, the method, for substituting nibble for original byte, presents a scheme for eliminating the TILE driven step.And another savings is gained, at the expense of vertical resolution, by doing each row of pixels with a second repeat. End result is you have 2 bytes per STAMP, where output will be 8 bytes (slices).Pls keep in mind, 'colors' in this example, are RGB, but only symbols. (I got tired of referring to ' second color replaces the latter coded bit pair', so using short-hand such as RED for actual bit pair of 10 b).I spent some more time, study of last year's "Retro-Gaming Expo, Kansas City. Some great C-64 Demo Art showing Commodore 64 color expansions.Pls refer to diagram explaining the nibble substitution scheme. In coding, there is a short table, 16 bytes, for translating / decompressing.I also have been terming these color limited options as belonging to Math Set theory (small sets), if I am using terminology correctly.Thanks.RJ

author: RJSV
author_rank: Super Contributor
timestamp: September 17, 2020, 09:45:18 pm
content: See photo diagram of a 5- bit compression / data reduction scheme. Basically, each 'color' can use 10 states now, for total 30 states. Other, full blanks, and one byte containing 3 colors, together.Why have the emphasis, on examining 'lossless' and blocky looking (C 64 screen) output ?Sometimes being lazy is a usable trait. Simply put;Lossless graphics routines don't require special corrections and assumptions for implementing compression and re-construction.

author: RJSV
author_rank: Super Contributor
timestamp: September 17, 2020, 10:12:42 pm
content: For a starting point, assume each Hires line is doubled up, making a total of 4 distinct lines, down the 8 slices of a Hires Multi color cell.See photo-diagram, when using a compression scheme, each C 64 output slice (byte) has 4 pixels, evoked by one of 16 codes, thus compressed by 50% (to a nibble).So, one byte high nibble supplies the output for lines 0, and 1, while low nibble supplies the code for output to lines 2, and 3.Now if we stop there, using a one-byte code will allow display, of a 4 pixel, by 4 row 'stamp'.This time, however, the stamp is integral with the TILE itself, rather than an indirect (pointer).

author: RJSV
author_rank: Super Contributor
timestamp: September 18, 2020, 12:50:05 am
content: For the backwards process, a simple table look-up, where each full, 4 pixel byte (bbbbbbbb) gets 'down-sampled, to 4 bits, or to five bits with some extra variety.Thus there are no judgement processes in any encoding process. Indirectly, of course, the authoring of the encoding table entries requires judgement, and awareness of trade-offs.For example:[ ]  [ ]  is closest to [ ] [ ]  That took only a short time, but there are 256 total patterns, more or less.Similar is   [ ] [ ] could be used, perhaps slightly less faithfully.If we proceed along this line, but more realistically, the use of 4 bytes to produce 8 nibbles, then un-compressed to 8 slices, Hires (byte).Of course, realistically having 4 bytes creates a possible '4' Billion combinatorials.Just four rows get the logical combos up, to 64 K.So obviously, nice to find code, to test best match, or even one of ' the near-best' match. Rather than build huge answer tables...

author: Bud
author_rank: Super Contributor
timestamp: September 19, 2020, 02:20:52 pm
content: Sorry perhaps i am missing something, but what is the point of this topic?

author: RJSV
author_rank: Super Contributor
timestamp: September 19, 2020, 08:35:10 pm
content: Sorry, to be cryptic, a little bit thinking aloud, the topic being around how to both compress, but also explore what original bridge has to do cross-formats.So while many new machines can do shading, etc the C64 is needing a 'vintage' approach... Maybe to much drama, and only mid-level skill.Right now, looking at various tools, for the source end. For example, finding a Vert flip flag does not help, unless making artificial graphics, rather than sampled.I do enjoy the ' migration' idea, for moving stamp data into direct (storage) in a TILE.Old ideas, many of them. Plus learning about the 8X8 conversions, using Cosine Transform

author: RJSV
author_rank: Super Contributor
timestamp: September 20, 2020, 10:05:17 pm
content: More Info, Compression graphics encoding:Here is a diagram (pls see attached photo).If you squint, that first is up top left, and has typical Commodore colors of a green 'frog', however crude.Moving to the right top corner, a Tokenize process compresses the many slight variations, into a manageable set (of 32 tokens).Next diagram, downward from top right, the middle diagram has result of further Tokenizing, this time using four vertical 'stripes' , and then yet again, the last diagram, bottom right, shows that result. Each of course being cruder and lost detail. Trying to see what the process, of repeated conversions, if will result in a (usefull) stable state, that resists further application of the transforms.Then, it can be easier task, to compare stamps, at a 4 by 4 size, that maybe has more likely matches, when encoding that's helpful.Left bottom, diagram up in middle is one Token conversion, in vertical direction.

author: RJSV
author_rank: Super Contributor
timestamp: September 22, 2020, 10:53:11 pm
content: For doing image capture and match / near-match comparisons, I always lack imagination. There, in the diagram attached, shows an original toy frog, plus a couple copies: Tokenized, then rebuilt.Figuring, simplified tokens make for less shear number, of possibilities.First, picture is compressed, by row, making 4 tokens (in each 4 X 4 cell.) Next, as shown top-right corner, the picture is rebuilt (back for hires screen pixel byte).After that, can be a second compression process, this time making Tokens, along each of the 4 columns.By that time, many of the 4 X 4 cells have 'settled' out, to a stable shape, where each slice, whether row or column, is represented by a token.There are some shapes, in possible 4 X 4 that are already stable. Another shape type never resolves, technically, by causing endless back and forth changes, each alternating.See the RED pixels, as an example in the attached diagram, of one such 'cell' where horizontal and vertical oriented transforms help to push various input shapes, into more simplified / stable.Then, with both images done that way (row transform, then column transforms), any comparison might be capable of handling near-matched cells.Having 4 tokens, makes a 20 bit address, range of 1 MOriginal had 4 tokens, 4 bits each (64 K range).Comparisons on screen, hires, that's going to be 32 bits, or range of 4 Billion.Idea, in comparisons, is also perhaps allow some small mis matches.The 'frog' graphic maybe looks better, when you squint.

author: RJSV
author_rank: Super Contributor
timestamp: October 05, 2020, 07:38:37 am
content: Photo shows diagram of current approach for having images searching and matching, in a quantizing process. Best results might be when using small- ish patterns, and 4 lines by 4 pixels will fit (the Commodore 64 screen cells).In the diagram, there are 2 of these stamps per char cell, and the approach now is to group these stamps as a 2 by 2 arrangement, taking up 2 char spaces.Now there are two issues with that approach:For one thing it helps to be able to exceed a single byte stamp number, having a greater variety, when using, say, total 445 to search through for matches.The search criteria itself needs some help, for being a little 'loose' with any near-matches. You need those image match / repeats at a lower level, I believe.Otherwise, searching through the larger, 8 by 8 Tile data for matches..., well, I just cannot imagine getting more than a couple handful of matches, with, say, 256 total Tiles.But yet, Video compression is doing useful things, all the time, using transforms.For further use, as a part of encoding, each graphic image 'slice' is quantized, to either a 5 bit token, or a 6 bit token. So any later match-up trials will be comparing sets of vertical strings, four numbers, as one token per row.These quantizing transforms were built by hand, as ultimately a translation table having 256 entries, based on the C64 being one byte per each 4 multicolor pixel. The game there, is to visually / manually create and enter each table 'slice' value. Please be forewarned: don't get mixed up, as I kept doing, having 5 bits per 4 dots kept, naturally, thinking '5' pixels per byte slice... Ain't so.Now another quirk involves the 6502 'Y' index which has to be used for both halves (of char cell) in a 0 thru 3 index config. This caused the use of a second pointer base, offset by 4. So you have 4 pointers total, for doing 2 transfers per loop iteration. Can't see any easy alternative.Doing the transfers this way, stamp copies to screen, when destination using direct-plus-index, forces the use of (hard-coded) dest pointers. But right now, I'm looking at doing things 'pointer indirect', having the 4 pointers, using 8 bytes of page zero (ouch!).By the way, I like to use a term, called 'Small Set' theory, often seen in astronomy / physics. Note that our solar system has a 'small' sized 'set', literally just 9.An example of a large set problem would be a biological chemical set, having hundreds of players (molecules) of concern. Here, with 6502, you have a minimized set of functions. Would be nice, to have a second way of indexd-indirect, such as including X register, that way can do source AND fest that way.

author: RJSV
author_rank: Super Contributor
timestamp: October 05, 2020, 07:40:13 am
content: Oops, see attached correct photo.. sorry

author: RJSV
author_rank: Super Contributor
timestamp: October 05, 2020, 08:06:39 am
content: Astute readers note: Much of this topic is (going to) be derivative, of existing video technology for compressing, to run on small platforms (C64). Yes, I know that, but the subject is so interesting.As per development on that, I have been considering actually migrating (up) to using a new SPECTRUM as s Z80 based cross development system ( more memory etc).Not a huge 'Lab'; (bedroom) or work table (file box). You've probably seen my 'graphics' unit output here (felt pens). I would be happy, developing graphics and coding, on the SPECTRUM and with one of those new/old C-64 models (the 2019 FPGA version).Plus, and a screen...yeah a cute 11 inch flat pan screen,I don't have huge room.Any questions ? Comments ? Beginners welcome.

author: RJSV
author_rank: Super Contributor
timestamp: October 10, 2020, 07:10:14 pm
content: OUTLINE OF TILE PLAYER CODEWith my shift towards a small'ish stamp, at 4 pixels by 4 lines, here is a presentation on that TILE / STAMP screen system.The tiles accommodate the Commodore 64 HIRES screen, where each 'Char Cell's is 4 pixels wide by 8 scan lines high. So, with cells combined in a pair, a Tile here is 8 X 8 pixels, a common size seen discussed (elsewhere), in DCT algorithms.Here then, each hardware defined 'char cell' can be made using two stamps, (stacked vertically). To a degree, these two stamps are multicolor, each pixel having 2 bits total, those act to select among nibbles in color RAM areas.It's slightly confusing, admittedly, but the result is a TILE containing 4 stamps (2 stamps per row).Considering a screen tiler of such small component sizes is ackward:'Y' register values act as the 'index' values 3,2,1,0 and such short reach forces creation of an additional pointer (in the char cell). That half-way split, and pointer location is pointed out in green, as being 4 bytes into each actual cell.The loop performs two moves per index, essentially moving two different stamps at once, (to the C64 HIRES screen).6502 Block Moves Here, vs Z-80 style ProcessorThis code reflects the best match, for moving the smaller blocks in memory. With Z-80 code, it always seems backwards, (IX + 4) for example, where you have a changeable 16 bit register, added to a fixed, small index (a single byte constant).In the case here, there are two simultaneous moves, involving two random specified stamps, copied to consecutive blocks (on Hires screen).To perform the second of that pair of moves, a copy of the screen pointer is made, offset by an additional 4 (byte locations).As the code starts, the current tile is accessed, pulling out 2 of the 4 stamp values. Then, those are copied to screen, 8 bytes total. This repeats a second time after pulling out the remaining two stamp values listed in tile.It works using an index to the first stamp, as clarified in enclosed diagram. Each time a two byte stamp value is read out, of the list, the index is moved.Stamps are stored (or actually pointed to) in terms of absolute memory locations, rather than using a single byte ID number. This has two advantages, firstly an obvious speed-up, but also allows stamp quantities to exceed 256, that's important when attempting to use duplicates, for compressing (the active screen movement). Precalculated pointers are simply stamp ID, times 4, plus Base (of stamp bank).Encoding issues are mostly skipped here, BUT, for example, using TOKEN concepts involves replacing full 8 bit pixel 'slices' with 5 bit 'TOKENS'; that's a 5/8 compression, but a lot of work to un-pack, for on-screen bitmap (bytes). The whole TOKENizing and encoding scheme is a separate deal.And, while the mem space packing / unpacking of the 5 bit TOKENs is not of concern here, each token CAN be optionally used, each separated in an addressed byte, for translation, producing a screen-ready full bit map byte. The simple translation table has 32 entries, each with a full byte 'answer'.For example, a Token= 7 is code for four dots, all on, producing a table answer of FF hex, all bits on or1111 1111 b.For first doing two stamps, a subroutine is called that will fetch the pointers, and do the 4 loop repeats.Then, for doing the remaining two stamps, the subroutine repeats, after fetching the additional two pointers (from the TILE list).It's slightly kludgey, but works when care is taken to keep the various items in the (expected) offsets within lists (Tile format).Likely not completely clear, next time I will include copy of the actual code, for writing tiles with the little, 4 by 4 stamps. Thanks, RJHAYWARD

author: RJSV
author_rank: Super Contributor
timestamp: October 10, 2020, 10:59:35 pm
content: For coding, page zero register (A0 and A1), points to current tile.COPY_TILE:LDY #15. Start index to pointer of 4th stampSTY INDEX_SAVERJSR COPY_CHAR:: The copy code runs twice this wayCOPY_CHAR:LDA (A0),Y. Tile has stamp pointerSTA $A2DEYLDA (A0),Y. High byteSTA $A3DEY:LDA (A0),YSTA $A4DEYLDA (A0),YSTA $A5DEYSTY INDEXSAVER:LDA $81STA $83. High byte of temp pointerLDA $80. Low byteCLCADC 4. Offset half way into cellSTA. $82. Low byte of offset pointerBCC StartCopyINC $83:StartCopy:LDY #3. Do loops 3,2,1,0PixelLoop:LDA (A2),YSTA (80),Y. That's upper stampLDA (A4),YSTA (82),Y. That's lower stampDEY. Next pixel rowBNZ PIXEL_LOOP:LDA $80. Need bump to screen plus 8CLCADC #8STA $80BCC DONE DESTINC $81. high byte of ptrDONE_DEST:RTS########################Now, on first pass the first two stamps are copied, and then the code falls through, and does the second pass, that second pass copies the 3rd and 4th stamps.After this finishes, the screen destination pointer has the next, empty screen location.