Drawing Letter Pixels in Output.printChar

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Drawing Letter Pixels in Output.printChar

blossoms75
I am working on the printChar function in the Output class. I can't seem to get more than a few random vertical lines drawn on the screen. I think I have the logic right. So, my guess is that I am doing something wrong with how I am choosing what pixels to draw. I posted part of what I've done below. Am I on the right track algorithm wise? Can someone provide a hint as to where I'm messing up?

                while(countY < 11){
                                       
                        //set the location of the current pixel
                        let calcPixelY =  (cursorY*11) + countY;
                       
                        //get a line in the character map
                        let charLine = charMap[countY];
                                                               
                                //once you have the line, convert the number to binary
                                //store the binary number in an array
                                let binaryNumber = Output.decToBinary(charLine);
                               
                                //go through the binary number and see if the bits are set
                                while(countX < 8){
                                        let calcPixelX =  (cursorX*8) + countX;
                                        let bitSet = Math.bit(binaryNumber[countX],countX);
                                        if(bitSet = 1){
                                                do Screen.drawPixel(calcPixelX,calcPixelY);
                                        }
                                        let countX = countX + 1;
                                }
                        let countX = 0; //reset countX for the next row
                        let countY = countY + 1;
                }

Thanks for any help!
               
Reply | Threaded
Open this post in threaded view
|

Re: Drawing Letter Pixels in Output.printChar

cadet1620
Administrator
'charLine' is the font line that you are setting. I do not understand the "convert the number to binary" comment'; charLine is already stored in memory as binary. There is no need for 'binaryNumber'.

In the countX loop, Math.bit can directly test the bits in charLine.

What should you do if 'bitSet' is 0? What if you are printing on top of a background image?

You do not show in you excerpt if you are incrementing (cursorX, cursorY). That would also cause letters to be piled on top of each other.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Drawing Letter Pixels in Output.printChar

blossoms75
Thanks. That helped a lot.

'charLine' is the font line that you are setting. I do not understand the "convert the number to binary" comment'; charLine is already stored in memory as binary. There is no need for 'binaryNumber'.
Even though I've almost worked through all of N2T, it's still difficult for me to think at a low level. I was trying to  convert the number for a row of pixels (i.e. "51") to binary and then use the Math.bit mask to see if each bit was set. But that doesn't make sense because the number (like you said) is already in binary when it's stored in memory.

You do not show in you excerpt if you are incrementing (cursorX, cursorY). That would also cause letters to be piled on top of each other.
I was moving the cursor forward. I was just trying to limit the amount of code I posted.

"What should you do if 'bitSet' is 0? What if you are printing on top of a background image? "
I didn't understand this until I saw the results of the "backspace" test. I noticed that the characters were just writing on top of each other. I figured that was because I don't take into account what happens when bitSet is 0 and I need to turn a bit white.

After trying various things with Screen.drawPixel, I looked to Memory.poke to see if I could just set white bits that way. But I need a pixel address for that, and that's where I run into my next question. To set bits properly, I need to:
- get the address of the first pixel in the row I am interested in
- take the current value at that address and set it to what should be according to the new bitmap (once I have the address, I'll use Memory.poke to set the bit properly)
- To find the address of the current pixel, I am doing:
 16384 base (address of the screen)+ cursorX*8 + countX (the current pixel location in the bitmap)

However, I keep getting an error saying that I am trying to access memory outside of the heap range. Can you give me a hint as to what I'm doing wrong?
Reply | Threaded
Open this post in threaded view
|

Re: Drawing Letter Pixels in Output.printChar

cadet1620
Administrator
This post was updated on .
[I wrote a more detailed post about Faster Character Drawing.]

Writing directly to the screen memory is tricky because each word of screen memory holds 16 pixels, 8 from each of 2 characters.
Address    Bit number      Hex   Dec
                  111111
        0123456789012345
16384   ..##.....####...   1E0C  3102
16416   .###....##..##..   330E  3635
16448   ####........##..   300F  3888
16480   ..##.......##...   180C  3096
16512   ..##......##....   0C0C  3084
16544   ..##.....##.....   060C  3078
16576   ..##....##......   030C  3075
16608   ..##....##..##..   330C  3123
16640   ######..######..   3F3F 16191
16672   ................
16704   ................
(Recall from writing drawPixel() that the bit order on the screen is LSB on the left.)

You need to do similar position computation as you did in drawPixel() to locate the starting word address, and do similar Anding and Oring to set the pixels, but you do it in 8-bit groups.  For example when drawing the "2" you would find it starts in the upper half-word or 16384 so the computation would be
pix = font["2"][0]
Screen[16384] = Screen[16384] & 0x00FF    // clear bits in upper half-word
Screen[16384] = Screen[16384] | (pix<<8)  // set bits in upper half-words
"<<" means left shift. The easiest way to do the 8-bit shift in Jack is to multiply by 256.


I suggest that you get your Output.jack working using DrawPixel(), then finish the rest of the OS. After the OS is working, then you can come back to Output and improve its performance.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Drawing Letter Pixels in Output.printChar

blossoms75
Great, thanks! I got it working. Thank you SO much for that detailed write-up. I've gone back and forth looking at the concepts you discussed individually, but having it there altogether helped me see where there were gaps in my understanding.