EASy68K  
It is currently Sat May 30, 2020 5:28 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Mon Dec 09, 2019 2:20 pm 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
So, I am working on my own little 68K project which actually has an indexed color graphics card with 2MB of framebuffer RAM.

The RAM is linear, so when placing a byte value at the first location of RAM, its the top left corner of screen. all the way to the bottom right at the end of RAM. (Plus there is a 2nd and 3rd framebuffer for double/triple buffering).

But I am stuck on a little problem that I dont know of an efficient way to work around. Here is my scenario:

Say, I draw a background polygon of a specific color. (Nothing more than filling RAM with that colors index, really). Now, I want to lay text on the screen. My text is a bitmap format font, and the value 00 in the font represents Alpha, basically that value doesnt get written to RAM, therefore that pixel is skipped, leaving any previous background draw/value alone. The rest get index offset calculated, and written into RAM. (foreground color, dropshadow).

This works fine. But, its slow. Very slow since its a byte wide transfer. (move.b) as its the only way personally that I know how to compare each value, and skip an Alpha write.

So, its not efficient. Of course, ideally, move.w, or better yet move.l, or even movem functions would work far more superior for drawing objects into framebuffer.

However, where I am stuck is how do I handle alpha? how can I mathematically handle in an efficient way drawing multiple bytes at the same time into framebuffer RAM, while keeping the background color intact in an alpha-style state? without having too many instructions keeping the routine slow? The machine I am working with, it was done in the past but that code is long gone and I dont know how they did it so I am recreating it myself.

Here is a routine that draws my text. Keep in mind the comments may not be accurate, and some of the code is commented out as I have been working to try and improve this routine. So I am posting it here so you can get an idea of what I am doing, maybe you have some insight?

Code:
;********************************************************************************************************
;Draws text in the framebuffer, with the specified font asset pointer.
;Can only handle an Asset maximum of 65536 Bytes for now.
;Asset Pointer (Longword)
;Start Address (Longword)
;Number of Characters (Word)
;Font Height Multiplier (Byte)
;Foreground Color (Byte)
;Dropshadow Color (Byte)
DrawText:
   ;Get Asset Pointer
   bsr      ReadFIFOLong
   move.l   Scratch,EntryPoint
   
   ;Get Start Address
   bsr      ReadFIFOLong
   move.l   Scratch,ProgramStart
   
   ;Get Number of Characters
   bsr      ReadFIFOWord
   move.w   Scratch,BlockSize
   
   ;Get Multiplier, Foreground Color, Background Color, and Dropshadow Color
   bsr      ReadFIFOByte
   move.b   D1,Multiplier
   bsr      ReadFIFOByte
   move.b   D1,ForeColor   
   bsr      ReadFIFOByte
   move.b   D1,DropColor
   
   ;Registers Used: (A0,D0,D1 used for VMERead)
   ;D2 = Font Seek Pointer
   ;D3 = Width
   ;D4 = Height
   ;D5 = Count Register Width
   ;D6 = Count Register Height
   ;A1 = Destination framebuffer address
   
   movea.l   ProgramStart,A1         ; Make sure our Destination Pointer is correct.
ASCIILoop:
   clr.l   D1                  ; Clear out register used for the seek pointer.
   bsr      ReadFIFOByte         ; Grab our ASCII Character from FIFO
;   movea.l   EntryPoint,A6         ; Store Asset entry point for Seek Pointer
;   move.w   D1,D3               ; Save our compare value into D3.
;   addi.w   #$7F00,D3            ; Add our marker byte.
   subi.w   #32,D1
   mulu.w   #652,D1                  
   addi.w   #2,D1
   move.l   EntryPoint,D2
   add.l   D1,D2
   movea.l   D2,A6
