Author Topic: BASIC programming tips  (Read 39683 times)

0 Members and 1 Guest are viewing this topic.

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.332
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2247
  • Likes Given: 3477
BASIC programming tips
« on: 16:23, 22 May 09 »
Here are some tips to help with BASIC coding.
If anyone has anymore, please add them and I'll compile a doc for the wiki to help those who want to program in BASIC.

------
A BASIC program to load a binary file

The simplest method to load a executable binary file using BASIC is:

10 memory <addr>-1
20 load"<filename>",<addr>
30 call <execution address>

where <addr> is the load address of the binary file, <filename> is the name of the binary file and <execution address> is the address to start the program from. e.g.

10 memory &1fff
20 load"demo.bin",&2000
30 call &3a56

Here, "demo.bin" is a binary file starting at &2000 with a execution address of &3a56.

If the code above is used, the minimum memory address that the file can be loaded to is &1173, without the "Memory full" error.

The above program can be improved to allow for a lower minimum memory address:

10 openout"d"
20 memory <addr>-1
20 closeout
30 load"<filename>",<addr>
40 call <execution address>

The minimum memory address now becomes &1a0.

NOTE:

    * The name of the file in line 10 can be anything. It is never written, and the above program will function on a write protected disc

The main advantage of a BASIC program to load a binary file is:

    * If a executable binary program is RUN directly: e.g.

      RUN"demo.bin"

      Then it will be started with the firmware function "MC BOOT PROGRAM". This will reset the state of the firmware and disable the disc operating system. Therefore the selected drive and other disc operating system variables are lost.

------
A HEX loader

This document describes various methods to poke a binary program into RAM using a BASIC program.

10 addr=&4000
20 read a$
30 if a$="*" then goto 70
40 poke addr,val("&"+a$)
50 addr=addr+1
60 goto 20
70 call &4000
80 data 3e,3a,cd,5a,bb,c9,*

Line 10 defines the start address (&4000) to poke the data to. Line 20 reads a string from the current data position. Line 30 tests to see if the string is the end of data marker Line 40 converts the string to a hexidecimal value which is poked into the memory address referenced by the "addr" variable. Line 50 increments the "addr" variable, so that the next byte is poked after the previous byte. Line 60 loops back to continue reading data. Line 70 executes the program Line 80 contains the data of the program

10 for addr=&4000 to &4006
20 read a%
30 poke addr,a%
40 next
50 call &4000
60 data &3e,&3a,&cd,&5a,&bb,&c9

Line 10 defines a loop for the entire range of the binary data. Line 20 reads a number from the current data position. Line 30 pokes the number to the destination RAM address. Line 50 executes the program Line 60 contains the data of the program.

------
Anthony Jordon writes:

Here's a little teaser for your CPC brain cells.

The short routine below (which could be part of a longer program) will display on the screen the highest line number of the program currently in memory.  Can you work out how it does it?

10 REM Last
30 last%=0
40 CALL &BFFE-35, &C970,&2371,&166,&DD00,&6EDD,&ED18,&4623,&4E23,&23EB,&19EB,&A28
,&B37A,&2B56,&235E,&EB00,&1,&170,&1100,@last%
50 PRINT last%

Executioner: Yes, it places the parameters on the stack which are opcodes for the routine below, then executes the code on the stack:

.at_last
dw #01ff
db 0

.start
ld de,#0170
ld bc,#0000

.loop1
ex de,hl
ld e,(hl)
inc hl
ld d,(hl)
dec hl
ld a,d
or e
jr z,exit
ex de,hl
add hl,de
ex de,hl
inc hl
inc hl
ld c,(hl)
inc hl
ld b,(hl)
jr loop

