Jump to content

XB Compiler v2.1


Recommended Posts

Attached in a zipped folder. This fixes the bugs that have been identified and adds CALL LOAD, CALL PEEK, MAX, MIN, RPT$


(edit 4/1/2014) Updated version is attached here and in post #132 - XB Compiler v211.zip

(edit 4/21/2014) Fixes a bug that kept numbers from being displayed when using DISPLAY AT. Also in post #140.


Edited by senior_falcon
  • Like 5
Link to comment
Share on other sites

Thank you very much for releasing this bugfixed version! I've now reinstalled the MAX, MIN and RPT$ functions in my program and recompiled it using the new compiler version, and now it runs flawlessly, as expected (except that the framerate actually seems to be a bit higher now).


In CPU overdrive of Classic99, it's now unplayable. :-)


I've attached a ZIP file with the current version of my compiler-aware SSGC Racer.


SSGC Racer compiled.zip

  • Like 2
Link to comment
Share on other sites

Glad to see that it works for you. Don't you love how fast it starts up? BTW, can the original version of SSGC Racer be played without using overdrive on Classic 99. When I tried it out in XB nothing much happened. I don't have joysticks on the PC and thought that might be the problem, but the compiled version responds fine to the arrow keys.

Link to comment
Share on other sites

Oh yes, you're right, it starts up very fast now. There's only a brief pause at the end of the game while it reads and converts the ending music.


The original version can be played without using overdrive. But by that, I mean the version I made before I adapted it to the compiler. The ready-to-compile version should be playable as well, but it only does about a frame in 2 seconds, and since the car isn't moving right or left anymore, you'll have to keep the left or right arrow depressed and wait a few seconds before anything happens.


I also don't have joysticks on my PC, but as far as I know, Classic99 responds to the cursor keys emulating a joystick even in games which only read the joystick, not the keyboard.

Link to comment
Share on other sites

  • 2 weeks later...

we had the 25th austrian ti-99 club meeting yesterday, where kurt presented his updated version of SSGC Racer on a real setup.

I also was doing a short demo of current status of my dr.mario clone in XB, I am thinking about trying a compiler (MLP or this one) for that...

Link to comment
Share on other sites

we had the 25th austrian ti-99 club meeting yesterday, where kurt presented his updated version of SSGC Racer on a real setup.

I also was doing a short demo of current status of my dr.mario clone in XB, I am thinking about trying a compiler (MLP or this one) for that...


Any screenshots of your dr. mario clone ? ;-)

Link to comment
Share on other sites

I made an unfinished TI Basic (no XB) version for the Basic On Cartridge Contest called Virus Fever. It always bothered that I didn't finish the game because I ran out of memory and failed at one big algorythm.

Here is the former game thread:



Now I am trying to recreate and finish the game in XB with 32KB. The new version is still a prototype, all you can do is move/spin the pill and pile them on top of each other :)

Link to comment
Share on other sites

Another feedback from my point:


I have started to use this XB Compiler for my game development on the weekend and I am very impressed with the quick results. Now I need HUGE delays in XB to make the game not too fast to play! Crazy world! Will use Call Sound for those delays like suggested in the manual.


The includable assembler routines "DISPY" and "VWRITE" are really useful! I use them to synchronisly relocate 2 sprites to the next char. Amazing!

CALL LOCATE(#1,Y1,X1,#2,Y1,X1+1) was never satisfying sync at least in XB - non compiled. You can see a delay between the first Sprite relocation and the 2nd Sprite relocation.

CALL LINK("VWRITE",768,CHR$(Y1)&CHR$(X1),772,CHR$(Y1)&CHR$(X1+1)) does the same but the relocation of both sprites is perfectly in sync, even in XB! It writes directly to the Sprite Description Table of the Video Ram.


Call me back into programming :)


With this Compiler XB Game Programming is fun again!


The manual is good written, congrats on that! As a sidenote: for a non assembler person it will be heard to understand the usefulness of VWRITE/VREAD. I know it's out of scope to explain all possiblities with direct VRAM writing but maybe a link to a good document on whtech, that deals with that, could be added to the manual.


