Hi guys, I read the tutorial about the display driver and how to write directly to the screen. But I also know that there is an "easier" way to draw to the screen (by using _GrBufCpy). I have to admit that I didn't read the tutorial completely but I've seen that it's difficult to draw lines and somethig like this. By using the driver I'm able to set the column and row easily and can use the auto-increment for more speed.
I just want to know whats easier/faster for programming games (and programs with sprites and other graphics).
In the moment I am trying to write a function for displaying sprites with the driver. it seems to be a little difficult to write outside of a byte. I think I'm going to read the byte, then OR it with my sprite and write it back.

Furthermore I think writing with the driver is faster, is it?

€dit:
Can somebody explain me the reason for this behaviour?!?

Code:
   ld a, (DrawSprite_MAXX)
   cp b ;doesn't work
   jr z, _DrawSpriteLoopY



Code:
   ld a, (DrawSprite_MAXX)
   sub b ;works?!?
   jr z, _DrawSpriteLoopY
I'm sure as soon as Kerm or someone else with some ASM experience comes on, they'll be happy to answer your questions Smile

And just for future reference, it's generally not a good idea to double post within a 12 hour period.
There are very few cases in which you want to write directly to the driver's memory. Advantages of using an in-memory buffer:
  • Double-buffering makes your code updating the display invisible.
  • Much easier to write to memory.
  • Faster (in most access patterns).
You'll typically read and modify a given display location a few times each frame (dependent on what you're actually displaying). Each write requires a delay for the driver, so it should be faster to use an in-memory buffer if you're touching any given part of the display more than once.
If you're not updating the entire display at once, it would be useful to update only the dirty region, which shouldn't be too difficult, depending on the granularity you want.

I wrote a routine for XORing sprites directly to the display a while ago. Not sure if it was ever tested though. Unless you have a compelling reason to write directly to the LCD, it's better to do the usual buffer+fastcopy.
Indeed, it's much better to do a fastcopy and use the buffer. Well-said, Tari. Unfortunately, the TI-OS _grbufcpy is quite poorly-written and quite slow, so the community has composed a variety of replacements. I for one wrote a version in Doors CS, which I believe is one of the fastest around. It also has special cases that let it work properly on the calculators with buggy LCD drivers and on Nspires at a faster speed, not to mention that it handles interrupts cleanly. Unless you have a burning desire to manipulate the LCD driver yourself, which I don't really think is worth your time, you should use iFastCopy (i for Ion) with graphics routines such as fastline, fastrectangle, and lots of other fun graphics libraries that shell libraries such as Doors CS's DCS and MOS libs provide.
Thank you for the informations! But unfortunately I do not understand why it is faster to write to the buffer.
I think when I call _GrBufCpy the calculator does send the whole buffer to the display. Why should it know what I've updated? And the TI-OS does use the same driver, doesn't it?

Thank you for the tip with Doors CS but first I want to learn "standard" programming for the calculator for understanding.
By driver we mean a special chip inside the ti8x. This chip has its own internal LCD ram, containing all of the pixel on the screen. Now, the CPU doesn't have direct access to that ram, hence why you must use in/out. This requires delays, which takes time.

KermMartian wrote:
Indeed, it's much better to do a fastcopy and use the buffer.

It is not always faster. Lets say you want to draw one sprite in the middle of the LCD. If that's the case, use direct LCD commands because they are faster in this case. If you will be doing heavy drawing, like tilemaps or other drawing that renders to the entire screen, or you are drawing by pixels (pretty much everything else), then a buffer will work better. This is because there is no delay when you write to a buffer directly accessible to the CPU.

Here's another way to think about using buffers: When you draw to the LCD driver, you are not drawing everything at once. You draw something, run some code, draw again, etc.. The LCD driver has an internal refresh rate (for me, ~60Hz) that will start drawing everything in its buffer to the LCD. This can cause the LCD to be updated when you aren't done drawing everything. It may take a few refreshes (showing an incomplete image on the screen) until you have everything drawn to the driver's ram.