;   move.w   #$95,D4               ; Use for Seek Loop Counter
;SeekLoop:
;   move.w   WDT,D7               ; Reset Watchdog
;   movea.l   A6,A0               ; Move Current Seek Pointer into A0 for VMERead
;   move.l   #2,D0               ; Set to read a word from Asset memory
;   bsr      VMERead               ; Read Asset Memory, Store into D1.
;   adda.l   #652,A6               ; Increase Seek Pointer by 2.
;   cmp.w   D1,D3               ; Compare Marker against current location.
;   beq.s   ProcessCharacter      ; We found the location of our marker and ASCII value.
;   dbf      D4,SeekLoop            ; If not found, and not at our limit, Check for more.
   
   ;If the character wasnt found, we will end up here.
;   movea.l   EntryPoint,A6         ; Store Asset entry point for Seek Pointer
;   adda.l   D0,A6               ; Advance Pointer to Character Width/Height
ProcessCharacter:               ; A6 now contains the pointer for our character.
   clr.l   D5                  ; Clear Character Pixel Count Width
   clr.l   D6                  ; Clear Character Pixel Count Height
   clr.l   D3
   clr.l   D4
;   suba.l   #650,A6
   movea.l   A6,A0               ; Move Current Seek Pointer into A0 for VMERead
   move.l   #1,D0               ; Set to read a word from Asset memory
   bsr      VMERead               ; Read Asset Memory, Store into D1.   
   move.b   D1,D4               ; Copy Font Character Height   
   adda.l   D0,A6               ; Increase Seek Pointer by 1.
   movea.l   A6,A0               ; Move Current Seek Pointer into A0 for VMERead
   move.l   #1,D0               ; Set to read a word from Asset memory
   bsr      VMERead               ; Read Asset Memory, Store into D1.   
   move.b   D1,D3               ; Copy Font Character Width   
   adda.l   D0,A6               ; Increase Seek Pointer by 1.   
      
;   movea.l   #DATAOUT,A0
;   move.b   D4,D1
;   move.l   #1,D0
;   bsr      VMEWrite
;   bsr    delay
;   movea.l   #DATAOUT,A0
;   move.b   D3,D1
;   bsr      VMEWrite
;   rts
   
FontLoopX:
   move.w   WDT,D7               ; Reset Watchdog
   movea.l   A6,A0               ; Move Current Seek Pointer into A0 for VMERead
   move.l   #1,D0               ; Set to read a word from Asset memory
   bsr      VMERead               ; Read Asset Memory, Store into D1.   
   adda.l   D0,A6               ; Increment Seek Pointer by 1.
   cmpi.b   #0,D1               ; Check if the Pixel was a Background color.
   beq.s   Alpha               ; If so, Fonts are Alpha so we skip the pixel write.
   cmpi.b   #1,D1               ; Check if the pixel was a Dropshadow Color.
   bne.s   SetForeColor         ; If its not, Then assume its a forecolor   
   move.b   DropColor,D1         ; Copy the real dropshadow color into D1.
   bra.s   ContinueDraw
SetForeColor:
   move.b   ForeColor,D1         ; Copy the real foreground color into D1.
ContinueDraw:
   move.b   D1,(A1)+            ; Set Pixel in Framebuffer Memory, Increment Pointer.
   bra.s   ContWrite
Alpha:
   adda.l   D0,A1               ; Increment pixel pointer in framebuffer, Skipping the write entirely.
ContWrite:                     
   addi.l   #1,D5               ; Increase Width Count Register
   cmp.l   D3,D5               ; Check to see if we are at our limit yet.
   bmi.s   FontLoopX            ; If not, Grab and draw the next Pixel.
   clr.l   D5                  ; Reset Count back to 0.
   
   move.l   A1,D1               ; Copy current address into D1 for math operations
   sub.l   D3,D1               ; Subtract Character width from address. (Returns back to Character Beginning)
   addi.l   #768,D1               ; Increase address pointer to the next line below
   movea.l   D1,A1               ; Move updated value back into our Address Pointer.
   move.w   WDT,D7               ; Reset Watchdog
   
   addi.l   #1,D6               ; Incrememnt Height by 1.
   cmp.l   D4,D6               ; Check to see if we are at our limit yet.
   bmi.s   FontLoopX            ; If not, Go draw another line of the character.
   
   move.l   A1,D1               ; Store Address pointer for math
