Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - MGOS

Pages: [1] 2
Axe / [Tutorial] Key hooks in Axe
« on: December 24, 2013, 05:52:56 pm »
Disclaimer: The code discussed here can be used in completely save and harmless applications, but may also cause damage to your calc if used improperly or even viciously. I'm not responsible for any results in abuse or misuse of this code.

Note this tutorial can be adapted to work with other types of hooks - I find the key hook to be quite easy and still useful so I chose that one for this tutorial.

What is a key hook?
Key hooks are functions which are called on a certain key presses anywhere in the OS or TI-Basic program (or assembly/axe program that uses the OS key press functions). Key hooks thus can be used to add your own awesome functionality to the OS. Many shells use some kinds of key hooks such as zStart. What I'm going to show in this tutorial is how to set up your own key hooks in your Axe program. I'm not that great at assembly programming, so it might not be the cleanest code, but it works nicely and is probably easy to understand.

Important note: To make this work properly and not create memory leaks, you need to compile the program as an APPLICATION! Other keyhooks (such as zStart's) have to be turned OFF to cause no interference!

The key hook function:
That is the routine that runs when any of the keys or combinations (like 2nd+[ ] or Alpha+[ ]) are pressed. You then need to check which one it was and decide what functionality to execute (similar to TI-Basic's getkey-function).
First we need to create a label with the name of the function (like any Axe subroutine). Because I am that creative I call it "HOOK":
Code: [Select]
: Header
:...  //Some other parts of your program

When the function is called we get the code of the key pressed last in the registers a. However, we have to add a,e as the first instruction so the OS recognizes our function as a hook. Because we don't want to mess up the registers in our function, we push them on the stack to back up.
Code: [Select]
add a,e
 push HL
 push BC
 push DE
 push AF

 ld l,a     ; load a to l to make it usable in axe
 ld h,00

 ;function goes here

 pop AF   ; restore the registers we might have messed up
 pop DE
 pop BC
 pop HL

Now the key code is prepared to be used in axe, since it is stored in axe's "ans", the HL register.
I already translated that assembly to Hex, so you can simply add it to your program:

Code: [Select]
: Header
... Some other parts of your program
:->K     //store ans in axe variable K to use in your compare statements

That's the first part done. No feel free to run any instruction according to your needs, as long as you don't jump out of the function. You find a list with the key codes (they differ from the getKey(x) ones) on DeepThought's WikiPad here under "_GetKey (Axe getKeyr)".

Installing your key hook:
Before we can use the key hook function, we need to tell the OS that it should run a key hook and where it is.
These few assembly instructions will set the current HL as the key hook address. In our case, that is the address of the function "HOOK", and we get that using the little "L" you find in the List-OPS menu. So "LHOOK" will return the address of that label.
Code: [Select]
in a,(6)   ;current ROM page to A
 ; Usually we now quit the program using
Now in Axe:
Code: [Select]
: // return to OS

You can put this in any position of your code - I usually put it right to the beginning of the program, so it will be always installed when you run it. But you can also create a menu with an option to turn it on that will then run this code etc.

Now you are basically set to work with your hook.

Disabling the hook:
Usually there is at some point the need to disable the hook again, so there is this simple line of Hex to do that job:
Code: [Select]
:Asm(EF6F4F)  // = _bcall(_ClrRawKeyHook)

You can disable the hook when a certain key is pressed (put in the hook routine) or at some other point (e. g. using again some kind of menu).

Manipulating key code data:
You can manipulate the return value of the getKey function inside your hook routine - a really mighty feature, e. g. you can block a certain key.
Since the key code is stored in register A which is on top of the stack we need to pop it off, manipulate it and push it back on the stack.
This only works at the end of the hook routine, since there the stack is like we left it and we don't want to mess things up.
This stores the value of the "ans" register HL as the return value of our routine.
Code: [Select]
pop AF
 ld a,h
 push AF
In Axe it looks like this:
Code: [Select]
:9    //this now replaces the key pressed with the code for "CLEAR" (example)
:...  //use only ends of if statements here - that doesn't mess anything up.
:Asm(F1D1C1E1)  //usual restore routine
Storing 0 will make the OS ignore the key press, that way you can block certain keys.

Now you should be ready to setup your own routines!

This example will disable the functionality of the "0" key. No idea why someone would do that ;). Pressing "STO->" makes it normal again.
Code: [Select]
:.KeyHook  //name of my app
:Asm(DB06EF664F) //enable Hook
:Asm(CD50002740) //return
:!If K-138   //someone pressed "STO->"
:Asm(EF6F4F)    //Disable the hook
:Else!If K-142   //someone pressed  "0"
:Asm(F17CF5)  //write 0 so the keypress is being ignored
:End   //only an end of an "if"-statement, that's ok

Have fun - and be careful not to mess things up - that happens quite easily.... :)

