Jump to content
bugbiter

can a program disable basic by its own?

Recommended Posts

I'm tired of pressing option to boot without basic. Why can't a program do that for itself when starting?

 

I just added

 

lda #243

sta portb

 

as the first statements in a XEX's init block. That should disable basic, keep OS ROM and normal RAM bank for subsequent main program load. Init code block is $3E00-$3FED.

 

Under SpartaDOS 3.3 I get some strange behaviour - black screen and infinite key click sound.

I'm not in the mood for intense debugging so I just ask you guys..Whats wrong with my idea?

Share this post


Link to post
Share on other sites

Well,

 

i am not a programmer, so I have no idea. But, errm, Bill Wilkinson was one of the authors of Atari Basic and also author of the book "Inside Atari Basic" - and he released a short utility in Compute! magazine, named "BASOFF.COM".

 

This utility has a length of only 57 bytes, it uses page 4 to switch off Atari Basic, right after that page 4 is available again... (maybe you want to disassemble this utility and see what it does or just use it)...

BASOFF.XEX

Edited by CharlieChaplin

Share this post


Link to post
Share on other sites

I am pretty sure you want to do a

 

lda portb
and %11111101
sta portb

 

This leaves PORTB intact, and only turns off bit 1 (BASIC enable).

Share this post


Link to post
Share on other sites

Bit 1 is a BASIC disable bit, so:

	lda #1
	sta $03F8 ; basicf
	lda $D301
	ora #$02
	sta $D301
	lda #$C0
	sta $6A ; ramtop

Setting BASICF and RAMTOP avoids any nasties.

Share this post


Link to post
Share on other sites

You'd also have to reopen E: as BASOFF.XEX does to actually relocate screen memory upward.... but yes, it's nicer for programs to auto-disable BASIC instead of requiring users to do it manually.

Share this post


Link to post
Share on other sites

Here's the disassembly. I can't quite understand the need to open E: in mode 12, then set RAMTOP, then open E: again in mode 3.

            org $0400
;
L0400:      lda PORTB
            ora #$02
            sta PORTB
            lda #$01
            sta BASICF
            lda #$0C
            jsr OpenE
            lda #$C0
            sta RAMTOP
            lda #$03
OpenE:      sta IOCB0+ICCOM
            lda #<Name
            sta IOCB0+ICBAL
            lda #>Name
            sta IOCB0+ICBAH
            ldx #$00
            jmp CIOV
Name:      .byte "E:"
            .byte $00
;
            org $02E2
;
            .word L0400
;

Share this post


Link to post
Share on other sites

I've updated the corresponding section in the Atari 8-bit Programming Tips and Recommendations

http://www.wudsn.com/index.php/productions-atari800/tutorials/tips

 

EDIT: hehe, concurrent post. My version uses a bit shorter code for E: and only re-opens it, if RAMTOP was not yet correct.

This way it does not flicker if somebody already did press OPTION before.

Edited by JAC!

Share this post


Link to post
Share on other sites

 

Here's the disassembly. I can't quite understand the need to open E: in mode 12, then set RAMTOP, then open E: again in mode 3.

            org $0400
;
L0400:      lda PORTB
            ora #$02
            sta PORTB
            lda #$01
            sta BASICF
            lda #$0C
            jsr OpenE
            lda #$C0
            sta RAMTOP
            lda #$03
OpenE:      sta IOCB0+ICCOM
            lda #<Name
            sta IOCB0+ICBAL
            lda #>Name
            sta IOCB0+ICBAH
            ldx #$00
            jmp CIOV
Name:      .byte "E:"
            .byte $00
;
            org $02E2
;
            .word L0400
;

 

It doesn't open the editor twice. The first call to "OpenE" passes the CIO close channel code in the accumulator, so it's a close/open sequence.

Share this post


Link to post
Share on other sites

 

It doesn't open the editor twice. The first call to "OpenE" passes the CIO close channel code in the accumulator, so it's a close/open sequence.

Thanks, I didn't know 12 $0C was close. I looked through the CIO stuff in Mapping, and must have missed it. :)

Share this post


Link to post
Share on other sites