Another good thing about buffers. What happens if you have overlapping sprites, or you keep modifying the LCD before the final image is ready? Lets say you draw 10 sprites on top of each other. With direct LCD drawing, the LCD driver may update the screen while you are drawing. This will give you a flickering effect where you could see all of those sprites. If you use buffered drawing, only the final result will be sent to the LCD.

Examples of buffered: Tilemaps, greyscale, pixel or line renderings.
Examples of direct LCD: Text output, cursors, small amount of sprites.
Thank you very much! Now I understood it. Admittedly it is possible to write (Port $11) without waiting - however i understand the advantage.

Overlapping Sprites are - as you said - difficult to handle because you have to read the pixels via IN A, ($11) (+ dummy read).
CakeOfDestruction wrote:
Thank you very much! Now I understood it. Admittedly it is possible to write (Port $11) without waiting - however i understand the advantage.
Nope, that is inaccurate. You still need the delay after writing to Port $11, about 10 microseconds' worth.
Sorry for writing wrong arguments, I did understand it wrong^^

I have 2 new questions:
1. Is it possible to decrease a 16-bit register with getting flags?
I want to write a loop with more than 255 loops, so I tried to use DEC BC. Unfortunately it did not work, so I decided to use SBC. But i think this is not a good solution
Code:

LD HL, 768
LD BC, 1
Loop:
SBC HL, BC
JR NZ, Loop

...


2. I wrote a procedure for deleting the whole GrBuffer because when I called fastCopy oder GrBufCpy it displayed me a coordinate system. It worked really well, but unfortunately I can't use anymore the graph. It seems to be deleted (I wanted to write l-o-l in these brackets but the forums replaces this word with 0x05^^).


Code:
DeleteGrBuf:
   ;============>gonna turn off interrupts
   DI
   ld hl, PlotSScreen + 768 ;backwards
   ld (SaveSP), sp ;save the stack pointer
   ld sp, hl
   ld hl, 768
   ld bc, 1
   ld de, 0
_DeleteGrBufferLoopBegin:
   push de
   sbc hl, bc
   jr nc, _DeleteGrBufferLoopBegin
   
   ld sp, (SaveSP)
   EI
   ret
SaveSP: .dw 0


Thank you for being patient Wink
1. This is the preferred formulation for a bc-based loop:
Code:
    ld bc,9001
Loop:
    ...do stuff...
    dec bc
    ld a,b
    or c
    jr nz,Loop


2. Is that faster than this?

Code:
    ld hl,gbuf
    ld de,gbuf+1
    ld (hl),0
    ld bc,767
    ldir


Edit: For more information on why we censor the word "laughing out loud", give this topic a read.

Code:
2. Is that faster than this?

€dit: "Not really" SORRY. Translation error in line 42 brain.z80
I meant that your code is faster... Don't feel offended please.

Unfortunately I can't see the coordinate system after launching this code (in the emulator)...
No offense would be taken, even if my code was slower. Smile

Ohhh, you mean that the axes go away? Yes, once you erase the screen, there's nothing automatic that draws the axes in. Remember, you have full control over the screen, and the OS doesn't get to intervene unless you say it can.
This would indeed be a faster way to clear the graph buffer (and the loop could be unrolled more if needed):

Code:
DeleteGrBuf:
   ;============>gonna turn off interrupts
   DI
   ld hl, 0
   ld d, h
   ld e, l
   add hl, sp ;save the stack pointer
   ld sp, PlotSScreen + 768 ;backwards
   ld b, 768/6 ;6 bytes pushed per loop
_DeleteGrBufferLoopBegin:
   push de
   push de
   push de
   djnz _DeleteGrBufferLoopBegin
   
   ld sp, hl
   EI
   ret


Edit: Save SP in HL
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement