Thursday, August 22, 2024

Let's Write Something...

Waiting for a system update to finish so I can sleep, when I know full well it can finish without me... but I remembered this existed and figured I should post! How will I ever become a famous blogger?

Sadly not a lot to report since March! We've got Cool Herders off to the publisher, just waiting for Piko to get everything set back up again. In the meantime, I finished Super Space Acer for the TI and ColecoVision, and those are off to ArcadeShopper and CollectorVision respectively - who I have heard back from are putting their packages together.


Apparently I need to take a few more screenshots! ;) Have a look at the teaser vid instead - https://www.youtube.com/watch?v=vb0D47OZML8

(Boy, I really should update Youtube more often too...)

Since then I started on a Gameboy Advance port. My original attempt was to port my libti99 library... which I did achieve for the most part. I also got the music player working. The problem is the library is way too slow drawing the TI screen, so I'll probably have to skip 'partially working' and go straight to porting the graphics. The goal, and I still don't know if it's achievable, is to introduce a 3D perspective angle to deal with the reduced resolution.

I still want to port to a few other systems, but it's really needing to be higher priority than it is. So now we can get to the lesson part of this post...

DECIDE YOUR PRIORITIES.

Unfortunately I've let myself be distracted by TWO projects. Both I thought would be simple, and neither were.

The first was a port of a newcomer to the TI community's game - he wrote it for cartridge using Compiled BASIC, but though it loaded from cartridge it needed a floppy for support files. I adapted it to read the files from cart instead, using a simulation of the disk access code -- but then I foundered for a few days trying to fit it into memory. Turns out when he said he had 100 bytes free, he wasn't kidding! But I did succeed.

The other is a port of CVBasic to the TI. This is a BASIC compiler for the ColecoVision - and now most Z80+9918A computers. I noted they were looking at a port to the 6502-based Creativision, and I noted if they did that, I'd extend the scheme to the TI.

Well, they did, and so I started in. What originally looked like properly isolated code turned out to be thousands of lines of undocumented assembly language, and more assembly in almost every file. So this has been taking a very long time -- and indeed when I finish I am not even certain it is going to work. My original high hopes were dashed by this and at this point it's more stubbornness than interest that has me finishing the task. I expect, if I can get it to compile the test app, I will report the repo and leave it at that.

I can probably share the Github for that -- if you are interested you can follow the fork back to the original and see Oscar's original compiler. https://github.com/tursilion/CVBasic/tree/ti99

I am back to RL work these days, so maybe I'll have more to rant about soon ;)


Wednesday, March 6, 2024

Willy's Chocolate Experience

So like everyone else, I've been looking at that disastrous Willy experience. My heart goes out to the actors who tried their damndest, and the kids who were expecting a lot more.

I was curious about the script. I meant, it largely didn't seem undoable. Might have taken more time to set up than was given, but... here's the copy I worked from: https://www.documentcloud.org/documents/24449349-willyschocolateexperince

Obviously, the candy supplies should have been right. You knew how many tickets you sold.

You would have needed to dress the entire visible portion of that set. So that would mean building walls and decorating, using lighting to hide the ceiling would probably work. Astroturf makes an easy ground cover.

Everyone picks on the audience reactions being in the script. I guess that's not normal, but it's kind a 'so what?' on top of everything else. ;) It's a live show. "Pause for reaction" means the same thing.

Sound track would be needed, of course. Speakers hidden in the set on loop would do - volume adjusted per scene might even work? Otherwise you could use a dynamically adjusted soundtrack, assuming one tour at a time. That gives you the singing flowers and whispering trees, as well as musical cues for mood.

The giggle grass is why I wanted to review the script. You could have some astroturf mounted a little higher, waist high for a child perhaps, and simple proximity sensors could trigger it to vibrate and play the giggles. Safer and more reliable than stepping on it, but meets the goal.

Same for the talking tulips, of course, though why flowers and grass are so prominent in a candy display seems odd to me. Even better, you can deal with the wilting using air pressure in a rubber tube stem, and have them react to nearby voices by no longer sagging and thanking the audience.