.exit
ld l,(ix+#00)
ld h,(ix+#01)
ld (hl),c
inc hl
ld (hl),b
ret

AJ: The hex values are basically just the machine code in reverse byte order.

For more details see my article in WACCI June 1994 Issue 79 page 17.

KT: Essentially it is a way to embed small binary programs inside basic without using a data statement to poke them. The values after the call are the 16-bit numbers to poke onto the stack and are poked from left to right, but because they are put on the stack the last number ends up being on the top of the stack. Note how the 16-bit values are two opcode bytes together and are the opcodes of the function. Then the CALL executes them on the stack. BFFE is the base of the stack in BASIC, and -35 is the length of the program.

-----------

Probably an old one:
POKE 370,0 hides first line number in BASIC
POKE the other line numbers also to 0 can hide a complete BASIC program.
(GOTO / GOSUB will not work then)

You can also reverse line numbers in listing like:
20 PRINT"HELLO"
10 GOTO 20

Play around with PEEKs and POKEs
-----------
 
- BASIC puts a limit on the number of parameters to a RSX (|) command to 32.

- RSX/CALL parameters are put onto the stack, this explains why you access them in reverse order compared to how they are written in the BASIC program.
-----------
Put setup code in a seperate loader program (e.g. font setup).
-----------
RAM available to BASIC.
RAM is available from the end of the BASIC program up to HIMEM-1.
You can find HIMEM with
PRINT HIMEM
HIMEM is also defined using MEMORY command.
The following effect the amount of RAM basic can use:
- expansion roms that are connected
- using MEMORY
- using SYMBOL AFTER to define a font
- variables defined in BASIC program
-----------
Finding the memory address of a BASIC variable.
PRINT HEX$(@<var name)
e.g.
PRINT HEX$(@a%)
For strings this actually points to a "string descriptor block" which is 3 bytes long. The first byte is the length of the string.
The 2nd and 3rd bytes are the memory address of the string itself.
-----------
MEMORY command
This sets the upper limit for BASIC. After this address you can store binary code and data safely. Basic will not overwrite it.
The upper limit is now dependant on the roms that have been installed. Around &a600 is normal.
You can find this upper limit by checking HIMEM before you modify it.
NOTE: If you define a font and then change MEMORY the font will still be in it's original position and could be overwritten.
Read how to relocate the font.
-----------
Moving the font in memory:
SYMBOL AFTER 256
MEMORY <address>
SYMBOL AFTER 32
If it tells you "Out of memory" then you need to increase HIMEM.
The font ends at HIMEM.
The size of the font can be worked out as follows:
If you entered SYMBOL AFTER n:
Size of font = (256-n)*8
So font will start at HIMEM-Size of font and end at HIMEM.
The first line "SYMBOL AFTER 256" will clear all defined chars. By default BASIC is initialised with "SYMBOL AFTER 240", and attempting to do this:
MEMORY <address>
SYMBOL AFTER 32
will give an "Improper argument" error.
Then you relocate HIMEM, then you tell it the chars you want to modify.s
« Last Edit: 13:15, 17 January 16 by Gryzor »
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 15.167
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3006
  • Likes Given: 5332
Re: basic programming tips
« Reply #1 on: 12:48, 14 June 09 »
Hmmmm if this expands it would make a nice wiki article... Want me to make this a sticky topic?

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.332
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2247
  • Likes Given: 3477
Re: basic programming tips
« Reply #2 on: 16:08, 24 June 09 »
Hmmmm if this expands it would make a nice wiki article... Want me to make this a sticky topic?
yes.

More:

- BASIC puts a limit on the number of parameters to a RSX (|) command to 32.

- RSX/CALL parameters are put onto the stack, this explains why you access them in reverse order compared to how they are written in the BASIC program.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 15.167
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3006
  • Likes Given: 5332
Re: basic programming tips
« Reply #3 on: 18:05, 24 June 09 »
Made sticky, thanks for your input. But I think it'd be better if one post only (the first one) is updated with new info instead of adding new posts?

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #4 on: 13:01, 19 August 09 »
Probably an old one:
POKE 370,0 hides first line number in BASIC
POKE the other line numbers also to 0 can hide a complete BASIC program.
(GOTO / GOSUB will not work then)

You can also reverse line numbers in listing like:
20 PRINT"HELLO"
10 GOTO 20

Play around with PEEKs and POKEs  ;)
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #5 on: 14:37, 27 July 10 »
I made up some speedy was of drawing stuff in BASIC (of course it was all based on Loops and drawing shapes like Circles), the idea was to vision the Memory as one large array just waiting to be filled. It would require two programs one which would draw the Image and Poke it to memory and the second to pull it back out of memory and draw it on screen really quickly. In the inital program to make it perform faster I wrote a simply POKE16 to POKE 16bit Numbers quickly into those memory allocations. Just making a Poke to Poke 16bit Numbers is handy in itself cause it just feels like your knocking two birds with one stone sort of thing!  ;D  Unfotunately I can't find my examples!  :(  Probably have to obtain it from my other dying computer before the HD dies!
« Last Edit: 13:37, 07 January 11 by CP/M User »
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #6 on: 15:23, 27 August 10 »
#1 Tip for people using BASIC:
 
* Never ever use "GOTO" unless you fancy a bit of Spaghetti Programming or as a Looping effect!  ;D
* Responcible "GOTOs" are possible if you keep them Local to a routine which is being applied, Bad is when a program is all over the place - moving to other sections which aren't related, or is a subroutine in which case should of been GOSUB instead!
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 15.167
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3006
  • Likes Given: 5332
Re: basic programming tips
« Reply #7 on: 10:58, 06 September 10 »
Damn, 20 years too late...

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #8 on: 12:18, 06 September 10 »
Gryzor wrote:

Damn, 20 years too late...

Heh!  ;D  I think everyone has been guilty of using GOTOs at one stage or another.  8)  I simply reduce them to what I could and was surprised by the result in the readability of my programs. Of course Amstrad Magazines like AA would try to help people understand BASIC better with Tutorials and they might have suggested to restrain using GOTOs as well, not sure if this ever came though. I simply restrain from using it as much as possible in BASIC cause I keep it to "0" GOTOs in my Turbo Pascal programs - and yes Borland were very naughty to incorporate GOTO into Turbo Pascal and some very naughty Turbo Pascal 3 website recommends the use of it!!  >:(  It should have been excluded cause it's not of a True Pascal at all!  One BASIC program I was interpreting did present a problem in TP cause of a certain GOTO in it. In the end I managed to write it with without any GOTOs by making an Array which returned the values the original program had - it was looping in such a way it was like "320 DO this : Do that : Do this as well : GOTO 320".
 
Which brings me to my next point  ;D  Having stacks of Code separated by the Colon ":"  per line is another one of those it's getting hard to read code. I guess the main problem here is for a program to be published in a Magazine, it was always better to stack in the code per line. I guess it's one of those things where if you wanted to learn some BASIC programming, nobody was around to say - just separate the code per line - you simply typed in the program and do whatever the program did. Keeping a line to a specific command is breaking the code into something more readable cause you can begin looking at the process of the program. The other thing I like is separating a BASIC program into it's own Line Numbers to give it more identity. "Renum" is sort of a enermy in a way cause a standard RENUM turns your program into that usual format of "10,20,30,40,50,etc" - Yeah sure you might have "10,20,30,40,50, etc" as your Main Nerve center of your BASIC program - the bit which runs the rest of the program, check out my Collision Detection Game for example and see how it's structured! I've set it up in such a way that it's got a main core, and then the routines are separated with the Line Numbers. This helps to define what belongs to what and kind of defines what an easy to read BASIC program should look like!  ;D  Of course over the years Magazines presented this standard way of presented programs, Authors were subjected to presenting their programs in such a way they could only cram in 255 bytes of Text per line cause it had to be a 10 Liner or because it helped to reduce space a program would take up (as in AAs case they were always on about making a program consume less space by cramming in longer BASIC lines). Though as a suggestion it maybe possible to take some of those programs and make them more readable. RENUM can be used properly when it's understood. The proper way to use RENUM is to issue a new Line number first, followed by the Old Line number and a third parameter relates to the Increment of it, so it looks like this RENUM <new line number>,<old line number>,<increment>. Just avoid the programs which have GOTO everywhere!  ;)
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.332
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2247
  • Likes Given: 3477
Re: basic programming tips
« Reply #9 on: 15:21, 21 September 10 »
Basic and using extra 128k ram:

Using OUT &7F00,&C4 or similar to change bank is not 100% safe with BASIC.
In fact, if HIMEM is between &4000 and &7fff, expect problems.

Normally you can "get away with it", if HIMEM is high (above &8000) and your basic program is small and doesn't use many variables.
You can also safely work with BASIC and banks if you set HIMEM < &3fff. But for large basic programs this is not useful.

But if your basic program is big (goes past &4000), or uses lots of variables (so fills up memory down from himem), or himem is low, you will find problems.

Basic doesn't know about the ram banking, and so if you change bank and then do something with BASIC it could read bad data and this will cause program to stop working, or work unpredictable.

So how can you solve this?

The best way is to use some assembler functions to help you to access the bank in a way that is safe for BASIC. e.g. You have control over banking, and only return back to basic when normal ram banking is set back (e.g. OUT &7F00,&C0).

Your asm code is then responsible for changing the bank to the one you want, doing some work, and then returning the banking back to normal.

Basic stores font/symbol data below himem. Then below this it stores strings and variable data.

Using these recommendations, HIMEM can be anywhere you want (sensible values), and you can still use the extra ram for data.

1. Use Bank manager. This is useful for reading/writing extra ram.

2. You need some asm/rsxs to handle your banking. You need to put this above HIMEM where BASIC can't touch it.
The asm/banking needs to be above &8000 so that it is safe when you bank memory into the range &4000-&7fff.

3. If you are loading data into the extra ram, then consider having an rsx, or asm function to do this safely:

Code: [Select]
setbank:
        ld (BuffBank),a
        and &3f
        or &c0
        ld b,&7f
        out (c),a
        ret

BuffBank: defb 0

;; CALL loadbank,<filename>,<address>,<bank>
;; e.g. a$="filename":call @a$, &4000,&c4

loadbank:   
        ;; load address
        ld l,(ix+2)
        ld h,(ix+3)
        push hl
       
        ;; string descriptor (note this is in main ram, so we can't change bank until
        ;; we have read the value. In addition cas in open needs to see it too. So either
;; copy filename to a buffer, or change bank when we read data.
;; Note, the buffer for AMSDOS or tape, needs to be above &8000. Normally for disc it is around &a700, and for tape a bit higher.

         ld l,(ix+4)
         ld h,(ix+5)
                           
         ;; length
         ld b,(hl)
         inc hl
;; address of chars in string
         ld a,(hl)
         inc hl
         ld h,(hl)
         ld l,a
         ;; address of string
        ld a,(ix+0)
        push af
;; this 2k buffer needs to be outside of &4000-&7fff. With binary it can be any value because the buffer is not used.
         ld de,&c000
         call cas_in_open
         pop af
         call setbank
         pop hl
         call cas_in_direct
         call cas_in_close

;; restore back for basic         
         ld a,&c0
         call setbank
;; return to basic
         ret

4. Any functions that access the extra ram, must set the ram bank, do some work and restore it. Remember if you are accessing any basic variables, then these are in main ram, so you need to read them and remember their data, now change banks, now work with them, and then restore bank back.

If you follow these tips your programs will work safely with basic, you can set himem as you want, and have less bugs.
 
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #10 on: 13:27, 07 January 11 »
A certain little BASIC program I'm working on (which is sadly bugged because I've tweaked it too much), had this problem where the Input from Keyboard was sluggish. I remember one of my assembly routines had a fairly fast way of testing for Keys with the use of KM TEST KEY which works for Keyboard or Joystick.
 
Code: [Select]
org &4000
 
ld a,8
call &bb1e
jr nz,left
ld a,1
call &bb1e
jr nz,right
ld a,0
call &bb1e
jr nz,jump
ld hl,value
ld a,255
ld (hl),a
ret
 
.left
ld hl,value
ld a,8
ld (hl),a
ret

.right
ld hl,value
ld a,1
ld (hl),a
ret

.jump
ld hl,value
ld a,0
ld (hl),a
ret

.value
defb 0

The result was a game running more efficiently because your character will easily move around the screen without pausing and dying in tight situations (sadly I'll have to go back to the original game so I can iron out the bugs which have got into my version). 
 
But how does this work:
 
For KM TEST KEY (&BB1E) which is rather fiddly to use in BASIC programs, you have to put the key number into the Accumulator ("A" Register), by calling KM TEST KEY if the key in the Accumulator is found a jump to a secondary routine is carried out. If that key wasn't found it will then look though the rest and if no key was pressed then in this situation it returns back to BASIC with a value of my own assigned to "value"." value" is there as a means to intergrate this routine in with the BASIC program. In this situation if a key is found it will go to that area and assign a value into "value" which can be found in BASIC by PEEKing into the memory address of "value".
 
Here's some examples - the first is some straight BASIC code which demonstrates how sluggish the INKEY$ is - perhaps there's a better way of doing it in BASIC?
 
Code: [Select]
10 MODE 1: BORDER 0:INK 1,26:x=20:y=13
11 WHILE 1
20 a$=INKEY$:oldx=x:oldy=y
30 IF a$=CHR$(242) AND x>1 THEN x=x-1
40 IF a$=CHR$(243) AND x<40 THEN x=x+1
41 IF a$=CHR$(240) AND y>1 THEN y=y-1
42 IF a$=CHR$(241) AND y<25 THEN y=y+1
50 LOCATE oldx,oldy:PRINT" ";:LOCATE x,y:PRINT CHR$(248);
60 WEND

When compared with the following program, it's quite slugglish.
 
Code: [Select]
1000 MODE 1:BORDER 0:INK 1,26:x=20:y=13
1010 WHILE 1:CALL &4000:oldx=x:oldy=y
1020 IF PEEK(&403F)=8 AND x>1 THEN x=x-1
1030 IF PEEK(&403F)=1 AND x<40 THEN x=x+1
1040 IF PEEK(&403F)=0 AND y>1 THEN y=y-1
1050 IF PEEK(&403F)=2 AND y<25 THEN y=y+1
1060 LOCATE oldx,oldy:PRINT" ";:LOCATE x,y:PRINT CHR$(248);
1070 WEND

This is the Assembly for that program above, again I've modified it to cater for the style this program is in, though the movement from it doesn't halt anywhere where compared to the first program, which makes it quite ideal for those programs which rely on quick responces.
 
Code: [Select]
org &4000
 ld a,8
 call &bb1e
 jr nz,left
 ld a,1
 call &bb1e
 jr nz,right
 ld a,0
 call &bb1e
 jr nz,up
 ld a,2
 call &bb1e
 jr nz,down
 ld hl,value
 ld a,255
 ld (hl),a
 ret
 
.left
 ld hl,value
 ld a,8
 ld (hl),a
 ret

.right
 ld hl,value
 ld a,1
 ld (hl),a
 ret

.up
 ld hl,value
 ld a,0
 ld (hl),a
 ret

.down
 ld hl,value
 ld a,2
 ld (hl),a
 ret

.value
 defb 0
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.332
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2247
  • Likes Given: 3477
Re: basic programming tips
« Reply #11 on: 13:51, 07 January 11 »
Use "INKEY" and not "INKEY$".

I looked at the dissassembly of the BASIC ROM.

"INKEY" uses BB1E/KM READ KEY.
"INKEY$" uses BB09/KM READ CHAR.

I think with KM READ CHAR you need to set the key repeat speed to make it work better (it's something I've done in one my examples).

Of course with KM READ KEY you are now using key numbers and not the char representation ;)
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #12 on: 01:07, 08 January 11 »
arnoldemu wrote:

Use "INKEY" and not "INKEY$".

I looked at the dissassembly of the BASIC ROM.

"INKEY" uses BB1E/KM READ KEY.
"INKEY$" uses BB09/KM READ CHAR.

I think with KM READ CHAR you need to set the key repeat speed to make it work better (it's something I've done in one my examples).

Of course with KM READ KEY you are now using key numbers and not the char representation ;)


