Sending a Color to Screen memory..

Started by stiggity, July 25, 2010, 03:53 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

stiggity

With the help from BigDumbDinosaur, and Lokalhorst, ive gotten pretty far on my 2nd programming project. Altho, there is something that is stumping me. Lets  say i store "STEVE" to location $0000 in VDC screen memory. How can i make the "STEVE" white..or reverse-white? Ive done numerous searches in the mapping the 128,. and cannot make heads or tails of where to look in the 128 PRM. Any help would be greatly appreciated..

-Steve

commodorejohn

There's a second area analagous to the VIC's color RAM in VDC memory that controls the color of the characters, as well as a few miscellaneous options like blinking; it's located at $0800 in VDC RAM by default, and it's laid out in exact correspondence to the character map. I wrote a (woefully incomplete) VDC tutorial some time ago that explains (among other things) which colors correspond to what values and what the other bits in the attribute map do; you can read what I had of it here.

stiggity

John:
Very nice article.. explains alot. Could you include an example source code, of sending a color to the screen memory?? Your article says $F is the color for white, and the color map starts at $0800 so im going to try with what i have available. Thank You.

-Steve'

commodorejohn

You've pretty much got it, I think; the procedure is simply to set the R/W address to $0800 + (screen position) and write a byte with the color in the low nybble and any mode flags (blinking, etc.) in the high nybble. That's pretty much all there is to basic VDC operation; where I never got anywhere with is in setting up non-standard resolutions.

BigDumbDinosaur

30 HI = (A / 256) AND 255 : REM GET THE HIGH BYTE

Too much monkey-motion.  Just do 30 HI = INT(A / 256) : REM GET THE HIGH BYTE.
x86?  We ain't got no x86.  We don't need no stinking x86!

commodorejohn

Yeah, suppose so. The BASIC code was kind of an afterthought, since I didn't expect anybody would be crazy enough to do VDC programming in BASIC in the first place.

BigDumbDinosaur

If I were going to fiddle with the VDC from BASIC, I'd write it as follows:

10 REM THE ADDRESS TO SET IS IN THE VARIABLE A
20 BANK 15:SYS 52684,A/256,18 : SYS 52684,A AND 255,19 : REM SET VRAM ADDRESS MSB/LSB
40 REM NOW THE ADDRESS IN SCREEN RAM IS SET AND VALUES CAN BE WRITTEN


BASIC automatically converts expressions such as A/256 into integers when they are POKEd or passed as SYS call parameters as above.  Therefore the above code will work without the intermediate steps.  Also, always include an initial BANK statement to assure that ROM is mapped in when you SYS.  You may be in for an unpleasant surprise if you don't...

BTW, there's are screen kernel calls that can write or read VRAM after the target address has been set, eliminating the need to separately tell the VDC to access register 31.  See WRITE80 ($CDCA) and READ80 ($CDD8).
x86?  We ain't got no x86.  We don't need no stinking x86!

stiggity

BDD:
I'm not trying to access the VDC from BASIC. Lokalhorst explained in detail about writing to the VDC, and im working on reading from the VDC. Thank you for the assitance, and help, I really appreciate it. And like i told u in another thread, i _will_ be remarking my code from now on. Too the best of my ability.

Regards,
-Steve

stiggity

BDD/John:
How do i put my desired color in the low nybble? $0F is white so what do i add/subtract from $0F to get my selection highlighted in white @ screen memory??

-Steve

stiggity

okay...Im trying to simplify my routine. currently i

ldx #$40
ldy #$01
jsr setadr

which sets-up the current pointer on the VDCs display. and i simply jsr $CDCA and my .A byte is stored top corresponding screen memory. Heres the question, i want bytes to be stored in "reverse/white" meaning LDA #$0F, AND #64, how do i setup screen "color" pointers??? i would post the source but its aweful...

-Steve

BigDumbDinosaur

Quote from: stiggity on July 27, 2010, 07:50 AMHow do i put my desired color in the low nybble? $0F is white so what do i add/subtract from $0F to get my selection highlighted in white @ screen memory??
I'm not going to write code for you, but the general procedure you'd follow to set any color would be:

       
  • Read the attribute value from the desired location in attribute RAM.
  • Logically AND the value with %11110000 to cancel the current color and intensity.
  • Logically OR the value with the desired color mask, which would be %00001111 for bright white.
  • Write the new attribute value back to the same location in attribute RAM.
Note the need for two consecutive logical operations, as merely ORing the attribute value with a color may not result in what you expect, due to OR not clearing any bits that are not applicable to the desired color.

Note how I used binary notation, not hex, to indicate which bits are being twiddled.  It all goes to readability and maintainability of a complicated program.  Also, the mask used in step 2 should be defined in your declarations with a meaningful name, so you know its purpose.  Color masks should also be similarly named.  Setting the color to hi_white is a lot more informative than setting it to $0F or %00001111.
x86?  We ain't got no x86.  We don't need no stinking x86!

BigDumbDinosaur

Quote from: stiggity on July 27, 2010, 08:57 AM
okay...Im trying to simplify my routine. currently i

ldx #$40
ldy #$01
jsr setadr

which sets-up the current pointer on the VDCs display. and i simply jsr $CDCA and my .A byte is stored top corresponding screen memory. Heres the question, i want bytes to be stored in "reverse/white" meaning LDA #$0F, AND #64, how do i setup screen "color" pointers??? i would post the source but its aweful...
C'mon, man!  Why are you asking such an obvious question?  Just where in video RAM do you think you should you go to change character attributes?  Hint: think real hard about the word "attribute."  Geesh!

BTW, just what does:

ldx #$40
ldy #$01


represent?  Remember my earlier warning about not labeling your constants?
x86?  We ain't got no x86.  We don't need no stinking x86!

stiggity

BDD:
With the aid of your examples, i am now able to write white to screen memory. And your AND - ORA examples worked, but what would i AND and ORA to get reverse white? i know it has something to do with bit #7 but im unsure as how to manipulate this..

oh..

LDX#$40    ;setup low byte of screen memory
LDY#$01    ;setup high byte of screen memory

incase u were wondering..

-Steve

commodorejohn

Quote from: stiggity on July 27, 2010, 11:51 PMAnd your AND - ORA examples worked, but what would i AND and ORA to get reverse white? i know it has something to do with bit #7 but im unsure as how to manipulate this..
You seem to be kind of overthinking the whole affair. The attribute map is really quite simple: each byte controls one position, the low nybble of that byte controls the color, and the high nybble controls the attributes. If you want to turn a character's reverse mode on, you can use ORA #$40 to make sure that bit 6 (reverse) is set.

Do you understand the correspondence between binary and hexadecimal values, and how Boolean arithmetic works? (i.e. why ORA #$40 turns bit 6 on?) If not, you should take some time out and brush up on that until you really understand it, because it's a major part of programming in assembler.

One other thing: the read-AND-ORA-write approach is good if you're trying to preserve the bits you aren't changing, i.e. if you want to change a character's color without affecting its flags. If, on the other hand, you don't care about those and just want to set it to a value regardless, it'll be much faster to simply load an immediate value (LDA #$4F for reverse white) and store it without bothering with the read-AND-ORA bit.

stiggity

John/BDD:
Folks, im at wits end. I cannot even come-up with a decent algorithm for a "lightbar" in 128 mode. I want the bar to run from column 0 to column 39. It has 13 options, and i know first i have to physically print the bar to the screen. Then i have an interrupt that scans for left/right arrow. If its left, i DEC the lightbar position byte, if it right in INC.. i got it to move left and right, and it even STORES my text right where its supposed to go. But!!! somehow!! i need to re-store the bar to memory (blanks out any previous selections) then print the new selection. Cuz if not, each option just gets printed in white, and thats it.. hrrmmm.. anyone understand what I'm trying to explain? I would post source, but its pretty ugly..

-Steve

stiggity

got the lightbar working.. wasnt too hard. I appreciate all the help, now i have to learn how to read from the vdc screen.. going to check out mapping the 128.

-Steve

stiggity

Greetings:
Got the lightbar routine working with left and right now, and it toggles through all selections, etc.. I have another question. While reading "Mapping the 128" i came across this..

readreg = $CDDA
then after screen memory is setup, i need to actually JSR $CDD8, once i read from vdc screen memory where is the valuer stored? .A ? Im writing a routine that once a selection is reached pressing the up-arrow puts a check-mark next to the desired selection...I need to read to see _IF_ the check-mark is there.. If it IS then clear it, and make a mem addy = 0, if not print it, and make the same mem addy = 1.. this may sound messy or not thorough but i just need to know how to read from screen memory, and once i do where is this value stored..

commodorejohn

If you look at the documentation for $CDDA in Mapping, it should probably tell you, but I believe it does return in A, and I'd be awfully surprised if it didn't.

BigDumbDinosaur

Quote from: commodorejohn on July 28, 2010, 12:32 AM
Quote from: stiggity on July 27, 2010, 11:51 PMAnd your AND - ORA examples worked, but what would i AND and ORA to get reverse white? i know it has something to do with bit #7 but im unsure as how to manipulate this..
You seem to be kind of overthinking the whole affair. The attribute map is really quite simple: each byte controls one position, the low nybble of that byte controls the color, and the high nybble controls the attributes. If you want to turn a character's reverse mode on, you can use ORA #$40 to make sure that bit 6 (reverse) is set.
It's probably better to give examples using binary notation, e.g., ORA #%01000000 instead of ORA #$40, so he can see which bit is being affected.

QuoteDo you understand the correspondence between binary and hexadecimal values, and how Boolean arithmetic works? (i.e. why ORA #$40 turns bit 6 on?) If not, you should take some time out and brush up on that until you really understand it, because it's a major part of programming in assembler.
That it is, especially when fiddling with hardware registers.  Almost everything there is bit-wise and if you aren't bit-wise your program won't be worth one bit.  :)  Sorry!

QuoteOne other thing: the read-AND-ORA-write approach is good if you're trying to preserve the bits you aren't changing, i.e. if you want to change a character's color without affecting its flags. If, on the other hand, you don't care about those and just want to set it to a value regardless, it'll be much faster to simply load an immediate value (LDA #$4F for reverse white) and store it without bothering with the read-AND-ORA bit.
The extra processing time required to do AND followed by ORA using immediate mode addressing is only two clock cycles, a microsecond in FAST mode.  The bulk of the execution time will be consumed in addressing the VDC.  Let's not encourage any more dubious programming habits by even suggesting blind writes into hardware.  :D
x86?  We ain't got no x86.  We don't need no stinking x86!

commodorejohn

Quote from: BigDumbDinosaur on July 29, 2010, 03:22 PMThe extra processing time required to do AND followed by ORA using immediate mode addressing is only two clock cycles, a microsecond in FAST mode.  The bulk of the execution time will be consumed in addressing the VDC.  Let's not encourage any more dubious programming habits by even suggesting blind writes into hardware.  :D
Oh feh, that's not dubious at all. If you know what value you want in the VDC memory, there's nothing at all suspect about just putting it there. And even in FAST mode, every microsecond counts!