CBM64 Bard's Tale 1 Disassembly

Any developer realated stuff
Post Reply
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

I checked tape 1 side A and I can now confidently state that it consists of the Bards Tale game (which includes the A Team characters), followed by the standalone "edit" party editor program.
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

So far this is concluded regarding tape 1, side A:

1) "BBOOT" (a basic-file loading and executing the file "BOOT")
2) "BOOT" (the loader - executes itself and loads files FC and FB)
3) (FC) (This is the "main" file of the game, to be executed after FB loaded)
4) (FB) (Some data and the party, ATEAM)

5) "EDIT" (a basic-file loading and executing the file "PARTYMER")
6) "PARTYMER" (the party-merger / editor)

The game loads and executes after file FB have been loaded. Skara Brae is included in the file FC - no extra file is initially loaded. Every event, battle, image or text in Skara Brae is running from memory.

Tape 1, side B:

(21) (CITY - Skara Brae, P1 - loads itself at mid-memory)
(22) (CITY - Skara Brae, P2 - loads itself at end-memory)
(23) (CELLARS - Wine Cellar, P1 - loads itself at mid-memory)
(24) (CELLARS - Wine Cellar, P2 - loads itself at end-memory)
(25) (SEWERS - Sewers Level 1, P1 - loads itself at mid-memory)
(26) (SEWERS - Sewers Level 1, P2 - loads itself at end-memory)
(27) (SEWERS - Sewers Level 2, P1 - loads itself at mid-memory)
(28 ) (SEWERS - Sewers Level 2, P2 - loads itself at end-memory)
(29) (SEWERS - Sewers Level 3, P1 - loads itself at mid-memory)
(2A) (SEWERS - Sewers Level 3, P2 - loads itself at end-memory)

The files marked "FILES" are visible. The files marked (FILES) are invisible to normal loading and loader through the game turboloader.

So far i'm extremely impressed by the tape-version. The text and events are definitly packed in some very nice fashion for being 1988 - I still haven't got a clue how this system works, but there are buffers - empty spaces - in memory which I believe is used for events, battles, etc.
/Twoflower
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

This is so awesome that people are appreciating and celebrating the achievement of the tape version.
Another speed improvement unique to the tape version is the bumping into the walls in darkness. In the disk version there is an obtrusive Ouch! animation that takes ages to complete. With the tape version, you get an instant blip sound feedback and even a quick flash of he maze, giving you a glimpse of whether a door is in front of you.

I you would like to wander around the dungeons and towers hastle-free, then try loading my superparty from this link

http://bardstale.brotherhood.de/talefil ... .php?t=951

The characters have ample hitpoints and spellpoints, plus they hold all the keys and objects to allow you to access the towers and barriers.
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

Some notes on the roster for Bard's Tale Tape:

As you might know, there are some differences in the roster-setup between the tape- and the disk-version. Thanks to ZeroZero's excellent breakdown of the disk-roster earlier in this thread, i've been able to look up some details on how the tape-roster is set up. Some major differences are:

* As mentioned - the tape-roster is handled as one party, not as characters.
* The characters are all defined by $65 (=101) bytes of data.
* The definition of the characters are identical to the first $65 bytes of the characters in the disk-version.
* There are 7 characters to be saved (6 + one for the summoned character).
* A saved party - one save-unit - is $343 bytes -> ($65 X 7) + $80 bytes.

So far, so good - a breakdown of what I found so far:

Code: Select all

0251-02B5   Summoned or recruited monster. Stored as a normal character, $65 bytes.
02B6-031A   First character, $65 bytes.
031B-037F   Second character, $65 bytes.
0380-03E4   Third character, $65 bytes.
03E5-0449   Fourth character, $65 bytes.
044A-04AE   Fifth character, $65 bytes.
04AF-0513   Sixth character, $65 bytes.
0514-0594   Unknown data, $80 bytes (will analyze).
There are no checksum on the characters, as there are in the disk-version.
Last edited by Twoflower on Sun Feb 05, 2012 3:57 pm, edited 1 time in total.
/Twoflower
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

Twoflower wrote:Some notes on the roster for Bard's Tale Tape:

Code: Select all