;   move.l   D4,D2               ; Grab character height and store into a temp register
;   mulu.w   #768,D2               ; Calculate the number of lines for each pixel height
   subi.l   #$6C00,D1            ; Subtract number of height lines from Address pointer (To begin the next character)
   add.l   D3,D1               ; Advance pointer to the next character position
   movea.l   D1,A1               ; Save new Address into Pointer.
   move.w   WDT,D7               ; Reset Watchdog
   
   subi.w   #1,BlockSize         ; Decrement our Number of characters left.
   tst.w   BlockSize            ; Test if Zero
   beq.s   EndDrawText            ; We are finished.
   bra      ASCIILoop            ; Otherwise, Check the next character.    
EndDrawText:
   move.b   #$90,D1               ; Send ACK to Data card to let it know the operation completed succesfully.
   move.b   #1,D0               ; Byte transfer
   movea.l   #DATAOUT,A0
   bsr      VMEWrite
   rts   


This routine is probably more convoluted than it needs to be, but thats all I could come up with out of my head, and I am green with the 68K still. Most routines use link/unlink with the stack and that always confuses me. still does. So I avoid it.

Any thoughts?


Top
 Profile  
 
PostPosted: Fri Feb 21, 2020 7:43 am 
Offline

Joined: Thu Feb 20, 2020 8:02 pm
Posts: 11
Since you represent everything with bytes (both the font and the framebuffer's pixels), you can just use a OR operation, isn't it ?
Also try to repeat and inline code rather than using branching because you don't do a lot of operations in between your branching instructions, so their overhead is significant in regard to the "useful" code.

AFAIK the Amiga has a similar framebuffer and I'm sure you can find some nice fast code for blitting fonts in the frame buffer. (The Atari ST is more complex because it uses bitplanes)

Some general rules for code speed:
* don't forget the 68000, although it has 32bit registers, has only a 16 bit address bus. So the less you transfer from/to memory (instructions or data), the faster (in principle).
* Consequently, loading/writing 32 bit integers is longer than doing the same for 16/8 bit ones. Use 32 only if needed.
* Look at instruction sizes, some at 16bits, some are 32 bits (that is easy to see in SIM68k because it displays them on the left). Using pc relative addressing mode when possible reduces that.
* 68k has plenty of registers and they are very flexible (you can put data in address registers). And moving from register to register is super fast. So use them all :)
* When you have multiple tests, write them by descending success probability
etc. :)


Top
 Profile  
 
PostPosted: Fri Feb 21, 2020 9:56 pm 
Offline

Joined: Thu Feb 20, 2020 8:02 pm
Posts: 11
Why don't your just OR.B your font's pixels with the frame buffer ?

If you want to improve speed, you can also repeat the code rather that use an bcc for iterating, as bcc has some overhead that if significant in regard to the "useful" code here.

You can also look at resources as the Amiga has a similar frame buffer and I'm sure there are good demo makers who have some tricks for rendering fonts in the most optimal way.

Usually, for speed:
* prefer 16bit operations over 32 bits (the 68k has a 16bit data bus so it takes more time to read/write a 32bit value than 16bits)
* use registers. The 68k has plenty, they're very flexible, and operations on register are very fast.
* avoid mul and div operations. They are the slowest instructions. Use bitshifting and add/sub instead, whenever possible.


Top
 Profile  
 
PostPosted: Fri Feb 21, 2020 11:59 pm 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
I ended up switching to C and using the GCC Optimizer. made a WORLD of difference.

BTW, not sure if OR would work as I thought about that originally. Reason is, its an indexed color system where each byte is its own color.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 13 guests


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 post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group