Bubble machines are next - that's easy and can be cued by Willy or a cast member. The bubble that pops in his hand and turns into a sparkling light that ascends to the sky would be hard to do convincingly. I'd be inclined to drop it. You might be able to use projection and rely on a controlled point of view if you had a smokey room. Otherwise I think I'd have him catch a prop on a string during a moment of distraction, then let a flickering LED prop be pulled into the rafters on his release.

The Twilight Tunnel is next and is pure construction - should be simple to create and completely controls line of sight. Musical cues go darker. LED 'stars' can light roof of the tunnel and twinkle. Again, Willy needs a lighted prop - he can pull this one from his pocket since it doesn't fly away. Apparently all the audience gets one - kind of unfortunate but I guess you're making cheap LED ping-pong balls ;) A button cell battery and a single LED will glow for at least an hour or so. When making them you can insulate the battery with a small piece of paper or fabric, and leave a slot to pull it out at distribution time to activate the light.

The tunnel obviously won't be as dark as described for safety reasons, nor as long. Open at the entrance, bend to hide the entrance, and end at a door for the scene with the Unknown. Everyone agrees the Unknown's actress nailed it, so nothing to do here, and no prop was needed, though there are some cute lighting cues.

Have a cast member open the doors, and stride out to the Bubble and Lemonade Room. Larger, brighter, and still still decorated. Large rooms like this are how you will decide the size of the tour group, as you need enough room for them to be comfortable while still keeping the theme.

The lemonade perhaps should be carbonated to match the 'fizzes' description? Backup drinks of water or such should be available to those who can't have it - check with a nurse what makes sense for kids. Likewise for the candies, of course, every kid deserves SOMETHING.

Apparently nothing else of importance here - this is the snack area. Bubble machines need to be going all the time, but be sure to protect the drinks from popping soap with simple lids or a cover. (Perhaps they can be kept in refrigeration - a cooler or such).

Ah, but then we're off to the Imagination Lab. Okay... so we have a big 'Keep Out' door (and this would be at least a double-wide because this is a tour). The text for this introduction is poor, but that's not my problem as imaginary technical side. 

The bizarrely flavored jelly beans are easy enough if they still make those Harry Potter jelly beans. We'll just use a bunch of those. Perhaps have the cast members hand them out. Give them a bunch of random, but a small reserve of known, pleasant beans for the less adventurous.

The big TV camera is easy - this is a classic photo op. Could be done a couple of ways, but the simplest might be to run people through an exit corridor after they get their beans with a marked location to stop and pose (with appropriate backdrop). People are told they can claim their photos at the end of the experience, and we will email them (or, as is the trend, they can take a picture of the screen they are previewed on.)

Now we're at the final scene with the anti-graffiti gobstopper. Obviously, there should be a display stage and it should be covered, so Willy can hop up and present it. There's a bit with Willy and the Unknown, up on stage where they are safe from bumping into the guests. We want a battlefield of lasters and lights... I don't know why, but okay! So the Unknown's appearance is prefaced with a fog machine, and now strobing lights and flashing lasers can create a scene of chaos. It might be important to identify anyone with photosensitivity before this scene so they can be escorted out.

During the scene Willy uses a remote to activate traps and 'illusions'. Simplest thing here is probably a cast member off stage who can slide false walls into the Unknown's path on cue once or twice. I was thinking from underneath, but such props would need to be light and might be unsafe if accidentally stepped on. No need for motors anyway, this can be kept very simple.

The Unknown's own weapon can be based on a laser pointer, with Willy dodging dramatically behind props. Some kind of response on the prop would be ideal - might be as simple as a projected explosion (or at least flash) with a sound. The audio engineering over this whole scene is what will sell it.

The final machine is probably going to be accomplished with projection across the stage. "Holographic" images of "sparkling cleanliness" can start across the stage. When Willy loads the Gobstopper into the machine's recepticle, the projection focuses into a wave that starts from the machine and flows across the Unknown, giving it time to be swept backwards. A wall panel opens showing a giant vaccuum with an opening large enough for them to enter, along with a vaccuum sound effect, seals the deal. He goes into the vaccuum, the panel slams shut, and the sparkle projection fades out.

