Jump to content
IGNORED

Assembly questions (porting TECO to Atari)


rankeney

Recommended Posts

Back in the dawn of time (around '81-82), I wrote a n implementation of TECO (DEC's Text Editor and COrrector) for the 6502. It was written as part of an operating system I developed for the Ohio Scientific line of beasts. The OS was called GenerOS (Generic Operating System), and barely saw the light of day. Years ago I posted the source on Usenet, hoping someone would port it to Atari, Apple, Commodore or whatever, but I think it was forgotten. A few years back someone nudged me about it, hoping to port it to the Atari. No word back on that, so I thought I'd have a look at doing it myself.

 

Digging through what I can find, I've installed Altirra on my windows box and both ATASM and MADS and am looking at the next steps to take. After browsing several assembly language manuals for the Atari, I have a few starter questions that may speed my efforts. No really obvious answers have presented themselves.

  • Is there some preferred starting address for my program? It seems like the start of available memory varies depending on configuration. I'd like a fixed address, and I gather $600 doesn't assure me something else might not live there.
  • Where should I place my text editor buffer? I'd want it to be as large as possible.
  • It seems like there should be simple routines I can JSR to put a character on the screen, check for a key pressed, and return the key pressed, but I can't find them. Do I need to set up an IOCB to do all this?
  • I hear great things about MADS, but my code uses '*=addr' instead of 'ORG addr', and '.BYTE 00' instead of whatever MADS uses. Should I bother converting? I'm not using any macros or conditional compilation.

Once I get these basic things running, I should be mostly there. The only other details would be file I/O, which looks manageable.

 

Any help would be appreciated!

 

BTW, this TECO is a pretty full implementation based on TECO for the PDP-11.

See: https://en.wikipedia.org/wiki/TECO_(text_editor)

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

Have you had a look at WUDSN? Unless you badly want to program in a historical environment, WUDSN is THE choice for 2000's assembly programming. It's a plugin for Eclipse and allows assembly programming for the Ataris with all modern comforts.

 

As for "safe" memory, $600-6FF is kept (mostly) unused by BASIC and therefore used for small machine language routines called from BASIC but for a longer program you'll need to find safe memory starting at MEMLO, the value of which varies depending on the DOS used. You might want to use bank-switched memory to either increase buffer space and/or have extra space for your code.

 

AFAIK there's a way for this to work cooperatively with other programs when using SpartaDOS.

 

You can use IOCB's for input from the "K:" device and output to the "E:" device. Whether the latter works for you depends a lot on what features your editor needs.

  • Like 2
Link to comment
Share on other sites

slx - Thanks for the quick reply. It's kind of what I was expecting. FWIW, I tried WUDSN using the quick install, but it failed with some sort of java error, and I didn't bother to delve into installing it the hard way. It looks like it's got a lot of great features, but probably more than I'll need for this project.

 

I've seen references to JSR $F6E2 to get a character and JSR $F6A4 to print one, but it seems like I tried these and had no luck. I'm guessing this may be tied to having BASIC loaded. I'll go with using the IOCBs.

Link to comment
Share on other sites

In general, you want to avoid jumping directly into the OS, except for the published vectors (in the $E4xx range). Here's a general CIO primer, even if it uses BASIC syntax instead of assembly.

 

Also, at least to get started, start assembling at $2000, since that should place you above most flavors of DOS. You can reassemble it lower or higher later, once you've got it working.

  • Like 1
Link to comment
Share on other sites

Hi rankeney!

 

Back in the dawn of time (around '81-82), I wrote a n implementation of TECO (DEC's Text Editor and COrrector) for the 6502. It was written as part of an operating system I developed for the Ohio Scientific line of beasts. The OS was called GenerOS (Generic Operating System), and barely saw the light of day. Years ago I posted the source on Usenet, hoping someone would port it to Atari, Apple, Commodore or whatever, but I think it was forgotten. A few years back someone nudged me about it, hoping to port it to the Atari. No word back on that, so I thought I'd have a look at doing it myself.

 

Digging through what I can find, I've installed Altirra on my windows box and both ATASM and MADS and am looking at the next steps to take. After browsing several assembly language manuals for the Atari, I have a few starter questions that may speed my efforts. No really obvious answers have presented themselves.

  • Is there some preferred starting address for my program? It seems like the start of available memory varies depending on configuration. I'd like a fixed address, and I gather $600 doesn't assure me something else might not live there.

