RAM used / corrupted by +3DOS
As I said previously, I'm trying to put some games in hard disk so they can be loadable by +3e. After some discussions in zonadepruebas, I've transferred some games, but I still have some doubts.
The Spectrum +3 documentation states that pages 1, 3, 4, 6 are used for buffers and Ramdisk. There is a DOS call (DOSSET1346) that can "free" this pages. However, the loaders that I've studied (those of Magic Knight Trilogy) load data in those pages without calling it, so I think they can be used freely. Is that true?
The other question is how much RAM is corrupted in page 7. Page 7 is used as "scratch" in +3DOS, but I don't think that the page is used completely. I want to know what areas in page 7 can be used freely and what areas will be corrupted.
To be more specific: in Gryzor 128, page 7 is used. I've been able to use some "empty" spaces in memory to store all data from page 7, so I could load everything from disk and, when disk is no longer necessary, rebuild page 7 back in place and execute the game. In other games (Operation Wolf, Typhoon) there are not enough free space (or at least I would need to check every page to find it out) to store page 7 completely, but I think that "corrupted" areas in page 7 would be small enough to allow me load most data in page 7 directly (everything below 6k would be fine... in most cases screen memory can be used as a buffer).
Can anyone explain how pages 1, 3, 4, 6 and 7 are used? What areas can be used freely (asuming no ramdisk usage) and what areas will surely be corrupted? The main goal is loading everything via BASIC (but with some touch of m/c for paging/transferring/rebuilding pages in RAM), so the games are loaded as files in +3 and +3e (opposed as diskette versions of Operation Wolf, that load everything directly from sectors of diskette).
The Spectrum +3 documentation states that pages 1, 3, 4, 6 are used for buffers and Ramdisk. There is a DOS call (DOSSET1346) that can "free" this pages. However, the loaders that I've studied (those of Magic Knight Trilogy) load data in those pages without calling it, so I think they can be used freely. Is that true?
The other question is how much RAM is corrupted in page 7. Page 7 is used as "scratch" in +3DOS, but I don't think that the page is used completely. I want to know what areas in page 7 can be used freely and what areas will be corrupted.
To be more specific: in Gryzor 128, page 7 is used. I've been able to use some "empty" spaces in memory to store all data from page 7, so I could load everything from disk and, when disk is no longer necessary, rebuild page 7 back in place and execute the game. In other games (Operation Wolf, Typhoon) there are not enough free space (or at least I would need to check every page to find it out) to store page 7 completely, but I think that "corrupted" areas in page 7 would be small enough to allow me load most data in page 7 directly (everything below 6k would be fine... in most cases screen memory can be used as a buffer).
Can anyone explain how pages 1, 3, 4, 6 and 7 are used? What areas can be used freely (asuming no ramdisk usage) and what areas will surely be corrupted? The main goal is loading everything via BASIC (but with some touch of m/c for paging/transferring/rebuilding pages in RAM), so the games are loaded as files in +3 and +3e (opposed as diskette versions of Operation Wolf, that load everything directly from sectors of diskette).
Post edited by Zup on
I was there, too
An' you know what they said?
Well, some of it was true!
An' you know what they said?
Well, some of it was true!
Comments
http://www.fruitcake.plus.com/Sinclair/Spectrum128/ROMDisassembly/Spectrum128ROMDisassembly4.htm
I would recommend using DOS SET 1346 to stop +3DOS using bits of RAM for its sector cache (or finding 1k of unused memory somewhere in banks 1,3,4,6 and putting the cache there). Just to be on the safe side.
They are too small...
An' you know what they said?
Well, some of it was true!
Normal: ROM 2, RAM 5,2,1
fe00-10000 (boot sector)
Special: RAM 4,7,6,3
runs boot code from $fe10; immediately switches back to:
LD BC, $7FFD : LD A, $13 : OUT (C), A
LD BC, $1FFD : LD A, $0C : OUT (C), A
Normal: ROM 3, RAM 5,2,3
c200-ce00
Does something tedious here from $f42c-$fc80, which I was planning to ignore, before the title screen is displayed.
Normal: ROM 3, RAM 5,2,3
8000-8200, 8500-8700, fed3-00d3, 4000-5400, 5400-5c00, 5cd8-64d8,
632f-6f2f, 6f2f-832f, 832f-972f, 972f-ab2f, ab2f-bf2f, bf2f-c32f,
c000-d400, d400-e800, e800-f000
LD BC, $1FFD : LD A, $09 : OUT (C), A
Special: RAM 0,1,2,3
0000-0800, 0800-1c00, 1c00-3000, 3000-4000, 4000-4400, 4400-5800,
5800-6c00, 6c00-8000
LD BC, $1FFD : LD A, $0F : OUT (C), A
Special: RAM 4,7,6,3
0000-1000, 1000-2400, 2400-3800, 3800-4000, 4000-4800, 4800-5c00,
5c00-7000, 7000-8000, 8000-8c00, 8c00-a000, a000-b400, b400-c000
LD BC, $7FFD : LD A, $13 : OUT (C), A
LD BC, $1FFD : LD A, $0C : OUT (C), A
Normal: ROM 3, RAM 5,2,3
4000-4c00, 4c00-5000
I got the game to load & run from CODE files constructed from BINs but it failed when it got to the "RESCUE THE HOSTAGES!" bit because I didn't have the paging right. Now that I've realised what it's doing I should be able to sort it out.
As a hint, I was using spanish and/or tape versions when normal disk versions are protected. Why?
- In most cases, tape versions are equal to disk versions (but some games have more content in disk versions).
- Tape loaders are easier to understand. In Operation Wolf, there are versions completely unprotected (but unloadable from disk, because of page 7).
- It's easier to know when a game has loaded completely (=runned the tape to the end). I don't know how to convert multiload disk games yet (probably hacking load/save calls), so I need to convert games that load completely in RAM.
- Spanish versions usually had different (and maybe easier) protections than english ones. Also, I'm spaniard ;)
For me, it's easier to keep track about what, when and where data is loaded looking at the tape loader. In some extreme cases I've executed the loader to the main entry point, and then I've extracted the contents of the memory using the "Save binary file" option of ZXSpin.
(A related note: When I was converting Rocky Horror Show 128k, I kept getting corrupt the first 4k of RAM1. I had to extract it via ZXSpin, and then I get that page corrupted when loading it in +3. The only solution I've found has been loading RAM1 into RAM4 and moving it to it's intended destination just before jumping into the code)
EDIT: It seems that, in adition to RAM7 page, the first 4k of RAM1 gets corrupted every time the disk is used. It is said that using SET DOS 1346 it can be avoided, but also that you still can get some memory corruption. I think I would need some extra 4k for some games...
An' you know what they said?
Well, some of it was true!
...removed link...
Sorry, they say no denied games are available, but only Ultimate and Codemasters are denied there as its an old site. So I removed the link.
Edit:
Download here:
https://dl.dropbox.com/u/9498358/Operation_Wolf_%28128_State%29.tap
My ZX Art Music Page
Carlos Michelis Theme
learning the +3 system is not too hard. I have converted every single game known to humanity to work on it (and have the whole lot with cool menu on a IDEDOS CF card). some are really tough, especially the multiloaders which need page7 preserved. but i have a set of tools which makes conversions easy. I wouldn't try Street Fighter 2, SpaceGun or Bart Vs Space Mutants until you know what you're doing, though....
I will usually let the game load to completion then dump out the entire ram. There's some tutorials in my conversion pack. Have a look here:
http://nugget.no-ip.biz/spectrum/+3disktools.rar
Looking into the code of nocache.bin, I don't understand how memory is paged. Page 7 and ROM 2 must be selected, in your code only page 7 and "any even" page is selected.
Won't be easier to do ld a,$07 (Select ROM0 or 2, RAM 7)? Is it so important to preserve the motor status and strobe status when using a custom loader? Also, I think that bit 2 of port $1ffd should be SET to ensure that proper ROM is selected, but In your code is not set. Is it safe to think that every time it is executed we're paging from ROM3 (I think the answer is yes, but lately I've been finding strange behaviour in my routines)?
Also, there are some suggestions for your toolkit (some programs I was using):
- Listador BASIC para +3 is a type-in from Microhobby. It list the contents of BASIC programs (can load them from disk and/or tape), also showing the "true" values of numbers. Also, it can list the vars area of BASIC programs (but it can't dissasemble the code hidden in them). I've been unable to make BASICLIS work to check if it is better, but...
- Tapedisc is another type-in from Microhobby. It was intended for copying standard load files from tape to disk. It can convert them without asking nothing (automatic mode), or asking the name of every file (manual). It is an alternative to COPYBYTE, and also there are some alternatives in +3e software page. I've typed that one and sent to WOS, so make sure to look at that :-D
- Disctape (again: type-in) will dump files into tape, as an alternative to TAPER.
- Pasadisk was a program for transferring programs saved with some interfaces to +3 disk. It does some screen corruption, but it does it's job. It makes almost no sense now (unless you've got a transtape copy of a missing program), but it may be handy.
An' you know what they said?
Well, some of it was true!
D=first buffer for DOS cache
E=number of DOS buffers
H=first buffer for RAM cache
L=number of RAM buffers
but when I call it I get DE=$E5E5 and HL=$E500. As $E5 is rather greater than 127 I'm somewhat bemused.
If I call DOSSET13346 to use buffers in page 3 with something like:
; 1st DOS buffer $28 @ $D000
; number $08 = $1000
; 1st RAM buffer $30 @ $E000
; number $00
with DE=$2808 and HL=$3000 then DOSGET1346 still comes back with DE=$E5E5 and HL=$E500. Can someone explain this please?
H - First Buffer for RAMdisk: 8 (RAM1, starting at $1000)
L - Size of RAMdisk: 120 sectors (60k).
D - First buffer for cache: 0 (RAM1, starting a $0000)
E - Size of cache: 8 sectors (4k).
In +2A and +2e there is no disk cache, but and RAMdisk takes all memory (starting at RAM1 $0000, 64k).
I've run made a call for setting to 32k RAMdisk (starting at RAM3) and 0k cache, and it runs fine in every computer. It seems that you've run in some kind of error... is carry set (=error) and what value has A when you do your calls?
An' you know what they said?
Well, some of it was true!
my latest loaders do everything in code and i'm lazy and just do :-
RES 4,(IY+1)
LD A,71
OUT 253,A
which sets +3 DOS and page 7 and sets "48K interrupt mode" ie it doesn't page the byte at 23388 on every interrupt.
* OpWolf-CODE.ASM : the boot sector loader & intro code.
* OpWolf-loader.ASM : my assembler program to load & run the CODE files.
* OpWolf-saver.BAS : a couple of tiny BASIC programs to build the CODE files & run the assembler loader.
* OWnotes.TXT : notes on the original loading sequence & files.
* Plus3notes.TXT : Notes on the +3's memory & disk setup.
* OWbuild.TAP : The three programs mentioned above.
* OWtest180-40-1.DSK: The three programs mentioned above and the 17 CODE files; they just fit on one single-sided disk.
At the moment the screen gets well messed up while loading; I'll see if I can do something about that. The program's not quite right yet as it crashes on level 3, but it crashes in the same way as it used to crash on level 1 and I fixed that so I should be able to apply the same correction to later levels. It's probably something to do with page 3, as that's usually been the contentious one.
Having worked through the boot sector loader to trace what & where files were being loaded, the main problems were:
a) where to put the assembler;
b) where to put the stack;
c) where to put the DOS buffers;
d) where to avoid in page 7.
At present the answer to both a) & b) is "in the middle of the screen" - hence the messing up situation while loading.
I used SET1346 to assign 8 DOS buffers and no RAM buffers, fitting them into a space in page 3.
Page 7 didn't cause too much of a problem, as I found that I could load the first 6912 bytes and the last 6144 bytes directly; the middle 3328 bytes I put in page 3 and then transferred them to page 7 via the screen after I'd finished using the DOS routines.
--
As further info on the original question, as long as BASIC and the editor have been left behind and disk accessing is being done by ROM calls from m/code, and DOS_BOOT isn't used, then most of page 7 seems to be free. The first 6912 bytes (the shadow screen) aren't referenced, nor the last 6144 bytes (which might otherwise be used by the editor or to store the bootstrap program); the middle 3328 bytes ($db00<-->$e7ff) might always be used by +3 DOS.
The other consideration is the DOS/RAM buffer extents, initially occupying all of pages 1,3,4,6 and 8/120 extents respectively. DOS_SET1346 can be used to set their number & location, so RAM buffers can be set to zero. The manual says not to set DOS buffers to zero as it says it will seriously degrade the disk performance. Buffers 0-31 are in page 1, 32-63 in page 3, etc. There can be a maximum of 16 DOS buffers, although only 15 of them can be in pages 1,3,4,6 as there's a permanent one in page 7 at $e090.
56064,2560 } regular disk area
58880,1 } timeout clock
59516,724
60416,926
62720,128
The last 3 ranges are used for CF geometry etc, and will fall over if incorrect.
In the old days, before +3e, it was easy to store a compressed 2560 byte image for loading multiloads,just decompressing to page 7 when disk access was needed, but +3e is initialised on boot, I use a simple compressor to compress the areas to about 560 bytes and have a 80byte routine which will rebuild the pg7 areas so long as it knows the partition name and it doesnt affect contents of pages 1346.....
Is OpWolf on disk multiload then? I'll have a look at it....
The loader program now removes itself from the game code after it's finished, and it's in a less hazardous place now anyway; it also restores the bits it's messed up before leaving (well, except for perhaps one bit which I haven't found yet). There are some convenient chunks in Op.Wolf with long runs of a repeating byte which I can overwrite with impunity as I only need to know that one byte value and the length of the run in order to restore them. The loader retreats into the display file at the end, removes any parts of itself remaining outside, and then is itself erased when the screen is refreshed.
The game runs much better now - in that now it doesn't crash until the final level (probably something to do with the missing bit which I mentioned earlier). I'll fix that tomorrow; ie. today, as it's now 4:30am in the morning of tomorrow ... errrmmm ... I've also discovered the lost POKE (ta-daaah!) - that is, infy grenades on the 128 version. It's in the notes file along with the other Op.Wolf infy POKEs from The Tipshop.
I don't understand the +3e comments. I thought that the +3e could just load Amstrad/Spectrum +3 disk games directly anyway, without any need for a conversion. The game's not a multi-load, by the way, I just did this version using plain CODE files and a BASIC loader as I'd got the impression that Zup wanted it to make transferring disk games to other formats easier, but when looking back at the original post I see that it mentions transferring to the +3e. And yet ... when I insert the original Op.Wolf +3 boot disk (image) version in the (virtual) drive on an (emulated) +3e and select "Loader" it loads & runs the game OK - and I even bunged in my converted version and it ran that as well!
I think I see why my Op.Wolf conversion works on both the +3 & +3e. I'm already preserving $db00<-->$e7ff (56064<-->59391), and if CF is Compact Flash (which I know nothing about anyway) then I wouldn't expect that it's going to be relevant to playing a game from a +3 disk.
I've nearly finished converting +3 Typhoon to use a normal BASIC CODE loader. It was made easier by there being a handy 4kb of empty space in the middle of page 4. Op.Wolf and Typhoon were fairly straightforward as everything on the WoS +3 disk version can be pre-loaded; once the game's running the disk doesn't need to be read again and so page 7 can be completely overwritten. I'd be interested in trying to convert an actual multi-load, if anyone has any suggestions.
NARC
Bart Simpson
Street Fighter 2
Space Gun
Final fight
Gauntlet 3
Last Ninja & Remix
Hostages
Real Ghostbusters
Pussy
I got it a few days ago, but I haven't had a proper go with it yet. On Op.Wolf & Typhoon I've used a different approach, in that I work from the disk pre-loading, not from the the RAM post-loading.
I think that I'll have a go with Space Gun now then ...
... although I didn't get very far without the POKEs. It was OK with +3e emulation as well.
Here's how I dealt with the files; the comma-separated numbers in the file names are the original load address & length. On the +3 DSK image I've just called the files A, B, C ... etc.
http://nugget.no-ip.biz/spectrum/Ocean-09.rar
With "clean" RAM contents, you may differ page 7 loading to the last moment, rebuild it from other pages and then jump to the game.
An' you know what they said?
Well, some of it was true!
Once I'd worked out what needed doing, what needed doing wasn't all that much, as there was a handy chunk of about 600 bytes in page 4 which could be discarded and replaced with the in-game disk loader. After that the main complication was that I missed an absolute "JP PE,..." in the unpack routine which needed to be altered for when the routine was relocated, and it took me three days to work out why half the graphics were all jumbled up - and ZXSpin trashing my DSK file didn't help - one minute it's OK, the next "No files found". I set the file attribute to read-only after that.
The only DOS data I needed to save was the 256 bytes from $5b00, plus I needed to save whatever the program had put at $db00->$e7ff whenever I wanted to load a level from disk. The former I could put in the handy space mentioned above, the latter I just bunged on the screen as the game blanked it between levels anyway. There were a couple of complications with files MAIN1 and BANK7; these are explained in the assembler listing.
DOS_INITIALISE rebuilds the workspace from the ROM, so in place of that I just used this cut-down version prior to using any DOS routines:
DOSInit:ld hl,$db00 ld de,$db01 ld bc,$09ff ld (hl),$00 ldir ; clear DOS workspace variables call $1f32 ; DD_INIT call $17d0 ; initialise A: & B: extended XDPBs ld hl,$0000 ; no RAMdisk, no cache ld d,h ld e,l push de call $1820 ; initialise RAMdisk pop de call $1539 ; setup cache jp $0500 ; set default drive and exitSo the main DOS level load procedure can be summarised as:The BASIC loader is just: The annotated assembler listing is in the ZIP file. There's also a couple of other programs which I used for transferring the files from TAP to DSK and for unpacking them to a separate TAP file (although the latter wasn't needed, as I had to use the packed versions anyway).
The reason I had so much space available was that the program uses a chunk of page 4 to copy in various routines, including its level loader, a copy of which resides in high memory. I just put my routine there instead and the program dutifully copied it into the active area and ran it each time it changed levels. The one other thing I had to change was the SP location. The primary position used by the game is $c000, which is invalid for DOS, which reserves the top 30 bytes of page 2. It turned out that $bfbe worked.
--
This one doesn't work on the +3e, although from nuggetreggae's earlier comments it would seem that there's not much involved in fixing it.
DOSInit:LD A, ($E42E) PUSH AF LD HL, $DB00 LD DE, $DB01 LD BC, $09FF LD (HL), $00 LDIR CALL $1F23 CALL $17B7 LD HL, $0000 LD DE, $0000 PUSH DE CALL $1818 POP DE CALL $1525 CALL $0510 POP AF LD ($E42E), A JP $28B5Although the game plays at about the same speed, the levels take twice as long to load on the +3e (emulation with ZXSpin).Used areas: Those marked as (+3e) are used if the computer is a +3e, maybe unused if it is a +2A or +3.
Free areas Those marked as ? may be unused, but there is a warning in the ROM disassembly stating that may be used (mostly because BASIC editor workings are not fully understood). I guess they're safe, mostly because BASIC editor is not used when running programs.
Also, I've found that writing some data in page 7 may crash some programs, even when running in a diskless +2A (try to load Amaurote 128k from tape and see what happens).
Are this data correct? Also, in this post Battle Bunny states that maybe only preserving bytes $db00 ~ $e7ff is necessary (if some conditions are met). In my case (if I ever try to make load from disk), I'm going to:
- Load everything I can from BASIC.
- From c/m, use DOS INITIALISE, DOS OPEN, DOS SET1346, DOS SETPOSITION and DOS READ.
I was going to use SET1346 to disable caching, then load from BASIC, and from c/m use DOS INITIALISE, DOS OPEN (opening a file as read only), keeping open the file and use DOS SETPOSITION and DOS READ to read chunks of data.
Is it necessary to call DOS INITIALISE (after all, BASIC has initialized it)?
What areas would be necessary to preserve? Note that I'm thinking about using only a file to keep all data, and keeping it open (no multiple DOS OPEN calls).
Thanks in advance.
An' you know what they said?
Well, some of it was true!
What's supposed to happen? I definitely loaded the Amaurote 128k version on the +2A, as it's got the extra animation at the start with the guy jumping into the machine, and I didn't have any problems (although I only played it for a couple of minutes).
Unless disabled by the POKE mentioned in the Dizzy thread, or unless a different interrupt routine has been loaded, the +2A will still call the disk motor timeout routine as part of the interrupt procedure.
Not after SET1346, as INITIALISE will undo any changes and restore the default DOS & RAM buffers. That's why I wrote a separate one for Space Gun, and why I had to write a slightly different one for the +3e (although it uses the same jump block as the +3, some of the routines are in different places, so a modified code fragment from the +3 DOS_INITIALISE was wrong for the +3e).
As long as DOS files are open the primary DOS workspace 7:$db00->$e7ff has to be preserved, either in situ or else copied somewhere & copied back whenever a DOS routine is going to be called, as the ROM keeps track of the current state of the files & system in there. Also the DOS ROM refers to and/or updates some of the standard 48k & extended 128k system variables.
I had problems with Space Gun because of the game's IM2 routine shifting stuff around - including the SP - and I couldn't keep interrupts turned off during the whole of the level loading phase. All but one of the EI lines in the DOS ROM are conditional (apart from those in the self-test section) and the EI is only executed on exit if interrupts were enabled on entry, but there's one line at $21f7 where the EI is unconditional (which gets executed as part of the disk login procedure). So I had to change to IM1 while I was using DOS, which was harmless, and restore IM2 for the game when I'd finished loading each level. (The point of this anecdote being that if there's a DOS file open all the time then the game code might wreck things even if it doesn't actually overwrite the DOS workspace or system variables.)