That's fine if you don't despise "INKEY" - unfortunately it's been spoilt for those who dislke "INKEY"!  ???
 
Incidently I have "KM READ KEY" at "&BB1B" and not "&BB1E" which the firmware guide has as "KM TEST KEY". "KM READ KEY" reads simular to "KM TEST KEY" though it returns a character code into the accumulator if one was found, "KM TEST KEY" does not.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #13 on: 02:57, 03 July 11 »
Nich Campbell had me fascinated when I discovered the ACU 10-Liners he'd manage to convert to run on a 464 using BASIC 1.0. Back in the day I would have dug out the 6128 Emulator from AA68 and load that before loading the BASIC 1.1 program - which came in real handy particularly for the "FILL" command (wasn't as fast as the one in BASIC 1.1, though faster than whole Subroutine written in BASIC!  ;D ). Unfortunately it was to my disappointment when I first began typing in type-ins before I knew anything about BASIC 1.1.
 
I found this short program in AA21 which I thought is a good example of a BASIC 1.1 program which can easily be converted to work just as good in BASIC 1.0 (and I'd probably imagine AA might of had a few people sending in their solutions to it!):
 
Code: [Select]
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action   June 87
10 MODE 1
20 ORIGIN 320,200
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 60
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a),,1
70 DRAW 200*COS(a/2),198*SIN(a)
80 RETURN