Other / Calc + TV remote = ???
« on: December 04, 2013, 09:23:33 am »
I was working an a completely different project, an infrared light barrier for outside and I needed some way to filter out the IR light of the LED from the sunlight. A common way to do this is modulation. Instead of just having a LED constantly on, you flash it really fast, e.g. with 33 kHz. The receiver filters out all other frequencies and gives a steady signal. We had a TSOP31233 (datasheet) lying around. This one connects the output pin over a transistor to ground when a 33 kHz signal is applied. The modulation worked fantastically, but the receiver is that sensitive that you cannot simply block the light with a simply object, you have to completely cover the receiver with a black box. That isn't really surprising, since those receivers where made for IR control systems and have to work under every condition. So I took the TV remote and looked what I can get out of it. Strangely enough it works with the same frequency, and it also uses a really simple protocol.


As you can see, there are no other electronic components needed!

I hooked up the sensor to my trusty 83+ and made a simple program that plots the state of the sensor over time. I figured out that the protocol starts with a rather long HIGH pulse, then a short LOW. The bits are coded in the length of the HIGH pulses (long pulse = 1, short one = 0), the LOW pulses are all the same time; the LSB arrives first, then a sequence of up to 15 bits. On this Sony remote, newer functions have more bits (such as enable surround sound or the Bravia sync system) where as functions that have been there forever (numbers, volume, power) have only 8 bits. I figured I only need the lower 8 bits so the following code ignores the upper bits. The program is written in pure Axe:
Code: [Select]
While 1
EndIf port    //wait for the start bit to end
  If EAT()  //return if Stop bit reached or abort
    Goto END
  GET()->{L1+r1}   //buffer the input
0->r2     //result
  r2*2->r2   //shift left
  {7-r1+L1}+r2->r2   //reverse and "or" together

Lbl EAT   //"eats" the Low state
  For(20):End  //some delay
End!If port  //wait until HIGH again
r3>100  // time out exceeded = Stop bit

Lbl GET   //measures the length of a HIGH pulse and returns the result as a bit
EndIf port   //wait until LOW again
r3 > 8    //8 seemed to be the threshold that worked best

You can now write programs which use this function. For example move a sprite around the screen:
Code: [Select]
FnOff  //disable the nasty OS interrupts
While 1
  !If port   //check for a keypress
    K-244??Y--   //up
    K-245??Y++   //down
    K-180??X--   //left
    K-179??X++   //right
EndIf getKey(15)
LnReg   //turn interrupts back on

--- Subroutines from above ---

The video is probably the thing you are interested in the most:

Currently it works at around 10 key presses per second and I haven't got much hope that this will increase, since the speed is defined by the remote control, so I guess real time games are quite hard to accomplish.

Going further

What I have shown you is only a proof of concept. You can include remote control to any Axe or Asm program.

What you then could do is place the routine into a link port hook (IIRC there is one to transmit programs "silently") which enables when a key code is incoming. The code is then translated to "real" TI 83+ keycodes via a LUT and then given to the OS as a regular keypress - making it possible to enter your calculations with a freakin' TV remote....

The question one might ask is "What's the point of this?".
I'll ask instead:
Where will this lead?