0251-02B5   Summoned or recruited monster. Stored as a normal character, $65 bytes.
02B5-031A   First character, $65 bytes.
031B-037F   Second character, $65 bytes.
0380-03E4   Third character, $65 bytes.
03E5-0449   Fourth character, $65 bytes.
044A-04AE   Fifth character, $65 bytes.
04AF-0513   Sixth character, $65 bytes.
0514-0594   Unknown data, $80 bytes (will analyze).
There are no checksum on the characters, as there are in the disk-version.
This is amazing information! Most amazing was the fact that the special character has the same memory layout as standard party members. I immediately loaded up my party which has Mangar himself as the special slot character (My high level archmage casted SPBI on him and it worked). With the Action Replay cartridge in place, I froze the program, entered the machine code monitor and ran the command
t 0251 02b5 02b6
to transfer the special slot character data into party member 1.
On unfreezing, I was rewarded with a Mangar at party position 1!
"Great!" I thought, "Now I can examine the stats of Mangar himself!". However, the results reveal that not much data is held, which is a surprisingly inefficient given the lengths that the authors made to cram the entire core game into memory.
Anyway, the result of my experiment was that party character 1 was:
1)Mangar AC: LO Hits:231 Con:231 SpPt:0 Class:??
On pressing '1', I get the information:
Mangar, Race: Human, Class: Party, St:0, IQ:0, Dx:6 Cn:3 Lk:0, Lvl:0 SpPt:0, Exper: 0( 000000000, Gold: 0
No items, SorcL 0, Conj: 0, Magi: 0, Wizd: 0

The class value is interesting. "Party". Where did that come from? Surely that must be a previously unknown value.
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

Twoflower wrote:* The definition of the characters are identical to the first $65 bytes of the characters in the disk-version.

There are no checksum on the characters, as there are in the disk-version.
This is the most fascinating snippet of information yet. It sounds likely that the $65 bytes of the 7 party members can be exported from the tape game and imported into the disk game, and we're almost there!

Two questions:
1. Are the seven $65 memory locations at the same address in the disk version?
2. How many bytes are used for the disk version checksum? If it is only one then that is 256 possible combinations... I'm willing to try the transfer procedure 256 times:)
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

Two questions:
1. Are the seven $65 memory locations at the same address in the disk version?
2. How many bytes are used for the disk version checksum? If it is only one then that is 256 possible combinations... I'm willing to try the transfer procedure 256 times:)
1) No. They aren't. For the exact location, please refer to ZeroZero's memory-layout and the disk-roster-layout earlier in this thread.
2) Probably one byte - though it might be more than that:

Code: Select all

64 - 7e      ????      ????
7f           byte      checksum, build routine in guild event 
As you can see, byte $64-7E is unknown - this might or might not be a part of the checksum. Then comes the question what the checksum is based upon - is it just the stats? The items aswell? The entire character-file? How is it created and where is the routine calculating it located? If we can locate it, there be a simple task to invoke it and create a checksum for every char. I figure that another option would be to bypass the check in the BT1-disk engine?

As for the no-information of the recruited monsters
- they probably act out of the monster-table - since they act on its own; they are using sort of a "reverse-monster-attack". Everything needed is allready stored in the engine - you don't need all the data which is needed for the other characters since you can't - for example - level Mangar up.
/Twoflower
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

if we are talking about the C64 versions, just forget that checksum. Although it is created by a routine in the guild event, it is never used for anything later (afaik).

I can send anyone the disassembled guild event of the disk version, just pm me an email addy.
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

ZeroZero wrote:if we are talking about the C64 versions, just forget that checksum. Although it is created by a routine in the guild event, it is never used for anything later (afaik).

I can send anyone the disassembled guild event of the disk version, just pm me an email addy.
I was hoping that this was going to be easy, and within my abilities, but I think I have underestimated the complexity.

I got off to a good start by freezing the tape game, entering the monitor and saving the party memory locations with the machine code monitor commands:
S"specialchar",8,0251,02b6
s"partychars",8,02b5 0595
I saved these to a .D64 file, ready to import into the Disk game.

I was hoping that I would be able to paste this data into the equivalent memory of the Disk game. In order to determine this memory location, I found the memory map text

000f - 0010 | * | often used to hold the pointer to the presently selected
| | character's roster in memory

So I viewed party member 1 and examined the memory content of 000f - 0010, which was 80 and CB. So I was hoping that either address CB80 (or 80CB) would be the address where party member 1 begins.

So I fired up the disk game, froze the machine and entered the following at the machine code monitor:
l"specialchar",8,cb80

but alas, that didn't change the party on the screen (neither did loading to address 80cb).

