Jump to content
IGNORED

Effectus - Action! cross-compiler using Mad-Assembler (MADS)


Gury

Recommended Posts

New benchmark: countdown from 1 999 999 to 0 with display. Rounded down due multiplication.

 

ASM circa about 10 seconds

Action! (IF) circa about 29 seconds

Action! (WHILE) circa about 28 seconds

Effectus  (IF) circa about 18 seconds

Effectus (WHILE) circa about 17 seconds

 

BYTE ARRAY DL=[$70 $70 $70 $42 $E0 $00 $41 $00 $20]

BYTE
  A=$E0,B=$E1,C=$E2,D=$E3,E=$E4,F=$E5,G=$E6,RT2=$14,RT1=$13,CHBAS=$2F4

CARD SDLSTL=$230

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

PROC MAIN()
  A=2 B=10 C=10 D=10 E=10 F=10 G=10
  MOVEBLOCK($4000,$E078,88)
  CHBAS=$40
  SDLSTL=DL
  WAIT(1) RT1=0 RT2=0
  WHILE A#0 DO
    B=10
    WHILE B#0 DO
      C=10
      WHILE C#0 DO
        D=10
        WHILE D#0 DO
          E=10
          WHILE E#0 DO
            F=10
            WHILE F#0 DO
              G=10
              WHILE G#0 DO
                G==-1
              OD
              F==-1
            OD
            E==-1
          OD
          D==-1
        OD
        C==-1
      OD
      B==-1
    OD
    A==-1
  OD
  GRAPHICS(0)
  PRINTC(256*RT1+RT2)
  DO OD
RETURN

 

ASM version done by @mono

A2ML-IF.ACT A2ML-WH.ACT effectus-countdown.xex millionzch.asx millionzch.obx

Edited by zbyti
source
  • Like 1
Link to comment
Share on other sites

Action! with ML 21 seconds :D

SET $E=$2000

; INCLUDE "H6:RUNTIME.ACT"

DEFINE DEC="[$C6",CED="]"

BYTE ARRAY DL=[$70 $70 $70 $42 $E0 $00 $41 $00 $20]

BYTE
  A=$E0,B=$E1,C=$E2,D=$E3,E=$E4,F=$E5,G=$E6,RT2=$14,RT1=$13,CHBAS=$2F4

CARD SDLSTL=$230

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

PROC MAIN()
  A=2 B=10 C=10 D=10 E=10 F=10 G=10
  MOVEBLOCK($4000,$E078,88)
  CHBAS=$40
  SDLSTL=DL
  WAIT(1) RT1=0 RT2=0
  WHILE A#0 DO
    B=10
    WHILE B#0 DO
      C=10
      WHILE C#0 DO
        D=10
        WHILE D#0 DO
          E=10
          WHILE E#0 DO
            F=10
            WHILE F#0 DO
              G=10
              WHILE G#0 DO
                DEC G CED
              OD
              DEC F CED
            OD
            DEC E CED
          OD
          DEC D CED
        OD
        DEC C CED
      OD
      DEC B CED
    OD
    DEC A CED
  OD
  GRAPHICS(0)
  PRINTC(256*RT1+RT2)
  DO OD
RETURN

 

atari000.png

MAIN.ACT

Edited by zbyti
source
  • Like 1
Link to comment
Share on other sites

More machine language! Action! 12 seconds :D

SET $E=$2000

INCLUDE "H6:RUNTIME.ACT"

DEFINE DEC="[$C6",CED="]"

BYTE ARRAY DL=[$70 $70 $70 $42 $E0 $00 $41 $00 $20]

BYTE
  A=$E0,B=$E1,C=$E2,D=$E3,E=$E4,F=$E5,G=$E6,RT2=$14,RT1=$13,CHBAS=$2F4

CARD SDLSTL=$230

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

PROC MAIN()
  SETBLOCK($E0,$28,$FF)
  A=1 B=9 C=9 D=9 E=9 F=9 G=9
  MOVEBLOCK($4000,$E080,80)
  CHBAS=$40
  SDLSTL=DL
  WAIT(1) RT1=0 RT2=0
  WHILE A#$FF DO
    B=9
    WHILE B#$FF DO
      C=9
      WHILE C#$FF DO
        D=9
        WHILE D#$FF DO
          E=9
          WHILE E#$FF DO
            F=9
            WHILE F#$FF DO
              DEC G CED [$D0$FC]
              DEC F CED
              G=9
            OD
            DEC E CED
          OD
          DEC D CED
        OD
        DEC C CED
      OD
      DEC B CED
    OD
    DEC A CED
  OD
  GRAPHICS(0)
  PRINTC(256*RT1+RT2)
  DO OD
RETURN

 

atari000.png

MAIN.ACT STEPBY.XEX

  • Like 1
Link to comment
Share on other sites

Effectus with ML ~12 seconds only ~20 frames less then Action! with ML (counting in multiplication)

