Jump to content
IGNORED

The Last Word 3.1 Released


flashjazzcat

Recommended Posts

Someone remind me why I do this! :) It's taken me about four hours' of precision debugging using Altirra's marvellous tools to get LW's screen display to appear (rather than a black void) using revised code no longer seated under the OS ROM. Awful, fiddly, seemingly thankless work. The fact that the code now sits under the banked window which holds the text has been a trickier trick than I'd expected.

 

Most of the access to the banked text buffers will be via subroutines which replace individual indexed LDA/STA operations with code wrapped in bank switching routines. The PORTB values are pre-masked, so that there's no EOR/AND/OR stuff to do when bank switching: just an STA from a value in a table. Time-critical stuff (such as screen refresh) will be done with the text bank presistently switched in for optimal speed. Using a system of markers and a virtual addressing system, I hope to implement text buffers in extended RAM of at least 32K in size. It will appear as a seamless, contiguous space, and you'll still be able to edit several files at once. I believe PaperClip used a similar system (I'm assuming so, since it reports large amounts of free space on a 130XE).

 

I may start a blog if it gets interesting: I'm sure these code ramblings are of interest to about three people. :) I may ring the Samaritans if I hit another serious bug, since the wife's no help! :D

I enjoy reading all about the code enhancements. It sure beats the stuff I've been working on during the day job :cool:

 

Stephen Anderson

Link to comment
Share on other sites

Thanks Stephen! :)

 

I finally beat the bug today: some kludges I'd put in to supposedly fix up the bank switching were causing more problems than they fixed. The OS isn't switched out any more, so there was lots to change. I now get some kind of cranky editor on the screen.

 

I'm pretty excited about pulling off the multi-bank text buffer trick. Some parts of LW lend themselves well to the idea: for example, although text sits at the high end of the buffer when the cursor's at the top of the document, the load operation can be accomplished across multiple banks just by filling them up from the bottom one bank at a time. With the text low in the buffer, the cursor's effectively at the end of the document, so a simple "cursor home" will push everything back up to the top, ready for insertions. The only unknown at this stage is how quickly this will work across 32K of text.

 

Another idea I had was to re-sample the 3-bit wide 80 column fonts on loading, so that instead of two characters per 8 bytes (side by side), there are actually two copies of every character side by side. This will completely eliminate bit-shifting when rendering the screen.

 

 

 

Link to comment
Share on other sites

All systems go. I have a version of the WP up and running now which uses no RAM under the OS, has 6K free for extra features, and addresses the text buffer indirectly using a kind of virtual memory handler. It's hoped that this will eventually allow text buffers spanning two or three banks.

 

 

The proof of concept suggests that the editor operates as fast as versions which address the text buffer directly (with the text switched into conventional RAM). The big test will be how long it takes to scroll from start to end in a 32K document.

 

Blog here.

Edited by flashjazzcat
Link to comment
Share on other sites

Just updated the blog. I wonder if I'm subconciously waiting for someone to tell me this will never work. :)

 

Suggestions welcome!

 

I wonder if you might be able to speed up the xbank text write routine by abusing the PIA's data direction register. Right now you're having to explicitly flip-flop the port B output register between two states, and that involves additional PHA/PLA sequences since apparently you're trying to preserve both X and Y. However, if you can make one of the states the default state ($FF = kernel ROM enabled, basic ROM disabled, extended RAM access disabled, self-test ROM disabled) then you should be able to use this sequence instead:

 

sta_pos_y
       dec portb     ;DDRB = $FF (enable output)
       sta (pos),y
       inc portb     ;DDRB = $00 (disable output)
       rts

 

The idea is that during text manipulation you leave the output register alone and instead toggle the data direction register between $00 and $FF, thus enabling or disabling whatever setting is in the output register. DDRB is selected by clearing bit 2 of PBCTL. The downside is that you can only control one of the bank settings used for alternation.

Link to comment
Share on other sites

Interesting: I knew nothing of this. So the idea would be to already have PORTB set up with the appropriate bits for the target bank, then we can easily swap the extended bank out with a simple INC/DEC (after first setting up DDRB)? This would be great if I weren't branching out into 2 bank text buffers. It's a good suggestion though, and something entirely new to me. :)

Link to comment
Share on other sites

I don't know that playing with the DDR would help anyway.

 

I was of the impression that regardless of what you did with the DDR, PORTB output would maintain it's values until you otherwise changed it.

 

On the other hand, by setting some bits to inputs, shouldn't that force their value to "always 1", which in theory might give you different toggling possibilities when using INC/DEC on PORTB.

