Write binary data to TRD from ASM

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Write binary data to TRD from ASM

Post by Ast A. Moore »

Seven.FFF wrote: Mon Dec 11, 2017 2:46 pm Ha, thanks! That's the one I have. I translated the TOC (and the first 20 pages), and I think there is nothing about TR-Dos at all in this book. Even the cover says "ZX Spectrum for users and programmers, no mention of TR-Dos.
[mention]Seven.FFF[/mention]
You just don’t know how to cook it. Chapter 24. ;)
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Yay that's it, thanks.

He wrote two different books, ISBN 5-7190-0025-9 (Spectrum and TR-Dos) and 5-87472-004-9 (just Spectrum). The online text is on your link is correct, but the download is linked to the wrong book, ha.

Ta!
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Anyway my asm calls aren't working, even Hikaru's reference asm load example. My basic calls work fine. At work now but I will try and debug later.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Write binary data to TRD from ASM

Post by Ast A. Moore »

Seven.FFF wrote: Mon Dec 11, 2017 2:58 pm The online text is on your link is correct, but the download is linked to the wrong book, ha.
Whoopsie. Didn’t notice the download link at all.
Seven.FFF wrote: Mon Dec 11, 2017 3:00 pm Anyway my asm calls aren't working, even Hikaru's reference asm load example. My basic calls work fine.
Mating calls of other species are notoriously difficult to master. Many have tried. Many have failed.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Write binary data to TRD from ASM

Post by Hikaru »

Seven.FFF wrote: Mon Dec 11, 2017 2:19 pm Hi [mention="Hikaru"]Hikaru[/mention], I wonder if you could link me to your copy of 'ZX-Spectrum & TR-DOS Для пользователей и программистов', if you have it as a scan. The one I have only goes up to page 114. It's either a different book or it's missing all the good stuff :)
Heys. This is the scanned version that I'm using. But it's in .DJVU format, not sure if that's useful for google translate and whatnot. Like Ast said, it should be available to read online at zxpress.ru as well, although their OCR quality tends to leave much to be desired.

Seven.FFF wrote: Mon Dec 11, 2017 3:00 pm Anyway my asm calls aren't working, even Hikaru's reference asm load example. My basic calls work fine. At work now but I will try and debug later.
One reason might be because, as a general rule, code like that or similar using #3D13 functions is intended to execute after the DOS is fully initialized, for instance as part of a loader. So for instance if you just run it from a snapshot, it is very likely not going to work.

Actually, this is something I'd like to know myself, because there's supposedly an 'init' function located at 15649 that is responsible for initializing the TR-DOS system variables (mentioned at p.190), but I've never had any success with it alone. Perhaps it needs something else besides that.
Inactive account
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

I've made a little progress. The error returned in $5D0F was 1 No file. i wasn't padding my filename with spaces in the file descriptor.

Now I get error 12 The channel is not open in $5D0F. But I have already been using TR-DOS - the code this is running from is loaded from basic with a TR-Dos call, so Dos must be initialised, surely?

My (rather chunky) basic loader looks like this:

Code: Select all

10 CLEAR 32767: BORDER 0: PAPER 0: INK 7: BRIGHT 1: FLASH 0: CLS 
20 PRINT AT 7,9; INK 2;"j"; INK 6;"e"; INK 3;"t"; INK 5;" p"; INK 2;"o"; INK 4;"w"; INK 3;"e"; INK 6;"r "; INK 3;"j"; INK 5;"a"; INK 6;"c"; INK 4;"k"; INK 7;AT 10,12;"LOADING..";AT 12,11;"3ArPy3KA...": PLOT 106,77: PLOT 106,78: DRAW 4,0: PLOT INVERSE 1;107,77: DRAW INVERSE 1;2,0: PLOT 121,78: PLOT 125,78: PLOT INVERSE 1;121,75: DRAW 3,0: PLOT INVERSE 1,122,74: DRAW INVERSE 1;2,0
30 RANDOMIZE USR 15619: REM :LOAD "jpj04" CODE 32768
40 RANDOMIZE USR 32768: RANDOMIZE USR 15619: REM :LOAD "jpj01" CODE 32768 
50 RANDOMIZE USR 15619: REM :LOAD "jpj02" CODE 56323
60 RANDOMIZE USR 15619: REM :LOAD "jpj03" CODE 65380
70 RANDOMIZE USR 32768
Nothing here loads any lower than $8000 [actually my stack is just below $8000, but surely it doesn't go down far enough to cause a problem with TR-Dos?], and it all gets loaded and runs fine.

Part of the code in jpj01 is my asm loader, which ends up at $AA00 and looks like this:

Code: Select all

                        di
                        ld hl, FileDescriptor
                        ld c, $13                       ; #3D13 C=#13: copy the file descriptor to TR-DOS system variables
                        call $3D13
                        di
                        xor a
                        ld ($5CF9), a                   ; #00: load, #FF: verify
                        dec a                           ; load the file to an address in HL
                        ld hl, $8000
                        ld c, $0E
                        call $3D13                      ; #3D13 C=#0E: load/save file
                        ei
                        ld a, ($5D0F)                   ; TR-Dos error is reported back here as "12 The channel is not open"
                        jp $8000                        ; This is supposed to be the code in jpj06. But it never gets loaded here.
FileDescriptor:
                        db "jpj06   "                   ; 8 characters
                        db "C"                          ; file type: code
I’m in IM 1 when it runs, and I’ve tried it with interrupts both enabled and disabled. I made sure it was in unpageable memory in case something was getting switched out unexpectedly.

The code in jpj06 is just a trivial test designed to be highly visible.

Code: Select all

BorderTest:             ld a, 2
                        out ($FE), a                    ; Magenta border
                        ld a, 5                         ; then
                        out ($FE), a                    ; Cyan border
                        jp BorderTest                   ; forever...
                                                        ; Actually this needs to be jr BorderTest, because I relocate the code,
                                                        ; but it's moot because it never gets loaded :(
This is my sadface TRD image. The failing loader runs when you hit the 0 key on the menu. Pentagon 128 only - the multicolour timings don’t work with Scorpion.

Any idea at all what gives?
Last edited by Seven.FFF on Tue Dec 12, 2017 2:21 am, edited 5 times in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Hikaru wrote: Mon Dec 11, 2017 6:05 pm Heys. This is the scanned version that I'm using. But it's in .DJVU format, not sure if that's useful for google translate and whatnot. Like Ast said, it should be available to read online at zxpress.ru as well, although their OCR quality tends to leave much to be desired.
THanks, perfect! Now I can read the code cleanly at least.

I tried OCRing a few pages with Tesseract high-quality Russian training data, and the results were not great either. I think it needs special training for that font.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Write binary data to TRD from ASM

Post by Hikaru »

Seven.FFF wrote: Tue Dec 12, 2017 1:01 am I've made a little progress. The error returned in $5D0F was 1 No file. i wasn't padding my filename with spaces in the file descriptor.

Now I get error 12 The channel is not open in $5D0F. But I have already been using TR-DOS - the code this is running from is loaded from basic with a TR-Dos call, so Dos must be initialised, surely?
Meh. It fails since it's actually doing a 'verify' operation - because guess what, there are actually two variables responsible for this, the second one being #5D10. Neither Rodionov's book nor the disassembly mention that one (I don't even see it listed as a TR-DOS variable), although it's possible to trace where the check occurs in the disassembly.
It looks like [mention]keith56[/mention] has figured this out on his own previously, since both #5CF9 and #5D10 are being set up in his code.

With this in mind, the loader example finally becomes:

Code: Select all

LoadExample
	ld hl,FileDescriptor
	ld c,#13		;#3D13 C=#13: copy the file descriptor to TR-DOS system variables
	call #3D13
	xor a
	ld (#5CF9),a		;#00: load, #FF: verify
	ld (#5D10),a
	dec a			;load the file to an address in HL
	ld hl,MyAddress
	ld c,#0E
	call #3D13		;#3D13 C=#0E: load/save file
	ret

FileDescriptor
	DEFB "FILENAME"		;8 characters
	DEFB "C"		;file type: code
Fingers crossed! xD

On a bit unrelated note,
1. OUTputting a random value from #5B5C to (#7FFD) at the start of your main code and hoping for the best isn't exactly a good idea. There's no telling which ROM/screen/page that would activate, or indeed whether you won't be screwed the next time an IM1 interrupt comes. It's better to set both of them to a known value of your own if you have to.
2. The correct spelling for the last option is 'Обнулить рекорды' (or 'Обнуление рекордов'). Regardless that's pretty cool I think, you don't often see people translating their games to Russian on their own. :)
Inactive account
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Write binary data to TRD from ASM

Post by Ast A. Moore »

Hikaru wrote: Tue Dec 12, 2017 1:03 pm Neither Rodionov's book nor the disassembly mention that one (I don't even see it listed as a TR-DOS variable), although it's possible to trace where the check occurs in the disassembly.
Well, there’s this, which describes the variable at #5d10 as “MSB of TR-DOS error code, cleared on 15616 calling, should be cleared when you call 15635.”

Then there’s the manual for BETA 128 interface itself, which isn’t particularly useful, but has a little assembly snippet nevertheless.

Code: Select all

CHADD  EQU   23645         Location of SOS variable CHADD
       ORG   XXXXX         XXXX=address of this code
       LD    HL,(CHADD)    Start to save true CHADD
       LD    (TEMP), HL    Temporary store of true CHADD
       LD    HL,49000      Address of SAVE routine
       LD    (CHADD),HL    CHADD now points to our routine
       CALL  15363         ENTER TRDOS SAVE via chadd
       JP    BACK          Jump to program point from which
                           the whole routine was called
       LD    HL,(CHADD)    
       LD    (TEMP),HL     The routine for LOAD now repeats
       LD    HL,49500      the above with just the address
       LD    (CHADD),HL    changed.
       CALL  15363         
BACK   LD    HL,(TEMP)     Start to restore CHADD
       LD    (CHADD),HL    Reload original CHADD
       RET                 Return from where you came
TEMP                       Label allocating memory for
                           temporary storage
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Yay, ld (#5D10),a makes it work! Cheers guys :)

Will write a longer reply later.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Hikaru wrote: Tue Dec 12, 2017 1:03 pm Meh. It fails since it's actually doing a 'verify' operation - because guess what, there are actually two variables responsible for this, the second one being #5D10. Neither Rodionov's book nor the disassembly mention that one (I don't even see it listed as a TR-DOS variable), although it's possible to trace where the check occurs in the disassembly.
Awesome, thanks. I will get there eventually. Somehow it's harder integrating new info in a foreign language until you reach a tipping point. I don't know how you multilingual guys do it, but you rock.
Hikaru wrote: Tue Dec 12, 2017 1:03 pm 1. OUTputting a random value from #5B5C to (#7FFD) at the start of your main code and hoping for the best isn't exactly a good idea. There's no telling which ROM/screen/page that would activate, or indeed whether you won't be screwed the next time an IM1 interrupt comes. It's better to set both of them to a known value of your own if you have to.
You're right. This is code that's I copied and pasted between projects, and somehow I have strayed away from the original intention - which was to set up the environment in a deterministic state after external loaders (mostly DivMMC/exsDOS) have dumped you into the starting point. Clearly I'm not doing what I intended here!
Hikaru wrote: Tue Dec 12, 2017 1:03 pm 2. The correct spelling for the last option is 'Обнулить рекорды' (or 'Обнуление рекордов'). Regardless that's pretty cool I think, you don't often see people translating their games to Russian on their own. :)
Thanks! I have had help I'm afraid. Mikhail Sudakov (Castlevania Spectral Interlude) kindly offered to help with translations. He already warned me about context and word-ending changes. I woke up to the same message from him as I did from you!! Обнулить таблицу рекордов was too long - and I just now saw that he gave me Обнулить рекорды as an alternative right from the beginning :D
Ast A. Moore wrote: Tue Dec 12, 2017 1:46 pm Well, there’s this, which describes the variable at #5d10 as “MSB of TR-DOS error code, cleared on 15616 calling, should be cleared when you call 15635.”
Another piece of the puzzle, cheers :)
Ast A. Moore wrote: Tue Dec 12, 2017 1:46 pm Then there’s the manual for BETA 128 interface itself, which isn’t particularly useful, but has a little assembly snippet nevertheless.
I had been trying to get this one working too. This is the "official" API that passes tokenized basic commands to TR-Dos. I ran into issues with my tokenization - the stuff in my reference REM statements were being tokenised as "C", "O", "D", "E" etc and it was causing confusion with some other problems I was having at the same time. It clearly works in my basic loader though, so I could revisit this later. But I don't really need to.

I now have an asm loader that loads everything except $6000-$7FFF (and updates my progress bar). Loading this block is breaking TR-Dos, so I need to debug to see what's going on. I don't really want to rearchitect the game because the codebase is shared with the non-Pentagon version (and space in unpageable RAM is TIGHT!!), so I will have to figure out a way to have code from $6000-> and stack from <-$5FFF, and still keep Dos working well enough to save my high scores every game end. Also I'm using the ZX Printer buffer as a general purpose buffer in a ton of places, so will need to figure out something different there.

Are there any special Pentagon-only horizontal MMU schemes that would help, by any chance? Mostly a rehetorical question - I have lots of reading to do... :)
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Write binary data to TRD from ASM

Post by Ast A. Moore »

Something interesting for you to investigate. This version of Battle Command has an unusual loader. It displays a scrolling text and plays music while loading the game. Might be worth reverse engineering.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Write binary data to TRD from ASM

Post by Hikaru »

Seven.FFF wrote: Wed Dec 13, 2017 7:39 pm I now have an asm loader that loads everything except $6000-$7FFF (and updates my progress bar). Loading this block is breaking TR-Dos, so I need to debug to see what's going on. I don't really want to rearchitect the game because the codebase is shared with the non-Pentagon version (and space in unpageable RAM is TIGHT!!), so I will have to figure out a way to have code from $6000-> and stack from <-$5FFF, and still keep Dos working well enough to save my high scores every game end. Also I'm using the ZX Printer buffer as a general purpose buffer in a ton of places, so will need to figure out something different there.
File level operations use a temporary extra buffer of about 256 bytes that is located after the regular TR-DOS variables (110-something bytes). Any BASIC data in the area gets temporarily saved higher in the memory. So I'd suggest you to clear the BASIC part of your loader first. 24576 doesn't seem that low in the memory, so that might just be enough to make it work.

I think this should do the trick, but don't take my word for it. :)

Code: Select all

ClearBasic
	ld hl,(#5C59)		;E-LINE: end-marker of the current variables area - the '80-byte'
	ld de,(#5C53)		;start of BASIC program area
	dec hl
	call #19E5		;RECLAIM-1
Inactive account
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Still messing around with this. I had several errors in how I was saving my binary chunks and also how I was loading them. No wonder it wasn't working. Hopefully will have time to finish debugging this weekend. Thanks [mention]Hikaru[/mention].

In the meantime I knocked up a repeating attract thingy on the menu. Amazingly I managed to get it locked to the alien timings so it doesn't drift out of sync. It's a bit jerky cos I don't have a good gif grabber that works with Pentagon timings.

Image
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Write binary data to TRD from ASM

Post by Ast A. Moore »

Seven.FFF wrote: Sat Dec 16, 2017 2:33 am It's a bit jerky cos I don't have a good gif grabber that works with Pentagon timings.
Fuse > fmfconv (Fuse utilities), maybe?

The menu looks splendid, by the way. Love the proportional font.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Another thing I'm stuck with - at the conceptual level.

I'm trying to save two files to disk. One is only 1 byte (the selected language, 1 sector), the other is 960 bytes (the high score table), 4 sectors.

I can write files with call #0B (Save <C> file). This only works if I save a new file, though. If I save an existing file, I get error 0 returned, suggesting it worked, but the contents don't change.

I can also delete the file with call #12. Then saving it works, but creates a new file at the end of the catalog, and leaves the sectors of the original file marked as deleted.

I would prefer to save the same file repeatedly, with the same filename, in the same sector. I'd rather not MOVE the disk programmatically to reclaim the deleted sectors.

There exist the sequential and random access files that can be used with OPEN #/PRINT #/INPUT#/CLOSE #. Will they do the job? Can they be only called the "official" API way, by placing tokenized Basic commands in memory? It looks like these have the disadvantage of not being able to be used on <C> files, as they have their own special <#> type.

There also exist PEEK/POKE "filename"Buffer_address, Sector_numbers commands. It looks like these can be used to read and write <C> files. Do they also have to be used with the "official" API?

There are calls to read (#05) and write(#06) individual sectors, but I can't see how to read the track and sector numbers from the catalogue. I know what my initial sectors are, as I built the disk, but I would corrupt the disk if I assumed that, as someone might do their own disk operations that moved the file.

What do you think the best and easiest way to do this is?

I also discovered that writing to a read-only disk displays the nice Retry, Ignore, Abort message, which clears my screen. I worked round this by saving and restoring the screen before and after all my disk commands. I read in Russian about a service screen - is this what's happening here? Has my screen already been saved, and I could restore it by calling TR-DOS?
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Write binary data to TRD from ASM

Post by Hikaru »

The whole 'leaving gaps' issue is normal in a sense, and is expected of programs that operate on the file level. Notice that, as long as the file you're working with is the last file on the disk, no gap would be left if it is deleted and subsequently saved back.
On the other hand, doing a MOVE within a game program is certainly an overkill and not what most people would expect. It's a bit like if a PC game tried to defragment the HDD on its own!

Random access and other unusual formats are best avoided. I doubt most people have any idea what those are (myself included), and I don't remember a single program that used those on a regular basis for its functionality.

(Why not just keep a single 961 byte file? Loading 4 sectors and 1 sector takes virtually the same time, and this is more efficient in terms of using the disk space.)

Seven.FFF wrote: Sat Dec 16, 2017 10:05 pm There are calls to read (#05) and write(#06) individual sectors, but I can't see how to read the track and sector numbers from the catalogue. I know what my initial sectors are, as I built the disk, but I would corrupt the disk if I assumed that, as someone might do their own disk operations that moved the file.

You can use a combination of #0A and #08 to read the track/sector information, and then read/save the data with #05 and #06. Sort of like this:

Code: Select all

Overwrite
	ld hl,FileDescriptor
	ld c,#13		;copy the file descriptor to TR-DOS system variables
	call #3D13
	ld a,9			;find a file with matching 9 first bytes in the descriptor (filename and type)
	ld (#5D06),a		;uses the extra buffer, as do file level operations
	ld c,#0A
	call #3D13
	ld a,c
	inc c			;C will contain #FF if the file with this name wasn't found
	jr z,NoFile
	ld c,#08		;#3D13 C=#08: loads a file descriptor specified in A at #5CDD
	call #3D13
	ld hl,SaveAddress	;or LD HL,(#5CE6) to assume the same saving address as in the file descriptor
	ld de,(#5CEB)		;file descriptor: track and sector
	ld a,(#5CEA)		;file descriptor: length, sectors
	ld b,a
	ld c,#06		;#3D13 C=#06: save sectors
	call #3D13
	ret
Another option is to do the #0A/#08 thing once in the beginning, store the file locations/lengths in memory, and then just use #05/#06 as needed. This would help to reduce unnecessary drive head movements to track 0 and back (is faster). Also, #05/#06 have the advantage of not requiring the extra buffer in order to work.

Seven.FFF wrote: Sat Dec 16, 2017 10:05 pm I also discovered that writing to a read-only disk displays the nice Retry, Ignore, Abort message, which clears my screen. I worked round this by saving and restoring the screen before and after all my disk commands. I read in Russian about a service screen - is this what's happening here? Has my screen already been saved, and I could restore it by calling TR-DOS?

It's definitely not doing anything that convenient. :lol:

The correct way to go about this is to intercept the Retry/Abort/Ignore message. The following code comes from my unfinished #3D13 driver so again, pretty much untested, but I believe it should be something along these lines.

Code: Select all

OneTimeInit
	ld a,#C3		;#5CC2: is used by TR-DOS to call the BASIC 48 ROM routines, typically contains a RET
	ld (#5CC2),a		;is also executed upon error during a #3D13 call (see #0201)
	ld hl,ErrorHandler	;here, it is set to 'JP ErrorHandler'
	ld (#5CC3),hl
	ret

DOS
	ld,(iy+0),#FF		;set #5C3A to 'no error', this is checked before exiting in #0201 but isn't reset by the DOS
	push hl
	ld (#5C3D),sp		;#5C3D: ERRSP
	ld hl,0			;zero out the two byte error code at #5D0F
	ld (#5D0F),hl
	pop hl
	call #3D13
	ret z			;Z: OK, NZ: ERROR
	ld a,c			;C = error code
	cp 20
	jr z,Break		;20: break
	sub 6
	jr z,NoDisc		;6: no disc
	dec a
	jr z,DiscError		;7: disc error (abort)
	jr UnhandledError


;intercept the Retry/Abort/Ignore message
ErrorHandler
	ex (sp),hl		;will eventually return if entered upon NO DISC or ABORT, with the error code in C
	push af
	ld a,h
	cp #0D			;the RIA situation is indicated by #0D6B on the stack (both 5.03 and 5.01)
	jr z,.ria
	pop af			;otherwise, we continue
	ex (sp),hl		;LIST, CAT, FORMAT and the like display additional messages, not handled here
	ret
.ria
	ld hl,12		;10+2
	add hl,sp
	ld sp,hl
	call RIAMessage		;our custom RIA procedure here, A should return an "R"/"I"/"A" ASCII code
	ld hl,#3F7E		;5.01 uses #3F74
	push hl			;return the user's response to TR-DOS
	jp #3D2F
Inactive account
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

keith56 wrote: Sat Dec 09, 2017 12:32 am it seems my problem was not the code, or trdtool, but something with my emulator, I was using TR-DOS 5.04 (UK) and it was somehow failing to even save a bas file to a newly formatted disk from it's own interface (It was renaming the disk??!!)

Well, I've moved to 6.04 (Russian) and the example works perfectly, so I don't know if I had a corrupt rom, or something messed up on my emulator, but all is good now! - out of interest, what is the best rom to use for testing (compatibility wise?)
I've just hit this one too. My Uno is loaded with 5.04T (UK), and doesn't even get past the first DOS command in the basic loader. I think this might be the version where the entry points have changed. I need to write a good detection routine.

Somewhere I saw a handy list of differences between several TR-DOS versions, but I can't find it now.
Hikaru wrote: Sun Dec 17, 2017 8:06 am The whole 'leaving gaps' issue is normal in a sense, and is expected of programs that operate on the file level. Notice that, as long as the file you're working with is the last file on the disk, no gap would be left if it is deleted and subsequently saved back.
On the other hand, doing a MOVE within a game program is certainly an overkill and not what most people would expect. It's a bit like if a PC game tried to defragment the HDD on its own!

Random access and other unusual formats are best avoided. I doubt most people have any idea what those are (myself included), and I don't remember a single program that used those on a regular basis for its functionality.

(Why not just keep a single 961 byte file? Loading 4 sectors and 1 sector takes virtually the same time, and this is more efficient in terms of using the disk space.)
Thanks! Your suggestion works nicely (on 5.03)!
Hikaru wrote: Sun Dec 17, 2017 8:06 am Another option is to do the #0A/#08 thing once in the beginning, store the file locations/lengths in memory, and then just use #05/#06 as needed. This would help to reduce unnecessary drive head movements to track 0 and back (is faster). Also, #05/#06 have the advantage of not requiring the extra buffer in order to work.
This is great, thanks. I haven't got this working yet (lack of time). But I will try to do so :)
Hikaru wrote: Sun Dec 17, 2017 8:06 am The correct way to go about this is to intercept the Retry/Abort/Ignore message. The following code comes from my unfinished #3D13 driver so again, pretty much untested, but I believe it should be something along these lines.
Ah, brilliant, thanks! I tried to do this before but couldn't figure it out. Much better way of handling it. I want the language selection to always write back to the disk when you start, but silently fail if it is write protected or something else happens. Resetting the high score table should only happen when you pick that option, and should fail verbosely. That why I originally had them as separate files. I can still do it the way I want having them share a file, it's just a little more complicated.
Last edited by Seven.FFF on Fri Dec 22, 2017 9:57 pm, edited 1 time in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Seven.FFF wrote: Fri Dec 22, 2017 9:12 pm I've just hit this one too. My Uno is loaded with 5.04T (UK), and doesn't even get past the first DOS command in the basic loader. I think this might be the version where the entry points have changed. I need to write a good detection routine.
Aaargh no, Everything looks the same between 5.03 and 5.04T, unless i missed something.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

Actually I'm completely wrong. Everything is working on 5.04T in SpecEmu. On the Uno, everything works except one of my #3D13 load commands, when the progress bar is about 85%.

I will need to hook up a debugger to see what is happening.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Write binary data to TRD from ASM

Post by Hikaru »

Good to know. I've had a similar experience recently trying to figure out the (low-level) +3DOS stuff. Those multi-byte OUTs/INs, madness. :lol:
Inactive account
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Write binary data to TRD from ASM

Post by Alessandro »

Seven.FFF wrote: Wed Dec 13, 2017 7:39 pm I had been trying to get this one working too. This is the "official" API that passes tokenized basic commands to TR-Dos. I ran into issues with my tokenization - the stuff in my reference REM statements were being tokenised as "C", "O", "D", "E" etc and it was causing confusion with some other problems I was having at the same time. It clearly works in my basic loader though, so I could revisit this later. But I don't really need to.
Hi, I suppose that's because you typed "CODE" in the string as four separate characters instead of the single character 175.

Tokenization of BASIC commands is actually more useful to me since it allows me, with a simple trick, to modify the code of the TR-DOS file management program, so that it can be compatible with the Brazilian clones of the Beta Disk interface, i.e. Arcade AR-20, IDS-91, CBI-95, which point of access for the commands is 15363 instead of 15619. This was pointed to my attention by Flávio Massao Matsumoto, and I have employed it in many of my games.

Code: Select all

LET d = 15363 + 256 * PEEK (15363<>195) 
If d = 15619 then it's a standard Beta interface; if d = 15363 the interface is a Brazilian clone. It's then easy to modify the most significant byte of the call to the interface OS in the loading routine to 61 or 60 in order to have the routine work in both cases.

If for instance the call routine is located at 25000:

Code: Select all

25000 034 093 092 LD (CHADD),HL 
25003 205 003 061 CALL 15619  
25006 042 181 097 LD HL,(TEMP)
25009 034 093 092 LD (CHADD),HL	
25012 201 RET
25013 DEFS 2
substituting the byte at 25005 from the BASIC loader before launching the program containing the routine will change 15619 to 15363:

Code: Select all

IF d = 15619 THEN POKE 25005,61
IF d = 15363 THEN POKE 25005,60
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Write binary data to TRD from ASM

Post by Seven.FFF »

That’s very useful, thanks Alessandro!
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Write binary data to TRD from ASM

Post by Alessandro »

You are welcome :)

Of course HL should point to the BASIC command of the block you wish to load. Another example, related to my post above (loading routine at 25000):

Code: Select all

  
  LD HL, CHADD
  LD (TEMP),HL
  LD HL,BLOCK
  CALL 25000
  RET

BLOCK:
  DEFB 234  ; REM
  DEFM ":"
  DEFB 239  ; LOAD
  DEFB 34   ; "
  DEFM "FILENAME"
  DEFB 34   ; "
  DEFB 175  ; CODE
  DEFB 13   ; [ENTER]
Notice that the CODE function is stored as character 175.
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Write binary data to TRD from ASM

Post by Alessandro »

Update. This comes from the forthcoming new version of the Al's Double Bill compilation.

Here is the "boot" program for the disk (any BASIC program named "boot" will be executed when RUN is entered at the TR-DOS prompt):

Code: Select all

10 BORDER NOT PI: PAPER NOT PI: INK NOT PI: BRIGHT SGN PI: CLEAR VAL "24499"
20 LET d=VAL "15363"+VAL "256"*(PEEK 15363<>195)
30 RANDOMIZE USR d : REM : LOAD "ADB" CODE
40 RANDOMIZE USR VAL "24500"
Line 20 checks if PEEK 15363 = 195; in this case, d = 15363 and a non-standard Beta Disk interface is connected.

And here is the code for the first MC block loaded from disk. First, it checks the type of Beta Disk interface - standard or not -, then it "recognizes" whether it is running on a 48K or not. Finally, it loads the main selection program accordingly.

The first trick was suggested to me by Einar Saukas, the second by Flávio Matsumoto.

Code: Select all

  ORG 24500
  
  KEY_VAL EQU 24587
  CHADD   EQU 23645
  
  CALL CLEANER
  
  LD HL, ADB_SCR
  LD DE, 16384
  CALL dzx7
  
  LD B,150
  CALL DELAY
  
  LD A,(15363)
  CP 195
  JR NZ, MEMORY     ; if PEEK 15363 <> 195 then a standard Beta Disk is connected

  LD A,60
  LD (KEY_VAL),A      ; ...otherwise it is a clone and the location is modified

MEMORY:

  LD A,(2899)
  CP 165
  JR NZ,ZX128
  
ZX48:

  LD HL,(CHADD)
  LD (TEMP),HL
  LD HL,ADB48
  CALL TRDOS
  JP 32770

ZX128:

  LD HL,(CHADD)
  LD (TEMP),HL
  LD HL,ADB128
  CALL TRDOS
  JP 32770

DELAY:

  HALT
  DJNZ DELAY
  RET

CLEANER:

  LD A,64            ; (64 for BRIGHT 1)
  LD (23693),A       ; PAPER 0, INK 0, BRIGHT 1
  LD (23624),A       ; the last two rows have INK and PAPER set to 0
  CALL 3503          ; CLS
  RET  

TRDOS:

  LD (CHADD),HL
  CALL 15619         ; recalls the TR-DOS loading routine (the last byte here is KEY_VAL)
  LD HL,(TEMP)	     ; reloads CHADD's original value in HL
  LD (CHADD),HL	     ; restores CHADD's original value
  RET

TEMP:	  DEFS 2     ; CHADD's original value is stored here   

ADB48:

	DEFB	234	; REM
	DEFM	":"
	DEFB	239	; LOAD
	DEFB	34	; "
	DEFM	"ADB-48"
	DEFB	34	; "
	DEFB    175     ; CODE
	DEFB	13      ; [ENTER]  

ADB128:

	DEFB	234	; REM
	DEFM	":"
	DEFB	239	; LOAD
	DEFB	34	; "
	DEFM	"ADB-128"
	DEFB	34	; "
	DEFB    175     ; CODE
	DEFB	13      ; [ENTER]

  INCLUDE "dzx7_agileRCS.asm"  ; Einar Saukas's RCS-ZX7 integrated decompressor

ADB_SCR:  INCBIN "ADB-ZX7.bin" ; compressed loading screen 
Post Reply