Then we're off to the gift shop, because you'd be dumb not to have some cheap merch to sell. Here people are encouraged to hang out by the need to claim their TV photos.

So that's my proposal for the technical sides. It's /still/ a ridiculously cheap and cheesy experience, but at least it would have delivered on some of the promise??

Friday, February 16, 2024

ITrax Module Teardown

While working on my car battery, I discovered a forgotten little GPS tracker tossed in with the jack. At first I couldn't figure out what I was looking at...


Why, it's a cellular GPS tracker! Eventually I figured out it came with the ITrax system I got when I bought the car way back in 2016. Some online investigation found that the company is long dead, and many believe it may have died in 2015, when the last Facebook post is: https://www.facebook.com/goitrax/

Anyway, I figured no harm seeing what was inside, so I took it apart.


Inside the base is this little instruction pad. Under that are a number of strong magnets used to attach it to metal parts of the car.


On the other side, we have two tiny antenna - labelled on the sides -- which are attached to with little pogo pins on the PCB.

PCB itself looks like this. There's a GPS module and a cellular modem, presumably under the two shields (which I didn't remove). They are labelled MB81 and MB70, but this doesn't appear to be meaningful.


On the other side of this PCB, and taking up most of the space, is this big ol' battery. It's a D cell sized 3.6v ER34615M - apparently a rather standard battery. It's pretty dead, of course. It had a foam pad glued all around it that was quite difficult to remove, even with heat (not that I wanted to try too much heat.) ie: https://www.batteryjunction.com/titus-er34615m-ax


The SIM card has no markings besides the standard identification data on the reverse side. I didn't take a picture of that in case it still worked -- but of course it doesn't still work. ;)


The USB port was interesting so I decided to power it up and see if it spoke to me as anything. It didn't take power from the USB port, so I ran 3.6v across the battery terminals, which happily didn't explode. The LEDs began blinking as the lid suggested they might.


Windows didn't know what to make of it, but gave me the VID/PID 0E8D/0003, which mapped down to a MediaTek MT6227 phone. I couldn't find a lot of information about this unit, but I did see it was supported under Linux. https://linux-hardware.org/index.php?id=usb:0e8d-0003


So I booted up Minicom to have a look at it, and yeah, it talks like a GSM modem! 


The MCU is also trying to initialize the connection, but since there wasn't one, it didn't seem to get very far.

I did try putting my T-Mobile SIM in, and seemed like it may have initialized it, eventually stopping on an ATH instead of the repeated AT%IPSYS? above, but I didn't catch it going further. (I didn't leave it on long, perhaps it was trying to acquire satellites.)


The MCU would appear to be over here, labelled SBK TI 571 AKY1. Couldn't find much, though there is a CH571 based on RISC-V. I think it has the right number of pins... This page has the 573/571 datasheet: https://www.aliexpress.com/item/1005005805175647.html - if that's it, it has 256k of flash, 18k of RAM, and a ton of onboard peripheral support at 20MHz.

I didn't go any further with it, but I was surprised to see at least as recently as 2020 people were still being sold these systems. The unit was dropped randomly all over the car - one person found it in their glove box! And cellular modems aren't really expensive anymore, so I'm not sure how useful this may be. But, if you wanted to use such a thing, you could try disabling the MCU to just have a USB modem (possibly), or even potentially try to reprogram it.

Other things I should have done but didn't - remove the the shields to verify what's under them, and see what the RX/TX pads under the SIM card are for. ;)











Tuesday, February 13, 2024

AI Code Gen

blah blah blah you've heard all about AI. Let's walk through a quick example of trying to get ChatGPT to generate some TMS9900 assembly code for us. This is a difficult challenge for it - it doesn't have a lot of examples to draw from.

My ChatGPT instance is set up to talk to me as Skeletor. So, just be warned about that. My text will be blue, replies will be red, and code I will have to figure out if Blogger has a format option... whatever.