If you wanna make arcade games in XB, go for this!!!


A question: I haven't tried it yet, but it is said that multiple CALL SOUND statements will make the compiled code to be just playing the sound until the sound is finished. With this limitation, how do you suggest to get background music to a game that doesn't interfere with game play?

Edited by kl99
Link to comment
Share on other sites

Klaus - still haven't used the compiler, but negative length sounds could be used for music - using positive sounds, in theory, would suspend the music until the sound completes.


I know that Owen had a library for XB for background music, but it was different than just playing notes, IIRC. Not sure if that'd work with the compiler.

Link to comment
Share on other sites

Klaus wants to use CALL SOUND for a real time delay, so he actually does need the suspending.


I think you should be able to use the VDP status byte though. When the console interrupt routine fires, assuming the compiler still uses it, it copies the VDP status byte to >837B in CPU memory. If you set it to an invalid value like 255 with CALL LOAD, then you should be able to create a loop that waits for it to change with CALL PEEK. When it changes, the vertical blank has occurred (which is every 1/60th of a second on NTSC of 1/50th of a second on PAL). You could synchronize your game to that, using something like this:


10000 CALL PEEK(-31877,X)
10010 IF X<>255 THEN 10000
10020 CALL LOAD(-31877,255)
10030 RETURN


You should be able to get a synchronized 1/60th second delay with GOSUB 10000. If you need longer than that, you can loop calls to it.


Of course, that assumes that you CAN get back to it 60 times a second. If you can't, it will always be set and return on you. In that case, maybe we can write a little piece of code on the user interrupt that increments a safe memory address, and then XB can check/reset that value? A single byte would be large enough to count more than 4 seconds, so it would be enough...?

Link to comment
Share on other sites

I guess I should add, if you don't mind it being perfect and just want to slow down, looping to the function above will always work:


FOR I=1 to 30::GOSUB 10000::NEXT I


Will always delay for about 1/2 a second, give or take up to 1/60th of a second.


Also I didn't test the above, I'm at work ;) But in theory it should work.

Link to comment
Share on other sites

This is awesome. Thanks. I'll try that for my timing. Kind of curious now how much real work could be done in 1/60 second. But, certainly for playing music with negatives, etc, this could allow the "next note" selection to be done inside the gosub. Might also be interesting to include any other sounds for playing by setting variables in code which the gosub then leverages... Could be really fun to play with.

Link to comment
Share on other sites

Tursi, you're barking up the right tree, and almost at the right branch. The byte at >8379 is the VDP interrupt timer. It is incremented every 1/60 second. You can see this with the following code in XB:

10 CALL PEEK(-31879,X)::DISPLAY AT(1,1) :x ::GOTO 10 (That is supposed to be a colon and an X - not an unhappy looking red disk!)

I don't think that anything serious would happen from changing this value to 0 - perhaps a hiccup in sprite motion. If you change it to 0, then the program can wait for it to be equal to or greater than 60 (for a 1 second delay) The program could miss it when it was exactly 60, but as long as it is greater than 60 then it will know the time is up.


This method of timing seems like a good one to me. Test it out and let me know what you think. I'll change the manual if it works well.


If I understand Klaus correctly he wants to have action plus music. If you are using multiple CALL SOUNDs to make music no other lines of code can run as long as the program is executing the CALL SOUNDs, unless they are interspersed with the program lines, which can be a bit complicated. A different way that might work well is to make a sound list and write it to VDP using VWRITE. You then have to use CALL LOAD to put the address of the sound list at >83CC, put a 1 at >83CE and use OR to set the first bit of the byte at >83FD. (You have to PEEK -31747, OR the value with 1, then LOAD it back) Then the sound list should play until it is finished. The beauty of this is that the sounds are played automatically while your program does other things. I'm no expert at this, but you can look it up in the E/A manual, pages 312 to 324. VDP ram from 14301 to 16106 is the disk buffering area and should be safe to use.

Edited by senior_falcon
  • Like 1
Link to comment
Share on other sites


I don't think that anything serious would happen from changing this value to 0 - perhaps a hiccup in sprite motion. If you change it to 0, then the program can wait for it to be equal to or greater than 60 (for a 1 second delay) The program could miss it when it was exactly 60, but as long as it is greater than 60 then it will know the time is up. ...


