Author Topic: Routines  (Read 314242 times)

0 Members and 1 Guest are viewing this topic.

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Routines
« Reply #570 on: June 20, 2011, 11:45:12 pm »
I think this is about as fast as it gets for drawing a white square to both buffers. It is not clipped. The code given is for drawing a 6x6 square, but it can be modified to draw a rectangle of any width from 1-9 and any height.

I haven't actually tested this, but hopefully it works. If it does work, it will be very fast. It is faster than drawing a single unaligned sprite to only one buffer.


Code: (79 bytes, 1164 cycles) [Select]
Lbl CLR
.Clear a 6*6 spot on both buffers
.r₁ is the X coordinate and r₂ is the Y coordinate
Asm(447D85856F29293AA5834FCB39CB39CB390911409319E5E607874F)
([03FF81FFC0FFE07FF03FF81FFC0FFE07])
Asm(095E2356E10606C57EA377237EA277013105097EA377237EA27701D9FA09C110E6)
Return


Code: (Source code) [Select]
  ld b,h
  ld a,l
  add a,l
  add a,l
  ld l,a
  add hl,hl
  add hl,hl
  ld a,(axv_r1)
  ld c,a
  srl c
  srl c
  srl c
  add hl,bc
  ld de,plotSScreen
  add hl,de
  push hl
  and %00000111
  add a,a
  ld c,a
  ld hl,$0000        ;Replace with mask LUT
  add hl,bc
  ld e,(hl)
  inc hl
  ld d,(hl)
  pop hl
  ld b,6
DrawLoop:
  push bc
  ld a,(hl)
  and e
  ld (hl),a
  inc hl
  ld a,(hl)
  and d
  ld (hl),a
  ld bc,appBackUpScreen-plotSScreen-1
  add hl,bc
  ld a,(hl)
  and e
  ld (hl),a
  inc hl
  ld a,(hl)
  and d
  ld (hl),a
  ld bc,plotSScreen-appBackUpScreen-1+12
  add hl,bc
  pop bc
  djnz DrawLoop
« Last Edit: June 21, 2011, 05:23:02 pm by Runer112 »

Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Routines
« Reply #571 on: June 21, 2011, 12:26:33 pm »
Runer, your routine doesn't appear to work for me.  Maybe I typed it in wrong, but I checked it after typing it in and don't appear to have. :-\

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Routines
« Reply #572 on: June 21, 2011, 05:23:37 pm »
I found an error and fixed it, try it again? Hopefully it was the last error.

Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Routines
« Reply #573 on: June 21, 2011, 05:45:39 pm »
Yay, that worked!  Thanks, Runer. ;D

Offline Deep Toaster

  • So much to do, so much time, so little motivation
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 8217
  • Rating: +758/-15
    • View Profile
    • ClrHome
Re: Routines
« Reply #574 on: July 01, 2011, 12:35:15 pm »
Simple stuff that you probably know already, but I'll post it here anyway.

To round a fixed-point number down (floor function), it's pretty simple. Just mask the first eight bits (· being the 16-bit AND operator):
EFF00
To round up (ceiling function), add 255:
A+255·EFF00
These obviously don't work (and don't need to work) on integers, but if you want integer division to round up instead of down, you can do:
A-1/B+1




Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Routines
« Reply #575 on: July 28, 2011, 10:31:39 pm »
Someone asked for subtring and instring functions like those in TI-BASIC. So I made an Axe library with those two routines! Here's a quick summary of each one:

  • SUB: Creates and returns a pointer to a substring of another string.
    • r1 = String
    • r2 = Start (1-indexed)
    • r3 = Length (1-255)
    • Notes: The 256-byte section of memory starting at $8000 is used as the substring buffer.
    • Example: SUB("HELLO WORLD!",7,6) would return a pointer to "WORLD!".

  • INS: Returns the 1-indexed position of one string in another, or 0 if not found.
    • r1 = String
    • r2 = Search string
    • [Optional] r3 = Start (1-indexed)
    • Notes: The optional starting position in the string being searched should not exceed the length of the string.
    • Example: INS("HELLO WORLD!","A") would return 0.
    • Example: INS("HELLO WORLD!","WORLD") would return 7.
    • Example: INS("HELLO WORLD!","L",5) would return 10.