I found it deep in the IOCB section.

For the ICCOM field, the following values apply (BASIC XIO
     commands use the same values):

     Command                       Decimal   Hex
     ----------------------------------------------------------------------
     Open channel                      3       3
     Get text record (line)            5       5   BASIC:
                                                   INPUT
                                                   #n,A
     Get binary record (buffer)        7       7   BASIC:
                                                   GET #n,A
     Put text record (line)            9       9
     Put binary record (buffer)       11       B   BASIC:
                                                   PUT #n,A
     Close                            12       C
     Dynamic (channel) status         13       D

Share this post


Link to post
Share on other sites

Hmm.. it's not working right. The init code block turns basic off all right, but after the main program is loaded, Basic is back on.

 

It seems SpartaDos turns it back on during continued loading. It's using RAM under the OS, right? So it sure meddles with portB..

 

I simply switch off Basic again in the main program, that's done the trick..

Share this post


Link to post
Share on other sites

Little off-topic...

I am still not 100% sure if Mad Pascal disables BASIC on program run or not. I checked the programs which use memory addresses beyond $A000 for storage data, but all of them work in text mode 0 with no additional call to InitGraph (I still have to test those examples on real hardware). I experimented with other modes by calling InitGraph procedure, which consequently blocked the usage of this area (I couldn't store values there anymore).

 

Share this post


Link to post
Share on other sites

Possibly it does dynamic storage allocation for stuff like stacks and arrays?

 

Fair chance it doesn't play with the Basic switching, especially if it came out before 1984.

You could probably work it out if you had a compiled program then try it in various configurations in emulation.

Share this post


Link to post
Share on other sites

 

On 5/8/2015 at 9:38 PM, bugbiter said:

Hmm.. it's not working right. The init code block turns basic off all right, but after the main program is loaded, Basic is back on.

On the XL operating system and Os++, this is normal if you run through a reset. The state of the basic switch is stored in address $3f8. The byte at this address shall be non-zero to enforce that the Basic ROM stays disabled after going through the reset vector.

 

On a second matter, it is in general not sufficient to switch basic off just before the binary starts. You need to turn it off before the binary loads. That is, you need to prepend a small code to the actual that is run through the init-vector of the dos loader, which turns basic off both through PIA Port B, through the BasicDisabled flag at $3f8, then adjusts memtop, then re-opens the editor, then continues loading.

 

This is because a binary may well use addresses above $a000 to load to, and this would fail if Basic would be still on during loading.

 

  • Like 2

Share this post


Link to post
Share on other sites

Hi,

 

    won't RAMTOP be wrong on a 16K 600XL? Am asking in context of a boot disk rather than XEX, though I think this would also apply to code after $2000.

Share this post


Link to post
Share on other sites
3 hours ago, E474 said:

Hi,

 

    won't RAMTOP be wrong on a 16K 600XL? Am asking in context of a boot disk rather than XEX, though I think this would also apply to code after $2000.

It would wrong, of course. There would need to be certain logic checking the RAMTOP and adjusting it.

On the other hand, software that really needs RAM below BASIC wouldn't work on a computer with less than 48 KB RAM anyway. 

 

Share this post


Link to post
Share on other sites
21 hours ago, thorfdbg said:

On a second matter, it is in general not sufficient to switch basic off just before the binary starts. You need to turn it off before the binary loads. That is, you need to prepend a small code to the actual that is run through the init-vector of the dos loader, which turns basic off both through PIA Port B, through the BasicDisabled flag at $3f8, then adjusts memtop, then re-opens the editor, then continues loading.

Thanks for info! I was not aware of the flag at $3f8.

Share this post


Link to post
Share on other sites

If the program knows that the machine won't reboot then it can be easier to just set the flag at $3F8 and call a warmstart $E474 - then the OS takes care of the memory management and proper E: stuff.

Share this post


Link to post
Share on other sites

There is also one thing specific to the CC65 and its ATARI target and runtime library.

It is, to my surprise, using MEMTOP to position its C runtime stack, though it is documented. So, for this specific situation, adjusting MEMTOP is also needed, even though it is a vector used by BASIC.

 

I didn't do it in the TRAIN 2 game and its loading screen gets a little glitch (P letter appears briefly on screen). Apart from the glitch, there is no other damage, fortunately.

A circumvention is to boot with the OPTION key pressed.

Edited by baktra

Share this post


Link to post
Share on other sites

MEMTOP is maintained by the OS and will be set when E: or S: is OPENed, pointing to the byte before the start of the Display List.

 

APPMHI ($E,$F) is the pointer that applications, languages and programs should use to tell the OS the highest address it should not use - a screen open that violates it will fail.

The 800 OS has a bug where if you set it above where the default Gr. 0 DList would appear then do a warmstart, the machine will become unrecoverable since E: can't open so no input is possible.

The XL OS has a check for this condition and will adjust APPMHI to allow E: to function normally if an open fails on warmstart.

 

A common mistake some people make is adjusting RAMTOP based on it's "current" value which can cause Basic programs to have memory creep issues.

The proper way is to use RAMSIZ ($2E4) as the reference to the actual top of RAM then adjust RAMTOP from that value.

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, Rybags said:

MEMTOP is maintained by the OS and will be set when E: or S: is OPENed, pointing to the byte before the start of the Display List.

 

APPMHI ($E,$F) is the pointer that applications, languages and programs should use to tell the OS the highest address it should not use - a screen open that violates it will fail.

The 800 OS has a bug where if you set it above where the default Gr. 0 DList would appear then do a warmstart, the machine will become unrecoverable since E: can't open so no input is possible.

The XL OS has a check for this condition and will adjust APPMHI to allow E: to function normally if an open fails on warmstart.

 

A common mistake some people make is adjusting RAMTOP based on it's "current" value which can cause Basic programs to have memory creep issues.

The proper way is to use RAMSIZ ($2E4) as the reference to the actual top of RAM then adjust RAMTOP from that value.

Thanks. I didn't know. In my program, I do not re-open the E: device (I just close it as I don't use it later).

