Jump to content
IGNORED

New BASIC Autorun


pcrow

Recommended Posts

Well, I just lost 3 bytes due to a bug.  When I check to see if the cartridge is loaded, I write zero to the upper byte of the initialization address, as this must be in the range of A0-BF to point inside the cartridge space.  If the read after the write returns zero, I know it's really RAM, so no BASIC.  However, if we have less than 48K of RAM, then a read from non-memory appears to return $FF, not $00.  I'm only using the atari800 emulator for this test, so I'm not completely certain that's correct.  The easiest fix is after the BEQ statement to do an INX and BEQ again to catch the $FF, again leaving X at zero as needed.

 

2 bytes to spare right now, but if I can get 3 more, I can set the foreground color to hide the command.

basrun.asm

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

3 hours ago, pcrow said:

2 bytes to spare right now, but if I can get 3 more, I can set the foreground color to hide the command.

If I'm seeing things correctly, this would save 2 bytes as execution continues under the BNE only if TRAMSZ is zero.
So save the zero in the X register and reuse it to store into BASICF.

CHKBA LDA LDX    TRAMSZ        ; set to 1 if cartridge is present
          BNE    BASREADY
...

          STA    PORTB
          LDX    #$00
          STX    BASICF        ; Set flag to keep BASIC enabled in PORTB on reset

Edited by 16kRAM
Message was sent before editing was completed.
Link to comment
Share on other sites

22 minutes ago, Irgendwer said:

Couldn't the "DO_OP" not also substituted by a "JMP (E_OPEN)" and would save 4 bytes?

Nope, by pushing it on the stack and doing an RTS, you jump to one-off of the address.  Why it's stored one-off, I don't know, but I expect some digging in the OS source would show that they saved a few bytes that way for some reason.  I can't see how to shrink the code I'm using for that.  The other option is to use IOCB #0 and issue a new open for the E: handler that way, but unless I'm missing something clever, that would take even more bytes.  That would also have to make more assumptions about the state of the system to have any chance of saving bytes.

 

And I assume the address of the open routine is different in different versions of the OS (and I just verified that 800 and XL are different), so hard-coding it is out (though it's exactly what I would have done if writing this pre-XL).

  • Like 1
Link to comment
Share on other sites

18 minutes ago, 16kRAM said:

If I'm seeing things correctly, this would save 2 bytes as execution continues under the BNE only if TRAMSZ is zero.
So save the zero in the X register and reuse it to store into BASICF.

CHKBA LDA LDX    TRAMSZ        ; set to 1 if cartridge is present
          BNE    BASREADY
...

          STA    PORTB
          LDX    #$00
          STX    BASICF        ; Set flag to keep BASIC enabled in PORTB on reset

Nope.  The check of TRAMSZ is disabled with #if 0 / #endif.  The assembler I'm using runs things through the C preprocessor first.  I found that it works to just skip the check, which results in calling the BASIC initialization routine again, but that's harmless.

Link to comment
Share on other sites

5 hours ago, pcrow said:

Well, I just lost 3 bytes due to a bug.  When I check to see if the cartridge is loaded, I write zero to the upper byte of the initialization address, as this must be in the range of A0-BF to point inside the cartridge space.  If the read after the write returns zero, I know it's really RAM, so no BASIC.  However, if we have less than 48K of RAM, then a read from non-memory appears to return $FF, not $00.  I'm only using the atari800 emulator for this test, so I'm not completely certain that's correct.  The easiest fix is after the BEQ statement to do an INX and BEQ again to catch the $FF, again leaving X at zero as needed.

This depends on what the bus does when no chip is connected at that address space. IIRC, the XL series pulls it high, so it reads all 1s. On the XE though, the bus is floating and could read anything.

 

Edit: oh, but normally there is at least 64kB in an XE, so never mind ;) It's just the 400/800 and 600XL. Would have to check the schematics if the 400/800 pull the bus high.

Edited by ivop
Link to comment
Share on other sites

18 minutes ago, ivop said:

This depends on what the bus does when no chip is connected at that address space. IIRC, the XL series pulls it high, so it reads all 1s. On the XE though, the bus is floating and could read anything.

 

