Jump to content
Sign in to follow this  
InsaneMultitasker

Adventure Cartridge and GPL

Recommended Posts

I added GPL code to set VR02 to >03. One thing I have not considered is the F18A 80 column mode as that might require being cautious with the register order. I forget whether or not the F18a must be unlocked to enable 80 column mode; if not, then VR8-15 order becomes more important.

 

You don't have to unlock the F18A to use the 80 columns mode.

  • Like 2

Share this post


Link to post
Share on other sites

Writing to VR8..VR14 will not bother the F18A while it is locked, and when unlocked only VR10 and VR11 are used; and then only if Tile-Layer 2 is enabled. Even VR15 might be ignored while the F18A is locked, but I need to check the HDL. But writing 0 to VR15 is always a safe value.

  • Like 1

Share this post


Link to post
Share on other sites

Writing to VR8..VR14 will not bother the F18A while it is locked, and when unlocked only VR10 and VR11 are used; and then only if Tile-Layer 2 is enabled. Even VR15 might be ignored while the F18A is locked, but I need to check the HDL. But writing 0 to VR15 is always a safe value.

Thanks Matthew. I took a quick look at TIMXT's routines today and came to the realization that my F18A/V9938 detection routine is flawed. When used with a V9938 system, TIMXT sets VR#2 to the unlocked value, which results in a weird split screen effect similar to what Michael posted a few days ago in this thread. Now it all makes sense (again).

 

I learned how to set each VR value individually using GPL, so my next challenge is to figure out how to loop through the registers. GPL is sort of like a cross between BASIC and Assembly; once you learn syntax its not all that bad either :)

  • Like 2

Share this post


Link to post
Share on other sites

One obviously safe detection method is to query status register 4, at least to tell apart TMS9918A and v9938. SR4 returns one of two values, 0xFE or 0xFF. Since the 9918A only has one status register, it will return its value, and it is highly unlikely that you get FE or FF from it, and impossible if you have less than 5 sprites on the screen. You need to check with the F18A, of course.

 

To read SR4, you have to set video register 15 to 4 and then read via the status register port. Remember to reset VR15 to 0 afterwards.

  • Like 1

Share this post


Link to post
Share on other sites

One obviously safe detection method is to query status register 4, at least to tell apart TMS9918A and v9938. SR4 returns one of two values, 0xFE or 0xFF. Since the 9918A only has one status register, it will return its value, and it is highly unlikely that you get FE or FF from it, and impossible if you have less than 5 sprites on the screen. You need to check with the F18A, of course.

 

To read SR4, you have to set video register 15 to 4 and then read via the status register port. Remember to reset VR15 to 0 afterwards.

 

I don't recall ever seeing (or trying) this detection method. Seems nice and simple. Typically, I have used VR14 to flip between two different VRAM banks, writing values then comparing the two banks. In TIMXT I am trying to detect the F18A, which used to work, so maybe I goofed up elsewhere. More research required.

 

fortunately, there is little need to detect the 80 column support type in the Adventure cartridge. I had considered adding some color to the status area but unlike Infocom, the status window is dynamic. And this is Adventure after all... :)

  • Like 1

Share this post


Link to post
Share on other sites

I don't remember where I saw it; at least it required me to fix that status register in the MAME implementation.

Share this post


Link to post
Share on other sites

I reviewed the TI Writer GPL source and found the lines that should perform a CALL FILES(1) using the GPL subroutine >16. I understand the CALL and the moves in memory. I don't quite understand how >8381 plays into the call. I'm thinking that for my purposes, all I need to do is call the routine and let the chips fall where they may. If there is an error, I don't care, and it wouldn't really make any difference.

 

Anyone have insight into 8381? The next question is how do I turn this into GPL code? I also included what looks like an efficient way to set all the VDP registers.

 