The offender in this case is line 60 which appears to be a routine "MOVE", if you look carefully though, this "MOVE" statement is using the 4th parameter which, in BASIC 1.1 is allowed. In BASIC 1.0 "MOVE" is a two parameter command which allows you to set X & Y co-ordinates for the graphics pointer and that's it!  ;D  So addition to X & Y Coordinates in BASIC 1.1 the MOVE parameter allows you to set an INK colour which is the 3rd parameter (think of this as another way to set the Graphics PEN) & the 4th Parameter allows you to set the INK Mode. The INK Mode determine how that INK is to be written - valid parameters are 0,1,2,3 - 0 is Normal, 1 is XOR (Exclusive OR), 2 for AND & 3 for OR.
 
So in that sense if we go back to that original program all it's doing is drawing a few lines for a few steps and once a becomes greater than "-0.1" it goes to that drawing routine and does another draw over. Because that "MOVE" in line 60 is setting the INK Mode to XOR, it's writing over what's there thus removing that graphical line and carries to move on which makes it look like an image spiraling around the screen.
 
In them days AA seemed to be dazzled by some of these programs and would even break them down and explain how they worked!  :o  I guess they were looking for reader feedback so people could collect their £10!  ;D  On a 464 you could do a number of things, you could take line 40 and point it to another set of move/draw statements like this:
 