Edit: oh, but normally there is at least 64kB in an XE, so never mind ;) It's just the 400/800 and 600XL. Would have to check the schematics if the 400/800 pull the bus high.

At some point I need to get my 800 out of the attic.  Since there's no memory between 48K and 52K, you can just peek(50000) and see what you get.  I don't have a 600XL to test.  I'm not sure if there are multiple motherboard revisions, though that's something that likely wouldn't have changed.  I'm guessing that having it read all 1s is preferable, as it makes scanning the amount of memory present simpler.

Link to comment
Share on other sites

And I found one more clever hack: I want to set the foreground color to the background color.  My first pass was to read COLOR2 and write COLOR1, using 6 bytes.  But since this is after doing a GR.0, we know the values, so I could just load #$94 and save it, bringing it down to 5 bytes.  But then I thought, could I do some magic bit trick on COLOR1 and get it to equal COLOR2?  Yes, I can!  ASL does the trick.  Perhaps that's a lucky coincidence, but I was able to blank out the text with only three bytes that way, which brings it back to 124 bytes total, the exact max for a one-sector DOS 2 file.

 

This hits all the features I wanted:

  • BASIC is enabled on XL/XE if not already active
  • An error is displayed if BASIC is missing on 400/800/1200XL
  • Space in the command for any 8.3 filename
  • Text is in ATASCII in the binary for easy editing
  • The command text does not flash on the screen

The only downside is there is one keypress click.  I could turn that off with three bytes (decrement NOCLK $2DB), I couldn't turn it back on without a poke in the BASIC command, making it just as bad as using auto-return mode.  I can live with that.

 

Thanks for all the help.  This was fun.  If anyone sees any more bytes I haven't identified that can be saved, please point them out.

basrun.asm

  • Like 3
Link to comment
Share on other sites

9 hours ago, Rybags said:

Reads from non Ram can't be relied on to have fixed values - 400/800 will often return address bus reflection, some systems will show $FF.

The address I'm reading is $BFFF, so if it's reflecting the lower address bits, it would be all 1s or 0s depending on whether it gets inverted; either of which I would handle just fine.  But if it's something else, my program would have trouble.  This is getting into an area where the emulators can't be relied on for accurate behavior.

Link to comment
Share on other sites

Hi!

14 hours ago, pcrow said:

And I found one more clever hack: I want to set the foreground color to the background color.  My first pass was to read COLOR2 and write COLOR1, using 6 bytes.  But since this is after doing a GR.0, we know the values, so I could just load #$94 and save it, bringing it down to 5 bytes.  But then I thought, could I do some magic bit trick on COLOR1 and get it to equal COLOR2?  Yes, I can!  ASL does the trick.  Perhaps that's a lucky coincidence, but I was able to blank out the text with only three bytes that way, which brings it back to 124 bytes total, the exact max for a one-sector DOS 2 file.

 

This hits all the features I wanted:

  • BASIC is enabled on XL/XE if not already active
  • An error is displayed if BASIC is missing on 400/800/1200XL
  • Space in the command for any 8.3 filename
  • Text is in ATASCII in the binary for easy editing
  • The command text does not flash on the screen

The only downside is there is one keypress click.  I could turn that off with three bytes (decrement NOCLK $2DB), I couldn't turn it back on without a poke in the BASIC command, making it just as bad as using auto-return mode.  I can live with that.

 

Thanks for all the help.  This was fun.  If anyone sees any more bytes I haven't identified that can be saved, please point them out.

 

 

Here it is a 121 byte version, with your restrictions. It could be 1 byte shorter if placed in zero-page (at address $80, for example), and 3 byte shorter with the text in screen codes (this is trivial with other assemblers, like MADS, CA65, xasm, MAC/65, etc. 😛 ), for a total of 117 bytes.

 

 

Attached is the 121 byte version.

 

Have Fun!

basload.asm

  • Like 4
Link to comment
Share on other sites

8 hours ago, dmsc said:

Here it is a 121 byte version, with your restrictions. It could be 1 byte shorter if placed in zero-page (at address $80, for example), and 3 byte shorter with the text in screen codes (this is trivial with other assemblers, like MADS, CA65, xasm, MAC/65, etc. 😛 ), for a total of 117 bytes.

