Last file name string.

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Last file name string.

Post by MonkZy »

Is it possible to retrieve the file name of the most recently loaded file? I have used the memory browser on Fuse and have seen the filename in RAM, is there a way of determining where the name will be stored?
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Last file name string.

Post by RMartins »

Fuse is open source, so you can modify it to export that info.
Either save it to a file or expose a service (at a port number) that allows you to query whatever you want.
User avatar
1024MAK
Bugaboo
Posts: 3104
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Last file name string.

Post by 1024MAK »

Are you asking if BASIC can access this information, if machine code can get it, or if the information can be got from an emulator?

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Last file name string.

Post by Ast A. Moore »

MonkZy wrote: Wed May 02, 2018 5:32 pm Is it possible to retrieve the file name of the most recently loaded file? I have used the memory browser on Fuse and have seen the filename in RAM, is there a way of determining where the name will be stored?
If it was loaded by the ROM routine, then yes, in some circumstances. It is saved in the workspace, and the actual space for it is reserved by the BC-SPACES routine. It doesn’t stay there forever, though. I mention it here (a long read; skip to Section 5, “The Inventory of Useless Skills”).

You can try the following BASIC program to fetch the name the last loaded block:

Code: Select all

10 LOAD "" CODE
20 LET n=(PEEK 23649+PEEK 23650*256)+18
30 PRINT CHR$ PEEK n: LET n=n+1
40 PAUSE 0: GOTO 30
It’s pretty volatile, but in assembly, it’s trivial to save the file name immediately after the loading has finished and save it elsewhere for retrieval later.
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
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

@RMartins At the moment attempting to patch Fuse is a bit beyond my abilities. Maybe someday I will look into it, I have a few ideas of add-ons for Fuse.

@1024MAK I was hoping to get the data via BASIC to use in a BASIC program. I have done some experimentation and it would seem you would have to call the ROM load routine with machine code then inspect/store the data before exiting back to BASIC.

@Ast A. Moore There is some really useful information in your 24 years in the making article. I will try your BASIC routine a little later on, I had zero joy extracting the data via BASIC myself. Any BASIC code seems to get processed in the same area in RAM where the filename data is stored. My understanding of ROM routines is minimal, I am reading a book The Spectrum Operating System by Steve Kramer, it is a lot to take in. I am focusing on the load/save routines for now.

[edit] Kramer with a K
User avatar
1024MAK
Bugaboo
Posts: 3104
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Last file name string.

Post by 1024MAK »