Link to comment
Share on other sites

It would get pretty complex using INC and DEC in any case: the bitmasks are precomputed and masked according to whichever memory upgrade is fitted to the machine. We'd have to isolate the bits which change (which admittedly the program already does), then further isolate a subset of maybe two bits to change, since the three states required for a 32K text buffer system are: MAIN bank, ext bank 1, and ext bank 2.

 

It might be a lot easier for the current single bank per text buffer system.

 

I can see savings to be made in other ways. The two banking bytes for the two halves of the 32K buffer could be stored in page zero, for example. And the screen redraw (placed outside the $4000-$7FFF region) will explicitly bank switch the two halves of the buffer in and do direct reads, since it will just access the text in a linear fashion, start to end, and when it reaches the end of the first bank it will then switch in the second one.

Edited by flashjazzcat
Link to comment
Share on other sites

Are you using a couple of subroutines exclusively to access the text buffer?

 

In an unrelated context, I was thinking the other day about extended access.

 

The idea I had was along the lines of having 16-bit pointers to x-RAM, and using the high byte to do a table-lookup (for banking control), then mask it off and OR in #$40 for addressing.

Or take it a step further and use 3 byte addresses, which would then cater for any expansion system.

Link to comment
Share on other sites

Yours is not a dissimilar system, as far as I can see - just on a much bigger scale. I'm delegating "random" reads/writes to subroutines to access the text buffer, while the screen redraw - being time critical - will explicitly swap the banks in. 16 bits is enough for me, since I can never see the text buffer being more than 64K long (it would take about half a minute to execute a "cursor home").

 

CIO access is also an issue. If the IO routines weren't in safe memory, you could just use double-buffering and "push" text into the extended memory, but I think I'll have room to bank the text in and out and just do direct buffer writes.

Edited by flashjazzcat
Link to comment
Share on other sites

I was tinkering with The Last Word this morning and I realized that the system of packing two 4-bit wide 80 column characters into each 8 byte cell was counter-productive, in as much as 50% of the time, any given character needs to be shifted left or right by four bits when being drawn on the screen. So I wrote (quite quickly, and it worked first time) a bit of code which converts the two-characters-to-an-8x8-cell fonts to a format whereby each cell contains two copies of the same character side by side. This eliminates bit shifting altogether when it comes to rendering the character, since there's always a copy of the character in the appropriate "half" of the byte. All that's required is to establish whether "X" is even or odd, and mask accordingly with $F0 or $0F (using the complement to mask the rest of the byte already on the screen). It has to be faster by the order of some thousands of machine cycles per screen redraw, although the improvement in speed is only just noticeable. Every little helps, though.

 

The existing 80-column font format needs no adjustment, since the fonts are automatically upsampled on loading.

Edited by flashjazzcat
Link to comment
Share on other sites

I've dumped the "hit and miss" screen refresh since it looked untidy and the screen updates are a lot faster now anyway. icon_smile.gif

 

I'm posting again because there are a couple of critical design changes coming up:

 

  • Cut, Copy and Paste are going to be attached to different keystrokes (i.e. windows compatible ones). This is not a trivial change, since many old 3.0/3.1 macros will no longer work and will have to be "translated".
  • The macro buffer on 64K machines is going to be slashed from 768 bytes to only 256. I needed two pages of RAM for the "upsampled" 80 column fonts (and thus the faster screen redraws). This probably isn't such an issue anyway since 64K support will be dropped in the next release following this one.
  • The "main" buffer, when using banked memory, will decrease in size by 512 bytes.
  • In order to address the problem that many European users have had - namely, having to press <CTRL+Esc> before typing international characters - the best I can manage at the moment is a fourth "state" for the keyboard (currently lowercase, uppercase, and control-lock): namely "International" mode, whereby <CTRL+Key> combinations will always enter literally into the text, but the cursor and editing controls will still work. This will need some finessing, since the same people who want to type control characters without pressing <Ctrl+Esc> also want the cut and paste shortcuts on <CTRL+X>, <CTRL+V>, etc. Control lock mode, as it stands in version 3.1, deactivates all editing controls including the cursor, which makes it less than useful for anything other than typing a continuous stream of characters.
  • I may duplicate the windows cut and paste shortcuts in the input line, so a highlighted input field can be copied to the paste buffer.

