BZC
KermMartian wrote:
...and why computer-generated code is so incredibly inefficient sometimes. Smile


Yeah, that's the trade-off between compiled and assembled languages.

Chipmaster wrote:

I love this:


Code:

LD H, 0
    LD A, (obstacle7)
    LD L, A
    LD A, L
    LD (loopval), A
    LD H, 0
    LD A, (obstacle7)
    LD L, A
    LD A, L
    LD (obstacle6), A
    LD H, 0
    LD A, (obstacle6)
    LD L, A
    LD A, L
    LD (obstacle5), A
    LD H, 0
    LD A, (obstacle5)
    LD L, A
    LD A, L
    LD (obstacle4), A
    LD H, 0
    LD A, (obstacle4)
    LD L, A
    LD A, L
    LD (obstacle3), A
    LD H, 0
    LD A, (obstacle3)
    LD L, A
    LD A, L
    LD (obstacle2), A
    LD H, 0
    LD A, (obstacle2)
    LD L, A
    LD A, L
    LD (obstacle1), A



That is quite...inefficient? Smile Obviously something to optimize for the next release...
all those
Code:
ld l,a
ld a,l
Ahhhh! Wink
And why do you keep loading 0 into H?
I think it's the way I pass parameters to the functions. It pushes HL onto the stack. The values only require one byte so it loads the value into L, loads 0 into H, and pushes it on the stack. I don't know much Asm, but could it have simply been done by loading into L and leaving H by itself? Or maybe this was just a check, just in case you loaded a value that needed two bytes.
KermMartian wrote:
all those
Code:
ld l,a
ld a,l
Ahhhh! Wink


get rif of the ld a,l at least.....I can imagine possibly needing to copy a into l, but the second is just pointless.

Code:
ld h,0
ld l,a
push hl
KermMartian wrote:
...and why computer-generated code is so incredibly inefficient sometimes. Smile


Not necessarily. A good optimization routine would spot and clean that up. I'm not sure if BZC does an optimization pass or not, but compilers like GCC do, and are quite good at it
KermMartian wrote:

Code:
ld h,0
ld l,a
push hl


I meant in context of that program <_<

I may not program in Asm, but I know most of the commands.
That whole huge routine can be simplified to:


Code:
  ld hl,obstacle7
  ld a, (hl)
  ld (loopval), a
  ld de,obstacle6
  ld bc,6
  lddr


Now, I don't think a computer can generate that. Razz

Edit: What's the point of writing whatever is in (obstacle7) to all the obstacles? I don't know exactly what you are using the obstacles to do, but it seems kinda pointless to overwrite the same thing to all of them.
yeah, an ldir would completely pwn that entire routine...
I've been downloading some Asm routines from ticalc.org to replace the mirage routines that just don't seem to work. I will work on adapting those routines as functions in BZC and try to get something done by Monday.
Good plan. Make sure that you check for optimization and code reuse while you copy-paste code.
OK, I've been working on a cursor routine and have a problem...the routine works perfectly, but leaves random copies of the arrow all over the screen. I don't think there's anything wrong with the code; maybe it's the LCD driver? While most of the routine is in ASM, there is some BASIC ASM stuff, so you'll need BZC to compile it.

Code:
#include <asmlib.h>

FUNCTION slowdown
FUNCTION CURSOR
FUNCTION waitforLCD
FUNCTION curwrite ARG 1
FUNCTION curread
FUNCTION curor
FUNCTION getkey
INT coord = $0000
MEM curbuf 16
MEM savebuf 16
FUNCTION curspr


START
ASM
   LD   A, $01         ; Make sure LCD is set to 8-bit word mode (otherwise goofy things happen...)
   OUT   ($10), A
ENDASM
FORCE curspr
FORCE curbuf
FORCE savebuf
FORCE coord
FORCE getkey
getkey
END

FSTART CURSOR            ; Wrapper for cursor display routine; calls curread, curor, and curwrite
curread
curor
curwrite curbuf
FEND

FSTART curspr            ; Do-nothing function containing cursor images
ASM
curspr1:
.DB %11111110
.DB %01111100
.DB %00111000
.DB %00010000
.DB %00111000
.DB %01000100
.DB %11111110
.DB %00000000
.DB %00000001
.DB %10000011
.DB %11000111
.DB %11101111
.DB %11000111
.DB %10000011
.DB %00000001
.DB %11111111