Hello evil one! Today we are going to work together to create a program in TMS9900 assembly language that bounces a ball on the screen of a TI-99/4A.

Ah, a worthy endeavor for our combined might, you puny mortal! The TI-99/4A, with its TMS9900 microprocessor, presents an interesting challenge for our dark purposes. We shall bend it to our will and make it display a bouncing ball upon its screen. Let us proceed with this nefarious plan step by step, weaving the dark magic of assembly language to bring our creation to life.

First, we must understand that to create a bouncing ball, we need to manipulate the graphics or character patterns directly, since the TI-99/4A allows for such manipulation through its Video Display Processor (VDP). The essence of our dark spell will involve:

  1. Setting up the screen: Prepare the graphics mode that we intend to use.
  2. Drawing the ball: Define a character or a set of characters that will represent our ball.
  3. Movement: Calculate the ball's position on the screen, updating its location to simulate bouncing off the screen edges.
  4. Looping and Delay: Implement a loop to continuously update the screen, along with a delay to make the movement visible to human eyes.

Given the complexities of TMS9900 assembly language and the limited space for incantations here, I shall provide you with a skeletal framework. You will need to flesh it out with your own dark powers (and possibly consult the TI-99/4A manual for specific details like VDP memory addresses and character pattern definitions).

* Setting up the screen LI R0, >02 * Load immediate VDP register number for setting graphics mode LI R1, >XXXX * Load immediate value for graphics mode * Drawing the ball at initial position LI R2, >YYYY * Load immediate address for character pattern in VDP RAM LI R3, >ZZZZ * Load immediate character pattern for the ball * Main loop for movement LOOP: * Calculate new position * Check for screen boundaries * Update position in VDP RAM * Delay JMP LOOP * Jump back to the start of the loop END

Ah, but heed this well, you aspiring dark wizard of code: the actual implementation details, like the values to load for setting up the screen mode (XXXX), the address for the character pattern (YYYY), and the pattern itself (ZZZZ), will require consulting the tome of knowledge for the TI-99/4A. The VDP memory manipulation commands (like VMBW for writing to VDP memory) and the exact mechanics of screen update will test the limits of your dark sorcery.

To implement the delay, you might use a simple loop that wastes time, or for a more sophisticated approach, delve into the TI-99/4A's interrupt system to create a timing-based delay, though this requires deeper knowledge of the system's dark heart.

Now go forth, and bring our vision to life! Let the TI-99/4A tremble at our combined might! Mwahahaha!

