FAQ  •  Register  •  Login

Tutorial: How to put inline assembly functions into ZX Basic

<<

LCD

Posts: 596

Joined: Fri Feb 13, 2009 3:11 pm

Location: Vienna, Austria

Post Mon Feb 20, 2012 9:20 pm

Re: Tutorial: How to put inline assembly functions into ZX B

britlion wrote:Ah - then you'd need one that just looks like this, I think:


  Code:
function fastcall mirror (number as uByte) as uByte
asm
   ld b,8
   ld c,a
   XOR A
mirrorLoop:
      RR C
      RLA
DJNZ mirrorLoop
end asm
END FUNCTION


I haven't tested it, mind. Just typed it here. Feels right, though :)

Works and is very very fast!!!
Simple but great!
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Wed Feb 22, 2012 12:40 pm

Re: Tutorial: How to put inline assembly functions into ZX B

LCD wrote:Works and is very very fast!!!
Simple but great!


It's a classic case of win by unrolled loop, though. As it stands, the main part of this function (not including the setup for being called, or the returning part at the end, which ZX Basic does for us) takes:

15 (intro) + (7*25) loop + 20 (last loop that doesn't jump back) = 210 T states.

An unrolled loop version would take

15 (intro) + 8*12 = 111 T states. Or 89% faster.... Those 13 T state DJNZ jumps are quite a big proportion.

If I was using this function, considering that I'm using a mirror function to replace storing the graphics in both left and right configuration, I'd want it to be fast, and I'd probably be willing to give up 12 bytes to do this - the loop version is 8 bytes. The unrolled loop is 20. [Edit - just realised that XOR A probably doesn't matter, since the rotates slide A off anyway. So 7 bytes versus 19 bytes, and 206 T states vs 107]

  Code:
function fastcall mirror (number as uByte) as uByte
asm
  ; ld b,8  ; We don't need this either. We're not looping.
   ld c,a
   ; XOR A ; Edit - I bet it works without this. Saving 4 T states

   RR C
   RLA
   
   RR C
   RLA

   RR C
   RLA

   RR C
   RLA

   RR C
   RLA

   RR C
   RLA

   RR C
   RLA

   RR C
   RLA
end asm
END FUNCTION
Last edited by britlion on Mon Feb 27, 2012 5:55 pm, edited 1 time in total.
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Wed Feb 22, 2012 1:38 pm

Re: Tutorial: How to put inline assembly functions into ZX B

Scuse the double post. Odd.
Last edited by britlion on Wed Feb 22, 2012 6:05 pm, edited 1 time in total.
<<

LCD

Posts: 596

Joined: Fri Feb 13, 2009 3:11 pm

Location: Vienna, Austria

Post Wed Feb 22, 2012 5:48 pm

Re: Tutorial: How to put inline assembly functions into ZX B

britlion wrote:If I was using this function, considering that I'm using a mirror function to replace storing the graphics in both left and right configuration, I'd want it to be fast, and I'd probably be willing to give up 12 bytes to do this - the loop version is 8 bytes. The unrolled loop is 20. [Edit - just realised that XOR A probably doesn't matter, since the rotates slide A off anyway. So 7 bytes versus 19 bytes, and 206 T states vs 107]

Excellent, thats why I always like to have choice between functions which are fast and functions which are just small. Thanks!
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
<<

slenkar

Posts: 282

Joined: Sun Feb 13, 2011 3:33 am

Location: Kentucky US, used to be Birmingham UK

Post Wed Feb 22, 2012 11:00 pm

Re: Tutorial: How to put inline assembly functions into ZX B

Is there any chance of getting an extra flag on the Print function that draws a character/sprite mirrored?
left/right and up/down
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Thu Feb 23, 2012 1:00 am

Re: Tutorial: How to put inline assembly functions into ZX B

I'd think that a very unlikely extension - you're asking for mirroring functions to be built into the compiler, and then for an extension to the print routine.

Given you can write your own functions, you can build these extensions into the system anyway - for example, using my mirror function there would be the basis of a left/right mirror.

Are you wanting to mirror UDG or the original character set?

