ScumSoft Posted April 17, 2011 Author Share Posted April 17, 2011 (edited) Thanks for the advice, I think I got it now thanks to your ideas: P0slot = 0 through 11 FrameNum = 0 or 1 for Frame1 and Frame2 ;******************************** ; [MASKING ROUTINE] ;******************************** MaskData: ldy P0shift ;[]+3 Load player shift amount ldx MaskTable,Y ;[]+4 Load mask into X ldy #15 ;[]+2 Y will be our counter for 16-bytes ;******************************** ;Choose from 4 scenarios ;Slot / Frame ;0/0 = 0 .F1SE ;0/1 = 1 .F1SO (no inc slot) ;1/0 = 1 .F1SO = Inc P0slot ;1/1 = 0 .F1SE ;******************************** lda P0slot ;[]+3 Load player GFXslot number and #1 ;[]+2 Clear all but bit 0 eor FrameNum ;[]+3 Will result in truth table above beq .doMask ;[]+2/3 Scenarios 1 and 4 ;In scenario 2 or 3 so invert mask txa ;[]+2 eor #$FF ;[]+2 tax ;[]+2 lda FrameNum ;[]+3 Test Scenario 2 or 3 bne .doMask ;[]+2/3 FrameNum = 1 = Scenario 2 inc P0slot ;[]+5 Scenario 3, INC P0slot ;[MASK BYTES] .doMask lda P0buffer,Y ;[]+4 sax P0buffer,Y ;[]+4 dey ;[]+2 bpl .doMask ;[]+2/3 rts ;[]+6 ;******************************** ; [TABLES] ;******************************** MaskTable: ;$00,$01,$02,$03,$04,$05,$06,$07 .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 What do you think? Greatly simplified from my initial posting Or did I miss something from your ideas? I am still understanding the rotate method Thomas posted, I think I've come up with a faster way to do them, but I'll see once I complete it. Edited April 17, 2011 by ScumSoft Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted April 18, 2011 Author Share Posted April 18, 2011 Okay here is the Rotate byte routine: ;******************************** ; [ROTATE ROUTINES] ;******************************** RotateBytes: lda #>Ror1 ;[]+3 Save high byte sta GENpoint+1 ;[]+3 Store in general pointer ldy P0shift ;[]+3 Load amount to rotate lda ROtableJmp,Y ;[]+4 Use shift as index sta GENpoint ;[]+3 Ready for jmp ldx #15 ;[]+2 Use counter as byte index .RORa lda P0buffer,X ;[]+4 Load Sprite byte to be rotated jmp (GENpoint) ;[]+5 Engage! ;Will have always branched by now, no need for further checks Ror4: lsr ;[]+2 bcc *+4 ;[]+2/3 ora #$80 ;[]+2 Ror3: lsr ;[]+2 bcc *+4 ;[]+2/3 ora #$80 ;[]+2 Ror2: lsr ;[]+2 bcc *+4 ;[]+2/3 ora #$80 ;[]+2 Ror1: lsr ;[]+2 bcc *+4 ;[]+2/3 ora #$80 ;[]+2 jmp .RotCont ;[]+3 Rol5: asl ;[]+2 adc #0 ;[]+2 Rol6: asl ;[]+2 adc #0 ;[]+2 Rol7: asl ;[]+2 adc #0 ;[]+2 .RotCont sta P0buffer,X ;[]+4 Store Result into 16-byte SPRITE buffer dex ;[]+2 Decrement counter bpl .RORa ;[]+2/3 Branch if more bytes to rotate rts ROtableJmp: .byte <.RORa, <Ror1, <Ror2, <Ror3, <Ror4, <Rol5, <Rol6, <Rol7 I haven't traced out the best/worst case scenarios for this yet, so it may be slower/same/faster. Just wanted to show that I am taking what was posted and learning from it. Thanks again guys as always! Here is a demo of it in action, nothing special just a 8x16 sprite you can move around of my guy with a sword. White color is drawn on Frame1 Red is drawn on Frame2 96x96 software controlled pixel playfield. SpriteTest.bin Quote Link to comment Share on other sites More sharing options...
bogax Posted April 19, 2011 Share Posted April 19, 2011 it appears there's a zp version of sax so ... ldx #$0F clc ror ;abcdefgh 0 ror ror ror sax temp ;fgh0abcd e 0000abcd adc temp ;fghabcde 0 carry zeroed for the next round 14 cycles for a 3 bit rotate plus the ldx, clc overhead probably as fast or faster to do something else for other rotates. even numbers RIGHT_4 ;12 cycles asl adc #$80 rol RIGHT_6 ; 6 cycles asl adc #$80 rol odd numbers RIGHT_5 ;10 cycles asl adc #$80 rol RIGHT_7 ; 4 cycles cmp #$80 rol Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted April 30, 2011 Author Share Posted April 30, 2011 (edited) Since I've switched over to using the DPC+ for now, I've run into a whole slew of new issues I mean fun challenges to overcome. How do I run a subroutine from another bank? I've looked around but don't understand the procedure. Switch banks then jump to routine you need? and to switch banks I have to just access the $1FFx slot the bank table has it set to? Does the bank start at the beginning, or does it continue on the same instruction count as when it was switched, e.g on PC#00E2 -> switch bank -> PC#00E2 ? Or will the PC reset to 00 and start at the top of the bank. I'm confused! [edit]Hmm found This Link which seems to have explained it pretty well. So if I wanted to access a 2k table from another bank, how would that work? Would I have to switch banks to read from it? Edited April 30, 2011 by ScumSoft Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted May 1, 2011 Share Posted May 1, 2011 Since I've switched over to using the DPC+ for now, I've run into a whole slew of new issues I mean fun challenges to overcome. How do I run a subroutine from another bank? I've looked around but don't understand the procedure. Switch banks then jump to routine you need? and to switch banks I have to just access the $1FFx slot the bank table has it set to? Does the bank start at the beginning, or does it continue on the same instruction count as when it was switched, e.g on PC#00E2 -> switch bank -> PC#00E2 ? Or will the PC reset to 00 and start at the top of the bank. I'm confused! [edit]Hmm found This Link which seems to have explained it pretty well. So if I wanted to access a 2k table from another bank, how would that work? Would I have to switch banks to read from it? DPC+ switches the cart's entire 4K memory space, so you'll need one or more bankswitching routines, and they'll need to be replicated at the same locations in all banks. I know Fred (batari) likes to use a stack/RTS method to switch banks. If you look at the "banksw.asm" code (shown below), you can see how he does it. ; every bank has this stuff at the same place ; this code can switch to/from any bank at any entry point ; and can preserve register values ; note: lines not starting with a space are not placed in all banks ; ; line below tells the compiler how long this is - do not remove ;size=32 begin_bscode ldx #$ff ifconst FASTFETCH ; using DPC+ stx FASTFETCH endif txs lda #>(start-1) pha lda #<(start-1) pha BS_return pha txa pha tsx lda 4,x ; get high byte of return address rol rol rol rol and #bs_mask ;1 3 or 7 for F8/F6/F4 tax inx BS_jsr lda bankswitch_hotspot-1,x pla tax pla rts if ((* & $1FFF) > ((bankswitch_hotspot & $1FFF) - 1)) echo "WARNING: size parameter in banksw.asm too small - the program probably will not work." echo "Change to",[(*-begin_bscode+1)&$FF]d,"and try again." endif I like to use a simpler approach, and I recently created some macros to simplify the process of calling my routines: MAC SKIP REPEAT {1} HEX 00 REPEND ENDM MAC GOTO LDY #[(>{0} & $F0) - $10] / $20 LDX #<{0} LDA #>{0} JMP Switch_and_Go ENDM MAC GOSUB LDY #[(>. & $F0) - $10] / $20 STY Return_Bank LDY #[(>{0} & $F0) - $10] / $20 LDX #<{0} LDA #>{0} JSR Switch_and_Go ENDM MAC RETURN JMP Switch_and_Return ENDM ORG $6FE6 RORG $BFE6 Switch_and_Go STX Target_Lo STA Target_Hi LDA Select_Bank,Y JMP (Target) Switch_and_Return LDY Return_Bank LDA Select_Bank,Y RTS "Target" is a two-byte variable in zero-page RAM. "Target_Lo" and "Target_Hi" simply redefine the two bytes of "Target." "Return_Bank" is a one-byte variable in zero-page RAM. So if I want to switch banks, and the routine I'm jumping to does *not* need to return to where it was called from, I can use "GOTO routine" to switch banks and jump to that routine. But if I want to switch banks and *return* later, I can use "GOSUB routine" to do that, and then use "RETURN" when I'm ready to return. The macro code assumes you've got each bank defined with its own logical address space as follows: ORG $0400 RORG $0000 INCBIN DPCplus.arm ORG $1000 RORG $1000 SKIP 128 Bank_0 ; User Code ORG $2000 RORG $3000 SKIP 128 Bank_1 ; User Code ORG $3000 RORG $5000 SKIP 128 Bank_2 ; User Code ORG $4000 RORG $7000 SKIP 128 Bank_3 ; User Code ORG $5000 RORG $9000 SKIP 128 Bank_4 ; User Code ORG $6000 RORG $B000 SKIP 128 Bank_5 ; User Code ORG $7000 RORG $D000 SKIP 128 Bank_6 ; DPC+ Display Data ORG $8000 RORG $1000 Bank_7 ; DPC+ Frequency Table ; Goes up through $83FF (The "SKIP 128" statement after each "RORG" uses the "SKIP" macro to set aside the first 128 bytes of each user ROM bank, since those bytes are used for the DPC+ registers.) Note that when you use my method, the original values of the A, X, and Y registers will be lost, so be sure to store them first if you want to get them back later. However, my "Switch_and_Return" routine leaves the X register untouched, so you could "GOSUB" to some subroutine in a given bank, store some return value in the X register, and "RETURN" to the calling location with the return value intact. Michael Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted May 1, 2011 Author Share Posted May 1, 2011 Darn I was hoping it wasn't going to be like this. Well what I wanted to do was parse a 2k table I store in another bank that holds index addresses to my framebuffer, which would realign the data linearly and simplify things. But if I have to switch banks to access the data and duplicate the parsing code, then it defeats the purpose of having this table in the first place. So I'll just sacrifice cycles and avoid the bankswitches for now. When I do bankswitch, your routines will come as a good reference. Thanks for the help Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted June 19, 2011 Author Share Posted June 19, 2011 Can I get the DPCFRACINC to increment twice per read so that it skips a byte? If not, can I get a custom DPC+.arm file that increments them twice per read? This would GREATLY simplify my custom kernals display output. Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted June 29, 2011 Author Share Posted June 29, 2011 Yes? No? Quote Link to comment Share on other sites More sharing options...
Glade Swope Posted January 20, 2014 Share Posted January 20, 2014 Alright I give. How does one implement a Jump table in 6507 code? I'd like to hold an offset like such to a table of Jumps: Offset = 0 through 3 JumpTable: jmp doThis jmp doThat jmp doSomething jmp DONTDOTHAT And I'd like to call it via jmp JumpTable,Offset to land on the right bounce. It's usually done by putting just the addresses in the table, putting one of them on the stack, and doing an RTS. Saves the jmp instruction in each entry, and it's also easier to multiply by 2 than 3. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted January 20, 2014 Share Posted January 20, 2014 Why not use jmp (ind)? Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted January 21, 2014 Author Share Posted January 21, 2014 I got an email saying that someone replied to a posting I made over two years ago >_< What I want to know is why Glade Swope is necrobumping old posts answering them. Does this new member really think we never got an answer after all this time? FYI I have a major real work deadline that is sucking all my time, otherwise I would be here working on my harmony projects. So I haven't disappeared completely again. Be back later on after work settles down Quote Link to comment Share on other sites More sharing options...
bogax Posted January 21, 2014 Share Posted January 21, 2014 Why not use jmp (ind)? and why not put the hi and lo in their own tables obviating the multiplication by two and use of the accumulator and transfer instruction to an index register and allowing tables up to 256 entries Quote Link to comment Share on other sites More sharing options...
+nanochess Posted January 21, 2014 Share Posted January 21, 2014 I figured out an scheme based in PHA/PHA/RTS TAX LDA table_high,X PHA LDA table_low,X PHA RTS Edit: just changed order of operands to the right way. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted January 22, 2014 Share Posted January 22, 2014 As Thomas said... tax lda table_lo,x sta blah lda table_hi,x sta blah+1 jmp (blah) It's quicker, and doesn't require stack -- a precious commodity. You can use any temporary zp for blah. 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 22, 2014 Share Posted January 22, 2014 True, but nanochess' takes 2 bytes less ROM, also a precious commodity 2 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted January 23, 2014 Share Posted January 23, 2014 (edited) Not at all. It's way easier to scrounge for 2 bytes of ROM than 2 bytes of stack space. You can also LDA $hotspot,X and have a program bankswitch to a dedicated routine residing in each. 4 cycles and done. No ram, and no jump. Just make sure it banks to the same address in each block. Edited January 23, 2014 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 23, 2014 Share Posted January 23, 2014 I've been reusing stack RAM as temp variables ever since Medieval Mayhem; so for me, since the stack was already allocated, the 2 byte ROM savings is nice. ; $FE - $FF stack ; reuse of stack RAM - no JSRs can be called when these are used TempInStack1 EQU $FE TempInStack2 EQU $FF For my current DPC+ with ARM projects it doesn't matter - Space Rocks uses 9 bytes of ZP RAM while Stay Frosty 2 uses 17. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted January 29, 2014 Share Posted January 29, 2014 Just found this today, for details look here. Here is the trick code: lda #$70 sta HMM0 sta HMM1 sta HMBL lda #$c0 sta WSYNC ;--------------------------------------- sta HMOVE SLEEP 5 sta HMM0 sta HMM1 sta HMBL This will triple the Cosmic Ark stars effect. Quote Link to comment Share on other sites More sharing options...
Eckhard Stolberg Posted January 30, 2014 Share Posted January 30, 2014 Here is the trick code: This will triple the Cosmic Ark stars effect. If you are triggering the Cosmic Ark effect on several or even all movable objects, wouldn't it be easier to use sta HMCLR instead, since it resets all objects at the same time? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted January 30, 2014 Share Posted January 30, 2014 Good idea. I just tried and it works! Even with all 5 objects. lda #$70 sta HMM0 sta HMM1 sta HMBL sta HMP0 sta HMP1 sta WSYNC ;--------------------------------------- sta HMOVE SLEEP 10 ; works up to 18 sta HMCLR We should test with some critical consoles. Maybe higher SLEEP values will work there. 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.