>rbsrc   Richard Murray ( Monday, 23rd October 2000 2 <5 Based upon a game I downloaded (or cover disc?) F P? This is an attempt to 'drop' features to squish the thing Z? into 1024 bytes... The original is 1688 bytes, so we only d/ need to offload just over a third!?!? :-) n x  = &8000 + (128*1024)   $+" at "+(/10) :   code% 2048   loop% = 8 10 2  P% = code%  L% = code% + 2048  [ OPT loop%  ; Program entry  = ; R1 = memory limit, so set this to be stack pointer. E MOV R13, R1 ; *** TESTING FROM BASIC *** D STMFD R13!, {R14} ; (you must patch it out)  "( ; Set up seed to be more random. ,5 ; This will take it over the 1024 byte limit. 6 ;ADR R1, seed @' ;SWI "OS_ReadMonotonicTime" J ;STR R0, [R1] T ^8 ; Redefine character 255 to be a rounded square. h ADR R1, buffer r.chardef_loop | LDRB R0, [R1], #1  SWI "OS_WriteC"  CMP R0, #32  BNE chardef_loop   .restart B \ Program is re-entered here if user wishes to play again.  , ; Select 1, and switch off cursor.  SWI &100 + 22  SWI &100 + 1 " SWI "OS_RemoveCursors"  9 SWI &100 + 12 ; [this is needed]  , SWI &100 + 18 ; 0,2  SWI &100 + 0 & SWI &100 + 2 0 :7 ; Draw a three-sided border (left, top, bottom) D MOV R4, #0 N# ADR R5, border_commands X.border_loop bI LDMIA R5!, {R0-R2} ; Border commands are stored as data lO SWI "OS_Plot" ; to allow this to work a little faster... v ADD R4, R4, #1  CMP R4, #4  BLT border_loop  ) ; Now set up and plot the blocks.  MOV R3, #0 .block_loop  MOV R0, #31  BL random X ADD R0, R0, #4 ; Add four, to push away from the left hand border. > MOV R4, R0 ; Preserve X random in R4  MOV R0, #31  BL random > MOV R5, R0 ; Preserve Y random in R5   9 SWI &100 + 31 ; 31,,,255  MOV R0, R4   SWI "OS_WriteC" * MOV R0, R5 4 SWI "OS_WriteC" > SWI &100 + 255 H R ADD R3, R3, #1 \I CMP R3, #70 ; This is the number of blocks drawn fW BLT block_loop ; 50 is suggested minimum, 90 is suggested maximum p z& ; Draw left-hand border blocks  MOV R0, #0 .left_block_loop 6 SWI &100 + 31 ; 31,0,,255 H SWI &100 ; Which is "TAB(0,);CHR$(255);"  SWI "OS_WriteC"  SWI &100 + 255  ADD R0, R0, #3  CMP R0, #32  BLT left_block_loop  ) ; Set up floating point registers  ADR R0, acceleration 7fp("LDFS F1,[R0]") ; F1 = acceleration  MOV R0, #4 Gfp("FLTS F2,R0") ; F2 = x (nb. F3 is below) (= 4) Gfp("FLTS F4,R0") ; F4 = xs (= 4) $Gfp("MVFS F5,#0") ; F5 = ys (= 0) .Gfp("MVFS F6,#0") ; F6 = sc (= 0) 8 ADR R0, gravity B-fp("LDFS F7,[R0]") ; F7 = gr L V% ; Calculate starting position `.start_point_loop j ; Get a random offset t MOV R0, #512 ~ SUB R0, R0, #1  BL random 4 ADD R8, R0, #256 ; R8 is temp. Y , ; Read that point, and +/- 8 from it  MOV R0, #4  MOV R1, R8  SWI "OS_ReadPoint" 2 MOV R5, R2 ; R5 is x,y)  ADD R1, R1, #8  SWI "OS_ReadPoint" 4 MOV R6, R2 ; R6 is x,y+8)  SUB R1, R1, #16  SWI "OS_ReadPoint" 4 MOV R7, R2 ; R7 is x,y-8)   - ; Did all points return zero (black)?  CMP R5, #0 ( BNE start_point_loop 2 CMP R6, #0 < BNE start_point_loop F CMP R7, #0 P BNE start_point_loop Z d+ ; Get here, R8 is good for Y offset n,fp("FLTS F3,R8") ; F3 = y x / MOV R0, #4 ; 0,  MOV R1, #0  MOV R2, R8  SWI "OS_Plot"  , SWI &100 + 18 ; 0,1  SWI &100 + 0  SWI &100 + 1  .game_loop 5 MOV R0,#19 ; Wait for VSync 5 SWI "OS_Byte" ; Corrupts R1,R2  -fp("ADFS F6,F6,#1") ; sc += 1   ; Draw next bit of line "0 MOV R0, #5 ; , ,Efp("FIXS R1,F2") ; Takes X and Y from FP registers 6fp("FIXS R2,F3") @ SWI "OS_Plot" J T ; Increment offsets ^,fp("ADFS F2,F2,F4") ; x=x+xs h,fp("ADFS F3,F3,F5") ; y=y+ys r | ; Read x+xs,y) -fp("ADFS F0,F2,F4") ; F0=x+xs +fp("FIXS R0,F0") ; Get X +fp("FIXS R1,F3") ; Get Y  SWI "OS_ReadPoint" 2 CMP R2,#3 ; Colour = 3? 2fp("MVFEQS F0,F4") ; Conditional: 4fp("SUFEQS F4,F4,F4") ; xs - xs - xs =fp("SUFEQS F4,F4,F0") ; (which equals "xs=-xs") ? MOV R6, R2 ; It'll be needed later...   ; ESC pressed? E ; A useful check, but would take us over the 1024 byte limit. % ;SWI "OS_ReadEscapeState" F ;LDMCSFD R13!, {PC} ; Abort if ESC has been pressed.   ; Space pressed? & MOV R0, #121 0G MOV R1, #226 ; 98 &80, = check LY for Space. : SWI "OS_Byte" DE CMP R1, #255 ; Returns 255 if key is pressed. N:fp("ADFEQS F5,F5,F1") ; ys=ys+ X b_fp("SUFS F5,F5,F7") ; ys=ys+gr - add a little gravity into the mix! Blub! Blub! l v\ CMN R6, #1 ; If not off-screen (told you it'd be needed again!)... 3 BNE game_loop ; ...carry on.  -fp("ADFS F0,F2,F4") ; F0=x+xs +fp("FIXS R0,F0") ; Get X # ADR R2, onetwoeightzero  LDR R1, [R2] 0 CMP R0, R1 ; X < 1280? 4 BLT game_lost ; If yes, LOST! Ifp("FIXGES R8,F6") ; Else, get score (preserve in R8)...  ' ; else carry on for game won...  * MOV R0, #0 ; 3  MOV R1, #3   SWI "OS_SetColour"   - SWI &100 + 31 ; 14,8) * SWI &100 + 14 4 SWI &100 + 8 >; ADR R0, msg_well_done ; Print congratulation H SWI "OS_Write0" R \9 ADR R1, high_score ; Compare high score f LDR R0, [R1] p CMP R8, R0 z BGT new_high_score  : ; else carry on for good (not won, not lost) score  * MOV R0, #0 ; 2  MOV R1, #2  SWI "OS_SetColour"  . SWI &100 + 31 ; 14,10)  SWI &100 + 14  SWI &100 + 10  2 ADR R0, msg_score ; Print score  SWI "OS_Write0"  MOV R0, R8  BL print_binary  $* MOV R0, #0 ; 1 . MOV R1, #1 8 SWI "OS_SetColour" B L MOV R10, #12 V! B print_high_scorer ` j t ~.new_high_score T \ If user has a won, give them a message, get their name, update high score. C \ Corrupts R0-R3, and expects a value to be stored in R8. 1 \ Does not return, calls another routine.  * MOV R0, #0 ; 2  MOV R1, #2  SWI "OS_SetColour"  . SWI &100 + 31 ; 12,10)  SWI &100 + 12  SWI &100 + 10  C ADR R0, msg_new_high_score ; Print congratulatory score  SWI "OS_Write0"  MOV R0, R8  BL print_binary ( 2. SWI &100 + 31 ; 12,12) < SWI &100 + 12 F SWI &100 + 12 P Z8 ADR R1, high_score ; Update high score d STR R8, [R1] n x B new_game    .game_lost Q \ If user has a good score (not won, not lost), then give them a message.  \ Corrupts R0,R1,R10. 1 \ Does not return, calls another routine.  * MOV R0, #0 ; 1  MOV R1, #1  SWI "OS_SetColour"  - SWI &100 + 31 ; 14,8)  SWI &100 + 14  SWI &100 + 8 : ADR R0, msg_bad_luck ; Print commiseration " SWI "OS_Write0" , 6* MOV R0, #0 ; 2 @ MOV R1, #2 J SWI "OS_SetColour" T ^ MOV R10, #10 h r/ ; carry on to print out the high scorer |   .print_high_scorer D ; expects R10 to be a horizontal offset to print score at... / SWI &100 + 31 ; ,10)  SWI &100 + 14  MOV R0, R10  SWI "OS_WriteC"  2 ADR R0, msg_high_score ; Print title  SWI "OS_Write0" 9 ADR R1, high_score ; Convert high score  LDR R0, [R1]  BL print_binary  6 ; carry on to ask if user wishes to play again & 0 : D .new_game N8 MOV R0, #15 ; Flush all buffers X MOV R1, #0 b SWI "OS_Byte" l v* MOV R0, #0 ; 3  MOV R1, #3  SWI "OS_SetColour"  . SWI &100 + 31 ; 14,30)  SWI &100 + 14  SWI &100 + 30 3 ADR R0, msg_press_space ; Print prompt  SWI "OS_Write0" .await_keypress  MOV R0, #121 L MOV R1, #16 ; Skip checking for modifier keys/mouse  SWI "OS_Byte" : CMP R1, #255 ; If HING pressed... 7 BEQ await_keypress ; ...keep looping. : CMP R1, #98 ; If Space pressed... 7 BEQ restart ; ...play again... 4 LDMFD R13!, {PC} ; ...else exit. * 4 > H.print_binary R ADR R1, buffer \ MOV R2, #8 f$ SWI "OS_BinaryToDecimal" p ADR R0, buffer z MOV R1, R2  SWI "OS_WriteN"  MOV PC, R14    .random X \ Taken from the "random.s" example on the ARM development demonstration CD-ROM.  " STMFD R13!, {R1-R4, R14} ADR R4, seed_pointer  LDMIA R4, {R1, R2} 8 TST R2, R2, LSR#1 ; to bit into carry : MOVS R3, R1, RRX ; 33-bit rotate right ; ADC R2, R2, R2 ; carry into LSB of a2 0 R3, R3, R1, LSL#12 ; (involved!) : R1, R3, R3, LSR#20 ; (similarly involved!) $ STMIA R4, {R1, R2} .U R0, R1, R0 ; random number with range, and store the result 8C LDMFD R13!, {R1-R4, PC} ; in R0 ready for returning... B L V ` \ **** j \ t \ **** ~ .border_commands S \ A sequence of commands for the OS_Plot loop, to draw a three-sided border 2 EQUD 4 ; 1279,1023 : EQUD 1279 ; (move to top right)  EQUD 1023 / EQUD 5 ; 0,1023 9 EQUD 0 ; (draw to top left)  EQUD 1023 , EQUD 5 ; 0,0 < EQUD 0 ; (draw to bottom left)  EQUD 0 / EQUD 5 ; 1279,0 = EQUD 1279 ; (draw to bottom right)   EQUD 0  .onetwoeightzero ( EQUD 1280 2 <.msg_press_space F EQUS " Again? (SPC) " P EQUB 0 Z EQUB 0 d n.msg_bad_luck x EQUS "Bad luck..."  EQUB 0  .msg_well_done  EQUS "Well Done!"  EQUB 0  EQUB 0  .msg_score  EQUS "Score: "  EQUB 0  .msg_high_score  EQUS "High: "  EQUB 0  EQUB 0  ".msg_new_high_score , EQUS "New high: " 6 EQUB 0 @ EQUB 0 J T.seed_pointer ^ EQUD seed h r .seed | EQUD &55555555  EQUD &55555555   .buffer  EQUB 23  EQUB 255  EQUB 126  EQUB 255   EQUB 255  EQUB 255  EQUB 255  EQUB 255   EQUB 255  EQUB 126  EQUB 32 & EQUB 0 0 :.high_score DT EQUD 320 ; Straight line across is approx. 318 points... N X .gravity b_ EQUD &3D800000 ; FP single precision value, calculated by trial and error l v.acceleration _ EQUD &3E000000 ; FP single precision value, calculated by trial and error   ]   ap$="IDEFS::Amy.$._ENTRY.Willow.Coding.Projects.Assembler.asmarea.apcsstuff.rebound.rebound1K" /("Save "+p$+" "+~code%+" +"+~(P%-code%)) ("SetType "+p$+" FF8")  Hcode%!0 = &E1A00000 : Patch out R13 set with "MOV R0, R0" (NOP)...  REPEAT  CALL code%  IF INKEY(-3) THEN END  UNTIL 0   B "Assembled in "+(P%-code%)+" bytes, need to optimise out ";  - (((P%-code%)-1024)/4)+" instructions." * 4 > H R ݤfp(a2$) \7 i%,c$,prec%,fd%,fn%,fm%,rd%,t$,op%,addr%,a$,noch% f pM "Error during assembly of instruction """+a2$+""" : """+$+"""": z a$=a2$  prec%=0  noch%= : M a$,5)<>"CMFEQ" a$,5)<>"CNFEQ" a$,5)<>"CMFE " a$,5)<>"CNFE "  t$=a$,4)  Ȏ t$  "CMFE","CNFE": (i%=%00001110000100001111000100010000  a$=a$,5) fd%=0:fn%=1:fm%=2:rd%=0  Ȏ t$  "CMFE":op%=%110  "CNFE":op%=%111  i%=i% (op%<<21)  $ .: 8 i%=0 B t$=a$,3) L Ȏ t$ VT "ADF","MUF","SUF","RSF","DVF","RDF","POW","RPW","RMF","FML","FDV","FRD","POL": `(i%=%00001110000000000000000100000000 j a$=a$,4) tfd%=1:fn%=2:fm%=3:rd%=0 ~ Ȏ t$  "ADF":op%=%00000 $ "MUF":op%=%10010 : op%=%00010  "SUF":op%=%00100  "RSF":op%=%00110 $ "DVF":op%=%10100 : op%=%01000  "RDF":op%=%01010  "POW":op%=%01100  "RPW":op%=%01110  "RMF":op%=%10000  "FML":op%=%10010  "FDV":op%=%10100  "FRD":op%=%10110  "POL":op%=%11000   i%=i% (op%<<19) * "FLT","FIX","WFS","RFS","WFC","RFC": ((i%=%00001110000000000000000100010000 2 a$=a$,4) < Ȏ t$ F- "FLT":op%=%0000:fd%=0:fn%=1:fm%=0:rd%=2 P- "FIX":op%=%0001:fd%=0:fn%=0:fm%=2:rd%=1 Z- "WFS":op%=%0010:fd%=0:fn%=0:fm%=0:rd%=1 d- "RFS":op%=%0011:fd%=0:fn%=0:fm%=0:rd%=1 n- "WFC":op%=%0100:fd%=0:fn%=0:fm%=0:rd%=1 x- "RFC":op%=%0101:fd%=0:fn%=0:fm%=0:rd%=1  i%=i% (op%<<20)  "LDF","STF":noch%= (i%=%00001100000000000000000100000000  a$=a$,4)  Ȏ t$ ) "LDF":op%=1:fd%=1:fn%=0:fm%=0:rd%=0 ) "STF":op%=0:fd%=1:fn%=0:fm%=0:rd%=0   addr%=2  prec%=1 i%=i% (op%<<20) Z "MVF","MNF","ABS","RND","SQT","LOG","LGN","EXP","SIN","COS","TAN","ASN","ACS","ATN": (i%=%00001110000000000000000100000000  a$=a$,4) fd%=1:fn%=0:fm%=2:rd%=0 " Ȏ t$ , "MVF":op%=%0000 6 "MNF":op%=%0001 @ "ABS":op%=%0010 J "RND":op%=%0011 T "SQT":op%=%0100 ^ "LOG":op%=%0101 h "LGN":op%=%0110 r "EXP":op%=%0111 | "SIN":op%=%1000  "COS":op%=%1001  "TAN":op%=%1010  "ASN":op%=%1011  "ACS":op%=%1100  "ATN":op%=%1101  i%=i% (op%<<20) i%=i% (1<<15)  "CMF","CNF": (i%=%00001110000100001111000100010000  a$=a$,4) fd%=0:fn%=1:fm%=2:rd%=0  Ȏ t$  "CMF":op%=%100  "CNF":op%=%101  &i%=i% (op%<<21) 0 : D: N" i%=0 78,"Unknown mnemonic" X: b c$=a$,2) lW (c$,1)="S" c$,1)="D" c$,1)="E" c$,1)="P" c$,1)=" ") c$,2)<>"EQ" v*i%=i% (%1110<<28): Set AL condition   Ȏ c$  "AL":i%=i% (%1110<<28)  "CC":i%=i% (%0011<<28)  "CS":i%=i% (%0010<<28)  "EQ":i%=i% (%0000<<28)  "GE":i%=i% (%1010<<28)  "GT":i%=i% (%1100<<28)  "HI":i%=i% (%1000<<28)  "LE":i%=i% (%1101<<28)  "LS":i%=i% (%1001<<28)  "LT":i%=i% (%1011<<28)  "MI":i%=i% (%0100<<28)  "NE":i%=i% (%0001<<28)   "NV":i%=i% (%1111<<28)  "PL":i%=i% (%0101<<28)   "VC":i%=i% (%0111<<28) * "VS":i%=i% (%0110<<28) 4 "LO":i%=i% (%0011<<28) > "HS":i%=i% (%0010<<28) H#: 78,"Unknown condition code" R \ a$=a$,3) f p: z c$=a$,1)  a$=a$,2)  noch%=  prec%=0  Ȏ c$  "S": No change needed  "D":i%=i% (1<<7)  "E":i%=i% (1<<19) ( "P":i%=i% (1<<7):i%=i% (1<<19) (: 78,"Missing precision indicator"    Ȏ c$  "S": No change needed  "D":i%=i% (1<<15)  "E":i%=i% (1<<22) ) "P":i%=i% (1<<15):i%=i% (1<<22) $(: 78,"Missing precision indicator" . 8 B L: V a$,1)<>" " ` c$=a$,1) j a$=a$,2) t Ȏ c$ ~ "P":i%=i% (1<<5)  "M":i%=i% (1<<6) ' "Z":i%=i% (1<<5):i%=i% (1<<6) ': 78,"Unknown rounding attribute"   : a$=a$,2): Remove space c$=a$,a$,",")): 1st reg  a$,",")=0 c$=a$ a$=a$,a$,",")+1) l (fd%=1 fn%=1 fm%=1) c$,1)<>"F" 78,"First register must be a FP register for this instruction" [ rd%=1 c$,1)<>"R" 78,"First register must be a ARM register for this instruction" ( fd%=1 i%=i% ((fpconst(c$))<<12)  ( fn%=1 i%=i% ((fpconst(c$))<<16) $ fm%=1 i%=i% ((fpconst(c$))) ( rd%=1 i%=i% ((fpconst(c$))<<12) (: 2 addr%=2 <1 c$="[Rx]<,#offset>" or c$="[Rx,#offset]" F a$=a$,2) Pc$=a$,a$,",")-1) Z a$,",")=0 c$=a$ di%=i% (fpconst(c$)<<16) n: x a$,",")<>0  c$,1)="]"  post-index c$=a$,a$,",")+1) E c$,1)<>"#" 78,"Only constants can be specified as an offset"  c$=c$,2) 9 (c$)>1020 (c$)<-1020 78,"Offset out of range" i%=i% (((c$)) 4)  (c$)>=0 i%=i% (1<<23)   pre-index i%=i% (1<<24) c$=a$,a$,",")+1) E c$,1)<>"#" 78,"Only constants can be specified as an offset"  c$=c$,2) 9 (c$)>1020 (c$)<-1020 78,"Offset out of range" i%=i% (((c$)) 4) " (c$)>=0 i%=i% (1<<23) , a$,1)="!" i%=i% (1<<21) 6 @ J T: ^'c$=a$,a$,",")): 2nd reg OR value h a$,",")=0 c$=a$ r a$="" 78,"Not supported" |a$=a$,a$,",")+1) e (fd%=2 fn%=2) c$,1)<>"F" 78,"Second register must be a FP register for this instruction" u fm%=2 c$,1)<>"F" c$,1)<>"#" 78,"Second register must be a FP register or constant for this instruction" \ rd%=2 c$,1)<>"R" 78,"Second register must be a ARM register for this instruction" ( fn%=2 i%=i% ((fpconst(c$))<<16) $ fm%=2 i%=i% ((fpconst(c$))) ( rd%=2 i%=i% ((fpconst(c$))<<12) ' fm%=2 c$,1)="#" i%=i% (1<<3)  a$="" 78,"Not supported"  c$=a$ t fm%=3 c$,1)<>"F" c$,1)<>"#" 78,"Third register must be a FP register or constant for this instruction" $ fm%=3 i%=i% ((fpconst(c$))) ' fm%=3 c$,1)="#" i%=i% (1<<3)  : [OPT loop%  EQUD i% &] 0 PRINT :( OSCLI "MemoryI "+STR$~(O%-4)+" +4" D=0 N: X fpconst(c$) bȎ c$,1) l "#": v (c$,2))=10.0 =7  (c$,2))=0.5 =6 o (c$,2))<0 (c$,2))>5 78,"No FP constant other than 0.0,1.0,2.0,3.0,4.0,5.0,0.5,10.0 are allowed" M ((c$,2)))<>(c$,2)) 78,"No FP fraction other than 0.5 is allowed" =(c$,2))  "R": W (c$,2))>15 (c$,2))<0 78,"ARM Register references must be between 0 and 7" =(c$,2))  "F": U (c$,2))>7 (c$,2))<0 78,"FP Register references must be between 0 and 7" =(c$,2))  =0 :  dfp   "F0: ";|(fpblk+0)  "F1: ";|(fpblk+8)   "F2: ";|(fpblk+16) * "F3: ";|(fpblk+24) 4 "F4: ";|(fpblk+32) > "F5: ";|(fpblk+40) H "F6: ";|(fpblk+48) R "F7: ";|(fpblk+56) \ f: p rad z[OPT loop% adr(0,pi) fp("LDFD F5,[R0,#0]") fp("MUFD F7,F5,F7") adr(0,oneeighty) fp("LDFD F6,[R0,#0]") fp("DVFD F7,F7,F6") ] =0     MOV R0, R1  ADR R1, buffer  MOV R2, #8 & SWI "OS_BinaryToDecimal"  ADR R0, buffer $ MOV R1, R2 . SWI "OS_WriteN" 8 SWI "OS_NewLine"