There isn't really room to add a great deal more in this version, but as ever I've been surprised at how much superflous code can be jettisoned when a program is looked at again with freshened eyes. The loop which paints 80 column characters on the screen is pretty trivial now that all the bit shifting has been removed. This bodes well for the upcoming Sparta 3.x compatible version, which will draw the 40 column text as bitmapped graphics too (the current version uses text mode) so that all the program prompts can be in a fixed "system" font, while everything the user types in can be in the character set of their choice.

 

Anyway, 3.11 will be released with the long-awaited Polish fonts. For those who've requested a menu system, all I can manage at the moment is a decent macro based interface attached to the <Start> key. A German version of the User Manual is also nearing completion, but I haven't had anyone volunteer to translate it into Polish yet. The idea of actual non-English Language executables of the program has been shelved for now. It seems many European users would be would be quite happy with a translated online help system, while leaving the program prompts in English.

 

 

Edited by flashjazzcat
Link to comment
Share on other sites

I was tinkering with The Last Word this morning and I realized that the system of packing two 4-bit wide 80 column characters into each 8 byte cell was counter-productive, in as much as 50% of the time, any given character needs to be shifted left or right by four bits when being drawn on the screen. So I wrote (quite quickly, and it worked first time) a bit of code which converts the two-characters-to-an-8x8-cell fonts to a format whereby each cell contains two copies of the same character side by side. This eliminates bit shifting altogether when it comes to rendering the character, since there's always a copy of the character in the appropriate "half" of the byte. All that's required is to establish whether "X" is even or odd, and mask accordingly with $F0 or $0F (using the complement to mask the rest of the byte already on the screen). It has to be faster by the order of some thousands of machine cycles per screen redraw, although the improvement in speed is only just noticeable. Every little helps, though.

 

The existing 80-column font format needs no adjustment, since the fonts are automatically upsampled on loading.

 

Some months ago I saw a BASIC MLSR for rendering 80-column characters, which had a copy of each character in the fonts it's used. Seemed pretty quick and was easy to use in BASIC. I didn't think much about the dual characters at the time, but obviously this was the reason why. I can't seem to find the routine now. It was from one of the Atari magazines.

Link to comment
Share on other sites

So I wrote (quite quickly, and it worked first time) a bit of code which converts the two-characters-to-an-8x8-cell fonts to a format whereby each cell contains two copies of the same character side by side. This eliminates bit shifting altogether when it comes to rendering the character, since there's always a copy of the character in the appropriate "half" of the byte. All that's required is to establish whether "X" is even or odd, and mask accordingly with $F0 or $0F (using the complement to mask the rest of the byte already on the screen).

Thats how I have usually done it, but another way is to store the character in the middle of the cell and then just bit shifting left or right two bits as needed.

Edited by kenfused
Link to comment
Share on other sites

Thats how I have usually done it, but another way is to store the character in the middle of the cell and then just bit shifting left or right two bits as needed.

That would cut out half of the bit shifting, but since you're now using a full 8 bytes per char, might as well go the whole hog and keep two copies of the character in each cell.

 

Some months ago I saw a BASIC MLSR for rendering 80-column characters, which had a copy of each character in the fonts it's used. Seemed pretty quick and was easy to use in BASIC. I didn't think much about the dual characters at the time, but obviously this was the reason why. I can't seem to find the routine now. It was from one of the Atari magazines.

I think memory shortage must have been the overriding concern when I decided on the 512 byte fonts with two characters per cell. It still makes sense to keep them that way on disk (it makes useful space savings), but the editor is a hell of a lot snapper with all the bit shifting done as soon as the font is loaded.

 

Actually, when I'd finished coding for the night last night I realized how to save another 512 bytes of RAM by keeping the header and footer buffers in the same area as the disk directory buffer (since printing and disk directory reading are never operational at the same time). Can't understand why I didn't think of that before, but it means the unbanked macro buffer can go back up to 512 bytes, and I'll still have a couple of hundred bytes for code expansion. On the other hand, I may find an alternative use for the other free page...

 

I'm really pleased with the "International Lock" keyboard function: most navigation functions still work, but European users can type control alpha characters with freedom (until they want to cursor home or save the file: "International Lock" has to be toggled back off for that. I'd really like to include some kind of rudimentary menu system to get around this).

Edited by flashjazzcat
Link to comment
Share on other sites

Were there many Atari WP's with a multi-level undo feature? I'm thinking of using an extended bank as an undo/redo buffer, structured as LIFO queue of some kind. It should be fairly trivial to write: just store insertions and deletions along with their location and size, and perform the "opposite" operation when recalling them.

Edited by flashjazzcat
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...