Yes, on the Atari OS start of available memory depends on DOS version/configuration. A safe address should be $2000, but if you don't need as much memory for your program, $3000 is better.

 

  • Where should I place my text editor buffer? I'd want it to be as large as possible.

 

This is in direct conflict with the above. If you want the text buffer to be as large as possible, there are tow possibilities:

 

1) Assume at least 48K ram and place your program at the TOP of RAM, up to $BFFF. You would need to move the screen address to bellow your program after loading, by writing to RAMTOP, closing and reopening IOCB #0. You now can use all the memory from MEMLO up to MEMTOP the for your buffer.

Sadly, this is not as easy as it seems because older OS versions will overwrite your program when clearing the screen (as the clear-screen routine has a bug that clears more memory than needed), not all values for RAMTOP are valid (depending on graphics mode the value should be aligned to 1k or 4k), and to reliably change RAMTOM you need to wait for a VBI to occur.

 

2) Use a split buffer. Simply load your program at an address "high enough", for example $3000, and use two buffers: from MEMLO to start of your program, and from end of your program to MEMTOP. This is a lot simpler and more compatible, but you have to deal with the two buffers with a hole in the middle.

 

3) Simply use a low enough load address (like $2000) and use as buffer the memory from the end of your program to MEMTOP. This is the simpler, but you loose all free memory before tour program, this could be up to 4K in SpartaDOS-X.

 

 

  • It seems like there should be simple routines I can JSR to put a character on the screen, check for a key pressed, and return the key pressed, but I can't find them. Do I need to set up an IOCB to do all this?

 

If you want to reliably read from keyboard / write to screen, you must use CIO. But, you don't need to call OPEN/CLOSE for each operation, you can use the ICPT (IOCB PUT VECTOR) directly to write one character to the screen, and most programs call the GET vector for the keyboard handler directly, like:

.proc   putchar
        tya
        ldx     #0        ; IOCB #0
        lda     ICAX1, x
        sta     ICAX1Z
        lda     ICPTH, x
        pha
        lda     ICPTL, x
        pha
        tya
        rts
.endproc

.proc   getkey
        lda     KEYBDV+5
        pha
        lda     KEYBDV+4
        pha
        lda     #12
        sta     ICAX1Z
        rts
.endproc
Sadly, the OS put-char routine is rather slow and can't write reliably to the last column of the screen (as tend to scroll-down the rest of the text). The editor included in my FastBasic uses only OS calls to write the screen and is a little slow.

 

 

  • I hear great things about MADS, but my code uses '*=addr' instead of 'ORG addr', and '.BYTE 00' instead of whatever MADS uses. Should I bother converting? I'm not using any macros or conditional compilation.

 

I personally use MADS for simple/small programs, and CA65 for larger, multi-segment programs (as I like using a linker). Note that MADS also understands ".byte".

 

Once I get these basic things running, I should be mostly there. The only other details would be file I/O, which looks manageable.

 

Any help would be appreciated!

 

BTW, this TECO is a pretty full implementation based on TECO for the PDP-11.

See: https://en.wikipedia.org/wiki/TECO_(text_editor)

Good luck!

 

If you need help, better to post in the programming sub-forum, as it will get more visibility.

Link to comment
Share on other sites

The OS screen routines are of next to no use if you want a fullscreen editor that can scroll.

 

At most you'd use the K: device to get keys. Then do screen output yourself.

It's not really feasible either to have a screen that just scrolls around the memory map without moving data because you'd have to retain all the spaces which would be really wasteful.

Link to comment
Share on other sites

Always good to see project like this surviving this long ! Good luck with it !

  • Is there some preferred starting address for my program? It seems like the start of available memory varies depending on configuration. I'd like a fixed address, and I gather $600 doesn't assure me something else might not live there.
  • Where should I place my text editor buffer? I'd want it to be as large as possible.
  • It seems like there should be simple routines I can JSR to put a character on the screen, check for a key pressed, and return the key pressed, but I can't find them. Do I need to set up an IOCB to do all this?
  • I hear great things about MADS, but my code uses '*=addr' instead of 'ORG addr', and '.BYTE 00' instead of whatever MADS uses. Should I bother converting? I'm not using any macros or conditional compilation.

1. Start address: I've been putting all my code from $2000 couple years now, and never had bigger problems. Guess it's a safe option unless you're using some sort of Dos I think (in that case this "safe bottom address" goes to $3306 or something like that).

 

