|
Post by D-Type on Apr 30, 2020 17:44:35 GMT -5
There are a bunch of trig function routines in the Vectrex BIOS, starting with the simple:
Malban tutorial: Rise_Run_Angle Get_Rise_Idx Get_Run_Idx Rise_Run_Idx Rise_Run_X Rise_Run_Y Rise_Run_Len Anyone ever used these?
I guess when the Vectrex was new and PROMs were $$$'s, using BIOS supplied trig routines seemed like a good idea, but the lookup table in the BIOS is tiny and I can't find any code in VIDE's library that uses them. The documentation on them also seems a bit limited. Malban's Release code, which has a load of onscreen circular movement stuff going on seems to have it's own similar table, but with twice the resolution/size.
It's 30+ years since I did any trig, so I did a quick refresher on the web, but I'm still have a bit of murkyness regarding what you'd use these routines for and how you'd use them. Everything I've even programmed has 90 degree angles - I'm no artist!
Anyone have anything to share on this topic? Code? Documentation?
Thanks!
You can also see them listed in Peer's C vectrex_rum.h file (same code, different function names): // COMPAS 0xF593 CMPASS Return angle for given delta 'Y:X' // COSGET 0xF5D9 COSINE Calculate the cosine of 'A' // SINGET 0xF5DB SINE Calculate the sine of 'A' // SINCOS 0xF5EF --- Calculate the sine and cosine of 'ANGLE'
// RSINA 0xF65B MSINE Multiply 'A' by previous sine value // RSIN 0xF65D LSINE Multiply 'LEG' by previous sine value // RCOSA 0xF661 MCSINE Multiply 'A' by previous cosine value // RCOS 0xF663 LCSINE Multiply 'LEG' by previous cosine value
|
|
|
Post by gauze on Apr 30, 2020 23:52:25 GMT -5
I've made several runs at these routines and never could figure them out, or the lay out of the lookup tables (they are in at least one rum source, i don't get it)
|
|
|
Post by Peer on May 1, 2020 0:15:12 GMT -5
I did some investigations, but that was several years ago. My memory could be failing, but from what I recall there are two tables in the ROM, one for sine and one for tangent. The routines are some trade-off between runtime efficiency and memory efficiency. The sine table e.g. just stores the values for the (logical) angles from 0 to 90 only, and the routines exploit the common identities like cos(a) == sin(a+90) or sin(a+180) == -sin(a). I never used them later on as they did not fit my needs (angle resolution and scaling). I now have a C preprocessor macro which generates trig tables or rotated vector lists at compile time
Btw, the (alternate) names in the comments of the rum header file are taken from the original GCE programmers manuals and documentation.
Cheers, Peer
|
|
|
Post by Malban on May 1, 2020 7:44:01 GMT -5
Hi, the sin/cos table is a little bit explained in one of my old videos: vide.malban.de/13th-of-may-explosionsAlso - in Vectorblade, the dodger mini game was written at a time where I had very little spacf left, so I used Bios functions the rotation of the mines is done with the bios functions. They are not too fast, but work great lda dodgerAngle1 ldx #MINE1 ldu #ROT_MINE1 jsr Rot_VL_Mode
... (angles range from 0=0 degrees to 63=355 degrees)
|
|
|
Post by Peer on May 1, 2020 8:01:31 GMT -5
Just to explain my previous post:
Yes, Rot_VL_Mode is indeed quite nice, and I do use it in my code whenever performance is not that critical. As Rot_VL_Mode uses the Get_Rise and Get_Run functions internally, I stand corrected here. I do use those, just not explicitly.
Cheers, Peer
|
|
|
Post by D-Type on May 1, 2020 15:20:28 GMT -5
Thanks for the feedback everyone, I'll have a look at the Malban video, if it's like the others he's done, it'll provide some big clues!
My original query was about the trig functions, I haven't got onto the rotation functions yet, which I now would guess are the main users of the trig functions.
I'm still not sure what I'd need to use a trig function for, may be for drawing moveable shapes without a precalculated vector list.
There are some descriptions of the various functions in the Vectrex Programmers Manual Volumes that also show what other functions they reference.
Unfortunately, they use the other RUM function names, which is a hassle, I wish there were not two different BIOS disassemblies!
If anyone has any other golden nuggets, such as "angles range from 0=0 degrees to 63=355 degrees" (I don't know what that means yet, but I'm looking forward to finding out) or code to share, please post!
|
|
|
Post by Peer on May 1, 2020 23:56:29 GMT -5
The Vectrex RUM functions use only 6 bits for angle encodings, i.e. only the 6 least significant bits of the angle byte are relevant. Thus you have a range of values 0 to 63, and a total of 64 different values. Those encode a full 360 degress circle. A delta of 1 thus corresponds to a step of 360/64 = 5.625 degrees. If you want to turn your vector list by 90 degress (counter clockwise, if I remember correctly), then use angle value 16. 180 degrees corresponds to value 32, 270 degrees to value 48, and 360 degrees would be 64, and thus 0 as only the lower 6 bits are used.
Each vector list format (diffy, duffy, and packet) has its own rotation function. They come in handy if you do not have (or do not want to waste) the ROM space for precalculated rotated lists. The functions need a working RAM buffer for the rotated result, and of course rotating on-the-fly takes time (so it is the usual trade-off between runtime and memory efficiency).
Cheers, Peer
PS: Code to share? Of course! If you are willing to read C
|
|
|
Post by D-Type on May 2, 2020 2:11:55 GMT -5
Thanks Peer. Yes, the 64 "RUM-degrees" is the key to my initial understanding, and it clicks into place when you consider the other BIOS commentary that to convert from site to cosine, you add $10 i.e. 1/4 of 64, because sine and cosine are the same except 90 real degrees displaced. Then I watched Malban's explosion video which added more clarity. Playing with the parameters of the explosion code in VIDE, you can set the number of explosions to 1 and the speed of explosions to 1 (slow) and the RUM-degree interval to 1, then you get an easy to see starburst of 64 dots. (Which then suffers a load of drift and, with the screen slow intensity fade, starts to look a bit like a horse shoe magnet .) Visually, you can see that 64 RUM-degrees is actually quite a reasonable resolution for a 9" screen, IMHO. I haven't looked at the assembly explosion code yet, but, now I have the concept in my head, I reckon I can code something to test it out also. I've coded my Forth API routines and I look forward to testing them out on the command line . Feel free to post a link to your C code, but only if it's handy. Whilst looking at C always makes me think "Wow, what a lot of text!"*, I can read it. 25 years ago, I could write it also. (*My entire Forth to BIOS API code is a couple of hundred lines in a single file, but C is pretty fast, I get it!)
|
|
|
Post by D-Type on May 2, 2020 19:12:22 GMT -5
I got Get_run_idx to do something. Here's some info, in case someone, oneday is interested. (You never know...) The Forth API for the function is super simple ("CODE _Get_run_Idx..."), just an A B exchange, because my Forth is a 16-bit system with values taking up the whole of register D by default. The output under the source code shows some numbers on the left and a generated sine wave on the right. The 16-bit value, i.e. the D-register (displayed with "4 u.r"), is the output from the Get_run_idx routine (i.e Sine function), you give it an angle (0 to $40 representing a full 360 degrees) and it gives you an value scaled to 8 bits (i.e. returned in Register A, the leftmost byte). The rightmost byte is a sign bit ($8x) and a flag representing whether you're on a 90 degree plane ($x1). The 8-bit byte ("2 u.r") is showing an absolute sine value once the negative flag is taken into account and the value has been scaled for printing as a number of stars. The stars depict a low-resolution version of what's actually returned returned by Get_run_idx. I've scaled the trend height from 8-bits+polarity to 4-bits+polarity (using "$10 /") and the number of samples from $40 for a rotation to only $10 ("4 +loop"), just so I can show it here, but it's still recognizable as a sine wave. I'm guessing the other Vectrex BIOS Rise/Run routines build further on these. Learn by doing... CODE _Get_Run_Idx A B EXG, Get_Run_Idx JSR, NEXT ;C \ angle -- value ; value A=VALUE,B=SIGN/OVERFLOW
: U.R \ \ u width -- ; Display u right-aligned in a field n characters wide. >R <# 0 #S #> R> OVER - 0 MAX SPACES TYPE ;
: sine-wave \ -- ; Display a sine wave to the terminal $80 0 do \ 360 degrees = $40 steps for Vectrex i _get_run_idx dup cr 4 u.r \ -- 180sine-val&negative-flags ; >< dup 0< if \ -- 180sine-val ; $FF and negate \ Yes, this could be factored else $FF and then \ -- 360sine-val ; $10 / $10 + dup space 2 u.r space \ -- 360sine-val-low-res ; display val ?dup if 0 do $2A emit loop then \ -- ; Print stars to form sine wave 4 +loop ; \ Make super coarse
VecForth v0.04 2020-03-26 based on 6809 CamelForth v1.1 2016-03-20 OK-0 OK-0 OK-0 hex sine-wave 0 10 **************** 6200 16 ********************** B500 1B *************************** ED00 1E ****************************** FF01 1F ******************************* ED00 1E ****************************** B500 1B *************************** 6200 16 ********************** 80 10 **************** 6280 9 ********* B580 4 **** ED80 1 * FF81 0 ED80 1 * B580 4 **** 6280 9 ********* 0 10 **************** 6200 16 ********************** B500 1B *************************** ED00 1E ****************************** FF01 1F ******************************* ED00 1E ****************************** B500 1B *************************** 6200 16 ********************** 80 10 **************** 6280 9 ********* B580 4 **** ED80 1 * FF81 0 ED80 1 * B580 4 **** 6280 9 ********* OK-0
|
|
|
Post by gtoal on Sept 7, 2020 21:04:57 GMT -5
|
|
|
Post by gtoal on Jan 20, 2022 12:15:02 GMT -5
I was reading this thread again today while looking for some info, so it reminded me... the useful trig function that I don't think has an equivalent in the RUM is atan2 ... here's my implementation, which is as fast as I could make it (algorithmic tweaks only, nothing low-level yet): gtoal.com/vectrex/atan2/iatan2_256.c.html - useful for converting an x,y displacement into an angle. It handles the perennial tangent problem of one of the sides being 0.
|
|
|
Post by gtoal on Jun 28, 2022 15:40:27 GMT -5
I should have posted this back when we were discussing it... if all you want to do is circular movement rather than complex geometry that requires accurate trig functions, the old 'Minsky circle drawing' hack is quite effective: (here's one set of values from gtoal.com/vectrex/title-spin.c.html ) sin = 8; cos = 99; for (;;) { dx = cos>>4; sin = sin + dx; dy = sin>>4; cos = cos - dy; } (I believe it's similar in principle to the more complex Cordic stuff in the link two posts up)
|
|
|
Post by Peer on Jun 29, 2022 6:12:48 GMT -5
I love such bit level hacks. I have probably already mentioned this in some other thread: "Hacker's Delight" by Henry S. Warren Jr. is a great book, containing lots of such things. Well worth a read.
|
|