Code: [Select]
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action   June 87
10 MODE 1
20 ORIGIN 320,200
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 90
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a)
70 DRAW 200*COS(a/2),198*SIN(a),1
80 RETURN
90 MOVE 220*SIN(a/2),98*COS(a)
100 DRAW 200*COS(a/2),198*SIN(a),0
110 RETURN

which produces a similar effect in BASIC 1.0 (not the same though cause it's deleting over some of the places where the lines cross over) and is a bit slower too.
 
The better approach is to tell BASIC 1.0 to start writing in XOR mode how? Have a look at this program:
 
Code: [Select]
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action   June 87
10 MODE 1
20 ORIGIN 320,200:PRINT CHR$(23);CHR$(1);
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 60
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a)
70 DRAW 200*COS(a/2),198*SIN(a)
80 RETURN

In this example I've gone back to what appears to be the original program and have inserted a Control Code in Line 20 - it could indeed be in Line 60 though. In this case that Control Code (which works in BASIC 1.0 & BASIC 1.1), works on the Graphics Write Mode, the first character call (23) initiates the setting to call up the Graphics Write Mode, the second character call (1) is the parameter for which write mode to be used, which in this case is set to XOR. Because this program is only using one Graphics Write Mode, I've stuck this instruction in line 20 because having it being called up all the time in Line 60 will also slow the program slightly.
 