2. Text buffer: anywhere between that bottom address and $A000 (if you don't use cartridges that would map into that upper area).

 

Some memory map explanations are here: http://atariage.com/forums/uploads/monthly_02_2012/post-6369-0-74418700-1329446208.png

 

3. Basic routines: stuff like keyboard and text drawing can be coded in very little code. If it's those simple routines just write exact parameters and results you want and we'll code that function for you :)

 

4. Mads: I would go for it 100%. Yes you might spend a day looking for those small syntax differences but for example ".byte" directive is the same. It produces labels, source files and Altirra loads them up automatically. Altirra has one of the best debuggers ever.

 

Instructions here: http://mads.atari8.info/mads_eng.html

 

ps. Anything else, just ask :)

 

Cheers!
Vladimir

 

  • Like 1
Link to comment
Share on other sites

Wow, thanks for all the suggestions! Based on what I've heard, I think initially I'll start my code at $2000, and I'll keep my buffer from the end of code to MEMTOP or $A000, depending on how I wrote my original code. I'm guessing I can easily do the calculation and go from there.

 

As to keyboard handling, using K: seems easy enough.

As to screen handling, I'm not sure yet what to do. Initially I'll try using S: and see where that gets me. TECO doesn't expect much. It was designed to work on dumb terminals, and would work find on a Teletype. My expectation would be that a character out routine would print a character. If it was at the last column of a line or was an end-of-line ($9B?), it would advance to the next line. If it was on the final row, it would scroll the screen. Does this mean I need to write the code to do this? (@dmsc - From your description, maybe the OS does *just* what I need, though slowly. I'll give it a try)

 

As to IOCB usage, I'm a bit confused about setting them up. At a glance, it appears IOCB0 is already open. Is it always open and set to the S:? Do I need to check if a specific device is open before opening one myself? Do I need to check each IOCB to see if it is in use before I do an open? Sorry, I haven't gotten around to the RTFM part thoroughly yet ;-)

 

FWIW, I tried a simple print character IOCB example from a book, but it didn't work at all. It opened E: on IOCB2 and called CIOV at $E456 to print a string.

 

I did try using the putchar macro from MADS stdio library, and it worked just fine. I'm guessing it is using the IOCB PUT VECTOR call mentioned by @dmsc?

 

As to assemblers, I'll probably stick with MADS. My code looks like it will take few mods to work with it. For specifying the start of a program, I assume the "run main" line means the code starts at label main? If so, is this the common approach across assemblers?

 

Thanks again, everyone. BTW, I thought I had posted this in the programming sub-forum. Apparently not, but it seems to have gotten sufficient attention! Once I've got the basics working, I'll try to remember to post there.

  • Like 1
Link to comment
Share on other sites

 

As to IOCB usage, I'm a bit confused about setting them up. At a glance, it appears IOCB0 is already open. Is it always open and set to the S:? Do I need to check if a specific device is open before opening one myself? Do I need to check each IOCB to see if it is in use before I do an open? Sorry, I haven't gotten around to the RTFM part thoroughly yet ;-)

 

It's been quite some time since I last coded CIO text output myself but there's a tutorial here and also in De Re Atari. I recall that one of those allowed me to code my routines 3 ½ decades ago.

Link to comment
Share on other sites

Looking at an article on it, it does seem like just a line editor so you could probably just use the already open IOCB #0 E:

 

The other component appears that it's got a sort of built in language processor that allows massaging of data... for that functionality there's not really anything built into the system that can help with parsing etc.

Link to comment
Share on other sites

Hi!

 

Wow, thanks for all the suggestions! Based on what I've heard, I think initially I'll start my code at $2000, and I'll keep my buffer from the end of code to MEMTOP or $A000, depending on how I wrote my original code. I'm guessing I can easily do the calculation and go from there.

 

As to keyboard handling, using K: seems easy enough.

As to screen handling, I'm not sure yet what to do. Initially I'll try using S: and see where that gets me. TECO doesn't expect much. It was designed to work on dumb terminals, and would work find on a Teletype. My expectation would be that a character out routine would print a character. If it was at the last column of a line or was an end-of-line ($9B?), it would advance to the next line. If it was on the final row, it would scroll the screen. Does this mean I need to write the code to do this? (@dmsc - From your description, maybe the OS does *just* what I need, though slowly. I'll give it a try)

Yes, the code I posted (putchar procedure) does exactly that. The problem is when you don't want the screen to scroll :P

 

