Just Jeff Posted September 24, 2022 Author Share Posted September 24, 2022 Well I haven't posted an update in a couple of weeks so I'll put this .bin up even though its glitchy and incomplete. Its been a significant amount of work, with little to show. Basically, my previous uploads had some cut corners that needed to be dealt with. I really wanted to get the program to run through all the screens- so a level intro, then a play screen, and so on. Even if the play screens are identical. But once I started, it seemed like I had to fix some things first or I'd be just duplicating messes. Firstly, you may have noticed that the previous version always played the same- I think it was pad 2 to pad 3, then pad 3 to Up. Now its randomized. All of that code I posted on September 3rd was static- wasn't going to get me past the one screen and always the same order. Now, that code is basically in table form, and the program can do those things in random order and future screens will just have their own tables. I wonder if the C64 version is random.. I'm just assuming it is. The other thing you'll notice is basic intro screens- this required me to redo my jump tables to make it more logical. Intro screens end in 0 (D0), play screens end in 1. This allowed me to split the jump tables in half- useful because a carry branch quickly gets to the proper bank with its own table. So its does like 3 screens now before it goes off the rails. I know why it does, I just haven't gotten around to writing the code. Also- the "Itinerary" of the dashboard is a little confusing at this point. The "Hey" and "Up" are gone at the moment, You'll always see a pad number when its generated- just remember- you don't see "Up" when its time to leave. Just look for the gate to disappear. .bin below. SpaceTaxi.asm.bin 8 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 2, 2022 Author Share Posted October 2, 2022 (edited) Much better progress this week. I achieved my major goal of having the game start with title screens, then run through 24 customizable play screens with 24 intros. Now... to get through it all, I had to point to existing code, tables, and routines and just did a few color changes for the first few play screens just as a proof of concept, so its pretty much the same screen over and over. But at this point the code is laid out nice and the customizations should be pretty straight forward. I'll basically copy a screen, rename it, change pointers for the jump, then customize it. I felt like this is the base point I had to reach and then build up from here. I also fixed and finished most of the stuff I left undone last week such as: Cab should be already occupied when screens start (except 1st) Correct hailing-shout-outs When you jump off a correct pad, then return, it no longer throws off the sequence When the gate is open, you can no longer land on the (hidden) designated pad (incorrectly) Passenger goes back into hailing state if you lift off prematurely This week saw the return of my famous task grid- and I credit much of my progress to it: Not a lot of items on it but it did help me focus and recall. -Jeff SpaceTaxi.asm.bin Edited October 2, 2022 by Just Jeff 5 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted October 2, 2022 Share Posted October 2, 2022 11 minutes ago, Just Jeff said: This week saw the return of my famous task grid- and I credit much of my progress to it: Not a lot of items on it but it did help me focus and recall. I am using a task list for the same reasons too, either on top of the code or as issues in GitHub. 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 8, 2022 Author Share Posted October 8, 2022 On 10/2/2022 at 2:20 PM, Thomas Jentzsch said: I am using a task list for the same reasons too, either on top of the code or as issues in GitHub. Nice.. I based my grid loosely on Steven Covey stuff- perfect for large tasks, largely because it helps me determine what not to work on. Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 10, 2022 Author Share Posted October 10, 2022 (edited) Greetings, New .bin attached.. I laid out the dashboard to prep for adding the tip, bank, and fuel functions as well as to see how much I could realistically fit in. Also trying some new colors which are more of a departure from the original. Any opinions on the new dash colors or anything else? SpaceTaxi.asm.bin Edited October 10, 2022 by Just Jeff 5 Quote Link to comment Share on other sites More sharing options...
TIX Posted October 15, 2022 Share Posted October 15, 2022 Looking smart, playing smoothly ! No big deal really, but some times the passengers move in the opposite direction from the one I was expecting.. 1 Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted October 15, 2022 Share Posted October 15, 2022 (edited) On 1/14/2017 at 5:05 AM, Just Jeff said: Has anyone ever attempted Space Taxi on the 2600? It think the 2600 could do a pretty decent version of it. 10 OCT 2022 Edit: Latest .bin here. SpaceTaxi.asm.bin 64 kB · 8 downloads “Hey, taxi!” “Voice clips please!” I understand if it won’t work though. Edited October 15, 2022 by Ecernosoft 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 16, 2022 Author Share Posted October 16, 2022 On 10/15/2022 at 4:41 AM, TIX said: Looking smart, playing smoothly ! No big deal really, but some times the passengers move in the opposite direction from the one I was expecting.. Thanks! Yeah that's going to take some effort because the RESP1 is taking place at different times in different locations. The taxi's X position will need to be translated into distance from each RESP1, not to mention, converted to early HMOVE values. So, when each screen is done, that's probably when I'll work on those. Right now I simply AND the FrameCounter and store it in HMP1 so the movement is only just to make him wander around until he collides with the taxi. 22 hours ago, Ecernosoft said: “Hey, taxi!” “Voice clips please!” I understand if it won’t work though. It will have voice for sure and I posted an example here some time ago, but like many other things, its probably something that is better done later. I plan to get a working gas gauge and a death plummet crash sequence next. I have the Tips and Score fields functioning now, so we're finally making some money: Its taking too much kernel time though. I'm at 267 scan lines now- 26 of them for the dash. And you can see the dash is a little distorted now as a result. I'd really like to reduce the dash height to 24 scan lines. The issue centers around setting up the digits for the Tips and the Score. Does anyone have any ideas? ;Setup line #2 ;Load up RAM buffer with either pointers or graphics lda Tip ;This is the Dollar sign and the 10s digit for the tip and #%11110000 lsr lsr lsr lsr tay lda DollarGfxLo,y ;Store a pointer which will be accessed while drawing sta Sprite1 lda DollarGfxHi,y sta Sprite1+1 ;This is dollar 1s digit before the decimal. The decimal will be manually added lda Tip and #%00001111 tax lda DigitBlankGfxLo,x ;Store a pointer which will be accessed when loading a RAM buffer sta Sprite1+6 lda DigitBlankGfxHi,x sta Sprite1+7 ;Load and combine cents lda Tip+1 and #%11110000 lsr lsr lsr lsr tax .loadCents10s lda DigitBlankGfxLo,x ;Store a pointer which will be accessed when loading a RAM buffer sta Sprite1+2 lda DigitBlankGfxHi,x sta Sprite1+3 lda Tip+1 and #%00001111 tax lda BlankDigitGfxLo,x ;Store a pointer which will be accessed when loading a RAM buffer sta Sprite1+4 lda BlankDigitGfxHi,x sta Sprite1+5 ldy #4 .loadSprites ;Load the RAM buffer with full sprites lda (Sprite1+2),y ;Load one of the penny digits ora (Sprite1+4),y ;Combine it with the other sta Sprite3,y ;Store the combo lda (Sprite1+6),y ;Load the single dollar digit in front of the decial sta Sprite2,y ;Store it, add the decimal to right nibble later dey bpl .loadSprites lda #%00000010 ;Add the decimal ora Sprite2 sta Sprite2 ;Set up the passenger's requests lda #>ShoutOuts ;Set the big end of the pointers. Don't go over one page. sta PadPtr4+1 sta PadPtr5+1 ldy #11 ;Load the offset for Hey! lda PassengerState bmi .storePtr ;If PASSENGER_HAIL, then store the 11 (Hey!) ldy #10 ;Load the offset for blank cmp #PASSENGER_ONBOARD ;Is the passenger onboard bne .storePtr ;If not, then don't display anything ldy #9 ;Load the offset for Up! just in case lda StopNumber ;Then check for which stop bmi .storePtr ;#$ff means the screen is done, so store 9 for Up! ldy CurrentTarget ;Otherwise, pick the message for the next stop .storePtr lda ShoutOuts4,y ;This is the table for the left half of the word(s) sta PadPtr4 lda ShoutOuts5,y ;This is the table for the right half of the word(s) sta PadPtr5 SpaceTaxi.asm.bin 3 Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted October 16, 2022 Share Posted October 16, 2022 (edited) 20 minutes ago, Just Jeff said: It will have voice for sure and I posted an example here some time ago, but like many other things, its probably something that is better done later. YES!!! Thanks! Edit: I know my jokes are terrible Edited October 16, 2022 by Ecernosoft 1 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted October 24, 2022 Share Posted October 24, 2022 @Just Jeff Did you find the cycles yourself by now? The code you posted can be slightly optimized, but that will not gain you 3 lines. Either you setup before the kernel (probably needs more RAM). Or you reduce the scanlines used for vertical blank and/or overscan. 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 25, 2022 Author Share Posted October 25, 2022 On 10/24/2022 at 10:39 AM, Thomas Jentzsch said: @Just Jeff Did you find the cycles yourself by now? The code you posted can be slightly optimized, but that will not gain you 3 lines. Either you setup before the kernel (probably needs more RAM). Or you reduce the scanlines used for vertical blank and/or overscan. Nothing really. My plan at this point is to load up the most time consuming 10 bytes in vblank and just hold on to it during the kernel. That would be the cents at the right of the decimals for both the tip and the score. Its the most time consuming because two nibbles need to be ora'd with each other then all stored as a sprite in RAM. That's the best I could think of. I think the rest could be set up inside the dashboard. What do you think? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted October 25, 2022 Share Posted October 25, 2022 (edited) The bottom row only needs 4 sprite copies, right? Can't you create that data on-the-fly? That would be 8 loads (8*5 = 40 cycles) and 4 stores (4*3 = 12 cycles). Should fit, no? BTW: You don't have to AND before shifting right 4 times. Edited October 25, 2022 by Thomas Jentzsch Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted October 27, 2022 Author Share Posted October 27, 2022 On 10/25/2022 at 5:56 PM, Thomas Jentzsch said: The bottom row only needs 4 sprite copies, right? Can't you create that data on-the-fly? That would be 8 loads (8*5 = 40 cycles) and 4 stores (4*3 = 12 cycles). Should fit, no? BTW: You don't have to AND before shifting right 4 times. Well I have those 4 indicator lights on the same row which I have not even started on. They require setup as well as time on those lines so I don't know what's going to happen there either. To make your idea work, I need to also add some ORAs- right? Indirect load left nibble, ORA indirect address of right nibble? Thanks for pointing out the ANDs.. I'll change that. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted October 27, 2022 Share Posted October 27, 2022 45 minutes ago, Just Jeff said: Well I have those 4 indicator lights on the same row which I have not even started on. They require setup as well as time on those lines so I don't know what's going to happen there either. Will they change between lines? 45 minutes ago, Just Jeff said: To make your idea work, I need to also add some ORAs- right? Indirect load left nibble, ORA indirect address of right nibble? Yup, that is why I calculated 8 loads (4 LDA + 4 ORA) Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted November 11, 2022 Author Share Posted November 11, 2022 OK.. I've gotten it back down to 192 scanlines and also the fuel gauge functioning now. .bin attached On 10/25/2022 at 12:56 PM, Thomas Jentzsch said: The bottom row only needs 4 sprite copies, right? Can't you create that data on-the-fly? That would be 8 loads (8*5 = 40 cycles) and 4 stores (4*3 = 12 cycles). Should fit, no? BTW: You don't have to AND before shifting right 4 times. Thanks Thomas... I converted several of the loads to this. I wasn't able to do one of them on the top half (with the fuel gauge) because there isn't enough time. I also created another set of digits 0-9 followed by a decimal in ROM so I could do a single load on those. And I have the same thing for dollar sign with one digit. .kernelLoop1 ;Top half of the dashboard sta WSYNC ;3 0 lda (PadPtr5),y ;5 5 sta GRP0 ;3 8 lda (PadPtr4),y ;5 13 sta GRP1 ;3 16 lda (Sprite1+6),y ;4 20 sta GRP0 ;3 23 VDELP0 is on lda FuelGaugeNUSIZ,y ;4 27 sta ENAM1 ;3 30 sta NUSIZ1 ;3 33 After ~31 lda (Sprite1),y ;5 38 ldx #RED ;2 40 stx COLUPF ;3 43 $34 Turn red after 42 sta GRP1 ;3 46 lda #GREEN ;2 48 $B0 SLEEP 3 ;3 51 sta COLUPF ;3 54 lda #3 ;2 56 3 players close sta NUSIZ1 ;3 59 store after ~55 lda Sprite3,y ;4 63 dey ;2 65 sta GRP1 ;3 68 bpl .kernelLoop1 ;2/3 70/73 -break- .kernelLoop2 ;Bottom half of the dashboard sta WSYNC ;3 0 lda (PadPtr4),y ;5 5 ora (PadPtr5),y ;5 10 Combine the 100s and the 10s sta GRP0 ;3 13 lda (Sprite1),y ;5 18 sta GRP1 ;3 21 lda (Sprite1+2),y ;5 26 ora (Sprite1+4),y ;5 31 sta GRP0 ;3 34 VDELP0 is on SLEEP 7 ;7 41 lda (Sprite1+6),y ;4 45 sta GRP1 ;3 48 dey ;2 50 bpl .kernelLoop2 ;2/3 52/53 SpaceTaxi.asm.bin 5 Quote Link to comment Share on other sites More sharing options...
Bomberman94 Posted November 12, 2022 Share Posted November 12, 2022 Plays and feels right - maybe you consider a PAL release in parallel please? 2 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 11, 2022 Author Share Posted December 11, 2022 Good afternoon! Two things... Firstly, YouTube suggested this video to me. Freaked me out- in a good way: Secondly, I finally worked up the nerve to begin the voice code this morning after I had an epiphany... Bit-Packing! I believe I need to run through 50 AUDV1 register changes for every frame shown. That's just in the kernel section which should be the most difficult part. Since the data is spread over multiple banks, its impractical to grab any data while in the kernel, therefore it must be grabbed in VBLANK and Overscan, then stored in RAM and used every 4 scan lines while in the kernel. But 50 bytes of RAM seemed impractical and wasteful, if not impossible. Finally, this morning it occurred to me that I can get away with 25 bytes if I take existing RAM that is only used outside the kernel and store the right nibble of it in the left nibble of 25 bytes of designated VoiceRAM. In this way, 50 right nibbles are available for use for the price of only 25 bytes. Oh right- it's important to note that only the right nibble is used by the Atari, so the left nibble will be ignored and can therefore still be used to store useful data for other things, which makes this whole scheme work. Additionally, 25 is on the high end. With some code changes, there are some bytes that can get wrecked entirely while speech is happening and therefore, don't even need the swap space (VoiceRAM). Also, some bytes don't need two nibbles to begin with, in those cases the data can simply stay in the left nibble full time. After these code changes, I think I can bring the dedicated bytes needed down to 19 if necessary. So here's my bit packing and unpacking code. I'd be curious to know if it could be more efficient. It does run in the time allowed as is but then again, all this is doing is splitting the bytes (in preparation for grabbing voice data), then putting them back together after the screen is drawn. The RepackingBits looks a little unwieldy to me. What do you think? ;in Bank 1 UnpackBits SUBROUTINE ;added in TypicalPlayLogic.asm ;Sound registers only use the right nibble. So preserve the right nibble in the left nibble of VoiceRAM while ;in the kernel. Then restore it when out of the kernel ldx #31 ;This can probably be reduced to about 19 with some code modifications. ;I have 10 RAM bytes that can probably be trashed during speech and 3 RAM bytes that are single ;nibbles so they don't need swap space. Additionally, I probably could have used #25 here to get ;through the kernel to begin with. .ramSplit lda Voice+32,x ;This area of RAM will be borrowed for voice asl asl asl asl sta Voice,x ;The right nibble is stored in the left nibble of Voice. Right nibble is zero which is convenient. dex bpl .ramSplit rts ;Return, then jump to a voice bank ;Added in Overscan RepackBits ;Restore the left nibble of Voice, to the right nibble of Voice+32 while preserving that left nibble. ldx #31 .ramCombine lda Voice+32,x and #$f0 ;Strip the right nibble of the RAM value sta Voice+32,x lda Voice,x ;Right nibble of Voice+32 was stored in left nibble here. lsr lsr lsr lsr ora Voice+32,x sta Voice+32,x dex bpl .ramCombine rts Any suggestions? -Jeff 3 Quote Link to comment Share on other sites More sharing options...
+Pat Brady Posted December 11, 2022 Share Posted December 11, 2022 4 hours ago, Just Jeff said: Any suggestions? I can't help with RAM, but you can save some cycles by using lookup tables. For unpack you only need a 16-byte table, and you'll save a byte of code. It saves 4 cycles per iteration in exchange for 15 bytes of ROM and clobbering Y. .ramSplit ldy Voice+32,x ;This area of RAM will be borrowed for voice lda leftshift4,y sta Voice,x ;The right nibble is stored in the left nibble of Voice. Right nibble is zero which is convenient. dex bpl .ramSplit rts ;Return, then jump to a voice bank leftshift4 ; this can go anywhere in any accessible bank .byte $00,$10,$20,$30,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$D0,$E0,$F0 You could also set up a macro to generate the table. Ideally, ensure that the table does not cross a page boundary, since each page crossing indirect load costs an extra cycle. If you use dasm you can use my prevsamehighas macro (from attachment in this post) to confirm that at build time. For pack, the principle is the same, but you would need a full-page table, so if you're at all tight on ROM this is a tougher trade-off. There may be other optimizations. This is the one that immediately came to my mind. 1 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted December 11, 2022 Share Posted December 11, 2022 This saves you 4 cycles/loop: RepackBits ;Restore the left nibble of Voice, to the right nibble of Voice+32 while preserving that left nibble. ldx #31 .ramCombine lda Voice,x ;Right nibble of Voice+32 was stored in left nibble here. lsr lsr lsr lsr eor Voice+32,x ;Strip the right nibble of the RAM value and #$0f ; clear left nibble gets xored once, eor Voice+32,x ; right nibble twice (== not xored at all) sta Voice+32,x dex bpl .ramCombine rts But as of now, your whole idea seems maybe overly complex. E.g. what happens with the right nibble of Voice? And why can't you e.g. duplicate the kernel for data access in different banks? Or why don't you use a more flexible bankswitching? 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 13, 2022 Author Share Posted December 13, 2022 (edited) On 12/11/2022 at 5:34 PM, Pat Brady said: .ramSplit ldy Voice+32,x ;This area of RAM will be borrowed for voice lda leftshift4,y sta Voice,x ;The right nibble is stored in the left nibble of Voice. Right nibble is zero which is convenient. dex bpl .ramSplit rts ;Return, then jump to a voice bank leftshift4 ; this can go anywhere in any accessible bank .byte $00,$10,$20,$30,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$D0,$E0,$F0 Thanks- this is a technique I wasn't familiar with, but it doesn't work here.. Looks like you are expecting y values of 0 to 15 but these bytes are 0 to 255. Probably that's what you meant when you mentioned a 256-byte table being necessary? Alternatively, I was able to get this code to work by loading the accumulator with Voice+32, then AND #$0f, then TAY, but at that point it saves no time. On 12/11/2022 at 6:14 PM, Thomas Jentzsch said: This saves you 4 cycles/loop: RepackBits ;Restore the left nibble of Voice, to the right nibble of Voice+32 while preserving that left nibble. ldx #31 .ramCombine lda Voice,x ;Right nibble of Voice+32 was stored in left nibble here. lsr lsr lsr lsr eor Voice+32,x ;Strip the right nibble of the RAM value and #$0f ; clear left nibble gets xored once, eor Voice+32,x ; right nibble twice (== not xored at all) sta Voice+32,x dex bpl .ramCombine rts But as of now, your whole idea seems maybe overly complex. E.g. what happens with the right nibble of Voice? And why can't you e.g. duplicate the kernel for data access in different banks? Or why don't you use a more flexible bankswitching? Thanks! That's some crazy code, but it does work. Note- it also saves 2 bytes. Though I don't think the comment "Strip the right nibble of the RAM value" is correct- values are left in there, being various xors of one of the preserved RAM nibbles and a used voice nibble. So to answer your questions.. The right nibble of voice- The right nibble is the only relevant nibble when it comes to AUDV1- but I'm sure you knew that. Here is an abridged, two byte explanation of what I'm doing: Note below, VoiceCounter and VoicePointer are really the same counter- just a typo. Voice ds 1 ;Left nibble stores right half of FrameCounter while in kernel FrameCounter ds 1 ;Can be any value. Left nibble is always FrameCounter's left nibble. Right nibble borrowed for voice nibbles ;So two pieces of voice data fit per 1 byte of RAM reserved.. ;If FrameCounter's value is at, for example $A2, then for the kernel split that up so ;Voice = $20 and FrameCounter = $A0. This is OK becasue FrameCounter is not used in the kernel ;Jump to a voice data bank ;The voice data is 4 bits, played right nibble first, then left nibble second ;Load a byte of Voice Data and store each nibble in the right nibble of Voice and FrameCounter lda VoiceByte and #$0F ora Voice sta Voice lda VoiceByte lsr lsr lsr lsr ora FrameCounter sta FrameCounter ;Complicated here, so the kernel is fast and simple Kernel ;This code every 4 scan lines dec VoicePointer 5 5 ldx VoiceCounter 3 8 lda Voice,x 4 12 sta AUDV1 3 15 ;or maybe tya 2 2 ;use the kernel index lsr 2 4 lsr 2 6 ;multiply by 4 tax 2 8 lda Voice,x 4 12 sta AUDV1 3 15 ;Then when the kernel is done, put FramCounter back together Secondly, duplicating the kernels is impractical since there are 24 screens and multiple kernel bands, and 8 voice data banks. I'll probably end up with 100 to 200 kernel bands then duplicated on 8 banks = 800 to 1600 kernels. I'll consider more flexible bank switching, but still I don't think that will help me inside the kernel. How am I doing? -Jeff Edited December 13, 2022 by Just Jeff 1 Quote Link to comment Share on other sites More sharing options...
+Pat Brady Posted December 14, 2022 Share Posted December 14, 2022 5 minutes ago, Just Jeff said: Thanks- this is a technique I wasn't familiar with, but it doesn't work here.. Looks like you are expecting y values of 0 to 15 but these bytes are 0 to 255. Probably that's what you meant when you mentioned a 256-byte table being necessary? Alternatively, I was able to get this code to work by loading the accumulator with Voice+32, then AND #$0f, then TAY, but at that point it saves no time. Ah, you're right. On all counts. 256-byte table should work but maybe not worth the ROM cost. Sorry for the wild goose chase. 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted December 14, 2022 Share Posted December 14, 2022 On 12/13/2022 at 5:23 PM, Just Jeff said: I'll consider more flexible bank switching, but still I don't think that will help me inside the kernel. Perhaps Thomas is thinking about a format with 2k banks, like 3F or 3E. That way your kernel can be in the non-ephemeral 2k bank, and your sample data can be swapped as desired in the ephemeral 2k bank. Whether you go with ram or rom samples, you could stagger the samples every 4 bytes, since that way you can use the scanline index for your samples, without modification. If you stick to ram, you can use a few consecutive kernels to access the bytes that were skipped over in previous kernels, with the sample data being stored in an interleaved fashion. 1 Quote Link to comment Share on other sites More sharing options...
Just Jeff Posted December 17, 2022 Author Share Posted December 17, 2022 On 12/14/2022 at 3:19 PM, RevEng said: Perhaps Thomas is thinking about a format with 2k banks, like 3F or 3E. That way your kernel can be in the non-ephemeral 2k bank, and your sample data can be swapped as desired in the ephemeral 2k bank. Whether you go with ram or rom samples, you could stagger the samples every 4 bytes, since that way you can use the scanline index for your samples, without modification. If you stick to ram, you can use a few consecutive kernels to access the bytes that were skipped over in previous kernels, with the sample data being stored in an interleaved fashion. On 12/14/2022 at 3:19 PM, RevEng said: Perhaps Thomas is thinking about a format with 2k banks, like 3F or 3E. That way your kernel can be in the non-ephemeral 2k bank, and your sample data can be swapped as desired in the ephemeral 2k bank. Whether you go with ram or rom samples, you could stagger the samples every 4 bytes, since that way you can use the scanline index for your samples, without modification. If you stick to ram, you can use a few consecutive kernels to access the bytes that were skipped over in previous kernels, with the sample data being stored in an interleaved fashion. OK I'm not familiar with those types of bankswitching. Do I have this correct?-- I could have my current voice data in the lower 2K area as needed (these will need to be switched) The upper 2K could contain game code that fetches from the lower 2K area with no bankswitch per each fetch? The description I saw mentioned JMPs and JSRs but didn't specifically mention what I would want- indexed loads and indirect addressing to the lower bank. Also, one person called it "RAM" is there RAM? Can I have multiple upper banks? The game code wouldn't fit into a single 2K upper bank. I currently have 4K for VBLANK and Overscan, and 8K reserved for the play kernels alone. Quote Link to comment Share on other sites More sharing options...
RevEng Posted December 17, 2022 Share Posted December 17, 2022 A disclaimer - while I've played around with a few banking formats, I haven't played around with these two specifically. That said, kevtris' mapper doc is pretty clear on how they work. Plus they're very similar to the 7800 supergame formats, which I have used once or twice. 9 hours ago, Just Jeff said: OK I'm not familiar with those types of bankswitching. Do I have this correct?-- I could have my current voice data in the lower 2K area as needed (these will need to be switched) The upper 2K could contain game code that fetches from the lower 2K area with no bankswitch per each fetch? Yep, that's correct. 9 hours ago, Just Jeff said: The description I saw mentioned JMPs and JSRs but didn't specifically mention what I would want- indexed loads and indirect addressing to the lower bank. Also, one person called it "RAM" is there RAM? However you've swapped them, the bank is there in address space for whatever kind of access you like. 3F was used back in the day by Tigervision, and only had ROM. 3E is the homebrew extension of 3F, and does have RAM in addition to ROM. 9 hours ago, Just Jeff said: Can I have multiple upper banks? The game code wouldn't fit into a single 2K upper bank. I currently have 4K for VBLANK and Overscan, and 8K reserved for the play kernels alone. Not with these schemes as they currently stand. You can go with a new scheme/variant, but then you're stuck with a heavier lift, with emulation and cart hardware needing to be updated to match your new scheme. 1 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted December 18, 2022 Share Posted December 18, 2022 I suggest you have a look at 3E+. It is more flexible than 3E, which has its limits due to the fixed last segment. And having just two segments turned out to be a bottleneck too, when @Andrew Davie and I developer Boulder Dash. Here is a brief description from the source code: Cartridge class for new tiling engine "Boulder Dash" format games with RAM. Kind of a combination of 3F and 3E, with better switchability. B.Watson's Cart3E was used as a template for building this implementation. Note: In descriptions $F000 is equivalent to $1000 -- that is, we only deal with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000 So, mask with top bits clear :) when reading this document. In this scheme, the 4K address space is broken into four 1K ROM/512b RAM segments living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.), The destination segment (0-3) is held in the top bits of the value written to $3E (for RAM switching) or $3F (for ROM switching). The low 6 bits give the actual bank number (0-63) corresponding to 512 byte blocks for RAM and 1024 byte blocks for ROM. The maximum size is therefore 32K RAM and 64K ROM. D7D6 indicate the segment number (0-3) D5D4D3D2D1D0 indicate the actual # (0-63) from the image/ram ROM: The last 1K ROM ($FC00-$FFFF) segment in the 6502 address space (ie: $1C00-$1FFF) is initialised to point to the FIRST 1K of the ROM image, so the reset vectors must be placed at the end of the first 1K in the ROM image. Note: This is DIFFERENT to 3E which switches in the UPPER segment and this segment is fixed. This allows variable sized ROM without having to detect size. ROM switching (write of segment+bank number to $3F) D7D6 upper 2 bits of bank # indicates the destination segment (0-3, corresponding to $F000, $F400, $F800, $FC00), and lower 6 bits indicate the 1K bank to switch in. Can handle 64 x 1K ROM banks (64K total). D7 D6 D5D4D3D2D1D0 0 0 x x x x x x switch a 1K ROM bank xxxxxx to $F000 0 1 switch a 1K ROM bank xxxxxx to $F400 1 0 switch a 1K ROM bank xxxxxx to $F800 1 1 switch a 1K ROM bank xxxxxx to $FC00 RAM switching (write of segment+bank number to $3E) with D7D6 upper 2 bits of bank # indicates the destination RAM segment (0-3, corresponding to $F000, $F400, $F800, $FC00). Can handle 64 x 512 byte RAM banks (32K total) D7 D6 D5D4D3D2D1D0 0 0 x x x x x x switch a 512 byte RAM bank xxxxxx to $F000 with write @ $F200 0 1 switch a 512 byte RAM bank xxxxxx to $F400 with write @ $F600 1 0 switch a 512 byte RAM bank xxxxxx to $F800 with write @ $FA00 1 1 switch a 512 byte RAM bank xxxxxx to $FC00 with write @ $FE00 Please, let me know if anything is not clear. 1 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.