+mizapf Posted May 27, 2022 Share Posted May 27, 2022 So here is a dedicated thread for discussions about porting games like those from Rasmus to the Geneve. Things to consider: Paging is done by writing to a memory address; this won't work with the Geneve mapper. Instead, these operations need to be replaced (possibly in the binary code). Maybe XOP? (not 0, which is used for the system calls) Or an MID-based approach? Keyboard control: The Geneve keyboard is very different to the TI keyboard, but if needed, keyboard access can be written on a low level as well. See https://www.ninerpedia.org/wiki/Geneve_keyboard_control As long as standard VDP (9918/9929) operations are used, there are only few (if any) problems on the 9938. F18A features are out of scope. 2 1 Quote Link to comment Share on other sites More sharing options...
+9640News Posted May 27, 2022 Share Posted May 27, 2022 44 minutes ago, mizapf said: So here is a dedicated thread for discussions about porting games like those from Rasmus to the Geneve. Things to consider: Paging is done by writing to a memory address; this won't work with the Geneve mapper. Instead, these operations need to be replaced (possibly in the binary code). Maybe XOP? (not 0, which is used for the system calls) Or an MID-based approach? The Geneve memory can be paged by writing to a memory address. One writes a byte with the range of >00 to >FF to any of the 8 memory addresses below to swap in a new 8K page: Mapper Address Page Bank >8000 >0000 to >1FFF >8001 >2000 to >3FFF >8002 >4000 to >5FFF >8003 >6000 to >7FFF >8004 >8000 to >9FFF >8005 >A000 to >BFFF >8006 >C000 to >DFFF >8007 >E000 to >FFFF An instruction as simple as: MOVB @MEM_LIST+4,@>8007 would change the memory page on >E000 to >FFFF. Now, if you are in MDOS mode, you use the XOP to request a free page of memory, then either retrieve a buffered list of memory pages available, or use another XOP call to map the page into memory. What I was proposing was to use a modified EXEC as the launch program to load the .bin file into range of free memory pages since the PINBALL game is a 256K file. Then, somewhere within memory, those pages where the .bin was loaded into, would be accessible or passed to the .bin program with the Geneve mapping code being used rather than the FinalGrom mapping code. Memory pages would then be indexed across those 32 x 8K pages. If there was an address to toggle the Geneve mapping code into use rather than using the FinalGrom mapping code, that would be the simplest. 57 minutes ago, mizapf said: Keyboard control: The Geneve keyboard is very different to the TI keyboard, but if needed, keyboard access can be written on a low level as well. See https://www.ninerpedia.org/wiki/Geneve_keyboard_control Fully agree. KSCAN code should be easy to resolve. 57 minutes ago, mizapf said: As long as standard VDP (9918/9929) operations are used, there are only few (if any) problems on the 9938. F18A features are out of scope. Fully agree here as well. If the code works on a TI-99/4A running a 9938 chip, then there should be no issue at all. I seriously doubt there would be an issue with the 9918 either. And the F18A, no way. I looked through Rasmus's PINBALL code and it was not immediately obvious to me where the mapping was occurring. Beery 1 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted May 27, 2022 Author Share Posted May 27, 2022 1 hour ago, 9640News said: I looked through Rasmus's PINBALL code and it was not immediately obvious to me where the mapping was occurring. These SETO/MOV operations cause a bank switch. Obviously, parts of the code were copied to RAM. 2CFC: MOV *R0+,R2 2CFE: SETO *R2 2D00: MOV *R0,R0 2D5C: AI R1,>6008 2D60: SETO *R1 2D62: ANDI R2,>001F 3634: AI R0,>6000 3638: SETO @>6034 363C: MOV *R0+,@>83EE 367C: B *R11 367E: SETO @>6034 3682: MOV @>83EE,R1 833A: MOV @>0006(R12),R1 833E: MOV *R3,*R3 (bank switch) 8340: MOVB *R0+,*R1+ 8354: JMP >833E 8356: SETO @>6000 835A: B *R11 6038: SETO @>6000 603C: LIMI >0000 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 27, 2022 Share Posted May 27, 2022 Unfortunately, /4A mode does not allow you to map pages into the >6000 space besides those that are locked into place by the gate array. You can perform 4096 MOV instructions to copy a page into the >6000 space during each trampoline operation; this works ok unless the program is doing a lot of bank switching. A reasonable, workable approach is to assemble the game/program with the following changes: 1) Use the /9640 mode VDP addresses 2) Use the /9640 mode sound address 3) Replace the trampoline code with an equivalent mapper routine and 4) Use the Geneve Keyscan routine or equivalent; keys may be buffered, which can lead to issues with repeat characters. 5) Check video registers for 9938 compatibility I worked with @PeteE a few years ago to create a wrapper proof-of-concept for one of his games using this method. The wrapper loaded the full ROM image into RAM and used the modified trampoline to index the pages. Perhaps this idea could be expanded and a suitable simple assembly toolkit created to simplify porting for this style of ROM image. 2 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 27, 2022 Share Posted May 27, 2022 Petee gave me the green light to share info from my ROM wrapper that was written for Tilda. The original wrapper performed a brute-force address search & replace at run-time and made use of /4A mode. The trampoline code copied each bank into >6000 as suggested above. This made for very slow gameplay but it did work. Ultimately, I felt /4A mode was too complicated. We successfully tested a /9640 mode brute-force change to the video/sound/mapper addresses in the ROM image. Later, I identified the changes needed for Pete to assemble his code base with the /9640 mode addresses and a few support routines. The attached source should be the latest version of the wrapper that ran Tilda on real hardware. tilda wrapper 2019 source.txt Feel free to use, abuse, and augment. Edit: here is an early version with key/joystick and other info. I'm not sure where my notes are for what Petee integrated into his code directly but this has most of the necessary elements. tilda wrapper original TI mode 2019 4 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted May 28, 2022 Share Posted May 28, 2022 18 hours ago, InsaneMultitasker said: You can perform 4096 MOV instructions to copy a page into the >6000 space during each trampoline operation; this works ok unless the program is doing a lot of bank switching. Pinball 99 is bank switching at least two times per frame (at 60 FPS), so that would never work, but it doesn't have to be the >6000 region - the >0000 region or the >4000 region should work fine. 3 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 28, 2022 Share Posted May 28, 2022 20 minutes ago, Asmusr said: Pinball 99 is bank switching at least two times per frame (at 60 FPS), so that would never work, but it doesn't have to be the >6000 region - the >0000 region or the >4000 region should work fine. Executing that cart from the 4000 space instead of the 6000 space is another good approach, and is one that could leverage the /4A mode relatively easily so long as the trampoline and keyboard scan (if raw) were modified and no DSR access was required. The wrapper was originally written to test whether I could take any ROM image and patch it on the fly without knowing much about the program. What's fun about these challenges is there are often many ways to do the same thing within the limitations of both systems. 3 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted May 30, 2022 Share Posted May 30, 2022 I’ve successfully made a 32K cartridge by prototyping on the 9640. I used GENPROG. There were minimal differences between the binary for a 4A cart and a 9640 image for GPL. First, the base address: the GENMAKE file creates two images, one for >A000 , one for >6000. There were trampolines common to all banks. I don’t recall how I chose the 9640 page numbers. The trampoline code was 3 words in either machine, so I could feel confident in the test. The 4A worked like the Guidry cart where address bits are latched. * 4A PAGE0 BYTE 0 PAGE1 BYTE 0 * Don’t care … BANK0 EQU >6000 BANK1 EQU >6002 … MOVB @PAGE1,@BANK1 … * 9640 PAGE0 BYTE >9A or whichever PAGE1 BYTE >9B … BANK0 EQU >8005 * page goes at >A000 BANK1 EQU BANK0 … MOVB @PAGE1,@BANK1 * 9640 4 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 4, 2022 Share Posted July 4, 2022 On 5/28/2022 at 10:53 AM, Asmusr said: Pinball 99 is bank switching at least two times per frame (at 60 FPS), so that would never work, but it doesn't have to be the >6000 region - the >0000 region or the >4000 region should work fine. I used the >4000 region to emulate the bank switching for the Geneve version of your Pinball 99 game. This works well because the Geneve's >6000 space is locked to two 8K pages by design (or by design error) when operating in /4A mode. On 5/27/2022 at 2:35 PM, 9640News said: What I was proposing was to use a modified EXEC as the launch program to load the .bin file into range of free memory pages since the PINBALL game is a 256K file. Then, somewhere within memory, those pages where the .bin was loaded into, would be accessible or passed to the .bin program with the Geneve mapping code being used rather than the FinalGrom mapping code. This is basically the approach that I used for the Pinball conversion, though a few enhancements are needed to minimize manual build intervention. Simple was easiest for me but I'd prefer to make the loader "aware" of the ROM header so that execution is contained within the image, and so that more than Pinball 99 can be ported. I had intended to use the Tilda approach to the wrapper then wondered what happens when the programmer uses the interrupt routine or doesn't roll their own keyboard/joystick scan. (There is also merit to using GPL though its overhead is too high for a stock system to emulate a 256K rom). All things considered, here is what I've done so far, at a high level: 1) Modify EXEC (a TI program environment and loader) - Request 256K of ram for the cartridge - Check for /4A "TIMODE", if disabled, exit. (I removed this limitation to allow the stock Geneve to run the game) - Store the page map starting at cart ram >7000 (we will not use the cart space pages so this is ok) - Load the 256K cartridge image into the requested pages starting at virtual page address >10000. - Load the program, in this case, the PINBALL program files for the >2000 and >A000->FFFF space. - Adjust the EXEC keyscan routine. The blanking code was writing to PAD ram, in turn destroying Pinball variables. 2) Update PINBALL 99 code: - Remove cleanup/setup code for F18A - Locate and replace bank switch code - Replace keyboard scan routine with Geneve keyboard scan, using Pinball 99 CRU table to match the key indirectly. I spent a long time on this yesterday before realizing that the EXEC key scan changed PAD ram in multiple places. I also mistakenly masked out the space bar by applying an "ANDI R1,>DF00" to mask out lower case. So much for cleverness. Also, I had forgotten that values in the range of >8370->8377 are used for the TI keyboard/joystick values, >837C is changed to reflect GPL status, and somewhere along the way EXEC restores the DSR page >07 to the mapper which blows away our ROM page, so I had to save/restore the mapper. 3) Example of Geneve banking code: The following Pinball 99 routine banks a requested collision map into the >6000 space. SETO *R1 maps the bank and there is an offset applied to the result a few lines later. We use the computed cartridge bank address [6000, 6002, 6004...] in R1 to generate an 8-bit Geneve mapper offset. To do this, we mask the high order byte, divide the remaining byte by two to obtain an index into our Geneve page map, and add offset 8 to point to the first virtual page. We then load the mapper (>8002) with the page number. The correct ROM bank is now presented at >4000. get_coll_value: mov r1,r2 ; Copy y andi r1,>01e0 srl r1,4 ; Bank ai r1,coll_map_bank ; Add base bank offset (>6008) ;; seto *r1 ; Select bank ;---------- mov r1,@savettr1 ;7.2.2022 andi r1,>00FF ;mask it srl r1,1 ;divide by 2 ai r1,>7000+8 ;location of our page map movb *r1,@>8002 ;set the mapper to our page mov @savettr1,r1 ;--------------- It is also necessary to correct the bank base from >6000 to >4000. Instead of applying an offset correction, I should probably change the EQUate "coll_bank_base" directly. andi r2,>001f ; Line swpb r2 ; Line offset a r0,r2 ; Add X ai r2,coll_bank_base ; Add ROM bank base address (>6000) ai r2,->2000 ;fix offset for >4000 7.2.22 clr r1 ; Clear result reg movb *r2,r1 ; Get byte swpb r1 rt *// get_coll_value 2 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 6, 2022 Share Posted July 6, 2022 Yesterday, I noticed that if I ran Pinball 99 multiple times, every other attempt resulted in incorrect collisions. Turns out that the memory routine was grabbing page >36 and using it for the 8K of ram at address >2000-3FFF. This only happened every other time, so it took me a bit to recognize the 'pattern'. TIMODE2 effectively blocks page >36 from the memory allocation request and resolves the issue. I believe there is a good case for adding a third TIMODE option that would block out page >36 and the three FAST ram pages for optimal ROM cart emulation. Since we are using the >4000 space for the banking, file access is inhibited. If disk access is desired, the programmer or porter could bank in the DSR at the start of the DSRLNK routine, which would require 2-3 instructions. Is anyone else consider porting a game to the Geneve? Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 7, 2022 Share Posted July 7, 2022 I've attached a functioning loader with the v1.0 PINBALL 99 ROM and modified game program files. The joystick and keyboard are enabled and function the same as the TI version. To exit the game, press ESCAPE. I am able to run this on my stock Geneve with the extra 32K SRAM installed. Speech has not been tested. If you download the loader and play PINBALL 99, please consider leaving feedback as to whether the loader/simulation works on your system. In the meantime, I'll work on a few remaining enhancements/ideas and figure out how to publish the changes I made to Rasmus' code. PINBALL99-Geneve v91.zip 3 2 Quote Link to comment Share on other sites More sharing options...
+9640News Posted July 8, 2022 Share Posted July 8, 2022 Tim, I just played the game. Thanks so much for converting the program to run on the Geneve. RASMUS did a great game. I had to pull the Rave Speech card as it did not like it in my system. I am not sure I would say the program was locked up, but there were random, rather quiet noises coming from the speaker. This is with PFM Geneve and Myarc 512K combo that gives 172 total 8K pages. Beery 1 1 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 8, 2022 Share Posted July 8, 2022 1 hour ago, 9640News said: I had to pull the Rave Speech card as it did not like it in my system. I am not sure I would say the program was locked up, but there were random, rather quiet noises coming from the speaker. This is with PFM Geneve and Myarc 512K combo that gives 172 total 8K pages. I appreciate the feedback. I will review the banking code this evening to confirm the speech data is being presented properly. This may be a timing issue with how fast (or slow) the speech data is being sent to the synthesizer. Are there any other speech-related programs that you can try running with EXEC so that we know if the issue is with the loader versus the game? If the latter, I'll need help from those of you that have experience with speech synth coding. 2 Quote Link to comment Share on other sites More sharing options...
+9640News Posted July 8, 2022 Share Posted July 8, 2022 2 hours ago, InsaneMultitasker said: I appreciate the feedback. I will review the banking code this evening to confirm the speech data is being presented properly. This may be a timing issue with how fast (or slow) the speech data is being sent to the synthesizer. Are there any other speech-related programs that you can try running with EXEC so that we know if the issue is with the loader versus the game? If the latter, I'll need help from those of you that have experience with speech synth coding. I can go into extended basic via the GPL interpreter and type CALL SAY("HELLO") and get speech. Beery Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 8, 2022 Share Posted July 8, 2022 10 minutes ago, 9640News said: I can go into extended basic via the GPL interpreter and type CALL SAY("HELLO") and get speech. Beery That's probably just speaking from the resident vocabulary in ROM. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted July 8, 2022 Author Share Posted July 8, 2022 Do a CALL SPGET("HELLO",A$) and then CALL SAY(,A$); this will run a speak external command. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 8, 2022 Share Posted July 8, 2022 It occurred to me that the indices to the speech data are addresses, and those addresses are AORG'd to the >6000 space. Since we are banking everything into >4000-5FFF, who knows what is being sent to the synthesizer. @9640News I PM'd you a set of files to test. Quote Link to comment Share on other sites More sharing options...
+9640News Posted July 8, 2022 Share Posted July 8, 2022 5 hours ago, mizapf said: Do a CALL SPGET("HELLO",A$) and then CALL SAY(,A$); this will run a speak external command. No issue. 4 hours ago, InsaneMultitasker said: It occurred to me that the indices to the speech data are addresses, and those addresses are AORG'd to the >6000 space. Since we are banking everything into >4000-5FFF, who knows what is being sent to the synthesizer. @9640News I PM'd you a set of files to test. Sent you a text message picture of the error message, invalid GPL access. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 9, 2022 Share Posted July 9, 2022 3 hours ago, 9640News said: Sent you a text message picture of the error message, invalid GPL access. Gremlins. I made one instruction change that has nothing to do with GPL, and I don't recall seeing anything related to GPL in Rasmus' code. I will test the files tonight on my system. Maybe there was an error during assembly that I didn't notice. @Asmusrdo you rely upon GPL or any ROM-based XML calls in your game(s)? Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 9, 2022 Share Posted July 9, 2022 4 hours ago, InsaneMultitasker said: @Asmusrdo you rely upon GPL or any ROM-based XML calls in your game(s)? No, I'm not using anything in the system ROMs or GROMs. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 9, 2022 Share Posted July 9, 2022 7 hours ago, Asmusr said: No, I'm not using anything in the system ROMs or GROMs. Thank you. ( I don't understand how adjusting the speech data index (speech_addr) by ->2000 affects any jump/branch operations that would cause the error Beery is encountering. Either I inadvertently edited/deleted something within speech.a99 or there is some instruction that isn't apparent to me. ) Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 9, 2022 Share Posted July 9, 2022 (edited) 1 hour ago, InsaneMultitasker said: Thank you. ( I don't understand how adjusting the speech data index (speech_addr) by ->2000 affects any jump/branch operations that would cause the error Beery is encountering. Either I inadvertently edited/deleted something within speech.a99 or there is some instruction that isn't apparent to me. ) Did you also remember to aorg speech-data.a99 at >4000 instead of >6000? Edited July 9, 2022 by Asmusr 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 9, 2022 Share Posted July 9, 2022 And adjust ROM address in speak and send_bytes_to_speech functions? 2 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 9, 2022 Share Posted July 9, 2022 1 hour ago, Asmusr said: And adjust ROM address in speak and send_bytes_to_speech functions? Yes, those routines looked good in the listing. I am sitting in my car about to run a few errands and it occurred to me that I am using a BL @>E to call the modified keyboard routine. GPLWS is the caller workspace, which means R11 is modified during the BL instruction. R11 is address >83F6 which just so happens to be the destination address for the speech read status routine, in PAD. I surmise the speech read status is overwriting the MSByte at the R11 address, sending the program into a tailspin. 3 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 9, 2022 Share Posted July 9, 2022 @9640News confirmed that R11 was the culprit; PINBALL speech is working properly now. I posted a question about the gameplay in the pinball development topic. To improve (and maybe simplify) the method for emulating this style of cartridge, applied a similar approach to the Flying Shark game. The title and demo mode work fine, gameplay starts but I haven't tied in the joystick or keyboard routines. On 5/27/2022 at 1:28 PM, mizapf said: Paging is done by writing to a memory address; this won't work with the Geneve mapper. Instead, these operations need to be replaced (possibly in the binary code). Maybe XOP? (not 0, which is used for the system calls) Or an MID-based approach? Keyboard control: The Geneve keyboard is very different to the TI keyboard, but if needed, keyboard access can be written on a low level as well. See https://www.ninerpedia.org/wiki/Geneve_keyboard_control As long as standard VDP (9918/9929) operations are used, there are only few (if any) problems on the 9938. F18A features are out of scope. So far, this has all been true. For Pinball and Flying Shark, Rasmus' banking approach made it "very easy" to change the bank location and memory mapping to suit the Geneve. The keyboard support depends on how the programmer implements the scan. Vsync-driven games might require activating the Geneve wait state and/or using slow ram, where gameplay is impacted by faster code execution. I will play the games in emulation to get a feel for their operation on the /4A versus the 9640. 4 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.