But the big surprise for me is that when I press '1' to view the character in the disk game, it wants to access the character disk! This is a downer as I suspect that anything I do in memory is going to be overwritten when this character disk is accessed. And I'm not versed with the skills required to edit the disk roster itself. So maybe this is a project for another time for me, unless someone wishes to give it a go, in which case I'd be happy to pass over the .d64 file containing the party data extracted from the tape game.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

A party is determined by 2 bits of data:

1 roster entry containing all party members names

1 roster entry per party member.

So the game wanted to access party member 1, lets say that would be "jimmy" and finds instead in neither slot a "jimmy", so it wants to reload it.

Btw:
this is the bit of code that makes the checksum byte:

Code: Select all

bb7c:057e:1   a0 00    mkchksum ldy #$00              ; init loop counter
bb7e:0580:1   98                tya                   ; clear accu
bb7f:0581:1   59 00 cf nextbyte eor $cf00,y           ; xor accu with roster byte
bb82:0584:1   c8                iny                   ; address next roster byte
bb83:0585:1   c0 7f             cpy #$7f              ; all done? 7f bytes
bb85:0587:1   d0 f8             bne nextbyte          ; xor next
bb87:0589:1   60                rts 
[/quote]
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

Flanimal wrote:S"specialchar",8,0251,02b6
s"partychars",8,02b5 0595
I saved these to a .D64 file, ready to import into the Disk game.

I was hoping that I would be able to paste this data into the equivalent memory of the Disk game. In order to determine this memory location, I found the memory map text.
This is exactly what you can't do. You have to save and load the character individually in that case - 6 files of 65 bytes - and load it from the start of the character in the disk-version since they have a different lenght. Furthermore, the name of the character and the padding is stored in a different way (you basically have to add $40 (?) to each value - can't remember). And, umm, I made a little mistake - the first character starts at $02B6.
/Twoflower
User avatar
Flanimal
Posts: 107
Joined: Sun Aug 08, 2010 3:40 pm
Location: London, England

Post by Flanimal »

Twoflower wrote:
Flanimal wrote:S"specialchar",8,0251,02b6
s"partychars",8,02b5 0595
I saved these to a .D64 file, ready to import into the Disk game.

I was hoping that I would be able to paste this data into the equivalent memory of the Disk game. In order to determine this memory location, I found the memory map text.
This is exactly what you can't do. You have to save and load the character individually in that case - 6 files of 65 bytes - and load it from the start of the character in the disk-version since they have a different lenght. Furthermore, the name of the character and the padding is stored in a different way (you basically have to add $40 (?) to each value - can't remember). And, umm, I made a little mistake - the first character starts at $02B6.
I underestimated the complexity of transferring a party from the tape BT game to the disk BT game. I'm afraid it is beyond my small brain's abilities, so I have given up. I'll be continuing to stick to the tape BT game and its swift responsiveness. There's still plenty of the life in the old game yet!
User avatar
Horpner
Posts: 224
Joined: Thu Jan 08, 2009 11:53 pm
Location: New England
Contact:

Post by Horpner »

ZeroZero wrote:if we are talking about the C64 versions, just forget that checksum. Although it is created by a routine in the guild event, it is never used for anything later (afaik).

I can send anyone the disassembled guild event of the disk version, just pm me an email addy.
I've been making a little use of some of the awesome work that's been done here since I left, and I believe that the character checksum might indeed be used.

It may be used when attempting to add a character to the party. I modified the attributes of a new character. I hate re-rolling hundreds of times to get good stats, so I'll just be assigning maximum racial stats for all characters. When I tried to add the modified character to the game using the Add command, it reported that no such character exists, even though he appears in the list when I Check Roster.

Fortunately, it is easy to get around this check by loading the character as part of a party.
Death and drek? WTF?
User avatar
Darendor
Posts: 1502
Joined: Wed Jan 14, 2009 1:53 am
Location: Red Deer, Alberta, Canada

Post by Darendor »

I've been trying to remember how I used 64Copy to edit the dungeon files a few years ago.

I downloaded it and got a copy of the dungeon disk loaded into the program, but when I go to hex edit, say, NMAF, it only gives me track and sector editing, not hex location editing.

No matter what I can't seem to get it to go to the edit mode I need.

What am I missing?
User avatar
Darendor
Posts: 1502
Joined: Wed Jan 14, 2009 1:53 am
Location: Red Deer, Alberta, Canada

Post by Darendor »

Nevermind, I managed to figure it out.

It was a lot more headache than it needed to be. :?
Post Reply