The Axe library is attached below. To use it in your program, simply send this to your calculator and include "prgmSTRLIB" in your program. I tested it a bit and think it works perfectly, but if not, please inform me! :)
« Last Edit: July 28, 2011, 10:42:09 pm by Runer112 »

Offline Michael_Lee

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1019
  • Rating: +124/-9
    • View Profile
Re: Routines
« Reply #576 on: August 03, 2011, 01:54:30 am »
Polygons:

I made a subroutine that can draw a shaded polygon with an arbitrarily high amount of vertexes.

It can also handle convex and almost handle concave polygons.

You have to designate a segment of memory that contains a list of vertex.  The 0th byte is the X-coordinate of the first vertex, the 1st byte is the Y-coordinate of the first vertex, the 2nd byte is the X-coordinate of the second vertex, etc...  The last pair of vertexes has to be identical to the first pair, to 'close the loop'.

Also, the first (and therefore last) point in the list has to be the left-most or right-most point of the polygon, otherwise it'll look weird.

I made a demo -- source attached, and comments and pic below.
[2ND] to place a vertex, [ALPHA] to display the polygon, and [DEL] to clear the screen.  [CLEAR] exits.

It should be compatible with Axe 0.5.x and 1.0.x

Code: [Select]
.POLYGON

Fix 5

10->A        .The X coordinate of the vertex selector
10->B        .The Y coordinate of the vertex selector

0->T         .Total amount of vertexes
20->M        .Maximum amount of vertexes (not necessary -- only for sanity checks)

L4->V        .Pointer to the list of Vertexes
L1->C        .Pointer to some free ram (for Calculations)

ClrDraw
ClrDraw^^r

RectI(A-1,B-1,3,3)^^r


Repeat getKey(15)
    RectI(A-1,B-1,3,3)^^r
    getKey(3)-getKey(2)+A->A
    getKey(1)-getKey(4)+B->B
    RectI(A-1,B-1,3,3)^^r
       
    Rect(80,9,40,40)
    RectI(80,9,40,40)

    Text(80,10,A>Dec)
    Text(80,18,B>Dec)
    Text(80,30,T>Dec)
       
    If getKey(54)          .Adds a vertex
        If T<M
            A->{T*2+V}     .The last element in the list must equal the first one.
            B->{T*2+1+V}
            T+1->T
            Pxl-On(A,B)
        End
        For(Z,0,20)        .Delay for usability
            DispGraph^^r
        End
    End

    If getKey(48)          .Draws the polygon
        {V}->{T*2+V}
        {V+1}->{T*2+V+1}
        sub(POL,T,V,C)
        0->T
        For(Z,0,20)
            DispGraph^^r
        End
    End

    If getKey(56)           .Clears the screen
        ClrDraw
        ClrDraw^^r
        RectI(A-1,B-1,3,3)^^r
        0->T
    End

    DispGraph^^r
End

Return


Lbl POL
    .Parameters
    .  r1: The total amount of vertexes
    .  r2: A list of vertexes (pairs of X and Y coordinates, each one byte)
    .  r3: A pointer to some free ram (Amount needed == approx. (max polygon width) * 2)
    .
    .Destroyed
    .  W, X, Y, Z, r3, r4, r5, r6
    .
    r3->W
    For(r4,0,r1-1)
        r4*2+r2->r5
        r4+1*2+r2->r6

        {r5}-{r6}->X
        {r5+1}-{r6+1}->Y
       
        If X>=>=0
            For(Z,0,X)
                {r5}-Z->{r3}
                ~Y*Z//X+{r5+1}->{r3+1}
                r3+2->r3
                M+2->M
            End
        Else
            For(Z,0,abs(X))
                {r5}+Z->{r3}
                Y*Z//X+{r5+1}->{r3+1}
                r3+2->r3
                M+2->M
            End
        End
    End

    For(Z,1,r3-W/2-1)
        Line({Z*2+W},{Z*2+W+1},{Z*2+W},{Z*~2+r3+1})^^r
    End
Return
« Last Edit: August 03, 2011, 02:10:17 am by Michael_Lee »
My website: Currently boring.