Not sure how quickly data in the workspace gets overwritten, but if using string functions does use the workspace, you may need to use PEEK and POKE to copy the data somewhere else (I'm assuming that simple functions and commands do not need to use the workspace). Of course using a small bit of machine code solves that problem.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Last file name string.

Post by RMartins »

I'm not sure of you are aware, but instead of:
LOAD ""

you can do:

LOAD "filename"

So, in principle, if you know what you are loading, then you already know what was loaded, or not, in case of error.

This only does not work, if you are trying to determine, what is next in the tape, to help the suer, to rewind or something, like some games used to do, when loading levels.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

I have made some progress with this problem.

This short piece of machine code is 'semi' working :

Code: Select all

	org 60000

	ld hl,0				;HL=0 ,address to load data block (0=take address from header)
	
	ld a,1
	ld (23668),a			;set T ADDR to 1 (1=Load 2=Verify)

	ld ix,dummy_header		;set IX to point to dummy header location

	call 1889			;call load ROM routine

	ret
	
dummy_header:
	defb 3				;(2)file type 3=CODE
	defb 255,0,0,0,0,0,0,0,0,0	;(3-12)file name (first byte is 255 to ignore)
	defb 0,0			;(13-14)file size (0 means ignore)
	defb 0,0			;(15-16)load address (0 means use address from incoming header)
	defb 0				;(17)ignore
	defb 0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0 		;padding for incoming header
When executed the code will load a CODE file and leave the incoming header data in RAM at 'dummy_header+17'. The problem is, the ROM call always skips past one file and then loads the file directly after it. I am testing using Fuse and a TZX which contains multiple CODE files of 768 bytes (Imported_Fonts.tzx). Does anyone have experience with loading CODE files with a standard header from machine code? Ultimately I wish to make a replacement for LOAD""CODE leaving the header data in RAM.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Last file name string.

Post by Ast A. Moore »

MonkZy wrote: Mon May 07, 2018 2:08 pm Does anyone have experience with loading CODE files with a standard header from machine code? Ultimately I wish to make a replacement for LOAD""CODE leaving the header data in RAM.
Nothing could be easier. You do it the same way you load any block from tape, specifying the flag byte (which, in case of the header is 0):

Code: Select all

	ld ix,50000	;destination address
	ld de,11	;length (header byte+10 bytes of the header itself)
	xor a		;zeroize A to load the header
	scf		;set carry (load, rather than verify)
	call 1366
At address 50000, you’ll have eleven bytes of your data: first the type byte (e.g. 3 for CODE, 0 for BASIC, etc.), then the ten bytes of the header itself padded with spaces. I talk about it in the article I linked above.
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
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

This call only loads the header block. I need to load the header block and also the data block defined by the header. I think my code is using the correct entry point to achieve this, it is just not considering the first file to be a match with the dummy header data I have given. It always matches and loads the second file it finds, leaving the header data in RAM to read via PEEK's. As far as I can tell the only header byte that needs to match is the type (1st dummy header byte) .I have given 255 (FF) as the first name character which denotes a null name field. Zero for data length should make the load routine take the length from the incoming header.

I have also tried giving the dummy header the correct data for the file size and destination but it still always skips the first file it finds and loads the next.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

I could use your entry point to read the header, and then load the data block with a second call.....this also keeps the filename off of the screen.

Back to the text editor.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

This is a treble post (hat-trick?)

[mention]Ast A. Moore[/mention] You sexy Bas**rd!

Final code, and problem solved!!

Code: Select all

	
	org 60000

	ld ix,dummy_header			;set IX to point to dummy header location
	ld de,17				;load header bytes
	xor a					;zero A for header
	scf					;set carry for LOAD not VERIFY

	call 1366				;call load ROM routine

	ld ix,(dummy_header+13)			;set IX to data block destination from header
	ld de,(dummy_header+11)			;set DE to data block length from header
	ld a,255				;set A to FF for data block
	scf					;set CF for LOAD

	call 1366				;call ROM routine

	ret
	
dummy_header:
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Last file name string.

Post by Ast A. Moore »

MonkZy wrote: Mon May 07, 2018 4:56 pm Ast A. Moore You sexy Bas**rd!
:lol:

By the way, the following will save you one byte.

Instead of

Code: Select all

	ld a,255	;set A to FF for data block
	scf		;set CF for LOAD
do

Code: Select all

	scf		;set CF for LOAD
	sbc a,a		;set A to FF for data block
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
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Last file name string.

Post by MonkZy »

The following BASIC program provides a replacement for the LOAD "" CODE command. Simply substitute LOAD "" CODE with RANDOMIZE USR 60000. The data will be loaded without any on-screen text and the filename is stored in memory (60027-60036).

Code: Select all

  5 REM Reserve some RAM for the loader 
10 CLEAR 59999
20 GO SUB 9500

30 REM Your code would go here

9400 STOP

9499 REM This POKE's the loader machine code.
9500 RESTORE 9600
9510 FOR a=0 TO 25
9520 READ b
9530 POKE 60000+a,b
9540 NEXT a
9550 RETURN

9600 DATA 221,33,122,234,17,17,0,175
9610 DATA 55,205,86,5,221,42,135,234
9620 DATA 237,91,133,234,55,159,205,86
9630 DATA 5,201
Example BASIC usage

Code: Select all

 400 RANDOMIZE USR 60000
 520 PRINT AT 1,1;" Filename : ";
 530 FOR a=60027 TO 60036
 540 LET b=PEEK a
 550 PRINT CHR$(b);
 560 NEXT a
Post Reply