Conditional termination ----------------------- In machine code: ; NC=continue, C=stop CALL C,&0008 ; RST &08,OK DEFB &FF ; or RST &38 If carry is set, ERROR is called with a inline byte of &FF which stops execution with an 0 OK error. If carry is clear, the call is ignored and the inline &FF byte is executed as a RST &38 which just runs an extra interupt call. The condition code can be changed to whatever the code needs. Other one-byte opcodes that don't have an effect on the executing code can also be used to terminate with a specific error. For example: CALL C,&0008:DEFB &00 ; NOP or 1 NEXT without FOR CALL C,&0008:DEFB &14 ; DEC D or L BREAK into program Keypress beep ------------- BEEP 0.0005,34.35 gives default PIP key beep. BEEP (1+PEEK23209)*0.0005,34.35 gives PIP key beep. Using integers: BEEP 1/2000,3435/100. In machine code: LD D,0 LD E,(IY-1) or LD DE,0 for default LD HL,&00C8 CALL &03B5 Load from current device ------------------------ LET f$="filename" LET d=PEEK 23766:CLOSE#0:IF PEEK 23734=244 THEN LET d=0 IF d=0 THEN LOAD f$ IF d>0 THEN LOAD "m";d;f$ Setting SCRCT ------------- Setting SCRCT at 23692 to a number larger than 1 prevents the 'Scroll?' prompt. The usual method is to regularly poke it with LD A,255:LD (SCRCT),A but a more efficient method is SET 7,(IY+82) or LD (IY+82),255. This sets SCRCT to some number larger than 127, without changing A, and in only four bytes instead of five. Using MEMBOT calculator workspace --------------------------------- There are 30 bytes of memory at 23698-23727 (&5C92-&5CAF) that are used in calulations to store intermediate values. If you are not doing any calculations then this area is unused and can be usefully used as temporary workspace. For instance you can set a temporary stack to 23728 (&5CB0) and have space for 10 stacked items (plus 5 used by the standard interupts). This can be useful for for a temporary stack while loading data where the data may overwrite the main stack. The ROM screen driver uses MEMBOT to create the mosaic bitmaps for CHR$128 to CHR$143. INKEY with key repeat --------------------- INKEY$ reads directly from the keyboard without waiting. This makes it slightly fiddly to use for normal keypress input. Initially, you would think that PAUSE 5:LET k$=INKEY$ would replicate the normal INPUT keypress input, using the default of 5/50th second key repeat. It does, but the normal INPUT keypress has an initial delay. PAUSE 5 waits 5/50th second only if there is no key being pressed. However, PAUSE 0:LET k$=INKEY$ waits forever or until a keypress, and the keypresses are processed with the same process as the INPUT keypresses, so the following code: 100 PAUSE 0:LET k$=INKEY$:IF k$="" THEN GOTO 100 110 PRINT k$;:GOTO 100 takes input with the same intial repeat delay and key repeat as when reading keypresses with INPUT. Machine code in printer buffer ------------------------------ ORG 23296 .L23296:DEFB 0 ; Parameter 1 .L23297:DEFB 0 ; Parameter 2 .L23298:DEFB 0 ; Parameter 3 .L23299:DEFB 0 ; Parameter 4 .L23300:JP Entry1 ; Entry point 1 .L23303:JP Entry2 ; Entry point 2 .L23306:JP Entry3 ; Entry point 3 etc. This makes entry addresses at useful fixed offsets from 23300. For example: ORG 23296 .L23296 :DEFW 0 DEFW 0 .L23300 :JP TapeInfo .L23303 :JP TapeLoad .L23306 :JP TapeSave .TapeInfo ; blah blah In BASIC LET bc=USR 23300:REM Display tape info LET bc=USR 23303:REM Save data to tape etc. Reading FRAMES counter without interuption ------------------------------------------ From Uwe Geiken There is a wonderful way to measure time intervals up to 21.8 minutes. Until now I used a user defined function FN T() to get the number of frames (=0.02s) since the last reset. But Slavo reminded me, that there could occur an error in some cases. So I researched the ROM, where the FRAMES variable is used, and strangely it was only twice. Once in the 'maskable interrupt' routine itself and once in the RANDOMIZE routine. Luckily in end part of the routine the last two bytes of FRAMES are loaded into the BC register, which allows to make a USR call with the result of BC. (The routine stores the value into the SEED variable, but that does not matter here.) The program part, that is to be measured, should be bracketed in two calls of the routine: ... 100 LET t=USR 7766 ... part to be measured ... 280 LET t=USR 7766-t:LET t=t+(65536 AND t<0) 290 PRINT "time: ";t/50;" s" ... The correction in line 280 is necessary, if a carryover to the third byte of FRAMES happened. So there is no need to make a sometimes faulty DEF FN T(). The only drawback I can think of would be a program depending on a special SEED value. In this case the RANDOMIZE statement should be put directly after line 100. I searched the internet for the use of USR 7766, but I found only examples to use a simple RANDOMIZE, e.g. in the one-liner game "ChamberMaze". Perhaps this method is general knowledge for you, but this method is new to me. If you know an article (books, magazines or internet), where it is already used, please let me know! Simple very big text -------------------- FOR a=64 TO 71:POKE 23681,a:LPRINT "hello":NEXT a This works by redirecting the printer PRCC to the screen memory.