You don't need to reset the timer to 0---just account for wraparound after 255.



Link to comment
Share on other sites

Ah yes.. I always confuse that with the screen timeout counter. ;) The screen timeout counter gets reset on keypress so I dismissed it.


Seems the GROMs use >8379 here and there, but not for anything critical (cassette and cursor blink). The sprite routines definately don't use it - nothing in the ROM does except where it is incremented.


So, yeah! That'll work better than I was thinking! Should be safe to reset it too, so I'd just do what's most convenient.



Link to comment
Share on other sites

Acutally the XB speech also uses >8379 (TIMER = >8379)

<0105>			   ***********************************************************
<0106>			   * SPEAK will actually speak the speech list. It tests the
<0107>			   * timing byte to see if it is an >FF. If it is, then the
<0108>			   * data following it points to a direct speech data string
<0109>			   * in VDP. If it is not, then the data following it points
<0110>			   * to a PHROM speech data list. In the first case, this
<0111>			   * routine will issue a speak external command to the PHROM
<0112>			   * and then feed bytes out to the PHROM as it requests them.
<0113>			   * In the second case, the address will be loaded out to the
<0114>			   * PHROM, and then a speak command will be issued.
<0115>			   ***********************************************************
<0116> B1CA 06,B5,51 SPEAK  CALL SETRW			 Set read/write address
<0117> B1CD C9,00,02 GB1CE  DCHE @PTLBSL,@PTFBSL   More speech list to go
<0118> B1D0 72,57		   BS   GB258
<0119> B1D2 06,B5,46	    CALL WAIT			  Yes, wait until previous
<0120>			   *							  speech is though
<0121> B1D5 D6,B0,00	    CEQ  >FF,V*PTFBSL	  External speech data
   B1D8 FF
<0122> B1D9 71,FD		   BS   GB1FE
<0123> B1DB BC,79,B0	    ST   V*PTFBSL,@TIMER   No, load timer
   B1DE 00
<0124> B1DF 82,79		   NEG  @TIMER			 and neg it to correct
<0125> B1E1 BD,12,E0	    DST  V@1(@PTFBSL),@PTFBPH   Put addr into PTFBPH
   B1E4 01,00
<0126> B1E6 A3,00,00	    DADD 3,@PTFBSL			   and skip to next node
   B1E9 03
<0127> B1EA D2,79,00 LOOP1  CGE  0,@TIMER		  Wait for time delay
<0128> B1ED 51,EA		   BR   LOOP1
<0129> B1EF 8E,12		   CZ   @PTFBPH		   If there is data
<0130> B1F1 71,FB		   BS   GB1FC
<0131> B1F3 06,B4,EC	    CALL LOADAD		    Load the addr to PHROM
<0132> B1F6 BE,C0,00	    ST   >50,@>8300(@WRITE)  and issue speak command
   B1F9 5A,50
<0133> B1FB 52,54    GB1FC  BR   CONTIN
<0134> B1FD 91,00    GB1FE  DINC @PTFBSL		   Speak external, skip over >FF
<0135> B1FF BD,5E,B0	    DST  V*PTFBSL,@PTCBED  Set up pointer to 1st byte
   B202 00
<0136> B203 BD,5E,E0	    DST  V@4(@PTCBED),@PTCBED    in external speech data
   B206 04,5E
<0137> B208 95,00		   DINCT @PTFBSL		  Skip addr bytes
<0138> B20A BC,62,EF	    ST   V@-1(@PTCBED),@LENWST  Get Len of whole string
   B20D FF,FF,5E
<0139> B210 A6,62,03 DIRSPH SUB  3,@LENWST		 Minus 3 bytes overhead
<0140>			   * All external speech strings start with a >60
<0141> B213 D6,B0,5E	    CEQ  >60,V*PTCBED	  Bad speech string
   B216 60
