Posted: Wed Feb 25, 2009 9:34 pm
You're getting an "?OUT OF MEMORY" error, which shouldn't be happening.
What exactly are you doing when you go to run the program?
What exactly are you doing when you go to run the program?
The Ultimate Bard's Tale Resource
https://bardstale.brotherhood.de/talefiles/forum/
https://bardstale.brotherhood.de/talefiles/forum/viewtopic.php?t=787
Darendor wrote:Download "btdungeoneditor.d64" and load "BOOT.PRG" and run it to see it.
Alright, well, I'm working on V1.2 at the moment, hopefully that'll resolve any issues.Chaney wrote:Sorry about the delayed response. RL got in the way. I actually tried all three items and got the same results each time.
Horpner wrote:True. I modified my text-dumping program to pull all the text from every NMXX file. The dungeon specials start in file NM1F.PRG, the stairs that go a long way up, and run consecutively up to NM44.PRG, Mangar's Antechamber. But I've so far been unable to make sense of the file pointers contained in the dungeon data.Darendor wrote:So, this is what we've found:
- each special that runs the disk drive is loading a file: "NMXX.PRG"; true or false?
For example, the pointer for the NM1F.PRG program (the long stairway) is 10. This seems easy: just add f to the pointer. This works fine throughout the cellars. But in the catacombs, it stops working. Bashar Kalivor is in program NM23, so using our formula we expect the pointer say 14. But it doesn't--the pointer says 16. It's off by +2. In the Castle, things are again different. The old man's riddle on the second level is in NM2A. So the pointer should be 1B. But it's really 1c, off by -1.
I'm going to have to go through and notate them each with their file pointer, and maybe eventually it'll make sense.
To simplify things as much as possible, let's consider a four-tile dungeon, with a correspondingly tiny memory map.- When the player trips a special, it looks at a memory location for that special. I'm still not crystal clear on this bit.
The map is stored at 00, and take up four bytes. Our map is just a square dungeon like this. It contains the stairs in with a welcome message, a dastardly anti-magic and darkness zone, 1 spinner, and a special that runs a program to award 500,000 xp to all your characters.
Using lookup tables I posted elsewhere, we must encode the map at location 00. The map is stored from bottom left to top right, proceeding right and upwards.Code: Select all
+--+--+ |A/ @| + + |^s s0| +--+--+
That binary code for that map is 0100 0100 0001 0100 0100 0001 0001 0001, or, in hex:
00: 88 18 81 11
Next, there's the array of special features, one byte per tile. That's not enough to store every kind of feature you might like, but it does encode stairs, darkness, traps, portals, and treasure chests. Each feature is stored in one bit. Also, there's a flag set if something other than those features encoded here--these are all detected as "something special is near" by the SESI effect. The tiles are stored in the same order.
The first tile has stairs up and an "other special"--the welcome message. That sets bit 0 for the stairs up, and bit 2 for the special.
The second tile has just an "other special". So we set bit 2.
The top left tile has Anti-magic, which is also an "other special", and darkness, which we encode directly. So we set bit 2, for other, and bit 3 for darkness.
The top right tile has a spinner, and that's an "other special," too.
So our next four binary patterns look like this:
00000101 00000100 00001100 0000100
or in hex
04: 05 04 0b 04
So now we need somewhere to store which remaining special is which. The game uses a set of lists of coordinates so it can tell.
First, is a list of coordinates of special programs to pull from disk. This dungeon needs only one program, the one that awards bonus xp, but there are room for as many as four. The coordinates of that tile are 0N, 1E, so we get:
08: 00 01 ff ff ff ff ff ff
The remaining, empty, slots for programs are padded with ff.
Below that, we store the pointers to the programs on disk. For the sake of example, xp award is progam 1.
10: 01 ff ff ff ff ff ff ff
Next down is a list of the coordinates of Anti-magic zones. We have one at 1N, 0E.
18: 01 00 ff ff ff ff ff ff
Next down is the list of teleporters, and then a list of destinations. We don't have any of either.
20: ff ff ff ff ff ff ff ff
28: ff ff ff ff ff ff ff ff
Next down are the location of up to four spinners. We have one at 1N, 1E:
30: 01 01 ff ff ff ff ff ff
Next comes three empty tables for HP drains, SP recharge, and tiles where you get stuck.
38: ff ff ff ff ff ff ff ff
40: ff ff ff ff ff ff ff ff
48: ff ff ff ff ff ff ff ff
Next comes a list of message coordinates. We have a message at 0N, 0E.
50: 00 00 ff ff ff ff ff ff
Next comes a list of monster coordinates. We don't have any set monster encounters, so it's empty. Below it is a table of which monster is actually supposed to be encountered at the corresponding tile, and how many. But this is blank, too.
58: ff ff ff ff ff ff ff ff
60: ff ff ff ff ff ff ff ff
Finally, the special message text appears. We have just one message.
68: <some BTSCII text encoding a welcome message, terminated by dc>
So here's the whole dungeon, in roughly 120 bytes:
As you walk around our little map, the game draws the screen and prevents you from walking through walls by looking at the 4 bytes at 00.Code: Select all
00: 88 18 81 11 05 04 0b 04 08: 00 01 ff ff ff ff ff ff 10: 01 ff ff ff ff ff ff ff 18: 01 00 ff ff ff ff ff ff 20: ff ff ff ff ff ff ff ff 28: ff ff ff ff ff ff ff ff 30: 01 01 ff ff ff ff ff ff 38: ff ff ff ff ff ff ff ff 40: ff ff ff ff ff ff ff ff 48: ff ff ff ff ff ff ff ff 50: 00 00 ff ff ff ff ff ff 58: ff ff ff ff ff ff ff ff 60: ff ff ff ff ff ff ff ff 68: <some BTSCII text encoding a welcome message, terminated by dc>
It also keeps track of the feature list at 04, so that SESI works right.
Let's say you just entered. The game checks location 04, the feature table, and sees there are stairs here, and a special.
On the C64, this means it first asks if you'd like to take the stairs out. If you don't, then it looks up the coordinates 0N, 0E in our little set of tables. It finds 00 00 at location 50, and knows this means it's a message. Since it's the first coordinate in the list, it looks up and prints the first message found at location 68.
Now you walk north. Oops! The game finds that the darkness flag is set, and turns out the light. It also sees the "other" flag, and so looks for 1N, 0E in the set of lists. It finds it in the memory location reserved for Anti-magic, and turns off all your spells.
So you quickly turn around, and go back south. You see the stairs and the welcome message again, and cast your spells again. Now you head east. When you walk here, the program sees that there's a special here (by checking the feature table), and looks up the coordinates in the set of tables. It finds them at 08, and knows this means it is to run a special program. Since this is the first coordinate, it looks up the first file pointer at 10, 01. So it runs NM01.PRG. Viola! You are 500,000 xp more awesome!
Yes I think so too. What I'm trying to find now is how the special in question is triggered from the flags set. Meaning that certain tiles have "Something special is near..." and so when the party steps on the square how does it know what special to load? And what of the non-disk loading ones, such as just plain text clues and so forth?ZeroZero wrote:As I see it, Horpner tries to find a rule, what file is loaded upon what special byte value. I assume the coder used a jump table, so that the real file to be loaded will be read from the offset in that table rather than from the direct byte value.
ZeroZero wrote:I can identify and confirm the following:
The table to load files for special events is located at 1b2c in memory.
It is referenced in this subroutine:
,1b19 a6 e0 LDX $e0
,1b1b e0 06 CPX #$06
,1b1d f0 08 BEQ $1b27
,1b1f bd 2c 1b LDA $1b2c,X
,1b22 20 cc 78 JSR $78cc
,1b25 18 CLC
,1b26 60 RTS
I was standing before Kylearan's Gate, with a breakpoint on that sub, and when I approached the breakpoint fired with X loaded with 0d. The line at 1b1f loaded A with contents of 1b2c + 0d (+ 1 of course) which reads 12 and loaded file NM12. Subroutine at 78cc builds the filename from the hex byte and loads the file. In NM12 there seem to be several messages in one file, and I didn't see how that is managed, must be a mix of an X that is handed over from a location and an index into the text to show.
I couldn't yet identify where on the disk that table is located, that byte sequence just isn't on the disk anywhere. However, I can approve that it is loaded with the main program from the BOOT disk. It is there, once the main program is loaded and initialized. The BOOT disk is a weak try to hide how the load progress works. The loader in fact is a simple program, but already the loader is NOT at T1S3, but starts at T3S0 and goes up to T9.
The main program starts at T19S0 and goes up to T27. The BAM was manipulated to show bs data and the directory entries except for the EA bootstrap is bs either.
The conclusion from this is this:
a maze editor must decide for one of two possible ways, it can
a) have it's own table and must write that into the BOOT disk, OR
b) it accepts the table present and then carefully remakes all NM* files and sets the right references acc. to the given table for it's own events.
Hope this helps a bit, ZZ
No no...Darendor wrote:I was thinking of having the editor system work with the way the game already loads the NMxx files. What do you recommend, exactly?
So on the BOOT disk at Track 3 Sector 0 is the loader for special events, whether in Skara Brae or in dungeons?