we would like to know: is there a faster way to do it ?
* Runer112 arrives on the scene.
After hours of work and many methods tested, I have developed code for what I believe is about as fast as bitmap scrolling can get in pure Axe! For comparison, here's a table of the time the routine you posted takes (with minor fixes, because it didn't work) versus my crazy new code.
Old routine
New routine
Horizontal scroll cycles
155500
48500
Vertical scroll cycles
184000
22500
Horizontal scrolling is twice as slow as vertical scrolling in my version, but that's still more than three times faster than the old horizontal scrolling!
Source and eye candy is attached. I'll also put the SourceCoder-ized source here, look at it if you dare:
Spoiler For Axe source code (SourceCoder format):
:.ISCROLL Image scrolling test : :DeltaList(256,192)[vIMG]→ºIMG : :DiagnosticOff :FnOff :ClrDraw :Tangent({-}80→X,{-}64→Y,ºIMG) : :While 1 : DispGraph : If getKey(1) : !If Y-1<{-}128 : Y-- : Vertical - : 63:DrawY() : End : End : If getKey(2) : If X : +1→X : Horizontal + : DrawL() : End : End : If getKey(3) : !If X-1<{-}160 : X-- : Horizontal - : DrawR() : End : End : If getKey(4) : If Y : +1→Y : Vertical + : 0:DrawY() : End : End :EndIf getKey(15) :Return : :Lbl DrawY : conj(→{r1}-Y*32+ºIMG+2,{L1}+2,32) : Fill({r1}*12+{L6},12,{E}0100→{{L1}}{^r}) : Tangent(X,{r1},{L1}) :Return : :Lbl DrawR : 11+{L6}→{r3} : {E}01→{r4} : 95 : Goto Draw0 :Lbl DrawL : {L6}→{r3} : {E}80→{r4} : and 0 : Lbl Draw0 : Select(-X,{^8+ºMasks}→{r2}) : *32/256-(Y*32)+ºIMG+2 : For(64) : not({→{r1}} and {r2}-1/256) and {r4} or {{r3}}→{{r3}}+12→{r3} : {r1}+32 : End :Return : :[8040201008040201]→ºMasks
If you want to look at the disassembly of an Axe executable, I would look at it in wabbitemu's disassembler or run it through a "real" disassembler on a computer. I don't really think it's worth it to add a custom compile option targeted for Mimas, which will probably add at least a few hundred bytes to the Axe application, just for the very small subset of people who use Axe, use Mimas, and are learning z80 assembly.
Just a small optimization I see with the new Nth string command. Because you restack the return location by popping it into bc, you're already loading bc with a value that's at least $4000 for applications and at least $8000 for programs, so the ld b,h inside the loop is not necessary.
Sorry Quigibo, I have a semi-bug report with Axe Fusion already. You may have already considered both of these and purposely left these out, but I'll throw these out there just in case.
If the Axe application is not found, you may want to consider doing a bit more than just displaying the "Axe required" string. First, I think it may be a good idea to perform a B_CALL(_HomeUp) and a B_CALL(_ClrScrnFull) before the display, or the message may pop up in very strange parts of the screen and possibly not even fully display. Second, it may be a good idea to have a B_CALL(_GetKeyRetOff) after the message appears, as when run by a shell, the message only appears for a split second before control is returned to the shell and the message is overwritten with the shell's UI. The user would probably be able to see the message with neither of these "bugs" fixed, but the question is whether 9 bytes is worth the cleaner appearance. I personally think it is worth it, because the lack of these calls may make Axe Fusion programs appear somewhat unprofessional, an issue which may bother some coders who like their programs to look clean.
Those all sound like good ideas. I'm surprised I didn't think of just using the size of the appvar to determine if token replacement data exists, and if so, how much data there is. Smart thinking, and it simplifies things.
Rect() is a good amount faster at drawing horizontal or vertical lines than Line(). Pretty much, you'd only not want to use Rect() if speed is not critically important and you already use Line() in your program, but not Rect(). This would save some size by not having to include the 113-byte rectangle routine.
Well you could make it work with a variable as well, it would just have to be the 6th argument and would need a speical handler to feed into the appropriate line routine. Yes it would be fairly bloated having multiple line routines, but I think people wouldn't often be using Line() with a variable mode argument anyways. And with the upcoming Axe framework, the size wouldn't matter.
Hmm I didn't think about the buffer argument... But making it an optional 6th argument would definitely work. However, I think it would also be nice if it were allowed to be an optional 5th argument and let the parser intelligently decide if the 5th argument is a buffer or mode. If it's a constant less than the total number of modes, treat it as a mode argument and direct the parser to the appropriate-colored routine. Otherwise, treat it as a buffer argument, because you shouldn't have a constant buffer argument that's any less than 32768 anyways. If this were possible, it would probably also be nice to apply this to the Bitmap() command, and possibly a new syntax for Rect() that allows for a mode argument. That could also solve the issue of white rectangles being bloated/slow, as you could add a white rectangle routine as a mode for Rect().
And I'm not sure what you mean about the optional 0 or 1 (or a 2 perhaps for xor) argument being a weird syntax, so I can't address that. Just kidding, I just figured out what you meant. I don't see why it's that weird, the user doesn't need to know that it's really a constant that gets special-cased by the parser. It would probably seem just like the mode argument for Bitmap(), albeit possibly with different codes. And it would be pretty much exactly like how Line() works in TI-BASIC, so it should be very easy to pick up.
Just wondering, why is something like Line(X1,Y1,X2,Y2,MODE) not possible? I would imagine that, since you do have complete control to do whatever you want in the parser, you could have special-case parsing like this.
I'm pretty sure the algorithm jacobly wrote is correct for how multiplication is usually done on z80 systems. Shifting left in situations like this is usually easier and faster on the z80. What may be confusing is that the math printed out above the algorithm steps is not actually showing the algorithm, it's just showing the elementary school multiplication method in binary.
However, you are correct that the last number added to the result of the long-hand multiplication should be 11001100.
A long time ago, the ability to enter inline data was added, so you could do things like Pt-On(X,Y,[FFFFFFFFFFFFFFFF]). This is quite useful. However, inline data cannot be the operand of any math operations, like Text A+[0606060600]. Could this ability be added? I realize that you can perform math on inline data by putting the inline data first or in parentheses, but both of those are less optimized and look a bit less clean.