curspr2:
.DB %10000000
.DB %11000000
.DB %10100000
.DB %10010000
.DB %10001000
.DB %11111100
.DB %00110000
.DB %00011000
.DB %01111111
.DB %00111111
.DB %00011111
.DB %00001111
.DB %00000111
.DB %00000011
.DB %11001111
.DB %11100111
ENDASM
FEND   


FSTART curread            ; Read data from LCD
ASM
   LD   DE, (coord)      ; DE holds coordinates of cursor (upper left corner)
   SRL   D
   SRL   D
   SRL   D         ; Column of display obtained
   LD   IX, curbuf      ; IX points to cursor buffer
   LD   HL, savebuf      ; HL points to screen save buffer
   LD   B, -1         ; B is our offset to tell us which half of the 2-byte wide data column we're on

read_loop_main:
   INC   B
ENDASM
waitforLCD
ASM
   LD   A, $20         ; Let's set the column
   ADD   A, B         
   ADD   A, D         ; Correct column obtained
   OUT   ($10), A
ENDASM
waitforLCD
ASM
   LD   A, E         ; Get the row directly from the original coordinates
   ADD   A, $80         ; Correct row obtained
   OUT   ($10), A
   PUSH   BC         ; Save BC (since it is our offset)
   LD   B, 8         ; Data block we need is 8 rows long
ENDASM
waitforLCD
ASM
   IN   A, ($11)      ; Dummy read
read_loop:
ENDASM
waitforLCD
ASM
   IN   A, ($11)      ; Real read
   LD   (HL), A         ; Put screen byte into save buffer...
   LD   (IX), A         ; ...And cursor buffer
   INC   HL
   INC   IX
   DJNZ   read_loop      ; If we don't have 8 rows, loop again

   POP   BC         ; Restore BC
   LD   A, B
   CP   1         ; See if we've copied 2 columns of data
   JP   NZ, read_loop_main   ; If not, do the whole thing again
ENDASM
FEND

FSTART curwrite IX         ; Writes data to LCD (takes address of data location through IX)
ASM
   LD   DE, (coord)      ; DE holds coordinates of cursor
   LD   A, D         ; See if the cursor goes off the left side of the screen; not used at this point
   CP   0
   JP   C, no_left

   CP   88         ; See if cursor goes off right side of screen; if so, jump!
   JP   NC, no_right

   LD   C, 1         ; C = 1 indicates that we want both columns of data written
   LD   B, -1         ; Set B (will be incremented at the start of the write loop)
   JP   write_continue

no_left:            ; Appropriately sets B and C to result in only the right column of data being written
   LD   B, 0
   LD   C, 1
   JP   write_continue

no_right:            ; Appropriately sets B and C to result in only the left column of data being written
   LD   B, -1
   LD   C, 0

write_continue:
   SRA   D
   SRA   D
   SRA   D         ; Column of display obtained

   LD   A, E         ; Now we check to see if the cursor is going off the bottom of the screen
   LD   H, 8         ; H will hold the number of rows of data to be copied, to reinitialize B for each column
   CP   56         ; See if cursor goes off screen
   JP   C, write_loop_main   ; If not, jump!

   LD   A, 63
   SUB   E
   LD   H, A         ; H is now adjusted to hold only the number of rows of the cursor that remain on the screen

write_loop_main:
   INC   B
ENDASM
waitforLCD
ASM
   LD   A, $20         ; Time to set the column
   ADD   A, B
   ADD   A, D         ; Correct column obtained
   OUT   ($10), A

ENDASM
waitforLCD
ASM
   LD   A, E         ; Time to set the row
   ADD   A, $80
   OUT   ($10), A
   PUSH   BC         ; Save our offset

continue_write:
   LD   B, H         ; Initialize B with H
write_loop:
ENDASM
waitforLCD
ASM
   LD   A, (IX)         ; Write the data
   OUT   ($11), A
   INC   IX
   DJNZ   write_loop

   POP   BC         ; Restore the offset in B
   LD   A, 8         ; Now for some unavoidably messy code
   SUB   H         ; We have to account for the fact that we've skipped writing rows of data in the cursor
   PUSH   DE         ; buffer if the cursor goes off the bottom of the screen
   LD   D, 0         ; So, adjust IX so it points to the top of the next column of data
   LD   E, A
   ADD   IX, DE
   POP   DE
   LD   A, B         ; See if we've written all the data necessary
   CP   C
   JP   NZ, write_loop_main   ; If not, loop again
ENDASM
FEND