It's just amazing how a little understanding of a program like this can present a solution which would have work on all computers - in AAs case their solution was to remove the "1" from the MOVE parameter which does produce an interesting effect, though somewhat different result which had the pattern drawing over itself!  ;D
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #14 on: 06:59, 03 July 11 »
I always recall this example from AA66 which is somewhat trickier than my last example which throws more parameters into the equation:
 
Code: [Select]
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 tag:x=0:y=0
30 MOVE x,y,2,1:PRINT CHR$(255);
40 FRAME:MOVE x,y,2,1:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y,2,1:PRINT CHR$(255);
110 GOTO 40
120 FRAME:MOVE x,y,2,1:PRINT CHR$(255);
130 GOTO 40

To replicate this for BASIC 1.0 this is what I came up with:
 
Code: [Select]
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
40 CALL &BD19:MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
130 GOTO 40

In this case the original BASIC 1.1 program is using:
 
Code: [Select]
MOVE x,y,2,1
for positioning the Cursor on screen x & y are used, but then a third parameter is used to change the graphics pen ink - in that case I've initally changed the graphics pen ink:
 
Code: [Select]
PLOT -2,-2,2
since this is the only colour used for the cursor. Like the last example this program is also using XOR mode to display the cursor in such a way that it's blinking away as it loops around. In this case I've place the XOR routine:
 
Code: [Select]
PRINT CHR$(23);CHR$(1);
after the move statement, however it should work in BASIC 1.0 after the PLOT routine in Line 20 since again it's writing in the same Graphics Write Mode.
 
The original program does have some differences from the original program, the main hurdle with it is the fact the original program is drawing a redefined text character as a graphic using TAG. In order to carry out those control codes, they must be carried out while the Graphical mode is switched off, hence the need to TAG..TAGOFF when displaying that Graphical character - otherwise it won't perform those control procedures and display funny control symbols instead!  ;D
 