Share this post


Link to post
Share on other sites

Here is Mad Pascal code which writes two consequent bytes to $A000 area even if BASIC is still ON. It does use code from JAC!'s page. I only removed program starting address setting and error trapping in case $A000 cannot be written to. Program runs in graphics mode 12 and shows results in text area (reading default values and then writing new values).

program testmem;

uses
  graph, crt;
  
const
  ram = $a000;   
  
var
  mem : array [0..0] of byte; 

begin  
  asm {
       LDA #$c0 ;Check if RAMTOP is already OK
       CMP $6a ;This prevent flickering if BASIC is already off
       BEQ RAMOK
       STA $6a ;Set RAMTOP to end of BASIC
       STA $2E4 ;Set RAMSIZ also

       LDA $d301 ;Disable BASIC bit in PORTB for MMU
       ORA #$02
       STA $d301

       LDA #$01 ;Set BASICF for OS, so BASIC remains OFF after RESET
       STA $3f8

       LDX #2 ;Close "E:" before re-openining it again
       JSR EDITOR
       LDX #0 ;Open "E:" to ensure screen is not at $9C00
EDITOR LDA $e401,x ;This prevents garbage when loading up to $bc000
       PHA
       LDA $e400,x
       PHA
RAMOK
  };

  InitGraph(12);  

  mem := pointer(ram);
  Writeln('Read  $A000 = ', mem[0], ' $A001 = ', mem[1]);
  
  mem[0] := 1;
  mem[1] := 2;
  
  Writeln('Write $A000 = ', mem[0], ' $A001 = ', mem[1]);

  repeat until keypressed;
end.

testmem.thumb.png.7a86248acf6db494132feaf54b1f45ad.png

 

  • Like 1

Share this post


Link to post
Share on other sites
8 hours ago, Rybags said:

If the program knows that the machine won't reboot then it can be easier to just set the flag at $3F8 and call a warmstart $E474 - then the OS takes care of the memory management and proper E: stuff.

Too late. Remember, a program may want to load into the $a000 area, thus at the time you run through warmstart, the conflict already happened.

Share this post


Link to post
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.

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