Other / Serial VFD to TI-83+
« on: May 23, 2013, 07:39:03 am »
Since I got my large LCD working with the 83+ I've been looking through old electronics and parts I had and found some VFDs by NEC (looks like early 90s, maybe even late 80s). In case you don't know VFD stands for vacuum fluorescent display. They were used in e.g. calculators, audio equipment and automobiles. Today, most of them are replaced by the much cheaper LCDs, but they look awesome and are readable from any angle :)
So I figured out how to hook them up to an arduino, which was really simple because of its built-in serial interface. You can control everything just with one wire and ground. Well, that should make it possible to use it with the link port of the 83+, right? I wrote my own Axe routine to transmit Data serially at about 9600 baud (it works, that is everything that counts :P). It was a lot of trial and error and I had to try out a lot of different delay values to make it work.

The display has an external power supply (5V, 200mA); 2.5 mm connector: tip or ring is connected to pin 33, sleeve to any ground pin on the connector

Spoiler For Axe Code:
Code: [Select]
SR(1) //Luminance 100%
SR(17) //Normal Write mode
SR(20) //Disable cursor
SR(12) //Clear Display
0->A //initialize counter
While 1
SR(13) //Carriage Return
SR(' ')
SR(' ')
SR(A/100+'0') //100s
SR(A^100/10+'0') //10s
SR(A^10+'0') //1s
A+1^256->A //increment counter
Pause 100
EndIf getKey(15)

Lbl SR //Serial
0->r2 //reset parity
3->port //start bit
For(30):End //some delay
If r1.1 // get LSB
r1/2->r1  //shift right
If r2.1 //parity bit
0->port //Stop bit
I know it can be optimized and made cleaner, but it does the job ;)

Other / Your 83+'s display is too small?
« on: April 03, 2013, 06:17:29 am »
I had an WG240128b graphics LCD (with the famous T6963 chip) lying around and I finally got it working with my 83+ :)
The interface is quite slow at the moment, because the arduino I'm using has not enough RAM (only one k) to store the whole content of the screen, so I displayed it pixel by pixel. I'm sure it can be done significantly faster when I manage my 84 MHz / 96 kB DUE to work with it.
The display is 240 x 128 pixels, so I scaled up the screen in both directions by the factor 2.

On the calculator side I made an application with a key hook which transmits the screen serially when you press a certain key (in this case ln) at any point in the OS.

Music Showcase / Glance of the Night
« on: March 27, 2013, 12:18:33 pm »
Oh it has been a long time since I made my last song. But here I am back with "Glance of the Night"
I hope you enjoy it :)

TI Z80 / [Axe] Temple Run 2D
« on: February 24, 2013, 08:19:57 am »
----> Latest update <----

A game which was requested a lot lately. I've seen some attempts on making it in 3D, but I figured it could be done in 2D to simplify things a lot.

Here is what I got working at the moment:
  • Running on a randomly generating temple
  • Corners, junctions, damaged parts and gaps
  • Steering and jumping (could need some aesthetics)
  • Speed increase
  • Collisions
  • Score display (not activated yet)

Planned features:
  • Collecting Coins
  • Power-ups
  • The monkeys / a giant ball (Indiana Jones style!) behind the player
  • High score table and menu

I probably won't add other "terrains" and obstacles, because the result in looks wouldn't justify the efforts. Also I'm not a big fan of the "shop" so I think I'll leave that probably out too (for now!).

You hold the calc across with the keypad on the right, so you can benefit of the high size / portrait screen. You play either with the arrow keys (up/down: steer; right: jump) or with the respective keys on the num pad (7/8: steer left; 5/6: jump; 1/2: steer left). Holding the keys will make the guy move to the sides (like tilting the device on the original game) and klicking short at the corners will make the guy turn (like swiping on the screen in the original game).

Feel free to try out the game, criticize and suggest features. It is still in an early stage, this is the first playable version.

Other / Hooking up PIC µCs with accelerometer to TI-83+
« on: January 20, 2013, 07:12:52 am »
Hey guys

You didn’t hear much from me for a while now, but don’t worry, I’m not gone. I just hadn’t a lot of time because of school. But that doesn’t mean I have nothing for you to show - especially for my b100000000th post :)