Projects:
Axe Interpreter
   > Core: Done
   > Memory: Need write code to add constants.
   > Graphics: Rewritten.  Needs to integrate sprites with constants.
   > IO: GetKey done.  Need to add mostly homescreen IO stuff.
Croquette:
   > Stomping bugs
   > Internet version: On hold until I can make my website less boring/broken.

Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Routines
« Reply #577 on: August 03, 2011, 09:18:55 am »
Nice.  :D  Great job, Michael. :)

Offline Happybobjr

  • James Oldiges
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2325
  • Rating: +128/-20
  • Howdy :)
    • View Profile
Re: Routines
« Reply #578 on: September 01, 2011, 10:59:31 pm »
Could someone make a routine to rotate the screen (or a 64x64 region) 64 (90) degrees?
School: East Central High School
 
Axe: 1.0.0
TI-84 +SE  ||| OS: 2.53 MP (patched) ||| Version: "M"
TI-Nspire    |||  Lent out, and never returned
____________________________________________________________

Offline WaeV

  • LV0 Newcomer (Next: 5)
  • Posts: 3
  • Rating: +4/-0
    • View Profile
Re: Routines
« Reply #579 on: September 21, 2011, 02:15:09 am »
This is an example of some functional code that we wrote in one of my programming classes.  The objective was to write a function that creates iterators.  Each time you call the iterator, it returns one more than the previous call.  Each time you call the iterator generator, it returns a new iterator.  We do this with lambda syntax and closures.  We wrote this in Scheme, but I was surprised and impressed to see it correctly execute in Axe.

The Axe code:
(I used liberal amounts of spaces to get it to line up the way I did)
Code: [Select]
.ITERATE

Iter()→L

Disp (L)()►Dec,i
Disp (L)()►Dec,i
Disp (L)()►Dec,i

Iter()→M

Disp (M)()►Dec,i
Disp (M)()►Dec,i
Disp (L)()►Dec,i

Lbl Iter
Return
λ(
  λ(
    λ(
      r₁+1→r₁
    )
  )(0)
)()

