Tagged: Plus/4 Toggle Comment Threads | Keyboard Shortcuts

  • Jay Versluis 11:43 am on March 14, 2018 Permalink | Reply
    Tags: , , Plus/4, VIC-20   

    Categories: Commodore ( 26 )

    String Operations on Commodore Computers 

    Commodore BASIC has some interesting and simple string functions built in. Three of them are self explanatory: LEN, LEFT$ and RIGHT$. But others, like the mysterious MID$ and INSTR functions, are a little tricker, and I can never remember how they works.

    So here’s a quick recap on how they all work.

    LEN (A$)

    Returns the length of any given string. For example,

    a$=”the cake is a lie”

    print len (a$)

    returns 17, which is the number of characters in our string.

    LEFT$ (A$,X)

    The LEFT$ function takes the x left characters from a given string. Here’s an example:

    print left$(a$,3)

    We get “one”, because those are the 3 leftmost characters in our string a$.

    RIGHT$ (A$,X)

    Likewise, RIGHT$ takes the x right characters from any given string:

    print right$(a$,5)

    Here we get “three”, because those are the 5 right characters of a$.

    MID$ (A$,X,Y)

    MID$ is a little more complex. It takes x characters from a given string, starting at position y. Let’s look at our earlier example again:

    print mid$(a$,5,3)

    We get “two”, because those are the 3 characters, starting at position 5. The first position in all these string operations counts as one rather than zero.

    But did you know that MID$ can also be used to assign and replace different characters in a string? Consider this:

    print a$

    Now we’ve replaced the 3 characters in our string with another string, starting at position 5.

    I had no idea it cold do that! All these string operations work in all variations of the Commodore BASIC, except for the MID$ assignment which only works on the Plus/4 and the C128.


    INSTR (A$, B$)

    On the Plus/4 and C128, we can even check if one string is contained in another and at which position this occurs. Consider this:

    a$="the cake is a lie"
    print instr(a$,b$)

    In our example, INSTR returns 5 because “cake” has been found at position 5 of “the cake is a lie”.

    We can also specify a position from which the search shall be started like this:

    print instr(a$,b$,6)

    Now INSTR returns 0 because “cake” has not been found beyond position 6 of our input string.

  • Jay Versluis 11:04 pm on March 13, 2018 Permalink | Reply
    Tags: Plus/4   

    Categories: Commodore ( 26 )

    How to play sounds and music on the Commodore Plus/4 

    The Plus/4 has a total of two voices thanks to its integrated TED chip, which is also responsible for rendering text and graphics on screen. The first voice can play square waves, while the second one can generate either square wave sounds or white noise.

    Let’s see how we can make him play a tune.

    We can use some BASIC keywords to make the Plus/4 be all musical. First we need to turn up the volume by using the VOL command. We can set this to anything between 0 and 8.

    VOL 8

    Next we can use the SOUND command to make each channel play a note, like so:

    SOUND 1,400,60

    This will play a one-second long note on channel 1.

    (More …)

  • Jay Versluis 5:16 pm on January 13, 2016 Permalink | Reply
    Tags: , , Plus/4   

    Categories: Commodore ( 26 )

    How to use direct block access commands in Commodore DOS 

    Commodore-Logo-PaddedWe can access each sector’s raw data on Commodore disk drives with direct block access commands. Supported drives include the 1541, 1571, the VICE emulator as well as the SD2IEC card reader (for the most part).

    Each single sided floppy contains 35 sectors, while a double sided 1571 formatted disk contains 70 sectors. Each track contains between 17 and 21 sectors depending on how far inside or outside they are. Each sector contains 255 bytes we can read or write.

    Sectors are the same as blocks: only the directory refers to them as “blocks” and shows us how many we have available.

    We’ll need to open two channels to our disk drives: a command channel and a data channel. Here’s how to do it:
    (More …)

  • Jay Versluis 9:33 am on June 15, 2015 Permalink | Reply
    Tags: , , Plus/4   

    Categories: Commodore ( 26 )

    How to split a long string into separate words in Commodore BASIC 

    Here’s a quick word splitter routine for CBM BASIC. It takes phrase and “explodes” all words into an array, removing spaces. Feel free to adopt it for your own needs.

    10 rem word splitter
    20 rem splits a long phrase into words at a space
    30 input "tell me something";a$
    40 rem clear current array of words
    50 for i=0 to 10: wd$(i)="": next: wd=1
    60 rem detect spaces
    70 for i=1 to len(a$)
    80 wd$(0)=mid$(a$,i,1)
    90 if wd$(0)=" " then wd=wd+1: next
    100 wd$(wd)=wd$(wd)+wd$(0): next
    110 print
    120 rem print all words
    130 for i=1 to 10
    140 if wd$(i)="" then 160
    150 print wd$(i)
    160 next

    Line 50 clears an array of 10 words called WD$(n). We also setup a word counter called WD. So in this example we can only detect a maximum of ten words. If you need more, you must DIM the array first.

    Lines 70 loops through all characters in our phrase. We make use of the first element in our array WD$(0) to store each single character. If it’s a space, we’ll increase the word counter and move on to the next character. If it’s not (line 80), then we’ll add this character to the current word which is stored in WD$(WD).

    The rest of the code simply prints each word on a new line to see our handy work.

  • Jay Versluis 7:49 pm on September 2, 2014 Permalink | Reply
    Tags: Plus/4   

    Categories: Commodore ( 26 )

    Commodore Plus/4 Screen Memory Map (Display RAM) 


    The Commodore Plus/4 – like his other brothers – has memory areas in which screen characters and colour values are stored independently from each other. Because it uses the TED chip these memory addresses are different from the C64 and C128.

    Each character from the top left corner to the bottom right corner occupies one byte of memory, 40 columns across in 25 rows.

    Screen Memory

    • starts at 3072 (decimal) or $0C00 (hex)
    • ends at 4071 (decimal) or $0FE7 (hex)

    You can POKE screen display codes into each position using this formula:

    POKE 3072 + X + 40 * Y, Z
    // where 
    // X = current column
    // Y = current row
    // Z = screen display code
    // write the letter X into the top left corner of the screen
    POKE 3072, 24

    Note that there’s a difference between screen display codes (A = 1, B = 2…) and ASCII/PETSCII codes (A = 65, B = 66…). The latter are used when printing single charters via CHR$ or returning their values via ASC.


    Plus/4 Screen Memory

    Colour Memory

    • starts at 2048 (decimal) or $0800 (hex)
    • ends at 3047 (decimal) or $0BE7 (hex)

    You can POKE colour values into each cursor position using the following formula:

    POKE 2048 + X + 40 * Y, C + L * 16
    // where 
    // X = current column
    // Y = current row
    // C = colour value (0 to 15)
    // L = luminance value (0 to 7)
    // turn the character in the top left corner of the screen light red
    POKE (2048+0+0), 2 + 7 * 16
    // or
    POKE 2048, 114

    Luminance is a TED feature. It was an attempt to increase the colour palette which still only consisted of 16 colours (like on the C64) by adding brightness to each value. When compared to the “pure” 16 colours of its brothers, the Plus/4 palette looks a little weird (for example, the standard BASIC background is white according to its colour value, even though it appears to be some shade of “dirty grey”).

    You can add 128 to each value to make the character flash at the same frequency as the cursor.

    Contrary to the Plus/4 user guide, the colour values are as follows (values in brackets show the luminance variations):

    0  (16 32 48 64 80 96 112) = black
    1  (17 33 49 65 81 97 113) = white
    2  (18 34 50 66 82 98 114) = red
    3  (19 35 51 67 83 99 115) = cyan
    4  (20 36 52 68 84 100 116) = purple
    5  (21 37 53 69 85 101 117) = green
    6  (22 38 54 70 86 102 118) = blue
    7  (23 39 55 71 87 103 119) = yellow
    8  (24 40 56 72 88 104 120) = orange
    9  (25 41 57 73 89 105 121) = brown
    10 (26 42 58 74 90 106 122) = yellow-green
    11 (27 43 59 75 91 107 123) = pink
    12 (28 44 60 76 92 108 124) = blue green
    13 (29 45 61 77 93 109 125) = light blue
    14 (30 46 62 78 94 110 126) = dark blue
    15 (31 47 63 79 95 111 127) = light green

    Plus/4 Colour Memory

  • Jay Versluis 4:27 pm on September 1, 2014 Permalink | Reply
    Tags: , , Plus/4   

    Categories: Commodore ( 26 )

    The evolution of Flow Control in Commodore BASIC 

    Commodore-Logo-PaddedWhen I had a C64 back in the days, the only IF/THEN statement we could create in BASIC v2 was just that: IF and THEN.

    There was no ELSE, and everything had to be on a single line. It was the only flow control we had back in those days, and it was a severe limitation compared to what we can do with higher level languages today.

    Here’s an example:

    10 input x
    20 if x=1 then print"x is one" : goto 100

    Such constructs weren’t very convenient when you wanted to react to anything other than the tested value. Instead you had to write an IF statement for every possible other outcome which could make the code very cluttered with several GOTO statements.

    When the Plus/4 came out Commodore added the ELSE statement. It still had to be on the same line as the IF and THEN, but at least we had ELSE as an option:

    10 input x
    20 if x=1 then print "x is one" : else print "x is not one"

    ELSE needs to be on the same line as the IF/THEN statement and separated by a colon.

    ELSE was a very handy addition to the BASIC arsenal, but it still didn’t solve the problem that your evaluation had to be cramped into a single line. This was improved on the C128 with the introduction of BEGIN/BEND.

    BEGIN and BEND allowed you to execute as many lines of code as you wanted between those statements when a condition was true (or false). Used together with IF, THEN and ELSE it was a very useful thing to have:

    10 input x
    20 if x=1 then begin
    30 print "x is one"
    40 print "which is like totally awesome"
    50 rem more code here
    60 bend : else begin
    70 print "x was obviously not one"
    80 print "which is a shame"
    90 print "but that's life"
    100 bend

    BEGIN means that everything starting from now until BEND is met will be executed as part of the IF/THEN statement – as many lines of code you like.

    When BEND is met the code continues as normal – but we can also use ELSE after a colon on the same line, indicating that this is still part of the first IF/THEN statement. Here we can use BEGIN again for as many lines as we like, until we finish with BEND again.

    It was very very cool!



    sys 32800,123,45,6 to show these credits (thanks, team!)

  • Jay Versluis 1:42 pm on August 30, 2014 Permalink | Reply
    Tags: , , Plus/4, sd2iec   

    Categories: Commodore ( 26 )

    How to use SD2IEC: a quick command reference 

    Photo 28-08-2014 19 30 57
    I’ve ordered an SD2IEC a few weeks ago from Nic over at http://sd2iec.co.uk. It’s an SD card reader for Commodre computers and emulates many features of the 1541 Floppy Disk Drive.

    I went for the Limited Edition made from authentic recycled C64 plastic – so this little critter used to be a real C64! This has to be one of the coolest gadgets for any Commodore fan in the 21st century. And we know many people like gadgets of any kinds, to do many different things, that’s why we have lists of Electronics & Gadgets – Top9Rated.

    Nic and several other sellers on eBay build the hardware, while the software was developed by Ingo Korb with contributions from others. In this article I’ll explain how you can get the most out of the SD2IEC.

    Reading and Writing Files

    The SD2IEC works out of the box with standard disk commands (such as LOAD and SAVE). This will save a BASIC programme as PRG just like your Commodore would save it to floppy disk.

    You can create, switch into and remove directories on the SD card with your SD2IEC (or your “contemporary” computer of course). You can also read from and write to D64/D71/D81 image files and I’ll explain how this works further down.

    When you’re in a subdirectory (or a disk image) all read/write operations are performed there until you switch images or directories. We can do this by communicating with the SD2IEC via the command channel, as if we’re speaking to a 1541.

    Looks like the SD card is hot-swappable without the need to “safe-eject” as long as none of the lights are on, indicating read/write access.

    Speaking to your SD2IEC

    To issue commands on your SD2IEC we must open that trusty old command channel on the device (number 15), PRINT# the command and then optionally close the channel again. Here’s how to do that:

    OPEN 15,8,15
    PRINT#15,”your command here”
    CLOSE 15

    You can also write this on a single line:

    OPEN 15,8,15,”your command”:CLOSE 15

    You can also leave channel 15 open and issue more commands. Notice though that if you use any other disk command after opening channel 15 (such as LOAD or SAVE) all channels including 15 are closed automatically. Commands such as DIRECTORY do not close the channel.

    I find it helpful to add these things to one my my programmable keys (C128 and Plus/4) via the KEY command:

    // open command with trailing quotes
    KEY 1,"OPEN 15,8,15,"+CHR$(34)

    Hit F1, then type one of the commands below. If the channel is already open, simply issue the command via PRINT#15,”command”.


    The CD command lets you navigate the directory structure much like you would in Linux and Windows from the command line.

    // change into the root directory
    // enter directory “mydir” (relative to where you are)
    // enter directory “mydir” (absolute from root directory)
    // navigate up one level (like the Linux cd .. command)

    You can also create directories to stay organised without the need for other tools. That’s where the MD command comes in handy:

    // create directory in the current location
    // create directory inside another directory
    // create a directory absolute to root

    When you’re done with a directory you can delete it with RD. Note that only empty directories can be deleted, otherwise you’ll get a FILE EXISTS error:

    // remove in current directory
    // remove directory absolute to root

    Mounting Disk Images

    The CD command can also be used to mount D64/D71/D81 image files, just as if they were standard directories. The same syntax applies as with switching directories:

    // mount “myimage.d64” in current directory
    // mount “myimage.d64” in subdirectory /mydir (relative)
    // or absolute
    // unmount a disk image (go back SD card directory in which the image resides)

    You don’t have to mount disk images of course and can instead use a FAT or FAT32 formatted SD card just like it was a floppy disk. However, CBM DOS can only address a maximum of 144 files in a directory which means that a cheap 4GB SD card will be exhausted by this limitation before it’s anywhere near full.

    Changing the Device Address

    By default the SD2IEC is set to be drive number 8. But like its vintage counterpart you can change this to 9,10 or 11 using the following command:

    // change from drive 8 to drive 9
    OPEN 15,8,15
    CLOSE 15

    Replace the CHR$ value with the desired drive number. Just like a real 1541 drive, the SD2IEC will not remember this change upon reset. You can however save the above to its internal EEPROM which will survive subsequent reboots:

    // save drive number to EEPROM
    OPEN 15,9,15
    CLOSE 15

    Replace 9 with your actual drive number.


    If you encounter flashing lights on your device, then the SD2IEC is trying to tell you something. On the C128 and Plus/4 you can read out the disk error channel by looking at the DS$ system variable:

    // print disk error channel on C128 and Plus/4

    This will show you what went wrong (FILE EXISTS, FILE NOT FOUND, etc). On the C64 this is a little harder and requires you to write a small programme to read those values out. This is necessary because the INPUT# command can not be used in direct mode:

    // read disk error channel on C64
    10 open 15,8,15
    20 input#15,a,b$,c,d
    30 print a;b$,c,d
    40 close 15

    There’s a lot more you can do with this device – check out the full documentation in the README file at Ingo Korb’s website:

  • Jay Versluis 9:01 am on July 25, 2014 Permalink | Reply
    Tags: , , Plus/4   

    Categories: Commodore ( 26 )

    How to merge BASIC programmes on your Commodore C64, C128 and Plus/4 

    Commodore LogoYou can merge / combine / concatenate BASIC programmes on a Commodore computer. It’s often useful to develop shorter chunks of code and put them together for a larger app.

    Sadly there’s no built-in command that lets you do this, even though the C128 user guide hints that the CONCAT command can do this (if you’ve ever tried you know that this is not the case and only works for sequential data files).

    With a few peeks and pokes we can accomplish what we need. Here’s how:

    • after loading the fist programme, we’ll set the start of BASIC to the end of programme 1
    • then we’ll load the second programme
    • and finally return the start of BASIC to the first one

    We’re left with both programmes in memory – without any changes in line numbers. Depending on how you write the code a quick RENUMBER command may be necessary here. Even though you can run a programme when the line numbers are out of sequence, GOSUB and GOTO routines may not work as expected.

    The commands are slightly different for each machine.

    On the C64

    The start of BASIC is stored in 43/44, and ends just before the variables begin – which is stored in 45/46. Load your first programme, then type this:

    poke 44,n/256
    poke 43,n-256*peek(46)

    Load the second part, then reset the BASIC pointers to where the first part resides:

    poke 43,1
    poke 44,8

    On the Plus/4

    The Plus/4 works almost identical to the C64 in regards to storing the BASIC pointers, however the start of BASIC is at a different address. Load your first programme, then type this (just like on the C64):

    poke 44,n/256
    poke 43,n-256*peek(46)

    Load the second part, then reset the BASIC pointers:

    poke 43,1
    poke 44,16

    On the C128

    The C128 stores variables in a different memory bank. Therefore it has a dedicated pointer to the end of BASIC which is missing on the other computers. The memory map is slightly different, and the start of BASIC is stored in 45/46. Load your first programme, then type this:

    poke 46,n/256
    poke 45,n-256*peek(46)

    Load the second part, then reset the BASIC pointers:

    poke 45,1
    poke 46,28

    And there you have it! Run any of these routines right after a reset or restart.

    Thanks to Rick Kephart for this tip. You may also be interested in another (more complex) solution to this puzzle by Jim Butterfield in which he reads each byte and merges them back on disk.

  • Jay Versluis 9:20 pm on July 16, 2014 Permalink | Reply
    Tags: Plus/4   

    Categories: Commodore ( 26 )

    How to listen to your Commodore Datasette 

    datasetteDid you know that there’s a way to “listen” to a Datasette Drive, even though it’s not meant to play back the latest top twenty mixtapes?

    I’ve recently acquired a Commodore Plus/4 with 1531 Datasette. I remember having one of those in the eighties (with an adaptor to connect it to my C64 back then).

    The datasette is misbehaving, allegedly saving programmes but never loading them back in. Power is working fine, but as I no longer have a “cassette player” as such, I have no idea if it’s actually recording anything on the tape, or hearing what’s on it.

    I needed a way to playback the tape when I found this super short and very useful machine code snippet:

    0600 LDA $01 
    0602 ADC #$38 
    0604 STA $FF11 
    0607 STA $FF19 
    060A JMP $0600 

    When started with SYS 1536 the outer border of the Plus/4 will change according to what’s coming from the tape when you press play, and audio is quasi-modulated to the speaker output. It sounds rather distorted, but nevertheless you can hear what’s on the tape!

    To enter the programme, first type MONITOR which will take your out of BASIC and into the machine language monitor. Then type A 0600 followed by the first command (LDA $01). Now TEDMON will give you the next hex address, so just type the next command.

    When you’re done hit return, then type X (and return) to exit to BASIC. Here you can start the programme with SYS 1536, then PRESS PLAY ON TAPE. Enjoy!

    Note that this will not work on the C64, but you can hunt around for several “tape alignment” programmes which will work with similar principles – but I couldn’t find one for the Plus/4.

    Thanks for Marton for the code:

  • Jay Versluis 1:33 pm on July 8, 2014 Permalink | Reply
    Tags: , Plus/4   

    Categories: Commodore ( 26 )

    How to load and save binary data on the C128 and Plus/4 

    Commodore LogoThanks to BASIC 7.0’s powerful commands we can load and save arbitrary sections of memory to disk using BLOAD and BSAVE.

    This was useful for dealing with machine code as well as raw image data. Both commands work on the C128 and Plus/4, but sadly the C64 was lacking in this area.

    BLOAD and BSAVE work much like DLOAD and DSAVE with the addition that you can specify a section of memory – like this:

    // save contents of the 40 column display
    BSAVE "FILENAME", P1024 TO P2023
    // save the contents of hi-res graphics and colour separately
    BSAVE "IMAGE", P8192 TO P16181
    BSAVE "COLOURS", P7168 TO P8167
    // save graphics and colour information together
    BSAVE "FULL IMAGE", P7168 TO P16181

    BLOAD doesn’t need additional parameters and will load a file back into memory where it originally resided – just like the standard LOAD “FILE”,8,1 (with the 1 at the end). You can however provide the starting memory and make the file load somewhere else instead:

    // load file to a different place in memory
    BLOAD "FILENAME", P10000

compose new post
next post/next comment
previous post/previous comment
show/hide comments
go to top
go to login
show/hide help
shift + esc