About half a year ago I came across the PIC microcontrollers by Microchip and since I was making a bunch of asm routines at that time, I decided to give them a try. I hooked up the PICkit3 demo board to my 83+ and programmed some routines for serial communication. With the accelerometer ADXL-335z at the AD inputs of the PIC it is even possible to control programs by moving the breadboard around. As power supply I’m using a Nokia BL-5C battery which lasts quite long (1020 mAh) and is relatively light in weight.


Spoiler For sender code (PIC asm):
Code: [Select]
; Byte to send in register “SerialData“

  MOVLF     0x8,Count
  BTFSC     SerialData,0    
  BSF       SDATA    
  BTFSS     SerialData,0
  BCF       SDATA
  BCF       CLOCK
  SDelay    0x12        ; delays have to be adjusted depending on clock speed; in that case: 18*3+6=60 cycles @ 1 MHZ -> 60µs
  BSF       CLOCK
  SDelay    0x12
  RRF       SerialData
  DECFSZ    Count,1
  GOTO      Serialout

Spoiler For receiver code(z80 asm):
Code: [Select]
; GET()
; gets a byte from the port as a sequence of 0s and 1s on the ring
; (bit 1 of port 00h) on falling edge of the tip (bit 0 of port 00h)
; the sequence begins with least significant bit.

; (1) Read tip
; (2) Repeat (1) until tip low
; (3) Read ring
; (4) Put that at bit 0 of result
; (5) Rotate result right
; (6) Wait until tip back high
; (7) Repeat from (1) total 8 times

    ld bc,$0803
    ld hl,$0000
    in a,(00h)
    bit 0,a
    jr nz,loop
    and c
    sra a
    add a,l
    ld l,a
    in a,(00h)
    bit 0,a
    jr z,wait
    djnz loop
Interrupts have to be disabled.

In later versions I used polling to keep sender and receiver in sync, but the delays between the bytes are fixed. Thus, there mustn't be too much code between each GET(). It works quite well for now, but the program might get stuck in more complicated applications. To prevent that, I'm planning to make a closed function for the whole communication process.

This project isn't finished, I showing just early prototypes.

Planned features:
  • General purpose functions for axe and pic programmers
  • Communication in both ways
  • Arbitrary packet length and check sum
  • Network applications

Let me know what you think :)

ASM / Custom vertical line routine crashes
« on: September 30, 2012, 06:45:32 am »
Writing some program in axe, I needed a fast vertical line routine to substitute this:
Code: [Select]
The routine should draw a vertical, at y=22 centered line expanding E pixels up and down to a total length of E*2+1 in column X.
This is my idea:
Code: [Select]
:X:asm(E5) ;push hl
:^8:asm(23E5) ;inc hl, push hl   (gets the number of rotating cycles needed)
:asm(The routine)

Code: [Select]
Stack: #Rotation cycles,  X
HL : E

 pop bc     ; #Rotation cycles  , Stack: 1
 pop de     ; X       Stack: 0
 srl e      ; Div 8
 srl e
 srl e      ; DE: X/8
 ld a,l     ; A: E
 add hl,hl  ; 2E
 inc hl     ; 2E+1
 ld b,l     ; B: 2E+1, #Lines
 push bc    ; #Lines, #Rotation cycles ,  Stack: 1
 ld b,a     ; B: E
 ld a, 22   ; A: 22
 sub b      ; A: 22-E
 ld l,a     ; HL: 22-E
 ld c,l
 ld b,h     ; BC: 22-E   MUL 12
 add hl,hl  ; *2
 add hl,bc  ; *3
 add hl,hl  ; *6
 add hl,hl  ; *12
 add hl,de  ; HL:  (22-E)*12+(X/8)
 ld de, $9340 ; plotsscreen
 add hl,de  ; HL: Start byte
 pop bc     ; #Lines, #Rotation cycles   , Stack: 0
 ld d,b     ; backup b
 ld b,c     ; #Rotation cycles
 ld a,(hl)  ; A: Byte to modify
 rla        ; rotate
 djnz Sloop1
 scf        ; Pixel on
 ld b,c     ; #Rotation cycles
 rra        ; rotate back
 djnz Sloop2
 ld (hl),a  ; restore modified byte
 ld b,d     ; Restore b
 ld de,12   ; DE: 12
 add hl,de  ; Next line
 djnz Lineloop  ; until #Lines-- = 0