Awesome!  I was thinking the zero-page trick would save on the JSR, but there's no zero-page version of that instruction.  It's the LDA for copying the message.  Clever.  I would be concerned about leaving all that full of junk when BASIC initializes, though.  I like running out of the cassette buffer to keep memory clean.

basrun.asm

  • Like 1
Link to comment
Share on other sites

Two bugs fixed:

 

I saved a few bytes by not checking TRAMSZ for a cartridge first, which resulted in incrementing it again if already 1.  I doubt anything cares, but I fixed it.  By loading it in X and then doing the BNE, I can skip the load of zero into X, so it's only two bytes.  I could drop the BNE and the later INC and save four bytes and not care about TRAMSZ being right.

 

Checking for BASIC on a 400/800/1200XL, I read the last byte of the cartridge, which is the high part of the cartridge initialization address.  This must be in the A0-BF range to point into the cartridge memory.  Previously I was writing zero and expecting to read zero if there was no cartridge, which works on the 1200XL or with 48K on a 400/800, but if there's no memory at all on a 400/800, then it can get weird bus reflections or stale data.  I'm told that the 400 and 800 behave differently, so they would need to be tested separately.  Now I just read the byte, AND it it mask of the low five bits, and the CMP it to see if it's 101xxxxx for Ax or Bx.  I dropped the write to the address, as it would have been the last character on the screen in that case, which would have to have been an inverse character in '@A..Z[\]^_' which wouldn't be the case in almost any sane state.  (A 3-byte write would eliminate that, but seems unnecessary.  I could also do a 3-byte JSR to do GR.0 before adjusting RAMTOP for the same effect.)

 

With all that, it's back to 121 bytes.  124 bytes if I put back that write to clear the possible screen memory.

basrun.asm

Link to comment
Share on other sites

I redid the logic to check if BASIC is loaded, as I can't rely on what we see we have less than 48K on a 400/800.  I'm told that the 400 behaves differently from the 800, and I don't have a 400 to test on.  This was going to push it to 125 bytes, but I saved a byte by rethinking the copy logic to avoid using X.  This shifts the run command over on the screen, but it's invisible, so that's fine.  Back to 124 bytes.  Perfect!

 

I was also thinking the load routine might initialize the init address to zero, so I could get away with only loading the page, but instead it initializes it to point at a RTS instruction so that it can be called regardless of whether the file sets it.  No byte to be saved there, but at least I tried.

basrun.asm

Link to comment
Share on other sites

Do you still have the :. after then RUN <filename> ? to cope with non-space data after the command?

If you can guarantee there's spaces for the remainder of the entered line you could lose the second quote.

 

I notice you still seem to be doing SBC to get the screen code, you could just encode the costant string direct.

 

Doesn't AUTORUN.SYS just use a run address only?  If an executable omits the INIT address it should just default to pointing to an RTS, that's the DOS or loader's responsibility.

 

 

Link to comment
Share on other sites

9 hours ago, Rybags said:

Do you still have the :. after then RUN <filename> ? to cope with non-space data after the command?

If you can guarantee there's spaces for the remainder of the entered line you could lose the second quote.

 

I notice you still seem to be doing SBC to get the screen code, you could just encode the constant string direct.

 

Doesn't AUTORUN.SYS just use a run address only?  If an executable omits the INIT address it should just default to pointing to an RTS, that's the DOS or loader's responsibility.

The quote at the end of the filename is because I'm using a 7.3 as an example, and I want to leave room for an 8.3.  The screen is reset at the beginning, so it's always spaces at the end.

 

Yes, I could save three bytes with using the screen encoding natively, but I have too many memories of wanting to modify an AUTORUN.SYS file for my own use, and having to adjust for screen codes was always a pain.  Using ATASCII is a stated feature for that reason.

 

I believe AUTORUN.SYS uses only the init address, not the run address.  That's different from a regular binary load file, but that's what DOS 2 does.  I haven't experimented with different DOS versions or multiple INIT blocks; that would be interesting.

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...