Page 4 of 5

Posted: Sat 11 Jun, 2005 4:28 am
by Dwedit
I've already made my multi-line text displayer used in bubble bobble...

Code: Select all

  call DrawText
  .dw Textlines
  ret

DrawText:
	ex (sp),hl
	ld e,(hl)
	inc hl
	ld d,(hl)
	inc hl
	ex (sp),hl
	ex de,hl
	;now loop...
DrawTextLoop:
	ld e,(hl)
	inc hl
	ld d,(hl)
	inc hl
	ld (pencol),de
	vputs
	ld a,(hl)
	inc a
	jr nz,DrawTextLoop
	ret

Textlines:
 .db 4,8,"Hello world!",0
 .db 4,14,"Line 2!",0,255

Posted: Sat 01 Oct, 2005 6:30 pm
by eightythreeplus
Here is an optimization I've used many times. Suppose you have a variable that contains a letter representing the current player (like 'O' or 'X' for Tic-Tac-Toe). After each move, the variable will alternate between each of two states - $4F or $58. Here is the simplest way to make this work (assuming the current state is in register a):

Code: Select all

     cp $4F
     jp Z, state2
     ld a, $4F
     jp done

state2:
     ld a, $58

done:

At the end of the code, register a contains the other value ($58 if it was $4F, or $4F if it was $58). But this code can be made shorter and faster. If you add $4F and $58, you get $A7. You can get the same results by evaluating $A7 - a. Here's how:

Code: Select all

     neg a
     add a, $A7

The code is much shorter and faster, but harder to understand what is going on (which is why you would document it :).

Posted: Sat 01 Oct, 2005 7:02 pm
by DarkerLine
Even shorter and even harder to understand:

Code: Select all

xor $17
Explanation: $4F xor $58 = $17.

Therefore $4F xor $17 = $58 and $58 xor $17 = $4F.

I don't think you can get any smaller.

Posted: Sat 01 Oct, 2005 7:36 pm
by CoBB
By the way, when you want to calculate N-A generally, never do this:

Code: Select all

neg
add a,N
You can cut off a byte and some clocks by doing it this way:

Code: Select all

cpl
add a,N+1
This is because neg is practically equivalent to cpl \ inc a.

Posted: Sun 02 Oct, 2005 7:15 pm
by eightythreeplus
Ahh, so if I have two states [x] and [y] that I want to alternate between:

Code: Select all

     ld a, [x]
     xor [y]
     ld (xor_val), a

Now if I save the value in register a, the following code will cause an alternation between the states [x] and [y] (assuming register b contains the current state):

Code: Select all

     ld a, (xor_val)
     xor b

Is this correct, DarkerLine?

Posted: Sun 02 Oct, 2005 8:02 pm
by CoBB
Yes, that's correct.

Posted: Wed 05 Oct, 2005 2:24 am
by eightythreeplus
In the expression N - a, it would actually be more efficient to use the "neg a/ add a, N" combination if N refers to a register rather than a constant. Or would there be a more efficient method in that situation?

Posted: Wed 05 Oct, 2005 2:35 am
by eightythreeplus
If you are displaying multiple strings at different locations and the strings are located sequentially in memory, you can optimize by using the de register to set curRow and curCol rather than the hl register; it does add 1 byte for each "ld (xxxx), de" instruction, but you save 3 because you don't have to repoint hl to the next string after it is "messed up" with a screen-coordinate value.

Change

Code: Select all

     ld hl, $0303
     ld (curRow), hl
     ld hl, strPtr1
     b_call(_PutS)

     ld hl, $0505
     ld (curRow), hl
     ld hl, strPtr2
     b_call(_PutS)

to

Code: Select all

     ld de, $0303
     ld (curRow), de
     ld hl, strPtr1
     b_call(_PutS)

     ld de, $0505
     ld (curRow), de
     b_call(_PutS)

when strPtr2 follows strPtr1 in memory to save 1 byte. Another alternative would be to save and retrieve hl from the stack; this would save de from being destroyed, but it would also keep you from using stack-related operations between the two blocks of code.

Posted: Fri 24 Nov, 2006 4:16 pm
by King Harold
Flags instead of bit, whenever possible, can save around 8 T-states.

Code: Select all

in (c)
jp s,label
instead of:

Code: Select all

in a,(c)
bit 7,a
jp z,label
works for sign bit since its a copy of bit 7

Posted: Fri 24 Nov, 2006 5:00 pm
by CoBB
That’s wrong. The dummy input does not use the flag register as the destination! It just sets the flags as in all other inputs and throws away the value that was read.

Posted: Fri 24 Nov, 2006 5:13 pm
by King Harold
It works though, for bit 7 anyway, its a pitty bits 5 and 3 don't have a conditional thing, they're also copies of the real value - or so the manual says.
@coBB: sorry wasn't paying much attention - corrected now :P

Posted: Sat 10 Mar, 2007 1:58 pm
by King Harold
You could use the flag trick for an LCD waiter:

Code: Select all

WaitLCD:
	ld c,$10
-:	in (c)
	ret p
	jr {-}
will wait until the LCD driver is ready for the next command, CPU speed etc. doesn't matter.

Posted: Sun 11 Mar, 2007 8:35 pm
by snowman_hater
instead of putting 2 nop's between setting the key group and reading from the key pad, use a 1-byte instruction that takes like 7 t-states.

Code: Select all

ld a,$fe
out (1),a
ld a,(de)
in a,(1)

Posted: Fri 23 Mar, 2007 8:50 pm
by Halifax
Gambit wrote:Normally, you would use the following to increment a variable:

Code: Select all

ld a,(var)
inc a
ld (var),a
But if hl is not tied up and all you do is check flags, use indirection:

Code: Select all

ld hl,var
inc (hl)
ld a,(hl)   ;Optional
Does this not waste 10 tstates.I looked up the tstates for the instructions and their parameters and it shows that indirection wastes 10 tstates.

Posted: Fri 23 Mar, 2007 10:10 pm
by Liazon
Halifax wrote:
Gambit wrote:Normally, you would use the following to increment a variable:

Code: Select all

ld a,(var)
inc a
ld (var),a
But if hl is not tied up and all you do is check flags, use indirection:

Code: Select all

ld hl,var
inc (hl)
ld a,(hl)   ;Optional
Does this not waste 10 tstates.I looked up the tstates for the instructions and their parameters and it shows that indirection wastes 10 tstates.
IIRC


ld a,(var) :arrow: 13 tstates
inc a :arrow: 4 tstates
ld (var),a :arrow: 13 tstates
total :arrow: 30 tstates

ld hl,var :arrow: 10 tstates
inc (hl) :arrow: 11 tstates
ld a,(hl) <optional> :arrow: 7 tstates
total :arrow: 28 tstates

and LESS space iirc taken up. (2 bytes less)

only downside probably is the fact you've swamped 2 registers.