Jump to content

bogax

Members
  • Content Count

    902
  • Joined

  • Last visited

Everything posted by bogax

  1. There's a typo ldx #0 txa Clear dex txs pha bne Clear ... I believe that should be 'since the txs and pha don't affect the flags,'
  2. Basically, any instruction that affects the contents of A, X or Y will set the N and Z flags accordingly. Also inc, dec, shift memory. If you need the flag later you can push the status register to the stack and pull it later. So if you dey and don't do anything that affects N or Z they'll reflect what the dey did untill you do do something that affects N or Z. If you dey then ldx they now reflect the effects of ldx. and, of course, there are instructions that don't affect the registers but do affect the flags, compare instructions, bit, plp, rti
  3. 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
  4. I see I goofed that comment up. Perhaps it would be better phrased like this lsr ; 000000A E Z flag will be set if F and S =0
  5. I'm still not sure if that's even close to what you want, but just for the hell of it I tryed to see how many cycles I could squeeze out of that preamble to the loop. This is the best I could come up with. If we can assume that bit 0 of FrameNum will always =0 and noting that if we add two bits (call them F, S) the sum is F eor S and the carry is F and S lda POslot ; xxxxxxS ? S=bit 0 of POslot and #$01 ; 000000S ? ora FrameNum ; xxxxxFS ? F is bit 1 of FrameNum. assumes bit 0 of FrameNum always =0 and #$03 ; 00000FS ? lsr ; 000000F S adc #$00 ; 00000AE 0 add S to F the sum, E, is F eor S the carry out, A, is F and S lsr ; 000000A E Z flag =0 for F and S =0 php lda #$FF adc #$00 ;if the carry is 1 the result will be $00 else $FF ldx POshift eor MaskTable,x tay ldx #$15 .LOOP tya and P0buffer,x sta P0buffer,x dex bpl .LOOP plp beq .SKIP inc POslot .SKIP rts Maybe I was wrong and it can't be streamlined much Only saves four cycles. Not sure it's worth it, apart from requiring bit 0 of FrameNum to be 0 its less obvious what's going on. But since you wanted to minimize cylces, there it is.
  6. I'm just looking at your routine I don't know enough about the context it's in to tell if my assumptions are correct so let me show you my reasoning. First I'm assuming that the FrameNum is multiplied by two so that if bit one of FrameNum is set it's an odd frame and you want to and with 10 binary ldy P0shift ;Sprite shift amount ldx MaskTable,Y ;Get proper bit masking by shift amount ldy Counter ;Fetch sprite index 15 to 0 lda P0buffer,Y ;Get sprite data to work on sax P0buffer,Y ;Apply mask and save new data lda #$FF ;Compare value, needed for addressing a 0 index? dcp Counter ;Decrement and compare bne .MaskN ;More sprite data to work on? Assuming POshift doesn't change during the loop you can pull that lookup out of the loop. I'd just stick the mask in y for quick access Now you don't need to use x in the loop so why not use x for Counter? Something like: ldx POshift ldy MaskTable,x ldx #$15 .LOOP tya and P0buffer,x sta P0buffer,x dex bpl .LOOP The mask needs to be inverted if POslot and FrameNum are either both odd or both even. you can get that by eoring them. lda FrameNum lsr eor POslot lsr ;carry will be 0 if FrameNum and POslot are the same lda #$FF adc #$00 ;add that to $FF a will be 00 if carry was 1 and $FF if carry was 0 ldx POshift eor Masktable,x tay Need a flag if FrameNum and POslot are both odd so we will know to increment POslot. Here's one way: lda FrameNum lsr and POslot lsr ;carry is one if both were odd php ;stash it on the stack for later So you'd end up with something like this: lda FrameNum lsr and POslot lsr ;carry is one if both were odd php ;stash it on the stack for later lda FrameNum lsr eor POslot lsr ;carry will be 0 if FrameNum and POslot are the same lda #$FF adc #$00 ;add that to $FF a will be 00 if carry was 1 and $FF if carry was 0 ldx POshift eor MaskTable,x tay ldx #$15 .LOOP tya and P0buffer,x sta P0buffer,x dex bpl .LOOP plp bcc .SKIP inc POslot rts .SKIP I hope I got that all correct at least you should get an idea of what I'm suggesting. I expect that could be streamlined some. Obviously it's untested.
  7. For the first 16 values of FrameNum ie 0-15, if you and with decimal 10 you take the beq branch when FrameNum 0,1,4,5 the rest fall thru and that repeats for every subsequent 16 values. That doesn't look like odd frames to me except for the first 8 ie 0-7 The odd frames fall thru.
  8. Having looked a little closer It looks to me like all those loops are basically the same If you have an even slot and an even frame or if you have an odd slot and an odd frame you invert the mask. If you have an odd slot and an odd frame you inc POslot. You mention reverse order but I don't see any reverse order. I assume you want this as fast as possible, looks like there's stuff you could pull out of the loops. eg POshift doesn't change. (does it?)
  9. Not sure why you count each frame twice, but this should read AND #%10. OH, duh! (palm-to-forehead) (I've been wracking my brains trying to figure that one out)
  10. I just gave it a cursory look and am not really sure what you're doing so sorry if this is non sequitor The only difference I see between MaskR2 and MaskR is the inc POslot instruction at the end so the obvious thing would be to set a flag and inc or not depending on the flag or possibly set an increment value of 0 or 1 (if you need constant time) EvenSlots: ;Slots 0,2,4,6,8,10 in GFXoutput ;This was tricky, since I have to know which frame I am on for correct masking order lda FrameNum ;Load current frame number and #10 ;Frame counts 0,2[,4,6 in my 4 frame kernal], so AND with #10 to determine even/odd frames beq .MaskR ;CHANGE PLACES! Mask in reverse order This seems to be intended to differentiate between odd and even frames in which case you need to and #01 .MaskN ;Mask Normal order ;Data used in Frame1 ldy P0shift ;Sprite shift amount ldx MaskTable,Y ;Get proper bit masking by shift amount ldy Counter ;Fetch sprite index 15 to 0 lda P0buffer,Y ;Get sprite data to work on sax P0buffer,Y ;Apply mask and save new data lda #$FF ;Compare value, needed for addressing a 0 index? dcp Counter ;Decrement and compare bne .MaskN ;More sprite data to work on? rts ;Done, return The sax I'm (not really) familiar with takes an immediate value. so sax P0buffer,Y makes no sense to me. Counter starts out positive and counts down so bpl should do ie dec Counter, bpl .MaskN and you can leave out the lda #$FF assuming you don't need a to be $FF for some other reason (and obviously Counter will be $FF when you fall through the bpl)
  11. I don't think you need that first and eg .RORa lda SPRITE,x ; ? abcdefgh ror ; h ?abcdefg eor SPRITE,x ; h xxxxxxxx and RorAndTbl,y ; h 0000xxxx eor SPRITE,x ; h abcddefg ror ; g habcddef ror ; f ghabcdde ror ; e fghabcdd ror ; d efghabcd an alternative lda SPRITE,x ; ? abcdefgh and RorAndTbl,y ; ? abcd0000 clc adc SPRITE,x ; a bcd0efgh ror ; h abcd0efg ror ; g habcd0ef ror ; f ghabcd0e ror ; e fghabcd0 ror ; 0 efghabcd of course you have to invert the mask(s) and if you know the carry will be clear you could leave out the clc and possibly gain a couple cycles for rol lda SPRITE,x ; ? abcdefgh asl ; a bcdefgh0 adc #$80 ; b ?cdefgha rol ; ? cdefghab ie three cycles per bit if you do them in pairs but I think you'd need a seperate routine for an odd number of bits
  12. bogax

    Macros

    It might be worth pointing out that there's a reason for using eg *4*4 instead of *16
  13. bogax

    Macros

    Finally installed bB macro set_hi_nibble {1}=(({2}*4*4^{1})&$F0)^{1} end Compiles just as one would hope .L00 ; macro set_hi_nibble MAC set_hi_nibble .L01 ; {1} = ( ( {2} * 4 * 4 ^ {1} ) & $F0 ) ^ {1} ; complex statement detected LDA {2} asl asl asl asl EOR {1} AND #$F0 EOR {1} STA {1} ENDM
  14. bogax

    Macros

    Oh, OK, I get it def is a simple substitution so that that expands to something like: callmacro set_lo_nibble a 5 The def statement supplies the first parameter and you supply the second where you invoke the def'd name.
  15. bogax

    Macros

    I'm getting lost. Here's an excerpt of the code from: http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#nybblemethis rem **************************************************************** rem * Reusable macros for nybble variables. rem * macro set_lo_nibble {1}={1}&$F0 {1}={1}|({2}&$0F) end macro set_hi_nibble asm lda {1} and #$0f sta {1} lda {2} asl asl asl asl ora {1} sta {1} end end rem **************************************************************** rem * One variable is split into two thanks to rem * macro and def. rem * def PEEK_Game_Level=a&$0F def POKE_Game_Level=callmacro set_lo_nibble a def PEEK_Hit_Points=a/16 def POKE_Hit_Points=callmacro set_hi_nibble a That looks to me like set_lo_nibble and set_hi_nibble both want two parameters and are both only being passed one, am I missing something? If you use exclusive or to swap in nibbles you'll only get the bit's you mask for, So I'd (re)write RevEng's code like this: macro set_hi_nibble asm lda {2} asl asl asl asl eor {1} and #$F0 eor {1} sta {1} end end It might even be possible to write something that swapped different nibbles depending on a parameter (I haven't tryed, didn't seem worth it) I haven't figured out when and where bBasic will choke on complex expressions. If bBasic fails to recognize powers of 2 greaer than 3, would something like this work (again using an xor swap) (1)=(2)*4*4^(1)&$F0^(1) (I don't know how many parentheses you'd have to stick in there to get the order of execution right or if that would make bBasic choke)
  16. Not sure I understand maybe this will help A eor A = 0 A eor 0 = A so A eor B eor A = B so you've got two bytes (letters are nibbles) ab, cd lda ab ; the byte containg ab eor cd ; the byte containg cd and #$F0 ; the high nibble of the accumulator is a eor c the low nibble is 0 eor cd ; the high nibble is a eor c eor c = a the low nibble is 0 eor d ; that is, the accumulator is now ad
  17. I don't understand them thar big words, but I am trying to add 10, then 15, then 20, then 25, then 30, then 35, and so on. Thanks. It's probably nothing The score goes up proportional to the square of the number of bonuses you get so it's going to go up fast. Potentially the first points you score could be microscopic compared to the last points you score. Since you limit it to 7 it's not going to get too far out. You know what you want and I don't so take this with a grain of salt, but I would have guessed that a smaller increment for "a" and a larger limit would work better. (And I'm not at all sure I know what's going on with game play so like I said a grain of salt ie I'm probably speaking out of turn, it's just my gut reaction to the numbers)
  18. Oops, I think I misunderstood what you're doing here. This should be done *after* adding to a, correct? Correct but like I said it's only sure to work if there's no carry out from a digit, which can't happen if what you add <= 6 it should always result in a BCD compliant number but it may not be the right number if you add more than 6 to a digit.
  19. I may be completely off here because I get 180 not 175 so maybe I don't understand what you're doing. Assuming "a" and "score" both start at 0 and both are BCD, 65 looks like 41 BCD so the last "a" you add to "score" will be 40 and by that time "score" will be 180 ie presummably the IF statement does't know the difference and just treats both as straight binary. btw you do know that accumulating a constant in "a" then accumulating "a" in "score" will make "score" go up quadratically (graph "score" and it will be parabolic)
  20. I don't know what you're doing but making sure "a" is BCD compliant may not be enough. You may have to make "a" BCD. That is treat, it as BCD. If you never add more than 6 to "a" then it's relatively simple, mask off the digits individually and test if they're greater than 9 and if a digit is greater than 9 add 6 to it, starting with the ones digit. If you add more than 6 it starts getting messy. If you do add more than 6 there's the possibility of a carry out of the ones digit which you'd have to detect independent of what ever you add to the tens digit. Probably be easiest to treat the digits seperately, ie add the digits one at a time, add the ones digit then adjust, then add the tens digit and adjust. I'm not that familiar with batari Basic but it would be something like: if (a & $0F) > 9 then a = a + 6 if (a & $F0) > $90 then a = a + $60 Edit: That code is just to make "a" BCD compliant (it doesn't convert binary to BCD) Here's code to add "n" to "a" (I hope ) "n" doesn't (necessarily) need to be BCD (if "n" is a single hex digit 0-F it should work) Not sure if this is proper batari Basic temp = (a & $0F) + (n & $0F) : REM seperate ones digit and add them : REM result in temp so they can be : REM decimal adjusted seperately if temp > 9 then temp = temp + 6 : REM decimal adjust the ones digit a = (a & $F0) + temp + (n & $F0) : REM add it all together if a > $9F then a = a + $60 : REM decimal adjust the tens digit
  21. here's a minimum space routine (untested) sec rol ByteToSwap LOOP ror asl ByteToSwap bne LOOP
  22. enter with byte to reverse in a tables not shown code is untested tax and #$0F tay txa lsr lsr lsr lsr tax lda hi_tbl,y ora lo_tbl,x
  23. You don't need to intialize the accumulator (you're shifting it all out any way)
  24. Well, now that I think of it, shouldn't it be FASTER if you leave the constants in? [EDIT: Yes, it is.] I mucked it up some what. I have seen BASICs where it appeared that the end value expression was re interpreted each time through the loop, I couldn't remember if the CBM BASIC was one of them. However I'd expect to initialize the beginning and ending "constants" near the beginning of the program and then just use the loop as needed. As an aside on optimizing BASIC programs, it is (iirc) usually faster to use a dummy FOR-NEXT loop than a GOTO if possible. The FOR-NEXT remembers where it's supposed to go, the GOTO has to scan the line list. And there's lots of other stuff you can do. A little Googling should turn up more. Years ago I timed all that stuff on the VIC20 Some where I've got a compilation of times in "milli-jiffies" No idea where it's gotten to now though
  25. I have no doubt you'll prefer the machine code version, but you should be able to improve the BASIC by taking the constant evaluations and the redundant math out of the loop. Try this: F=55296:L=56295:FOR I=F TO L:POKE I,N:NEXT I don't recall how muti statement lines compare speed wise to going to the next line, but I'd put it all on one line just in case Also I don't think you need to get the constant out of the initial asignment of I, but I did that just in case too
×
×
  • Create New...