<< I have this routine in FBII basic code, but is too slow for my. Everyone that made this in Asm code for my is free for a week or more at my home in Venice..... >>
While not in assembler, this should at least be a lot faster if you call it often:
LOCAL
DIM punta%
LOCAL FN nuovacolonna(punta%) '(Gcolonna$,Gpt)
SELECT PEEK (@Gcolonna$+punta%)
CASE 49 'ASCII Code for a 1
POKE (@Gcolonna$+punta%),88
CASE 88 'ASCII Code for a capital X
POKE (@Gcolonna$+punta%),50
CASE 50 'ASCII Code for a 2
LONG IF punta% < 13
POKE (@Gcolonna$+punta%),49
INC(punta%)
FN nuovacolonna(punta%)
END IF
END SELECT
END FN
The only difference is that I replaced complex string operations with simpler number compares by using PEEK to look at the contents of the string in the same way that you had been using MID$. After that, it's a lot faster to just POKE in the actual ASCII code than to use MID$. You might also want to try removing the recursive function call, but without knowing exactly what you're doing I won't mess with that.
I think the first byte of pascal string is length, so to access directly, offset must be add 1.
ex. POKE (@Gcolonna$+punta%+1),88
LOCAL
DIM punta,a$
LOCAL FN nuovacolonna(punta) '(Gcolonna$,Gpt)
adr& = @Gcolonna$+punta+1
SELECT PEEK(adr&)
CASE _"1"
POKE adr&,_"X"
CASE _"X"
POKE adr&,_"2"
CASE _"2"
LONG IF punta < 13
POKE adr&,"1"
INC(punta)
FN nuovacolonna(punta)
END IF
END SELECT
END FN
Note that you must check the length of Gcolonna and punta must be small than it.
The following code is not tested, but just compiled. It be seemed OK.
COMPILE 0,_macsbuglabels
LOCAL FN nuovacolonna(punta%)
REGISTER(a0) = @Gcolonna$
` ADD.L ^punta%,A0
` ADDQ.L #1,A0
` MOVE.B (A0),D0
` CMPI.B #49,D0
` BNE @1
` MOVE.B #88,(A0)
` BRA @EXIT
`@1
` CMPI.B #88,D0
` BNE @2
` MOVE.B #50,(A0)
` BRA @EXIT
`@2
` CMPI.B #50,D0
` BNE @EXIT
` MOVE.W ^punta%,D0
` CMPI.B #13,D0
` BCC @EXIT
` MOVE.B #49,(A0)
` ADDQ.L #1,D0
` MOVE.W D0,^punta%
FN nuovacolonna(punta%)
`@EXIT
END FN
Whoohoo, hey, I'll bite - a week in Venice? Does this include airfare? <g>
The following version of FN nuovacolonna runs 100,000 iterations in 31 ticks on my machine, as opposed to 181 ticks for the original.
LOCAL
DIM punta,a$
DIM gColPtr&, gAstrPtr&
LOCAL FN nuovacolonna(punta%) '(Gcolonna$,Gpt)
gColPtr& = @Gcolonna$
`nuovacolonna_top
` move.w ^punta%, D1
` ext.l D1
` addq.l #$1,D1
` move.l ^gColPtr&, A0
` adda.l D1,A0
` clr.w D0
` move.b (A0), D0
` cmpi.w #49, D0
` bne.s caseeightyeight
`casefortynine
` move.b #88, (A0)
` bra.s end_select
`caseeightyeight
` cmpi.w #88, D0
` bne.s casefifty
` move.b #50, (A0)
` bra.s end_select
`casefifty
` cmpi.w #50, D0
` bne.s end_select
` cmpi.w #14, D1
` bgt.s end_select
` move.b #49, (A0)
` move.w D1, ^punta%
` bra nuovacolonna_top
`end_select
END FN
Mars
This will be about 50 times as fast and you don't have to use any assembly.
LOCAL FN nuovacolonna(punta) '(Gcolonna$,Gpt)
SELECT PEEK(@Gcolonna$+punta)
CASE _"1"
POKE @Gcolonna$+punta,_"X"
CASE _"X"
POKE @Gcolonna$+punta,_"2"
CASE _"2"
LONG IF punta < 13
POKE @Gcolonna$+punta,_"1"
INC(punta)
FN nuovacolonna(punta)
END IF
END SELECT
END FN
I wonder if you really need to be using asm. Sometimes a different approach can help.
Here is a tiny little FB function that does the same thing as yours. It probably can't compete with asm, but on my machine your code took 226 ticks for 100,000 iterations. This code took 53. 8)
Unless another 15% increase in speed is essential, why mess with it?
COMPILE 0,_macsbuglabels
GLOBALS
Gcolonna$ = "1111111111111"
DEFSTR LONG
g2X1& = _"2X1 "
END GLOBALS
LOCAL FN nuovacolonna(punta)
t = PEEK(@Gcolonna$ + punta) AND 3
POKE @Gcolonna$ + punta,PEEK(@g2X1& + t)
LONG IF t = 2
LONG IF punta < 13
FN nuovacolonna(punta + 1)
XELSE
POKE @Gcolonna$ + 13, 50
END IF
END IF
END FN
This code may be very hard to understand, but if it works fast, who cares? It does work because when you AND the ascii values of "X", "1", and "2" with 3, you get 0, 1, and 2. Use these as lookups for the three replacement bytes stored in g2X1&. Then, for the single case where you don't want a replacement (former value = 2 and punta = 13), just go back and fix it! That case is rare enough not to slow things down significantly.
Hats off (once again) to Staz! Not only does his code run 45% faster than mine (which I thought was fast), it maintains the clarity of Alessandro's original and avoids the assumptions I made which might not be true (like punta will only have values of 1 to 13).
I've learned a lot from this exchange. Now I wonder what is the purpose of this blazing piece of code. It _looks_ like something for a card game.