6342 CALL [email protected]>6663 |call files routine
BYTE >01 | (1 file)
BS [email protected]>6686 error (maybe for Adventure we don't care if this works or not)

6663 FETC @>834C # of files (from CALL)
; ST >01,@>834C (can use this instead of byte after CALL)
DST >0116,[email protected]>077E "pab" for these two bytes
DST >077E,@>8356 pointer for subroutine call
ST >EE,@>8381 not sure why we set this? what is 8381?
CALL [email protected]>10 |link sub [16]
BYTE >0A |

BS [email protected]>6682 error
ST @>8350,@>8381
CZ @>8381
BR [email protected]>6682 status error
RTN
6682 CEQ @>8300,@>8300 return with error
RTNC

; VDP registers set all at once (versus one register at a time)

60EA MOVE >07,[email protected]>68BB,#>01 set VDP regs 1-7
68BB BYTE >20,>00,>0E,>01 VDP registers 1-7
BYTE >01,>06,>00,>F5

Share this post


Link to post
Share on other sites

I reviewed the TI Writer GPL source and found the lines that should perform a CALL FILES(1) using the GPL subroutine >16. I understand the CALL and the moves in memory. I don't quite understand how >8381 plays into the call. I'm thinking that for my purposes, all I need to do is call the routine and let the chips fall where they may. If there is an error, I don't care, and it wouldn't really make any difference.

 

Anyone have insight into 8381? The next question is how do I turn this into GPL code? I also included what looks like an efficient way to set all the VDP registers.

 

>8381 is the second byte of the default subroutine stack space, >8380 – >839F, with LSB of stack pointer at >8373 (followed by the default data stack space, >83A0 – >83BF, with LSB of stack pointer at >8372).

 

Re >8381, it could be that TI Writer uses the first stack position as free space and views the bottom of the stack as >8382 It certainly looks as though the second use of >8381 is viewed as free space. I cannot figure out the storage of >EE at >8381, either.

 

...lee

Share this post


Link to post
Share on other sites

TI Intern page 80:

"GPL uses essentially the area of the CPU-RAM's >8372 through

>83FF. The work space for the GPL interpreter is located at 8370.
The pointer for the GPL data stack is located at >8370 and the
pointer subroutine stack is located at 8372. The complete address
for the stack consists of the pointer plus >8300. Usually the ROM
area >8380 through >83BF is used for the stacks."
>8380 is Register 0 of the GPL Stack space.and >8381 is the LSB of Register 0
The OS ROM will scan update R0 and mask the byte at >8381 and when it returns to GPL
CZ @>8381 looks for zero and if not jumps to >6682 CEQ @>8300,@>8300
this resets the GPL STATUS >837C
RTNC is GPL code to return with no change to >837C to the caller.
Now if >8381 is zero it just returns normally back to caller and >837C is reset.
Edited by RXB

Share this post


Link to post
Share on other sites

Thanks Rich and Lee. I think it is safe not to worry about the >EE stored in >8381. My next challenge is how to get the code to assemble. The TI Writer GPL code syntax seems to be different than the disassembly of the Adventure cartridge. Is there a GPL toolkit available? I have some things RXB sent me but I'm still confused on how to turn this into a properly assembled image file.

Share this post


Link to post
Share on other sites

Was nibbling at this code again a few nights ago. Does someone know the GPL bytes necessary to branch and execute to a memory location equivalent to "B @>A000"?

 

Secondly, if there is such an instruction, how would I then return execution to GPL at a specific location?

 

I want to jump out of the GPL interpreter to run some assembly code then return to GPL. The return gpl address may or may not be the one directly after the branch to my assembly routine.

Share this post


Link to post
Share on other sites

I have made GPL to ASSY branch, for a power-up cartridge header.

I,d use a GPL XML op-code "0F" followed by table 12 "b" procedure 0 "0".

So the answer is "0fb0".

I don't know if I ever did a return. I think maybe it's on the return stack?

GPL Stacks...

 

GPL uses two stacks, located in the scratch-pad memory: the subroutine stack and the data stack.
Subroutine stack

The first one serves to store the return address of procedures called with CALL. The address will be retrieved from the stack by a RTN or RTNC instruction and used to return to the calling point. SWGR and RTGR also make use of this stack but store the GROM base in addition to the return address.

The stack pointer is found in byte >8373. It points to the current return address, i.e. CALL must increment it by two before to save a new return address, whereas RTN reads the address directly and decrement >8373 by two afterwards.

The subroutine stack normally grows upwards from >8380, but this is not an absolute requirement: theoretically it could be located anywhere in the scratch-pad. Note that the GPL interpreter does not check for stack overflow, nor for empty stack: a long serie of nested CALL may therefore crash the interpreter...

Data stack

This stack is meant for use by the programmer. Its pointer is to be found in byte >8372 and the user can push a byte on it with the GPL opcode PUSH. Here also, >8372 points at the current byte, i.e. the pointer is incremented (by one) before saving the byte. For some strange reason, the symetrical POP instruction does not exist (although my assembler simulates it). You'll have to retrieve the byte "manually" with ST *>8372,dest and then decrement the pointer with DEC @>8372.

This stack is normally located at >83A0 and grows upwards with no check for overflow. Be carefull with that one: bytes >83C4-C5 contain the interrupt routine hook. Placing a non-zero value in there will cause the interrupt service routine to branch at the corresponding address in CPU memory (now there's an idea...). Again, it is possible to relocate this stack by just changing the value of the pointer in >8372, but it has to be in the scratch-pad since the pointer is a byte.

 

 

from:

 

http://www.unige.ch/medecine/nouspikel/ti99/gpl2.htm#XML

 

http://www.unige.ch/medecine/nouspikel/ti99/gpl.htm

Share this post


Link to post
Share on other sites

Thanks, I'll give that a shot. I'm thinking returning to the GPL interpreter will be easy so long as I don't muck around with the GPLWS registers. Haven't given it much thought for a few years,maybe it is as simple as branching back into interpreter at 0x70 or 0x6A.

Share this post


Link to post
Share on other sites

Gnawed on this old bone this weekend:

1) Implemented call to GPL DSRLNK to set CALL FILES(1); the primary purpose for this was so that I could move the PAB out of the way of the screen/character set/game that reside in memory.  A secondary, unintended effect is that the maximum game size is now 0x3700 (14,080) bytes, though I don't know that we have anything larger than the Adventure Editor allows.  This same limit is now "imposed" on cassette-based games.  

2) The Save and Restore game option changes are working now, though there is a visible screen twitch when Adventure flips the screen modes for the Cassette operation. 

