[mention]Seven.FFF[/mention]
You just don’t know how to cook it. Chapter 24.
Whoopsie. Didn’t notice the download link at all.
Mating calls of other species are notoriously difficult to master. Many have tried. Many have failed.
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 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
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.
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
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
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 :(
THanks, perfect! Now I can read the code cleanly at least.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.
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.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?
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
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.”
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
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 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.
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 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.
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
Another piece of the puzzle, cheersAst 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.”
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.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.
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.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.
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
Fuse > fmfconv (Fuse utilities), maybe?
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.
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
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?
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
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.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?)
Thanks! Your suggestion works nicely (on 5.03)!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.)
This is great, thanks. I haven't got this working yet (lack of time). But I will try to do soHikaru 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.
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.
Aaargh no, Everything looks the same between 5.03 and 5.04T, unless i missed something.
Hi, I suppose that's because you typed "CODE" in the string as four separate characters instead of the single character 175.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.
Code: Select all
LET d = 15363 + 256 * PEEK (15363<>195)
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
Code: Select all
IF d = 15619 THEN POKE 25005,61
IF d = 15363 THEN POKE 25005,60
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]
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"
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