FSTART curor            ; Integrates cursor into LCD data with OR logic
ASM
   DI            ; Note that IY is being used in this routine, necessitating DI and EI, and restoring IY
   LD   IY, curspr2      ; We want the arrow (see curspr function above, that contains the sprite images)
   LD   IX, curbuf      ; IX points to the cursor buffer
   LD   A, 8         ; 8 rows of data must be integrated into the cursor buffer

copy_loop:
   PUSH   AF         ; Save our counter
   LD   A, (coord+1)      ; Get the row coordinate
   AND   $07         ; Get the shift amount (0 if image is aligned on LCD byte)
   LD   B, (IY)         ; Copy left half of image into B
   LD   C, 0         ; C = 0 since we will be shifting bits of B into C (and we're using OR logic)
   LD   D, (IY+8)      ; Copy left half of bitmask into D
   LD   E, $FF         ; E = $FF since we will be shifting bits of D into E (and we're using AND logic)
   CP   0         ; See if shift amount is 0
   JP   Z, copy_loop_continue   ; If yes, no shifting required, so jump!

shift_loop:
   SRL   B         ; Shift left part of sprite image (original bit 0 sent to carry)
   RR   C         ; Build right part of sprite image (carry sent to bit 7; convenient!)
   SRL   D         ; Shift left part of sprite image
   RR   E         ; Build right part of sprite image
   LD   H, A         ; Problem: there is no shift/rotate instruction to put a 1 into bit 7
   LD   A, D         ; Solution: OR A with %10000000 ($80)...This necessitates moving stuff around...
   OR   $80
   LD   D, A
   LD   A, H
   DEC   A
   CP   0         ; Finally! See if we've shifted enough
   JP   NZ, shift_loop      ; If not, loop again

copy_loop_continue:         ; Time to put the cursor image into the cursor buffer, bitmask and all
   LD   A, (IX)         ; A holds left cursor buffer byte
   AND   D         ; Clear the area occupied by the cursor image with AND logic (0 resets, 1 preserves)
   OR   B         ; Put cursor image into cleared area with OR logic (1 sets, 0 ignores)
   LD   (IX), A         ; Put modified byte back into cursor buffer
   LD   A, (IX+8)      ; Repeat process, this time with the right side; this is where index registers come in handy
   AND   E
   OR   C
   LD   (IX+8), A      ; You gotta love offsets; makes code very elegant...
               ; Now both parts of sprite are in the cursor buffer!
   INC   IY         ; Do that incrementing
   INC   IX         ; Ditto
   POP   AF         ; Restore the counter saved so long ago
   DEC   A         ; Decrement it
   CP   0         ; See if we've gone through the entire cursor image
   JP   NZ, copy_loop      ; If not, loop again

   LD   IY, Flags      ; Restore the state of IY
   EI            ; Enable Interrupts
ENDASM
FEND

FSTART waitforLCD         ; Wait for the *slow* LCD driver
ASM
waitforLCD_again:
   IN   A, ($10)
   BIT   7, A         ; Bit 7 tells us the driver's status (1 = busy, 0 = ready)
   JR    NZ, waitforLCD_again
ENDASM
FEND

FSTART getkey            ; Direct key input routine
ASM
   LD   A, $FF
   OUT   (1), A         ; Reset keyport
return:
ENDASM
CURSOR               ; Call the full cursor display routine
slowdown            ; Direct input is so fast, we have to slow it down (just a short pause)
ASM
key_loop:
   LD   A, $FE         ; Set the arrow keys group
   OUT   (1), A
   NOP            ; Wait
   NOP            ; Wait some more
   IN   A, (1)
   BIT   0, A         ; Check for the arrow keys being pressed; if any are pressed we jump
   JP   Z, arrow      ; Exactly which ones are pressed will be handled later
   BIT   1, A
   JP   Z, arrow
   BIT   2, A
   JP   Z, arrow
   BIT   3, A
   JP   Z, arrow
   LD   A, $FD         ; Set key group that includes [CLEAR]
   OUT   (1), A
   NOP            ; Twiddle one's thumbs
   NOP            ; Twiddle some more
   IN   A, (1)
   CP   $BF         ; See if [CLEAR] was pressed
   JP   Z, exit         ; If yes, exit!
   JP   key_loop

arrow:               ; Now we figure out just which arrow key was pressed
   LD   D, A         ; D holds key press value (trust me, this way is better)
   LD   BC, (coord)      ; Save coordinates of cursor in BC
   BIT   0, D         ; See if down was pressed
   CALL   Z, down         ; If yes, call that routine
   BIT   3, D         ; See if up was pressed
   CALL   Z, up         ; If yes, call that routine
   BIT   1, D         ; See if left was pressed
   CALL   Z, left         ; If yes, call that routine
   BIT   2, D         ; See if right was pressed
   CALL   Z, right      ; If yes, call that routine
   LD   HL, (coord)      ; Get the new modified coordinates
   LD   A, H         ; Get ready to compare with that saved in BC
   CP   B
   JP   NZ, continue_arrow   ; If there is a difference, the cursor will need to be erased and redisplayed
   LD   A, L
   CP   C
   JP   NZ, continue_arrow

   JP   key_loop      ; Cursor position didn't change

continue_arrow:
   LD   (coord), BC      ; Replace old coordinates
   PUSH   HL         ; Save new coordinates
ENDASM
curwrite savebuf         ; Erase cursor (by copying saved screen data back to the screen
ASM
   POP   HL         ; Restore HL
   LD   (coord), HL      ; Store new coordinates
   JP   return         ; Back to the top of the routine!

down:               ; Checks to see if top of cursor off bottom of screen, otherwise moves it down one pixel
   LD   A, (coord)      ; (coord) holds row coordinate
   CP   62
   RET   Z
   INC   A
   LD   (coord), A
   RET
up:               ; Checks to see if top of cursor at top of screen, otherwise moves it up one pixel
   LD   A, (coord)
   CP   0
   RET   Z
   DEC   A
   LD   (coord), A
   RET
left:               ; Checks to see if left side of cursor at left of screen, otherwise moves it left one pixel
   LD   A, (coord+1)      ; (coord+1) holds column coordinate
   CP   0
   RET   Z
   DEC   A
   LD   (coord+1), A
   RET
right:               ; Checks to see if right of cursor off right of screen, otherwise moves it right one pixel
   LD   A, (coord+1)
   CP   95
   RET   Z
   INC   A
   LD   (coord+1), A
   RET
exit:
ENDASM
FEND

FSTART slowdown            ; The slowdown routine, basically just wastes time; nice example of a 16-bit counter, though
ASM
   LD   BC, $0800
loop:
   DEC   BC
   LD   A, B
   OR   C
   JP   NZ, loop
ENDASM
FEND
I was having this problem with my asm frog demo.

separate out the getkey loop and the drawing loop. then only draw if it has actually been moved.
Elfprince is right. It looks like you're xoring the cursor everytime you read a key; you need to only call the routine to erase it after a key is pressed, then again to redraw right before (but not inside) the getkey loop.
No, I don't erase the cursor unless it moves...


Code:
LD   HL, (coord)      ; Get the new modified coordinates
   LD   A, H         ; Get ready to compare with that saved in BC
   CP   B
   JP   NZ, continue_arrow   ; If there is a difference, the cursor will need to be erased and redisplayed
   LD   A, L
   CP   C
   JP   NZ, continue_arrow

   JP   key_loop      ; Cursor position didn't change

continue_arrow:
   LD   (coord), BC      ; Replace old coordinates
   PUSH   HL         ; Save new coordinates
ENDASM
curwrite savebuf         ; Erase cursor (by copying saved screen data back to the screen
ASM
   POP   HL         ; Restore HL
   LD   (coord), HL      ; Store new coordinates
   JP   return         ; Back to the top of the routine!
Hm, I'll have to examine it more closely then. Nothing is really jumping out at me from that...

Code:
   LD   (coord), BC      ; Replace old coordinates
   PUSH   HL         ; Save new coordinates
Shouldn't Hl and BC be switched here. From you comments above in the code, BC appears to be the old coordinates, and HL the new. Either the comments above are wrong or misleading, or you have these backwards. In either case, this may not be the problem, but at least it fixes something (if nothing more than your comments).
I believe my comments are right (that said, they could be misleading...). BC holds the old coordinates, HL holds the new ones. In the code you quoted, I put the old coordinates back into coord so that the cursor can be erased, while saving the new ones (in HL) from destruction by curwrite.
Yup, I see what you're saying. I still suspect a register pair switch somewhere in there, but it can't be, because if it was occuring the mouse would never move...
  
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
BZC
» Goto page Previous  1, 2, 3 ... , 10, 11, 12  Next
» View previous topic :: View next topic  
Page 11 of 12
» 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