<0142> B217 4D,EE		   BR   ERRBV
<0143> B219 06,B5,46	    CALL WAIT			  Wait for go ahead
<0144> B21C 95,5E		   DINCT @PTCBED		  Skip spk ext & 1st byte len
<0145> B21E BC,60,B0	    ST   V*PTCBED,@LENCST  Get len of current string
   B221 5E
<0146> B222 91,5E		   DINC @PTCBED		   Skip len byte to 1st real byt
<0147> B224 BE,56,10	    ST   16,@TEMP2		 Do 1st 16 bytes (fill buff)
<0148> B227 BE,C0,00	    ST   >60,@>8300(@WRITE) Start Speak External
   B22A 5A,60
<0149> B22C BC,C0,00 LOOPR  ST   V*PTCBED,@>8300(@WRITE) Write byte to PHROM

99/4 GPL-ASSEMBLER (Pass 3) correct								   PAGE 0052
   B22F 5A,B0,5E
<0150> B232 91,5E		   DINC @PTCBED		   Go to next byte
<0151> B234 92,62		   DEC  @LENWST		   1 less char in whole string
<0152> B236 72,54		   BS   CONTIN		    Finished whole string?
<0153> B238 92,60		   DEC  @LENCST		   1 less char in curr string
<0154> B23A 72,10		   BS   DIRSPH		    Finished current string?
<0155> B23C 92,56		   DEC  @TEMP2		    1 less char in this loop
<0156> B23E 52,2C		   BR   LOOPR			 Not finished curr loop yet?
<0157> B240 BC,69,C0 GB241  ST   @>8300(@READ),@SPKSTS   Read status from PHROM
   B243 00,58
<0159>			   * If the next statement is true, it means that speak was
<0160>			   * probably interupted and that it is shot at this point.
<0161>			   * Therefore, we are going to quit now.
<0162> B245 DA,69,80	    CLOG >80,@SPKSTS
<0163> B248 72,54		   BS   CONTIN
<0164> B24A DA,69,40	    CLOG >40,@SPKSTS	   Loop till buff below half
<0165> B24D 72,40		   BS   GB241
<0166> B24F BE,56,08	    ST   8,@TEMP2		  Put 8 more bytes to PHROM
<0167> B252 52,2C		   BR   LOOPR			  and go do these
<0168> B254 05,B1,CD CONTIN B    GB1CE			 We've said it all!!
<0169>			   * Now pop all entries off stack that we put on!
<0170> B257 0F,78    GB258  XML  VPOP			  Free up a temporary string
<0171> B259 D5,6E,4C	    DCEQ @FAC2,@VSPTR
<0172> B25C 52,57		   BR   GB258
<0173> B25E 50,F1		   BR   GB0F2			 And return to the caller


It uses it as a timer for loading more speech.



Link to comment
Share on other sites

What a tease!


Any hints? Perhaps disk file access? :)


If this compiler came out at the peak of the 99/4a popularity it would have changed the world. I think it is an amazing concept and have been playing with it daily since the release. In due course I think some fantastic stuff will be born as a result. Personally, Assembler has always been out of my league, but I am now estatic about the possibility of have assembler performance with a language that I can understand. Finally the only real limit for the XB programmer now is imagination . That's a great spot to be in. :applaud

  • Like 1
Link to comment
Share on other sites

Sorry-no disk access. Phase one is to write XB support routines that allow greatly enhanced graphics that utilize much more of the capabilities of the 9918A VDP. You can toggle between 2 different screens. Screen1 is the normal XB screen. Screen2 offers 256 character definitions (compared to 112 in XB), plus the additional color information you get with 32 character sets. In addition to the definitions for screen2 you can use all the available character definitions in screen1 for sprites. Since you don't need the character definitions for text you can have 28 unique 16x16 sprites. Highlighted text will be available for menus. Rows of graphics can be smoothly scrolled pixel by pixel just like in Parsec. Plus some other scrolling routines. You can use one screen for a game/program and the other screen for a help menu - when changing screens the graphics and colors be just like you left them. All this from XB!!


Most of this is written and works great - what's left are the scrolling routines which I will start on tonight. Release of the XB enhancements will be in a couple of weeks. Then to merge this with the compiler and fix a few more bugs (Joe Morris is merciless in finding them!) and release that soon after.

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...