These would be ideal functions to write in BASIC, and then replace with inline assembly :)
<<

slenkar

Posts: 282

Joined: Sun Feb 13, 2011 3:33 am

Location: Kentucky US, used to be Birmingham UK

Post Thu Feb 23, 2012 2:51 am

Re: Tutorial: How to put inline assembly functions into ZX B

I would like to mirror UDG,
does the mirroring function alter the stored image or create a new one?

I think altering the stored image would be best for most uses
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Thu Feb 23, 2012 1:43 pm

Re: Tutorial: How to put inline assembly functions into ZX B

slenkar wrote:I would like to mirror UDG,
does the mirroring function alter the stored image or create a new one?

I think altering the stored image would be best for most uses


It doesn't do either - it's a function. I think you misunderstand what a function does - it takes a parameter and has a return value.

For example, in Sinclair Basic, CHR$ is a function. It takes a number, and returns a string character. So you do CHR$(65) - sending it 65, and it comes back with "A" as a string. This is why PRINT CHR$(65) prints out "A" on the screen.

The mirror function I listed above is the same thing - it takes one number, and returns another number, such that the bits in the first number are a mirror image of the bits in the second.

Let's use the same number as an example. In Binary, the number 65 is '0100 0001'. So mirrored, that would be '1000 0010' right?

If you do PRINT mirror(65), it prints 130 - which is the decimal equivalent of '1000 0010'

This doesn't change your UDG at all, but it can be the basis of /making/ a udg that's mirrored from another one.

For example, to mirror a udg in place:

  Code:
for i=USR "A" to USR "A" +7
poke i, mirror(peek i)
next i


Would probably work. It reads the byte with peek, sends it to mirror, and what comes back from mirror is poked back into the byte again. (Note that with the default graphic of "A" in the UDG A slot, this won't be very obvious, since a left-right mirrored Capital A looks identical before and after). I'm quite certain an assembler version SUB for this could be much better.

In a similar way, vertical reflection means swapping the byte order, so you need somewhere to put them temporarily:

  Code:
DIM buffer (7) as uByte
for i = 0 to 7
let buffer (7-i) =peek (USR "A" +i)
next i

for i = 0 to 7
poke (USR "A" +i), buffer(i)
next i


(The code is all off top of my head and untested. Again, an assembler subroutine would be much faster)
<<

slenkar

Posts: 282

Joined: Sun Feb 13, 2011 3:33 am

Location: Kentucky US, used to be Birmingham UK

Post Thu Feb 23, 2012 3:47 pm

Re: Tutorial: How to put inline assembly functions into ZX B

thanks i can use that to draw tanks that face left or right, saving a few bytes,
it would also help in one of those top down games where the sprite has to face in 8 or more directions
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Mon Aug 19, 2013 9:37 am

Re: Tutorial: How to put inline assembly functions into ZX B

Up on WOS, someone schooled me.

This code will apparently mirror a byte as well. Still trying to get my head round the logic! (and if it works)

  Code:
;17 bytes and 66 clock cycles
Reverse:
    ld b,a         ;b=ABCDEFGH
    rrca         ;a=HABCDEFG
    rrca         ;a=GHABCDEF
    xor b \ and %10101010 \ xor b     ;a=GBADCFEH
    ld b,a         ;b=GBADCFEH
    rrca         ;a=HGBADCFE
    rrca         ;a=EHGBADCF
    rrca         ;a=FEHGBADC
    rrca         ;a=CFEHGBAD
    xor b \ and %01100110 \ xor b     ;a=GFEDCBAH
    rrca         ;a=HGFEDCBA



n=0
n A B
0 0 0 -> 0 = B
0 0 1 -> 1 = B
0 1 0 -> 0 = B
0 1 1 -> 1 = B

n=1
1 0 0 -> 0 = A
1 0 1 -> 0 = A
1 1 0 -> 1 = A
1 1 1 -> 1 = A

a XOR b and n xor b


aaaaaaaa xor bbbbbbbb and 10101010 xor bbbbbbbb = abababab
Previous

Return to How-To & Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by Vjacheslav Trushkin for Free Forums/DivisionCore.

phpBB SEO