3) Tweaked V9938/F18A video register settings for compatibility; a little more testing is needed here and for item #2

4) I now have a much better appreciation for GPL; the syntax of the program code neatly follows the more verbose pre-assembled code. I even found it 'easy' to recognize and write some of the code by hand after a while. 

 

image.png.94a8af4d8d436d5aafb36adee3b0ce86.png   image.png.9a6168d7604dd30c90a818c9a053bc45.png

  • Like 7

Share this post


Link to post
Share on other sites

After much head scratching, the Adventure 80 column cartridge is now also working on the Geneve.

 

For the last few days, no matter what I tried the cartridge was 'stuck' in 40 column mode. I thought it was my code or the 9938, ultimately the root cause was found in the Geneve's GPL interpreter.  

 

80 column mode requires VR0 set to >04.  To rule out a problem with the interpreter's routine for VWTR (that lives in the TI ROM at >0698) I disabled the video writes in this routine and in the keyboard SCAN routine.  When I ran Adventure, the screen mode still changed; this was 'impossible'!  It led me to realize that the interpreter is being patched at run-time to inhibit video register writes that are out of range and/or incompatible with the 9938.  

 

In the commented patch below, Video Register 0 has a mask of >FC and the SZCB resets those Corresponding bits to zero. This in turn means that VR0 was masked from >04 to >00, leaving us stranded in 40 column mode.  


PAT#3  SZCB @MASK(R2),R11   ;mask the video register found in MSByte R11
       MOVB R11,*R15    ;write the register data to VDP
       ORI  R2,>80    
       MOVB @>83E5,*R15  ;write register number/mode to VDP

..code continues
MASK  BYTE >FC,>84,>F0,>00   ;register masks (0-3)
HF8    BYTE >F8,>80,>F8,>00  ;masks 4-7

 

By modifying the VR0 mask from >FC to >F8, the needed bit is now passed along to the 9938.  I don't know how many cartridges errantly set VR0, so I might create a one-off patch for the Geneve. 

 

With a little luck I'll post the updated cart later this month.  

  • Like 6

Share this post


Link to post
Share on other sites

Great job pilot! I've been waiting years to see someone writing about GPL and 80-column mode.

  • Like 2

Share this post


Link to post
Share on other sites
4 hours ago, dhe said:

Great job pilot! I've been waiting years to see someone writing about GPL and 80-column mode.

I certainly never thought I'd be poking around GPL. ;) There is no defined mask for registers greater than 7, so if there was a GPL program that needed to set blink mode, for example, a similar problem would occur .  I also discovered that some of the typical environment setup, such as the color table for graphics mode 1, sits right in the middle of the 80 column screen. I'll have to move that around a bit as well.  With exception of a few cosmetic items, I'm about done with the changes.

  • Like 2
  • Thanks 2

Share this post


Link to post
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.

Guest
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.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...