Okay, well, that's a bit of a cop-out. But it's right in that organizing the code into blocks is the first step. But the code doesn't do anything but load a few registers, and frankly most of that is junk anyway. So let's educate it a little bit and try to get the screen clear done (we don't need to set a graphics mode on the TI.)

Let's drill down deeper. Let's start with the screen setup. Since the screen mode is already set for us by the OS, all we need to do is clear the screen. You will need some information - the VDP memory is accessed as a memory mapped device. The screen starts at address 0 which is convenient. To clear the screen, we need to write the two bytes of address 0 to >8C02, then we can write the ASCII space character to >8C00. We will need to write 32 times 24 times to clear the entire display. Generate this method.

Note here that I didn't explicitly tell it several things. For instance, I gave it the screen dimensions, but not the total number of bytes. I also didn't tell it that the TI uses '>' as a hexadecimal prefix (but, the previous code infers it knew that.)

Ah, focusing on the task of clearing the screen, are we? Very well, let us dive into the abyss of assembly to command the TI-99/4A to bend to our will.

To clear the screen by filling it with spaces, we must repeatedly write the ASCII space character (which is >20 in hexadecimal) to the entire display area, which consists of 32 columns and 24 rows. Since you've enlightened me about the method of accessing VDP memory, let's proceed with crafting the spell in TMS9900 assembly.

We'll use the VDP write address >8C02 to set the address pointer, starting at 0, and then repeatedly write >20 to >8C00 to fill the screen with spaces. Here's how you can do it:

LI R0, >0000 * Load the initial screen address into R0 LI R1, >8C02 * Load the VDP write address register LI R2, >2000 * Load the ASCII space character (>20) and the repeat count (32*24 = 768 = >0300) CLEAR: MOV R0, R3 * Move the current address to R3 for manipulation SWPB R3 * Swap bytes to get the address in the right format for VDP MOVB R3, *R1 * Write the high byte of the address to the VDP write address register AI R3, >4000 * Adjust R3 to correctly position the low byte of the address MOVB R3, *R1 * Write the low byte of the address to the VDP write address register LI R3, >8C00 * Load the VDP data write address MOVB R2, *R3 * Write the space character to the VDP data register AI R0, 1 * Increment the screen address CI R0, >0300 * Compare current address to the end of the screen area JNE CLEAR * If not at the end, jump back to CLEAR RT * Return from subroutine

This code starts by initializing the registers:

  • R0 holds the current address we're writing to in the screen memory, starting at 0.
  • R1 is set to the VDP write address (>8C02), used to set where we're writing in the VDP memory.
  • R2 holds the ASCII value for a space (>20) and the repeat flag set to >0000 as we will manually control the loop.

The loop labeled CLEAR does the following:

  • Moves the current address in R0 to R3 for manipulation.
  • Swaps the bytes of R3 to match the VDP's addressing format.
  • Writes the high and then the low byte of the address to the VDP write address, effectively setting the VDP's address pointer.
  • Writes the space character to the VDP at the current address.
  • Increments the address in R0 and checks if we've filled the entire screen. If not, it repeats.

This code should effectively clear the screen by filling it with spaces. Note, however, that this is a simplified and direct approach. Optimizations and error checking have been omitted to focus on clarity and to maintain the essence of our dark endeavor. Proceed with caution, and may your path be lit with the dim glow of the TI-99/4A's screen!

This is interesting. It clearly has seen some TI code before, as it knew to load the space character into the MSB of R2 (needed for MOVB), it knew to load the VDP address LSB first (although the comment is incorrect), and it knew that to set a write address to the VDP, you needed to set bit >4000. AI isn't the best choice, but it would work for any valid VDP address.

However, the actual order of operations is a bit jumbled. It resets the address every loop, and it sets the >4000 bit in a funny place. (Actually, looking at it now that I write this, it actually WOULD have worked but only when the address is >0000. Normally you'd swap the bytes back and so that is what I asked for.)

But the loop itself would work and has the right termination, if a little inefficient (using AI instead of just INC R0, for instance).

You have correctly inferred many things. However, please make the following changes. First, the address must be set before the loop and outside it. You must add >4000 before the first swpb happens, then use a second swpb between the two writes to >8C02.

Ah, I see the refinement in your dark counsel. Let us adjust the incantation to properly align with the arcane mechanisms of the TI-99/4A's Video Display Processor. By setting the address outside the loop and manipulating the bytes as you've wisely suggested, we ensure that our spell is both efficient and potent. Here's the revised sorcery:

LI R0, >0000 * Load the initial screen address into R0 LI R1, >8C02 * Load the VDP write address register LI R2, >20 * Load the ASCII space character (>20) AI R0, >4000 * Add >4000 to the address to prepare it for VDP addressing SWPB R0 * Swap bytes to get the address in the right format for VDP MOVB R0, *R1 * Write the high byte of the address to the VDP write address register SWPB R0 * Swap bytes back to prepare for writing the low byte MOVB R0, *R1 * Write the low byte of the address to the VDP write address register LI R3, >8C00 * Load the VDP data write address LI R4, 768 * Initialize loop counter for 32 columns * 24 rows = 768 CLEAR: MOVB R2, *R3 * Write the space character to the VDP data register DEC R4 * Decrement the loop counter JNE CLEAR * If the counter is not zero, continue looping RT * Return from subroutine

In this revised version, the address is set outside the loop:

  • R0 is initialized with the screen start address (>0000), and we immediately add >4000 to it to prepare for the VDP addressing scheme.
  • We then perform a byte swap (SWPB) on R0 to align the address bytes correctly for the VDP.
  • The high byte of the address is written to the VDP write address register (>8C02), then we swap the bytes back and write again to set the low byte of the address.
  • With the address set, we enter the loop to clear the screen by writing spaces (>20) to the entire display area using the VDP data write address (>8C00).
  • R4 serves as our loop counter, decrementing with each iteration until the screen is fully cleared.

This approach correctly sets the screen address before entering the loop and uses the correct sequence of operations to ensure the VDP address is properly configured for our nefarious purpose. Now, proceed with this dark art, and may the shadows guide your path to dominion over the TI-99/4A!

This is really close, and would almost work. But it's also fascinating to note that it's a complete rewrite of the previous code. A different counting mechanism is used (a better one), and more importantly a new bug was introduced - the space character is loaded into the LSB of R2, meaning the MOVB will be storing 0 instead of >20. Also, it has generated invalid comments for the VDP address load - but in fairness I never explained that part to it.


Very close! However, please correct the comments on the address set - the first MOVB is writing the LSB, and the second writes the MSB. Also, the space character must be in the MSB of the register for MOVB to work.
Ah, a critical observation in our dark assembly ritual. Let us refine the incantation further, correcting the misalignment in the comments and ensuring the space character is properly positioned for the MOVB command to enact its will upon the VDP. Here is the amended spell, with the precision you demand:
LI R0, >0000 * Load the initial screen address into R0 AI R0, >4000 * Add >4000 to the address to prepare it for VDP addressing SWPB R0 * Swap bytes to get the address in the right format for VDP LI R1, >8C02 * Load the VDP write address register MOVB R0, *R1 * Write the LSB of the address to the VDP write address register SWPB R0 * Swap bytes back to prepare for writing the MSB MOVB R0, *R1 * Write the MSB of the address to the VDP write address register LI R2, >2000 * Load the ASCII space character (>20) into the MSB of the register LI R3, >8C00 * Load the VDP data write address LI R4, 768 * Initialize loop counter for 32 columns * 24 rows = 768 CLEAR: MOVB R2, *R3 * Write the space character to the VDP data register DEC R4 * Decrement the loop counter JNE CLEAR * If the counter is not zero, continue looping RT * Return from subroutine

Corrections and clarifications:

  • The first MOVB now correctly comments that it writes the LSB (Low Byte) of the address to the VDP write address register, after adding >4000 to prepare for VDP addressing and swapping bytes with SWPB.
  • The second MOVB, following another SWPB, correctly comments that it writes the MSB (High Byte) of the address to the VDP write address register.
  • The space character (>20) is loaded into the MSB of R2 to ensure it's correctly positioned for writing with MOVB to the VDP data register. The LI R2, >2000 instruction achieves this by loading >20 into the high byte and 00 into the low byte, which is then correctly written by the MOVB command.

With these corrections, our spell is now precisely woven, ensuring that the VDP obeys our command to clear the screen with spaces. Let the screen be cleansed in preparation for our further machinations! Proceed, acolyte, and wield this power wisely.

I think at this point the code works. Note how many parts it has re-ordered again, but although I didn't actually test it, this should clear the screen. The only remaining issue is that the label shouldn't have a colon in TI assembly, normally, but that's a nitpick.
I find it fascinating to be able to refine the request in this manner. This was pretty much a conversation in which I provided information, and it provided information. However, were this a learning experience it would have been completely pointless. And due to how long just this part took, I decided not to go for the rest of the code. (I have done similar before though, I had it generate java code to move an AI tank around a screen. It was not a very smart tank, but it worked.)
But the amount of effort it took to generate working code was high, and so without the ability to educate the chatbot on the parts you need most, it is most useful for tasks that are well defined and common enough to trust the results on. Certainly, I could have looked up how to clear the screen in the TI Editor/Assembler manual (although this direct method is much faster).
I do know people who say they use it in their normal coding, and I admit I haven't called on it to help a lot with modern code yet, so I don't know how much better it is. But based on the samples I get out of it personally, I would treat them with high suspicion. I guess I just prefer to learn the stuff myself?