BYTE ARRAY DL=[$70 $70 $70 $42 $E0 $00 $41 $00 $20]

BYTE
  A=$E0,B=$E1,C=$E2,D=$E3,E=$E4,F=$E5,G=$E6,RT2=$14,RT1=$13,CHBAS=$2F4

CARD SDLSTL=$230

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

PROC MAIN()
  SETBLOCK($E0,$28,$FF)
  A=1 B=9 C=9 D=9 E=9 F=9 G=9
  MOVEBLOCK($4000,$E080,80)
  CHBAS=$40
  SDLSTL=DL
  WAIT(1) RT1=0 RT2=0
  WHILE A#$FF DO
    B=9
    WHILE B#$FF DO
      C=9
      WHILE C#$FF DO
        D=9
        WHILE D#$FF DO
          E=9
          WHILE E#$FF DO
            F=9
            WHILE F#$FF DO
              G==-1
              [$D0$FC]
              F==-1
              G=9
            OD
            E==-1
          OD
          D==-1
        OD
        C==-1
      OD
      B==-1
    OD
    A==-1
  OD
  GRAPHICS(0)
  PRINTC(256*RT1+RT2)
  DO OD
RETURN

 

atari000.png

Eff2ml+ML.eff Eff2ml+ML.xex

Edited by zbyti
counting in multiplication
  • Like 1
Link to comment
Share on other sites

Mad Pascal from DEC(1) generate proper ML DEC $XX but Action! from X==-1 always generates sec/lda/sbc/sta.

WHILE loop ML code is most of the time better in Mad Pascal then Action! WHILE loop.

 

How could we seen when I removed this quirks from Action! result was close.

 

For beginners is better to use Effectus (or Mad Pascal) then ML by hand in Action! code ;) 

Edited by zbyti
Mad Pascal
  • Like 1
Link to comment
Share on other sites

I made a mistake with ASM version of the 2miliionare ;) benchmark, millionzch.obx works without multiplication 575 frames in PAL = 11,5 seconds. Here updated scores:

 

ASM 11,5 seconds

 

Action! (IF) circa about 29 seconds

Action! (WHILE) circa about 28 seconds

Effectus  (IF) circa about 18 seconds

Effectus (WHILE) circa about 17 seconds

 

Action! (WHILE) ML circa about 12 seconds

Effectus (WHILE) ML circa about 12 seconds

 

Mad Pascal (FOR DOWNTO) ML circa about 11 seconds @tebe Great work!

 

2ml-for-ml.pas 2ml-for-ml.xex

2ml-for-ml.png

Edited by zbyti
Mad Pascal frames - screen
  • Like 1
Link to comment
Share on other sites

Last but not least, the main Action! rival, ladies and gentlemen: Quick 2.2

 

INCLUDE
[
  D:GRAPH.LIB
]
BYTE
[
  RT1=19,RT2=20
  CHBAS=756
  A=176,B=177,C=178,D=179,E=180,F=181
  G=182,N=224
]
WORD
[
  SDLSTL=560
  TMP
]

MAIN
  DATA(176)
  [
    2,10,10,10,10,10,10
  ]
  DATA(24576)
  [
    112,112,112,66,176,0,65,0,96
  ]
  BMOVE(57464,25600,88)
  CHBAS=100
  SDLSTL=24576

  N=RT2
  WHILE N=RT2
  WEND
  RT1=0
  RT2=0

  WHILE A<>0
    B=10
    WHILE B<>0
      C=10
      WHILE C<>0
        D=10
        WHILE D<>0
          E=10
          WHILE E<>0
            F=10
            WHILE F<>0
              G=10
              WHILE G<>0
                G-
              WEND
              F-
            WEND
            E-
          WEND
          D-
        WEND
        C-
      WEND
      B-
    WEND
    A-
  WEND

  MULT(RT1,256,TMP)
  ADD(RT2,TMP,TMP)

  .GRAPHICS(0)
  ?("FRAMES: ",TMP)
  WHILE 1=1
  WEND

ENDMAIN

1384 PAL frames = ~27 seconds

 

atari000.png

2ML.QIK 2ML.COM

 

And with inline ML code

676 PAL frames = ~13 seconds

 

atari000.png

2ML-ML.QIK 2ML-ML.COM

Edited by zbyti
Quick with ML
  • Like 2
Link to comment
Share on other sites

4 hours ago, Gury said:

Great tests... Quick can also be very fast.

 