But, you don't use "S:", you use "E:". "S:" is the handler for graphic modes, supporting plotting pixels and drawing lines. "E:" is the handler for the editor, this means writing text with scrolling and a cursor.

 

As to IOCB usage, I'm a bit confused about setting them up. At a glance, it appears IOCB0 is already open. Is it always open and set to the S:? Do I need to check if a specific device is open before opening one myself? Do I need to check each IOCB to see if it is in use before I do an open? Sorry, I haven't gotten around to the RTFM part thoroughly yet ;-)

 

FWIW, I tried a simple print character IOCB example from a book, but it didn't work at all. It opened E: on IOCB2 and called CIOV at $E456 to print a string.

You can safely assume that the IOCB#0 is opened with the "E:" device when your program starts, as this is the default for the OS, so you don't need to open it again.

 

I did try using the putchar macro from MADS stdio library, and it worked just fine. I'm guessing it is using the IOCB PUT VECTOR call mentioned by @dmsc?

Yes, that is the standard way.

 

As to assemblers, I'll probably stick with MADS. My code looks like it will take few mods to work with it. For specifying the start of a program, I assume the "run main" line means the code starts at label main? If so, is this the common approach across assemblers?

I think that only MADS supports the "run" and "init" pseudo-commands.

 

Thanks again, everyone. BTW, I thought I had posted this in the programming sub-forum. Apparently not, but it seems to have gotten sufficient attention! Once I've got the basics working, I'll try to remember to post there.

Link to comment
Share on other sites

FWIW, I now have an initial port of TECO for the Atari. See:

 

http://atariage.com/forums/topic/273861-teco-for-the-atari/

 

What's left to do is File I/O, which I'll be looking at next. A few questions:

  • As I recall, my old implementation of TECO does some parsing of the filename to figure out if a device name is specified, and if the filename is legal (i.e. no funky characters used, syntax is correct, etc). I gather that may not be necessary - I can just pass the specified filename and CIO will figure out the rest. Is this correct? Or are there, for example, limits to the length of the filename?
  • If a file open or create fails, is there an error code that I can look at? (I seem to recall it return Minus on fail or something like that and the status is in the X register, or I can make a Get Status call). Whichever, I can consult the manual. But I don't recall seeing a list of returned status values...
  • Is there a rename file function?
  • Is there a delete file function?

Anyway, I'm hoping to add these features to make for a complete TECO port.

 

Thanks!

Robert

  • Like 4
Link to comment
Share on other sites

Hi!

 

FWIW, I now have an initial port of TECO for the Atari. See:

 

http://atariage.com/forums/topic/273861-teco-for-the-atari/

 

What's left to do is File I/O, which I'll be looking at next. A few questions:

  • As I recall, my old implementation of TECO does some parsing of the filename to figure out if a device name is specified, and if the filename is legal (i.e. no funky characters used, syntax is correct, etc). I gather that may not be necessary - I can just pass the specified filename and CIO will figure out the rest. Is this correct? Or are there, for example, limits to the length of the filename?
  • If a file open or create fails, is there an error code that I can look at? (I seem to recall it return Minus on fail or something like that and the status is in the X register, or I can make a Get Status call). Whichever, I can consult the manual. But I don't recall seeing a list of returned status values...
  • Is there a rename file function?
  • Is there a delete file function?
Anyway, I'm hoping to add these features to make for a complete TECO port.

 

Thanks!

Robert

 

Great!

 

Responding your questions:

1. You don't *need* to parse the filename, just place a 0 or a $9B at the end. Good programs detect if there is a ":" already in the second or third character, and if not, adds "D:" at start. So, your user can type the filename without the device. Please, don't place the "D:" always, as it makes imposible to read/write to other devices (like "H:")

2. Yes, after the CIOV call, the "N" flag is set on error, and the Y register contains the error code, so you simply place a "BMI handleError" after the "JSR CIO". Status values ar in appendix B of the OS User Manual, basically errors from $80 to $9F are generic CIO errors, errors from $A0 are DOS errors.

3 & 4. Yes, there are some standard DOS calls that work in a *closed* IOCB (the same as "OPEN"): you place the command in IOCMD, filename address (or two filenames separated with a comma in RENAME) in ICBAH/L, and call CIOV. Commands are:

 ICRENAME  = $20           ;rename disk file
 ICDELETE  = $21           ;delete disk file
 ICLOCKFL  = $23           ;lock file (set to read-only)
 ICUNLOCK  = $24           ;unlock file
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...