TGB1718 Posted July 10, 2020 Share Posted July 10, 2020 I'm writing a program that uses a VBI routine, I want the program to survive a warm start which would mean re-initialising the VBI routine as part of the warm start. My program is run from the DOS prompt mainly with SDX (Incognito or U1M) The program does what I want until I press reset. I've had a look at addresses $2E0 and $2E1 after the program has loaded and they are not set to $00,$06 as I expected. Is there another way to survive a warm start I'm using MAC65 as my assembler I've tried the following *=$600 ; My code here to set VBI routine INIT LDA #0; Prog Init Address . . . . RTS VB ...... ; VB code here . JMP XITVBV *=$2E0 .WORD INIT Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 10, 2020 Author Share Posted July 10, 2020 (edited) Just found an example in De-Re-Atari by stealing the DOS vector at locations $C and $D, the code steals the DOS vector, but the address in $C and $D don't change which seems wierd, does SDX reset these locations if they change ? 0000 0130 *= $0600 0140 .INCLUDE #D:HEADER.M65 0100 ; UPDATE 09/07/2020 2800 .OPT LIST 2810 .ENDIF 0600 200306 0150 INITDOS JSR TEMPADR ; WILL CHANGE WHEN INIT RUNS 0603 4C1606 0155 TEMPADR JMP SETPORT then my code here and this from De Re-Atari, this code does run due to the $2E2 init address as the address for the JSR TEMPADR changes to the valuse originally in $C and $D ($2A, $9), but $C and $D also still have $2A and $9 in them ??? as set by SDX 06DF 1110 *= $2000 2000 A50C 1120 GETDOS LDA DOSINI 2002 8D0106 1130 STA INITDOS+1 2005 A50D 1140 LDA DOSINI+1 2007 8D0206 1150 STA INITDOS+2 200A A900 1160 LDA #INITDOS&255 200C 850C 1170 STA DOSINI 200E A906 1180 LDA #INITDOS/256 2010 850D 1190 STA DOSINI+1 2012 60 1200 RTS 2013 1220 *= $02E0 02E0 0306 1230 .WORD TEMPADR 02E2 0020 1240 .WORD GETDOS Edited July 10, 2020 by TGB1718 Update Quote Link to comment Share on other sites More sharing options...
Rybags Posted July 11, 2020 Share Posted July 11, 2020 The $2E0-3 locations are just used by Dos or a loader during the load. There's no obligation for a Dos to take your Run address and ensure your program reruns after a warmstart. The only ways for a Ram based program to start again after warmstart are CASINI (2,3) DOSINI ($C,$D) and DOSVEC ($A,$B) If your program is to be permanently in control until the user turns off then you could just steal one of those vectors. The order of calling is CASINI then DOSINI. DOSVEC is only run if there's no cartridge present or if called by the user typing DOS. The expectation normally is that you return from CASINI and DOSINI but for a game there's not a need. In the modern day it's usually desirable that a game or demo just coldstarts when you press Reset so the user can preserve Ramdisks. Or alternately returns to a usable Dos environment. Use ESC as an alternate soft reset method. With CASINI/DOSINI you want to set the flag in location 9 - bit 0 means tape has booted, bit 1 means disk has booted. To preserve a Dos you'd want to save the old DOSINI vector then call it if there was a DOS present (bit 2 of 9 = 1) If you want to give the user a way to soft coldstart then you could allow Shift+Reset, then just test for the Shift key in your warmstart code, jump to $E477 if it's being held. 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 11, 2020 Author Share Posted July 11, 2020 Many thanks for that information, I didn't set the flag in location 9, also, I might change the code to use CASINI instead. The software I'm writing is a keyboard handler which allows me to use any USB keyboard on my 800 and 130XE, so if I need to use RESET, I need to re-initialise the VBI Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 11, 2020 Author Share Posted July 11, 2020 (edited) Just used CASINI, still get the same result, code not working after reset. I checked location 9 after loading my code and it's set to 1, my code sets it to 2, as it's being set back to 1, pressing reset does not use my code vector set at locations 2 and 3 which have been set correctly to $00,$06. So I put my software on a bootable .ATR and loaded that with SDX disabled on my 800 and hey presto the code works as intended, my USB keyboard still works after a reset. So it looks like SDX is doing something to those vectors and flags after my program has loaded, a BUG maybe ?? I certainly isn't working the way it should. In a nutshell SDX is resetting locations $2E0,$2E1,$2E2,$2E3 and $9 back to their previous values after they have been set by my program, I would assume it's doing some processing before returning to the command prompt. 2000 A902 1150 GETDOS LDA #2 2002 8509 1160 STA BOOT 2004 A900 1170 LDA #INITDOS&255 2006 8502 1180 STA CASINI 2008 A906 1190 LDA #INITDOS/256 200A 8503 1200 STA CASINI+1 200C 60 1210 RTS 200D 1220 *= $02E2 02E2 0020 1240 .WORD GETDOS Edited July 11, 2020 by TGB1718 Update Quote Link to comment Share on other sites More sharing options...
+David_P Posted July 11, 2020 Share Posted July 11, 2020 Have you consulted the excellent SpartaDos X programmer's manual at: http://sdx.atari8.info/sdx_files/4.49/SDX449_Programming_Guide_EN.pdf Quote Link to comment Share on other sites More sharing options...
Rybags Posted July 11, 2020 Share Posted July 11, 2020 Location 9 gets altered during boot so if you set it too early it might end up with the wrong value. Note that it holds the flag for tape as well as disk (and both set is valid). In your code you should OR in the bit value, don't just set the value as a constant. e.g. LDA 9 ORA #2 STA 9 if you're using CASINI. Assuming you have a disk based DOS active, then yep, the flag should = 1. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 11, 2020 Author Share Posted July 11, 2020 Just modified the code, but SDX keeps setting $9 back to 1. I'm not currently loading this during boot, just manually when the DOS prompt appears. 1 hour ago, David_P said: Have you consulted the excellent SpartaDos X programmer's manual at: http://sdx.atari8.info/sdx_files/4.49/SDX449_Programming_Guide_EN.pdf Yes, there is nothing there that I can find concerning this. The only mention of DOSINI is in an application CAD.SYS which I'm not using. It appears DOSVEC is used internally by SDX:- "Several SD variables are available to programmers to allow easy access to the command line for applications and utilities. This data table is referredto as COMTAB and is pointed to by the OS variable DOSVEC at memory location 10 ($0A).! Quote Link to comment Share on other sites More sharing options...
+David_P Posted July 11, 2020 Share Posted July 11, 2020 Page 53 discusses TSR routines and how to add them to the queue. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 11, 2020 Author Share Posted July 11, 2020 2 hours ago, David_P said: Page 53 discusses TSR routines and how to add them to the queue. Many thanks for that, at least I know there's a mechanism available, unfortunately it doesn't explain how to make the call, it says Such TSR programs can be registered using S_ADDIZ. In the AX registers (LSB and MSB respectively) But it doesn't explain how you make the call in your program, I assume there is a vector somewhere in SDX, but I searched and can't find any other references to S_ADDIZ. I found a utility in the SDX toolkit and the symbol equates to this:- S_ADDIZ $A03F but no examples of how to use this Quote Link to comment Share on other sites More sharing options...
+David_P Posted July 12, 2020 Share Posted July 12, 2020 You can reach out to the programming team at: for more info. (email address is in a PNG to prevent spammers from scraping it). Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 12, 2020 Author Share Posted July 12, 2020 Many thanks, I will contact them Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 12, 2020 Share Posted July 12, 2020 Here are some code snippets. First shows reset protection in native SDX relocatable driver. Second shows a means of obtaining symbol values from a non-SDX, non-relocatable binary. The third and last method is the easiest, and is the one used by The Last Word; simply stealing DOSINI, but calling what DOSINI pointed to as part of your RESET handler. The original contents of DOSINI are restored before the program terminates (by jumping indirectly through DOSVEC). S_ADDIZ SMB 'S_ADDIZ' ; add entry to reset queue ... lda reset_hand_p ldx reset_hand_p+1 jsr s_addiz ; attempt to install reset handler in queue bcc rhok jsr printf .byte 'Reset table full',155,0 rhok ... reset_hand_p .word reset_hand ********************************************************************** jcar_sw equ $7fa jcar_old equ $7fd JFSymbol equ $7EB lda #$ff jsr jcar_sw ; turn on SDX cartridge lda #< symbol ldx #> symbol jsr JFSymbol sta ptr1 stx ptr1+1 jsr jcar_old ; restore SDX cart ROM to original state symbol .byte 'SYMBOL ',0 ; 8 bytes, space padded, NUL terminated ********************************************************************** lda $0c sta warm+1 lda $0d sta warm+2 lda #< warm sta $0c lda #> warm sta $0d Warm jsr $ffff ; execute original DOSINI code (restore original contents before exit to DOS) ; do what you need to do every time reset is pressed here rts I wouldn't use SDX-specific methods unless your program mandates the use of SDX, or is capable of dynamically configuring itself to the host DOS. 1 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 13, 2020 Author Share Posted July 13, 2020 21 hours ago, flashjazzcat said: I wouldn't use SDX-specific methods unless your program mandates the use of SDX Thanks for the information and examples, the reason I'm having problems is that SDX doesn't conform to expected rules where "stealing" DOSVEC, or DOSINI or CASINI remain in force, SDX is reverting them back to it's values, although CASINI does keep my address, it changes to BOOT flag at $9 back to 1, so on reset it doesn't vector through CASINI. In example 1, thats the approach I was looking to do, but I don't know the address for s_addiz, it's not documented where this is. I used a call to $7eb to find s_addiz which it did, but when I look for the address to jump through in the symbol table the address makes no sense and there's nothing there, maybe I have to turn on the SDX cartridge first to get the correct data (thanks for that address). Not sure the last example would work for me as the only part of my code thats running is in a VBI routine, after loading, my program goes back to the command prompt, after that I can use the normal keyboard if needed or I can use a USB keyboard as if it was the 800's normal keyboard. I just need to run the VBI init routine on reset. What I've done seems to work on every DOS I've tried, even disk based Sparta Dos, but not SDX on Incognito. Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 13, 2020 Share Posted July 13, 2020 28 minutes ago, TGB1718 said: Thanks for the information and examples, the reason I'm having problems is that SDX doesn't conform to expected rules where "stealing" DOSVEC, or DOSINI or CASINI remain in force, SDX is reverting them back to it's values, although CASINI does keep my address, it changes to BOOT flag at $9 back to 1, so on reset it doesn't vector through CASINI. This is odd, since The Last Word does nothing but point DOSINI at its own reset handler as shown above, and it remains reset protected. 30 minutes ago, TGB1718 said: maybe I have to turn on the SDX cartridge first to get the correct data (thanks for that address). Yes: this is exactly what jcar_sw is doing in the example, and the SDX ROM will almost certainly need to be enabled in the same way before calling the address obtained by jfsymbol. 34 minutes ago, TGB1718 said: Not sure the last example would work for me as the only part of my code thats running is in a VBI routine, after loading, my program goes back to the command prompt, after that I can use the normal keyboard if needed or I can use a USB keyboard as if it was the 800's normal keyboard. I just need to run the VBI init routine on reset. It should work, but you will need to install a small piece of resident code (TSR) above MEMLO which is reset-proof in the manner described, and which reinstates you VB service routine each time reset is pressed. 36 minutes ago, TGB1718 said: What I've done seems to work on every DOS I've tried, even disk based Sparta Dos, but not SDX on Incognito. Do you have a binary I can run and look at with the Altirra debugger? Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 14, 2020 Author Share Posted July 14, 2020 @flashjazzcat I have a few more thing to try before I send a binary if thats ok, however I've been doing a lot of reading through the manual and found some really good information, but key elements are missing e.g. the addresses of the functions themselves, so I started looking through the toolkit ATR and found what looks like all the info I need but it's in Polish on the toolkit disk under UTILS\PROGRAMM.ING There are several files that detail system calls, unfortunately I can't understand most of it. Do you know of any english versions of those files thanks Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 14, 2020 Share Posted July 14, 2020 4 hours ago, TGB1718 said: There are several files that detail system calls, unfortunately I can't understand most of it. Do you know of any english versions of those files Yes there are a lot of useful looking tools there, but sadly I know of no English versions. FA.COM is the 'Fast Assembler' which allows compilation of SDX native binaries on the A8, but the last I heard, there were a few unresolved bugs. Your best bet remains the SDX Programming guide, which is available in English on the SDX Upgrade Project site. If you wish to write tools and drivers specifically aimed at SDX, I heartily recommend using MADS and making the jump to relocatable SDX binaries. 1 Quote Link to comment Share on other sites More sharing options...
drac030 Posted July 15, 2020 Share Posted July 15, 2020 On 7/10/2020 at 6:01 PM, TGB1718 said: the code steals the DOS vector, but the address in $C and $D don't change which seems wierd, does SDX reset these locations if they change When a program terminates, SDX checks if the DOSINI vector ($0c/$0d) has changed, which means that some TSR wants to be initialized after reset. The new value of that vector is then registered in the init queue, and the original address is restored. Your mistake was checking "if the vector changed" instead of just checking, if the program works as intended. 17 hours ago, TGB1718 said: key elements are missing e.g. the addresses of the functions themselves The functions pointed to by symbols have no fixed addresses, this is why the documentation does not list them. This is the whole purpose of the symbols, by the way... Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 15, 2020 Author Share Posted July 15, 2020 4 hours ago, drac030 said: Your mistake was checking "if the vector changed" instead of just checking, if the program works as intended. Hi, many thanks for you comments, however I was only checking the vectors as my program stopped, was trying to figure out why it wasn't being re-initialized. I've been doing some testing on Altirra, and my VBI route stops after a reset, but not when booting disk based DOS's . 2000 A900 1100 GETDOS LDA #INITDOS&255 2002 850C 1110 STA DOSINI 2004 A906 1120 LDA #INITDOS/256 2006 850D 1130 STA DOSINI+1 2008 EEAC06 1135 INC X1 ; FOR DEBUG 200B 60 1140 RTS 200C 1150 *= $02E2 1160 ; .WORD TEMPADR 02E2 0020 1170 .WORD GETDOS This code sets the vectors, the INC X1 is just to prove this code runs which it does. The following code runs when loaded, but on reset, I want the ports set and the VBI restored. 0600 4C1306 0150 INITDOS JMP SETPORT 0603 000000 0160 KEY .BYTE 0,0,0 0606 000000 0170 KY .BYTE 0,0,0 0609 A907 0180 SETVB LDA #7 060B A206 0190 LDX #VB/256 060D A02C 0200 LDY #VB&255 060F 205CE4 0210 JSR SETVBV 0612 60 0220 RTS 0613 AE02D3 0230 SETPORT LDX PACTL 0616 A938 0240 LDA #56 ; SET BIT 2 TO 0 0618 8D02D3 0250 STA PACTL ; TO SET BITS 0260 ; 7=OUT 4-6=IN 061B A988 0270 LDA #$88 ; 10001000 061D 8D00D3 0280 STA PORTA 0620 8E02D3 0290 STX PACTL 0623 A988 0300 LDA #$88 0625 8D00D3 0310 STA PORTA ; SET ACK HIGH 0628 200906 0320 JSR SETVB 062B 60 0330 RTS 062C 20BF06 0340 VB JSR WAIT0 062F AD00D3 0350 LDA PORTA . . . . . etc. 4 hours ago, drac030 said: The functions pointed to by symbols have no fixed addresses, this is why the documentation does not list them. This is the whole purpose of the symbols, by the way... I thought as much, however I can't find any examples of how to extract the symbol and use the recieved data to call the routines. Just need a pointer(excuse the pun) on how to successfully extract a symbol and then use the resulting data. I've also tried the code snippets @flashjazzcat kindly supplied, but still no joy Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 15, 2020 Share Posted July 15, 2020 This RTC driver for Sparta 3.x variants uses DOSINI to reset protect itself, and if you add 'jmp GotHardware' immediately after '.proc Start' to bypass the host DOS checks, it will install at MEMLO under SDX and the code at '.proc resetHandler' is executed every time system reset is pressed: ultd.s I realise the vast majority of the code may be surplus to requirements, but the method of manipulating DOSINI does work. In your 'resetHandler', you can readjust the VBI vector to suit your needs every time system reset is pressed. If it's set up as shown, 'resetHander' will be executed every time. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 15, 2020 Author Share Posted July 15, 2020 @flashjazzcat thanks for that, I'm not used to that assembler, but I'm sure I can figure it out and will give it a try tomorrow Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 16, 2020 Author Share Posted July 16, 2020 Had a look at the code, but can't really make any sense of it, I've never used MADS, I did download it, but it's no real help. I tried all sorts today but nothing works, I even had the VBI routine itself push the reset vector back into $C & $D which it did, but on reset, the vector was changed back by SDX, in a nutshell SDX is broken in this area I'm just going to "NOT" press reset. I think any "normal" program, one that doesn't go back to the command prompt will survive a warm start if you intercept the DOS vector, but think the problem lies in the fact if I return to the command prompt and in that situation SDX resets the vectors. Maybe if I could get some info on using S_ADDIZ & S_LOOKUP, again total lack of useful information on using these, I did email the SDX team, but got no reply. I had S_LOOKUP work without an error flag, but what addresss is returned in the A and X registers and how do you use it, I thought it pointed to the SYMBOL that you looked up and you could access the structure to get the call address, but when I look at the data at that address (address +0 to address+$C) the data made no sense. Quote Link to comment Share on other sites More sharing options...
dmsc Posted July 16, 2020 Share Posted July 16, 2020 Hi! 2 hours ago, TGB1718 said: Had a look at the code, but can't really make any sense of it, I've never used MADS, I did download it, but it's no real help. I tried all sorts today but nothing works, I even had the VBI routine itself push the reset vector back into $C & $D which it did, but on reset, the vector was changed back by SDX, in a nutshell SDX is broken in this area I'm just going to "NOT" press reset. I don't really understand this problem, as I just tried my E accelerator https://github.com/dmsc/e-accelerator/blob/master/src/efast.asm and it survives reset ok in SDX 4.48 I just do the normal thing, install my reset handler in DOSINI and on reset I reinstall the handler and jump to the old DOSINI value. Have Fun! 1 Quote Link to comment Share on other sites More sharing options...
drac030 Posted July 17, 2020 Share Posted July 17, 2020 (edited) 22 hours ago, TGB1718 said: think the problem lies in the fact if I return to the command prompt and in that situation SDX resets the vectors As I said already, resetting the vectors is intended. Actually bytes 9,a,b,c,d (boot?, dosvec, dosini) are always reset to defaults on program termination (among many other things). As I said as well, if dosini was changed, its new value gets copied to the init queue, actually the same which you want to update with S_ADDIZ. But I found out why it does not work for you: it only works in SDX, when the memlo is raised simultaneously. If memlo is raised, SDX assumes that a "legacy" TSR has been installed, so it checks dosini, and if it is changed too, its value is copied to the init (S_ADDIZ) queue. If memlo is not changed, this phase is skipped. Now your program is on page 6 and does not change memlo, so SDX does not register the changed dosini. This looks like a bug and should be fixed. S_ADDIZ is described in the Programming Guide. S_LOOKUP is too, but it is not very useful for you, as the procedure leaves its results in the structure SYMBOL which requires the previous knowledge of the SYMBOL value. Chicken and egg. The procedure you need is jfsymbol, please search the Prog. Guide PDF for the information on it. Edited July 17, 2020 by drac030 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 17, 2020 Author Share Posted July 17, 2020 4 minutes ago, drac030 said: But I found out why it does not work for you: it only works in SDX, when the memlo is raised simultaneously Many thanks, I was begining to think it was me ? , I nearly changed my program to load at as higher address, but thought that would be a bit daft, if only I had !!! I will do what you suggest and place my program in the free area pointed to by MEMLO and adjust, fingers crossed it will work as expected. Once again, many thanks (I feel my headache ? going) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.