I hope somebody can help me finding the error, I'm stuck :/

Edit: It doesn't crash immediately, it does it when the program returns. The error is before lineloop I think

TI Z80 / [Axe] Bullet Proof
« on: August 19, 2012, 06:06:05 am »
Since playing games with friends is much more fun than alone and everyone loves shooters :P, I decided to make another mini game for the 83+:

                                                  Bullet Proof

(Edit: It was actually Eiyeron who came up with the name sometime on irc, and I thought it was a nice idea. ;))

So what I wanted to do was a little, not too complicated platformer with decent physics and collision stuff playable on only one calc.
It has got a variable key configuration, so each player can choose his keys for the control of his character. It also comes with a level editor which let's you "draw" a custom map and place the spawns of the characters. It only saves one map atm in the same appvar as the keys.

Some Gameplay

The Map editor

Key configuration
(all running at 6 mHz; sorry for bad gameplay - it's Wabbitemu)

Facts & Features:
  • Pixel collisions
  • Vertical acceleration for realistic jumps
  • Stair detection
  • Health power-up to regenerate damage of 5 shots
  • Key settings
  • Map editor
  • less than 5 kb (not the current version)

Default controls (changeable):

Player 1:   
Player 2:

Next step:
  • Optimizing
  • More Power-ups, like weapons and armor (added now!)

What I've been thinking of but isn't included yet:
  • Playing via link
  • Bigger maps and scrolling

Controls of the editor:
  • Move cursor:
  • Add blocks:
  • Remove blocks:
  • Clear all:
  • Save and set spawn points:
  • Confirm spawns:
  • Display current spawn points:   
Arrow keys

-> Current version

Download this version:

ASM / [z80 asm] picture enlarge routine for axe
« on: August 11, 2012, 10:54:29 am »
Hey guys,
this is my first real try on Asm, I need it to embed in an axe program.
It takes a 156 byte file located where theta ($89EA) points to, should scale it with factor 2 and write it to AppBackUpScreen, starting at L3+24 ($988A). I use IX for read and IY to write. It converts each byte of the input to 2 bytes by shifting.
10011101 becomes 1100001111110011 etc.

Code: [Select]
ld   de,6  ; byte counter for lines, each 6 bytes next line
 ld   ix,($89EA)  ; get the location of file
 ld   iy,$988A    ; get location to write
 ld   b, 156      ; counter init
 ld   a,(ix+0)  ; get element of file
 ld   hl,0      ; reset hl
 ld   c,b       ; backup b for second loop
 ld   b,8       ; initialize second loop
 rrca     ; get a bit of a in carry
 rr   l   ; shift that in l
 rr   h   ; shift also h
 sra  l   ; doublicate bit and shift once more
 rr   h
 djnz -9  ; repeat "double" for each bit

 ld   (iy+0),l   ; write first half
 ld   (iy+1),h   ; second half
 ld   (iy+12),l  ; next line
 ld   (iy+13),h
 dec  e   ; count one down (each 6 bytes there has to be a line skipped)
 jrnz 9   ; execute only if counter 0, otherwise jump to else
 ld   de,12
 add  iy,de   ; add 12 to skip next line
 ld   e,6     ; reset counter
 ld   b,c   ; get backup of main counter
 djnz -43   ; jump back to loop to repeat if counter finished

First of all, it isn't working exactly correctly, but it doesn't crash immediately. Where is my logical mistake?
Secondly, it makes things weird on my calc (83+). I have to clear ram each time. Are there any things that you need to do when using these registers? Backup them? How?

I'm quite a noob in asm, so please excuse when I'm doing things really stupid. Asm was the only way I could think of solving this fast.

TI Z80 / Tanx 3D
« on: June 24, 2012, 05:51:33 am »
As said, I can't finish this for the contest, but I will work on it since I put a lot of effort in it.
Since now only two weeks are left until the contest ends, I decided to post what I've been working on the last few weeks. The game I'm making is a strategy board game. Each player has a specified amount of tanks placed on a map and tries to survive longer that the opponent(s).

Spoiler For History of the game:
The history of the game started in 7th grade, when me and my friends where bored in class and randomly started to build little papercraft tanks. We made little maps and just played with them in the breaks. We decided to lay down rules and created different sized boards with walls and teleporters etc. Also, each tank has different features and characteristics, e.g. there are regular tanks (long range, straight shot), howitzers (short range, ability to shoot over walls) and rocket launchers (long range, missiles can go around corners). Later we also added helicopters and fighters.

A bit crushed but they are still alive!

In 8th grade, our maths teacher gave us TI calculators and we all where like "Oh, this thing is complicated (compared to the little casios we were using before)". However, we found out that it is programmable so we learned to make little games in TI-Basic. One of the games I made was quite similar to the board game, it was extremely buggy but still fun to play.

I learned to program with xLib the next summer and tried to make another version of it (still with a lot of bugs). It had a map editor and better graphics.

I took a little break from calc programming after that and started C++ for PC, so as you can guess, I made "Console TanX" for PC.
There are actually 3 different versions of that game, a strategy version, one for multiplayer (up to 4 players) and another one with AI enemies. The last two are all action games, where every player moves at the same time. All of them are in ascii style, because I failed so often with graphics :P

Random (but pronounceable) name generator for computer enemies included! ;D

Then I came back to calc programming last year with axe, and a few months ago, I came up with isometric graphics. The contest inspired me to redo the TanX in 3D-ish style.

The graphics are almost done and the editor and the main menu are already finished. The game will be like the first board game version, so players take turns after each other. Since a lot is already done and the game like this is a classic for me and my friends, I won't change the rules or the main setup.
The board will be viewed from above, you won't be able to move the camera.

The tilemapper (not the latest version) and the editor:

The gray is perfect on a TI-83+

Feel free to ask questions and let me know what you think.

General Calculator Help / Silverlink doesn't install correctly
« on: June 16, 2012, 05:08:37 am »
I'm not sure whether I'm right in this forum or not, but here's my problem:

A few weeks ago I installed a new sound card for my Windows 7 64-bit computer and suddenly the graph link didn't work anymore. I looked into the device manager and it says the driver can't be verified to be signed or something. I never had this problem before.
Every time I plug in the cable, after it tried to install software and says it failed. Reinstalling/updating driver leads always to the same problem, it says the driver is the newest version.
Booting without driver signature is possible and it shows up the device is working correctly, but TIConnect is acting up and doesn't find the device.

I'm using TIConnect with a TI 83+.

TI-BASIC / [TI-83+] Using Recursive Sequences in a Program [solved]
« on: June 07, 2012, 08:58:50 am »
Hey, for my Maths I have to make a program to calculate increasing and stuff, and it needs to have recursive sequences as well.
The problem is, I can't find the right commands and variables in the program editor.   >:(
How would I store a recursive equation ( u(n) = u(n)*2 as an easy example) into u, v or w?
And how can I set the start ( uMin and u(nMin) = {x} )?  ???

I hope there is somebody who can help me.

Art / Sprite Request: 8x8 artillery sprites
« on: June 01, 2012, 07:21:19 am »
No need anymore.

Spoiler For original post:
Hi there,

For my current project I need 3 very basic, symbolic sprites 8x8 of those (self-propelled) artillery vehicles.
(click on the name for example if you don't know what it is)

It only has to be identifiable what type it is, the specific model isn't necessary (it's only for an editor, not for the game).
I know little sprites are extremely difficult, but maybe you have good ideas how to do this.

Axe / 3D in Axe - Isometric Projection
« on: April 27, 2012, 10:39:18 am »
Since I always wanted to make some 3D ish stuff in axe, I tried to figure out how isometric graphics work and made a whole bunch of functions to draw pseudo 3D tiles on the screen and to display an 8x8x8 bit array as a model made from little cubies.
It supports 3-level greyscale.

I will post code or a tutorial later if you are interested, this is just a preview of my upcoming stuff and what I've done so far.

       ?    ?    ?    ?    ?
Spoiler For the interesting stuff:
My editor for a 3D map:
(reuploaded gif)

The grey is better on calc.

Download can be found here

Pages: [1] 2