To carry out a FRAME in BASIC 1.0 is simply a CALL &BD19 which waits for the frame to flyback!
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #15 on: 12:04, 09 October 13 »
You should change line 100 to this:
Code: [Select]
100 MOVE x,y:LOCATE 1,1:PRINT CHR$(23);CHR$(1):TAG:PRINT CHR$(255);:TAGOFF
Otherwise you will see your screen move up after a (longer) while...
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #16 on: 12:41, 09 October 13 »
You should change line 100 to this:
Code: [Select]
100 MOVE x,y:LOCATE 1,1:PRINT CHR$(23);CHR$(1):TAG:PRINT CHR$(255);:TAGOFF
Otherwise you will see your screen move up after a (longer) while...

Isn't that what the Semi-Column does after executing the XOR Mode? I don't remember having the screen move up when I was testing it, though maybe it's a BASIC 1.1 issue?
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #17 on: 12:52, 09 October 13 »
Sure you didn't see the screen wandering up, because the ; @ end of PRINT.

In MODE 1 you have 40x25 chars (=1000)  first before the screen moves up. (Long time for testing it, you need more than 999 keystrokes until it takes effect, but it will take effect)
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #18 on: 13:20, 09 October 13 »
Sure you didn't see the screen wandering up, because the ; @ end of PRINT.

In MODE 1 you have 40x25 chars (=1000)  first before the screen moves up. (Long time for testing it, you need more than 999 keystrokes until it takes effect, but it will take effect)

Oh ok, so if there was some text on the screen for example the control codes would interfere and force it to roll up.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #19 on: 14:22, 09 October 13 »
Try this and you will see, what happens:

Code: [Select]
100 MOVE x,y:PRINT CHR$(143);CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
I added a CHR$(143) just to demonstrate it...

I did not test the code, but it should do as I expect it to do:
█  █  █  █  █... and so on....

Edit:

Well I will test it... Looks like you only need to do the PRINT CHR$(23);CHR$(1); only once... (Also the TAGON/TAGOFF)
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #20 on: 14:27, 09 October 13 »
Tested and optimized:

Code: [Select]
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline Urusergi

  • CPC6128
  • ****
  • Posts: 172
  • Country: es
  • Liked: 253
  • Likes Given: 1202
Re: basic programming tips
« Reply #21 on: 17:01, 09 October 13 »
Code: [Select]
50 a$=INKEY$
I think this line is no longer needed, isn't it? ::)
« Last Edit: 17:03, 09 October 13 by Urusergi »

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.718
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 952
  • Likes Given: 1676
Re: basic programming tips
« Reply #22 on: 05:30, 10 October 13 »
Tested and optimized:

Code: [Select]
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40

Hmmm okay, was that tested with BASIC 1.0? I'm only asking because TAG works a little bit differently in BASIC 1.0 and I had to switch it off, it looks okay because as the program is, you only need to switch on the XOR mode. Earlier I wrote WIN7.BAS which is simply this routine along with a little Icon & Message to Screen so in that case I had to switch off TAG to display those other Images.  :D
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #23 on: 12:39, 10 October 13 »
It works fine with BASIC 1.0

To make sure, you can also move in diagonal ways:

Code: [Select]
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 IF INKEY(0)=0 THEN y=y+6:p=1:IF y>398 THEN y=398
60 IF INKEY(2)=0 THEN y=y-6:p=1:IF y<16 THEN y=16
70 IF INKEY(8)=0 THEN x=x-6:p=1:IF x<0 THEN x=0
80 IF INKEY(1)=0 THEN x=x+6:p=1:IF x>630 THEN x=630
90 IF p=1 THEN p=0:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40

Edit: Now also the cursor stays in the screen bounds.
« Last Edit: 12:44, 10 October 13 by Devilmarkus »
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Offline Devilmarkus

  • Vivid source of indefiniteness
  • 6128 Plus
  • ******
  • Posts: 4.035
  • Country: de
  • WebCPC / JavaCPC developer
    • index.php?action=treasury
    • CPC-Live website
  • Liked: 1011
  • Likes Given: 926
Re: basic programming tips
« Reply #24 on: 12:48, 10 October 13 »
For oldschool reasons:

When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release