Oh yes, Quick got it´s name for some reason ;) Back in the days I used it a lot as it had some advantages above ACTION!. What one can achieve with Quick shows best imho Jacobus` work. Even the big map routine, he shared some days ago with us, was done with Quick.

 

For me Quick is best choice, when you wan´t to have fast as assembler programme but easy as BASIC code.

Ok, this changed over the years - we have huge IDEs and tools on other plattforms to develop for the A8, but in the 90s this statement was 100% correct. And if you want to code native on A8 this statement still stands, at least for me.

 

... OT of ;)

Edited by pps
  • Like 2
Link to comment
Share on other sites

On 7/17/2020 at 6:11 AM, zbyti said:

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

@zbyti

Would you please explain what the asterisk (*) does in this line of Action!  code.  I recognize the format of the instruction as similar instructions appear in the runtime library but I never understood what the asterisk does.

 

Regards,

-SteveS

 

Link to comment
Share on other sites

@a8isa1 of course :]

 

If you are going to write a procedure and want to passing parameters through registers AXY (for a speed reason) or (after then variables exceeded 3 bytes) zero pages $Ax and use it with ML you must use asterisk.

I also use asterisks before procedures that do not have parameters (and local variables) because in this case generated ML code starts immediately from the body of the procedure without unnecessary JMP to procedure body, it's important if procedure runs inside big loop or if you want place procedure code exactly on address in memory you want.

 

For example:

SET $E=$2000
SET $491=$2000

PROC SET_COLBK=*(BYTE COLOUR)[$8D$1A$D0$60]

PROC MAIN()
  SET_COLBK(10)
RETURN

;---------------------------

2000: 8D 1A D0  STA $D01A   ; accumulator have a value from COLOUR, we set this in $2007
2003: 60        RTS
2004: 4C 07 20  JMP $2007   ; MAIN without asterisks have JMP to body
2007: A9 0A     LDA #$0A    ; set BYTE COLOUR for SET_COLBK
2009: 20 00 20  JSR $2000   ; call SET_COLBK
200C: 60        RTS

 

Edited by zbyti
typos
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Time to test how fast is the access to BYTE ARRAY when array index is also BYTE.

 

The guinea pig will be bubble sort ;)

 

SET $E=$2000

; INCLUDE "H6:RUNTIME.ACT"

DEFINE
  DEC="[$C6",CED="]",INC="[$E6",CNI="]",
  PHR="[$48$8A$48$98$48]",PLR="[$68$A8$68$AA$68]",
  SETVBV="$E45C",JMP="$6C"

;------------------------------------------------------------------------------

BYTE ARRAY DL=[$70$70$70$42$E0$00$41$00$20]

BYTE
  CHBAS=$2F4,LSB,MSB,
  A=$E0,B=$E1,C=$E2,D=$E3,E=$E4,
  N1=$CA,N2=$CB,I=$CC,SIZE=$CD,TMP=$CE

BYTE ARRAY SORTTABLE(255)

CARD
  VVBLKD=$224,SDLSTL=$230,OLDVBL

;------------------------------------------------------------------------------

PROC WAIT=*(BYTE F)[$18$65$14$C5$14$D0$FC$60]

PROC SETVBLK=SETVBV(BYTE WHICH,MSB,LSB)

;------------------------------------------------------------------------------

SET $E=$3000
PROC VBLANKD=*()
  PHR
  INC E CNI
  IF E=10 THEN INC D CNI E=0 FI
  IF D=10 THEN INC C CNI D=0 FI
  IF C=10 THEN INC B CNI C=0 FI
  IF B=10 THEN INC A CNI B=0 FI
  PLR
  [JMP OLDVBL]

;------------------------------------------------------------------------------

SET $E=$3100
PROC MAIN()

  GRAPHICS(0)
  TMP=255
  FOR I=0 TO 254 DO
    SORTTABLE(I)=TMP
    TMP==-1
  OD
  FOR I=0 TO 254 DO PRINTB(SORTTABLE(I)) PUT(32) OD
  WAIT(100)

  MOVEBLOCK($4000,$E080,80)
  SETBLOCK($E0,$28,$FF)
  A=0 B=0 C=0 D=0 E=0 SIZE=254
  CHBAS=$40 SDLSTL=DL OLDVBL=VVBLKD
  WAIT(1) SETVBLK(7,$30,0)

  WHILE SIZE#0 DO
    FOR I=0 TO 253 DO
      N1=SORTTABLE(I) N2=SORTTABLE(I+1)
      IF N1>N2 THEN
          SORTTABLE(I)=N2
          SORTTABLE(I+1)=N1
      FI
    OD
    SIZE==-1
  OD

  LSB=PEEK(@OLDVBL) MSB=PEEK(@OLDVBL+1)
  SETVBLK(7,MSB,LSB)

  WAIT(100)
  GRAPHICS(0)
  FOR I=0 TO 254 DO PRINTB(SORTTABLE(I)) PUT(32) OD
  DO OD

RETURN

Note that when you declare the size of the arrays when index is the BYTE size Action! works much more efficiently than with the location declaration BYTE ARRAY SORTTABLE=$5000 slow. Always better will be BYTE ARRAY SORTTABLE(254) fast.

 

bsort.gif

MAIN.ACT BSORT-FAST.XEX BSORT-SLOW.XEX

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...