Output:
Code: [Select]
asm(prgmITERATE
    1
    2
    3
    1
    2
    4

An interesting side-effect of this is that the current iteration value is not stored in any variables - it's captured in the closure.  Not that it's efficient to do this on a calculator with limited memory, but it's interesting to say the least.
« Last Edit: September 21, 2011, 02:16:07 am by WaeV »

Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Routines
« Reply #580 on: September 21, 2011, 03:26:58 pm »
This is an untested routine for displaying text with newlines in Axe.
Quote
:Lbl TXT
:.sub(TXT,Initial X,Initial Y,String)
:r1->r4
:For(I,0,length(r3))
:If {I+r3}->{L1}r-255
:Text(r1,r2,L1)
:r4+4->r4
:Else
:r2+7->r2
:r1->r4
:End
:End
:Return

Here is a sample usage:
Quote
:"TEXT[FF]NEWLINE[FF]ANOTHER LINE"->Str1
:sub(TXT,X,Y,Str1)
« Last Edit: September 21, 2011, 03:27:37 pm by ztrumpet »

Offline Darl181

  • «Yo buddy, you still alive?»
  • CoT Emeritus
  • LV12 Extreme Poster (Next: 5000)
  • *
  • Posts: 3408
  • Rating: +305/-13
  • VGhlIEdhbWU=
    • View Profile
    • darl181.webuda.com
Re: Routines
« Reply #581 on: October 08, 2011, 01:19:49 am »
How feasible would it be to make a line clipping routine?  I'm seeing more and more games that could use it, and iirc Quigibo doesn't plan on building it in :(
Vy'o'us pleorsdti thl'e gjaemue

Offline Deep Toaster

  • So much to do, so much time, so little motivation
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 8217
  • Rating: +758/-15
    • View Profile
    • ClrHome
Re: Routines
« Reply #582 on: October 08, 2011, 01:24:48 pm »
They're actually pretty simple. (Let's see if I can find my routine...)

The idea behind it is to shorten the X- and Y-lengths of the line so it's completely within the screen, but keeping them proportional (so the slope Y/X stays the same). For example, if the line runs from (X1,Y1) to (X2,Y2) and X2 is the only out-of-bounds point (say 99), you assign 95 to X2 (within the screen bounds), then move Y2 so the slope stays the same.

Take 95–X1 (which is the horizontal length of the clipped line), divide it by the original horizontal length (in our case, 99–X1), and multiply it by the current vertical length (Y2–Y1), to find the vertical length of the clipped line. Add that to Y1 and you get the new value for Y2. Now that both the points are completely within the screen, you can use Line() to draw the new line.
« Last Edit: October 08, 2011, 01:24:59 pm by Deep Thought »




Offline Darl181

  • «Yo buddy, you still alive?»
  • CoT Emeritus
  • LV12 Extreme Poster (Next: 5000)
  • *
  • Posts: 3408
  • Rating: +305/-13
  • VGhlIEdhbWU=
    • View Profile
    • darl181.webuda.com
Re: Routines
« Reply #583 on: October 10, 2011, 02:51:05 pm »
I'll try to work something out of that, thanks ;D
Vy'o'us pleorsdti thl'e gjaemue

Offline Darl181

  • «Yo buddy, you still alive?»
  • CoT Emeritus
  • LV12 Extreme Poster (Next: 5000)
  • *
  • Posts: 3408
  • Rating: +305/-13
  • VGhlIEdhbWU=
    • View Profile
    • darl181.webuda.com
Re: Routines
« Reply #584 on: October 11, 2011, 09:10:46 pm »
Ok, I'm confused.  Using the ideas from Deep's post I threw something together:
(S,T)="(X1,Y1)"
(X,Y) are manipulated
(N,O)="(X2,Y2)"
Spoiler For Code:
Quote from: Axe
.ATEST1
40XY
48S
32T
Repeat getKey(15)
If getKey(54)
ClrHome
Disp "N",N>Dec,"  O",O>Dec,i,"X",X>Dec,"  Y",Y>Dec
While getKey(54)
Pause 10
End
End
X+getKey(3)-(getKey(2))X
XN
Y+getKey(1)-(getKey(4))Y
YO
If N>>95
95N
(95-S)//(X-S)*(O-T)O
O+TO
End
If O>>63
63O
63-T//(Y-T)*(N-S)N
N+48N
End
If N<<0
-1N
~S//(X-S)*(O-T)+TO
End
If O<<0
-1O
~T//(Y-T)*(N-S)+SN
End
Line(S,T,N,O)
DispGraphClrDraw
Pause 20
End


Generated by the BBify'r (http://clrhome.tk/resources/bbify/)
But for some reason, once the manipulable point goes off-screen, the program does something wrong and will only draw horizontal or vertical lines.  I'm suspecting it's rounding down to zero where the division happens, but idk.

After screwing around with it for a bit, I got this:
Spoiler For Code:
Quote from: Axe
.ATEST2
40XY
48S
32T
Repeat getKey(15)
If getKey(54)
ClrHome
Disp "N",N>Dec,"  O",O>Dec,i,"X",X>Dec,"  Y",Y>Dec
While getKey(54)
Pause 10
End
End
X+getKey(3)-(getKey(2))X
XN
Y+getKey(1)-(getKey(4))Y
YO
If N>>95
95N
(95-S)//(N-S)*(O-T)O
O+TO
End
If O>>63
63O
63-T//(O-T)*(N-S)N
N+48N
End
If N<<0
-1N
~S//(N-S)*(O-T)+TO
End
If O<<0
-1O
~T//(O-T)*(N-S)+SN
End
Line(S,T,N,O)
DispGraphClrDraw
Pause 20
End


Generated by the BBify'r (http://clrhome.tk/resources/bbify/)
...and it somewhat* works, I have no idea why but it does. :P

So um yeah, I guess have a really unoptimized line routine (with other stuff thrown in)! ;)

*watching the screenie, you can tell the endpoint of the line is fixed on the edge, so the slope doesn't change accordingly...?

EDIT: btw it runs a bit slower than it should b/c there's a Pause 20 in there.  It can run faster than in the screenshot.
« Last Edit: October 12, 2011, 11:46:43 am by Darl181 »
Vy'o'us pleorsdti thl'e gjaemue