PCEngineFans.com - The PC Engine and TurboGrafx-16 Community Forum
Tech and Homebrew => Turbo/PCE Game/Tool Development => Topic started by: Bonknuts on May 05, 2016, 04:46:11 PM
-
I know there are some existing libs out there for BRAM support (HuC), but I've written a set of my own. I'm just cleaning everything up and reducing the code/data/bss/zp footprint. This is mostly for Hucard projects, but it should be compatible with any CD project as well.
I tried to offer a little more support than what the syscard bios funcs provided. I know mednafen had an option to allow up to 8k of BRAM. So I added compatibility for that, as well as upgrading the BRAM header to 8k size. BRAM doesn't mirror, so it should work in theory. IIRC, Ryphecha said one game didn't like it (but only one). I know people have been talking about making BRAM boosters for their systems, so would work with that - if that ever comes to pass (larger than 8k).
I going to do some tests over the next couple of days and then I'll release the lib. I would definitely appreciate feedback on it (suggested support, interfacing, etc).
Edit: (old)
Ok, I was wondering if anyone out there with some experience with bram interfacing could help out?
I have Dragon Warrior for the PCE that I promised to release for Bernie, but I don't want to release it without BRAM support. I have very-very little time, so I'm seeing if anyone else could help out with the explanation of how to interface with it (the save file interfacing)? I also remember someone (Ccovell?) saying that HuC had a bug in one of its support functions.
Anyone interested in helping out?
-
So, here's the info I gathered so far:
The bram entries are made up of ID num + text header; the FCB. The BRAM search function has a pointer to this ID in BX (ID for compare is in local memory). I'm not quite sure what _AL is (number of file from top=1), but I'm guessing that's the number of instances of this ID string?
So it appears BRAM Write is also for creating new files as well as updating existing ones.
So something like BRAM search (pointer, instance). If exists (call $1D returns $00), then update it (call $1B with pointer to data and ID), if not - check for free memory (call $19 returns amount in CX). If enough, write update (call $1B with pointer to data and ID).
Edit: Also, I'll need some brave souls to try out this Dragon Warrior BRAM stuff. Any takers?
-
Dude, I'm knee deep into BRAM atm :)
The BRAM starts with a 16 bytes header.[ul][li]00-03 - Header tag (equals to "HUBM")[/li][li]04-05 - Pointer to the first byte after BRAM storage[/li][li]06-07 - Pointer to the next available BRAM slot (first unused byte)[/li][li]08-0f - Reserved (set to 0).[/li][/ul]A BRAM entry is formatted as follow:
[ul][li]00-01 - Entry size. This size includes the 16 bytes of the entry header[/li][li]02-03 - Checksum. The checksum is the sum of the entry bytes starting from byte #4 (i.e all bytes except the entry size and checksum). The value stored is the opposite of the computed checksum. This way the consistency check only consists in adding the stored checksum and the newly computed one. If this sum is 0, the entry is valid[/li][li]04-0f - Entry name.[ul][li]00-01 - Unique ID[/li][li]02-0b - ASCII name padded with spaces[/li][/ul][/li][/ul]
If I understood what was written in the Develo Book, the bm_files routine of the system card fetches the nth entry (n stored in _al). _bx stores the address where the entry information will be stored (id,name,size). At the end _si will contain the address of the matching entry.
-
The bug was/is in bm_delete().
-
I think there's a HuC/MKit library interface in my BRAM manager that you can use.
Also, one thing I suspect is that the HuC BRAM_Detect / Unlock code may be faulty (at least the version that I have.) It writes $80 to $1807, when it really needs to write $48,$75,$80 to that register. CD systems work with the faulty code, but TennoKoe2s don't.
-
I think there's a HuC/MKit library interface in my BRAM manager that you can use.
Also, one thing I suspect is that the HuC BRAM_Detect / Unlock code may be faulty (at least the version that I have.) It writes $80 to $1807, when it really needs to write $48,$75,$80 to that register. CD systems work with the faulty code, but TennoKoe2s don't.
Ohh, that's good to know. For DW, I'll be using the syscard functions, but for the hucard version and two other nes2pce hucards, I'll need to directly access bram.
-
Dude, I'm knee deep into BRAM atm :)
The BRAM starts with a 16 bytes header.[ul][li]00-03 - Header tag (equals to "HUBM")[/li][li]04-05 - Pointer to the first byte after BRAM storage[/li][li]06-07 - Pointer to the next available BRAM slot (first unused byte)[/li][li]08-0f - Reserved (set to 0).[/li][/ul]A BRAM entry is formatted as follow:
[ul][li]00-01 - Entry size. This size includes the 16 bytes of the entry header[/li][li]02-03 - Checksum. The checksum is the sum of the entry bytes starting from byte #4 (i.e all bytes except the entry size and checksum). The value stored is the opposite of the computed checksum. This way the consistency check only consists in adding the stored checksum and the newly computed one. If this sum is 0, the entry is valid[/li][li]04-0f - Entry name.[ul][li]00-01 - Unique ID[/li][li]02-0b - ASCII name padded with spaces[/li][/ul][/li][/ul]
If I understood what was written in the Develo Book, the bm_files routine of the system card fetches the nth entry (n stored in _al). _bx stores the address where the entry information will be stored (id,name,size). At the end _si will contain the address of the matching entry.
This seems easy enough. I should be able to write my own interface code.
So what about the linked list system? Is there a WORD pointer at the end of an entry?
On that note: does the system card take care of defragmenting the entries?
-
So what about the linked list system? Is there a WORD pointer at the end of an entry?
Don't believe so. It adds up the entry sizes. Recognizes list end by comparing to next available byte.
On that note: does the system card take care of defragmenting the entries?
<lol>. No, I don't think it does.
-
On that note: does the system card take care of defragmenting the entries?
I take my comment back. I just checked, and it looks like it shifts the directory/data blocks backwards, over writing the old data, and adjusts the available pointer.
Must have been thinking of the HuC version....
-
On that note: does the system card take care of defragmenting the entries?
I take my comment back. I just checked, and it looks like it shifts the directory/data blocks backwards, over writing the old data, and adjusts the available pointer.
Cool. I think I have all the info that I need (and it all checks out from looking at an existing near full bram file in hex editor). For the hucard libs I'll make, I'll be sure to reorganize the blocks if I add a delete option.
-
On that note: does the system card take care of defragmenting the entries?
I take my comment back. I just checked, and it looks like it shifts the directory/data blocks backwards, over writing the old data, and adjusts the available pointer.
Must have been thinking of the HuC version....
^^^^^ Yeah
-
Updated the main post. I'll be posting the library and any updates to it in this thread.
Note: I'm using fast 16bit compares (cmp+sbc), but man.. that inverse logic of the carry flag always trips me up :/
-
Updated the main post. I'll be posting the library and any updates to it in this thread.
Note: I'm using fast 16bit compares (cmp+sbc), but man.. that inverse logic of the carry flag always trips me up :/
I'm over here writing z80 and laughing at you.
-
Haha, you can keep that z80. I'm not a fan.
-
Ok. Preliminary BRAM support tested out fine. I tried to cover as much safety and bounds checks as I could (not sure how much the sys card handles). Lots of error reporting (more than sys card functions, and more detailed/specific). I don't have as fully featured set as the sys card ones (specifically for partial updates to an entry vs full updates/writes), but they work out great so far. I'll probably post an example suite, but it's more for musings than anything else at this point. Currently implementing this BRAM lib into Dragon Warrior.
-
Seems I'm running into a problem using the same BRAM libs from a CD project. Looking at the emulator, it's not unlocking bram. It works fine as a hucard project and the exact same routines. Is the emulator looking for something specific to CD games? Is there some different hardware unlock process for the CD unit or sys card that the emulator is looking for?
-
Who knows? Are you banking in BRAM to an "oddball" location? Did you try it on a real CD system yet?
-
No. I stuck with the system card protocol (logical address range, etc), as well as used Neutopia as a guide. Even did the long string to port $1807 instead of just $80. I think it might be an emulator thing. I haven't tried it on the real system yet.
Guess I'll just switch over to using the sys card routines for the CD project, for now. I wanted to use my own lib because it's faster and cleaner than switching to MPR1, MPR7, and maintaining two stack pointers (as well as different VDC IRQ routines for each).
-
Silly question: Did you format the BRAM? I vaguely remember having to do that to create the BRAM file for <Mednafen?> Look and see if theres a 2K file in with the emulator stuff.
Also, do you drop to low-speed mode?
-
Yeah. That's the first function that is called. Check for valid header, format if absent. Yup, in low speed and interrupts disabled (extra caution). I mean, everything that I did for the hucard project that worked fine in mednafen, now appears to do nothing in the CD project for mednafen. I'm assuming the emulator must have some other check or such for its bram emulation code when in CD mode.
-
Seems I'm running into a problem using the same BRAM libs from a CD project.
It seems to me that if it works for a Hucard project, it should work for a CD project.
The only difference might be where the routines are located. I know the syscard version
is in the $00 bank, and mapped in at page 7 ($e000-$ffff). Possibly something is un-mapping your
routines / data. Or the emulator won't unlock BRAM from any other page.
[The system card routines use indirects to save to BRAM, since the data-to-save could be anywhere in the cpu address space. And the same for BRAM, iirc.]
-
Is the BRAM function on the CD project your own function, or the CDROM card's function ?
I seem to recall ccovell identifying a more complex 'unlock' requireement several years ago... if I recall correctly, it needs a 3-write unlock sequence rather than 1-write.
Of course, this only applies if you are writing your own. In HuC projects, the library automatically chooses between HuC code and CDROM card functions based on the target type.
-Dave
-
I seem to recall ccovell identifying a more complex 'unlock' requireement several years ago... if I recall correctly, it needs a 3-write unlock sequence rather than 1-write.
It's on the 1st page of this same thread, in fact.
-
Is the BRAM function on the CD project your own function, or the CDROM card's function ?
I seem to recall ccovell identifying a more complex 'unlock' requireement several years ago... if I recall correctly, it needs a 3-write unlock sequence rather than 1-write.
Of course, this only applies if you are writing your own. In HuC projects, the library automatically chooses between HuC code and CDROM card functions based on the target type.
-Dave
Yeah, it's my own BRAM code (for both hucard and CD project). I definitely took note of the 3 byte sequence Chris mentioned and I'm using it.
Seems I'm running into a problem using the same BRAM libs from a CD project.
It seems to me that if it works for a Hucard project, it should work for a CD project.
The only difference might be where the routines are located. I know the syscard version
is in the $00 bank, and mapped in at page 7 ($e000-$ffff). Possibly something is un-mapping your
routines / data. Or the emulator won't unlock BRAM from any other page.
[The system card routines use indirects to save to BRAM, since the data-to-save could be anywhere in the cpu address space. And the same for BRAM, iirc.]
Actually, yeah. On the hucard project, I'm doing the bram access from bank $0 and MPR 7. And in the CD project the bram code is in bank $69 and MPR 2. I'll MPR7 and see if that has any effect.
-
And in the CD project the bram code is in bank $69 and MPR 2. I'll MPR7 and see if that has any effect.
Hunh? MPR2 is the $4000 cpu range, iirc. I'd have to trace through that stuff again, but I think thats actually where the BRAM 'appears' (I could be wrong, though)
Can you re-build the HuCard project as a cd, and see if it works? That will let you know if its a bank placement problem.
-
MPR2 is the $4000 cpu range, iirc.
My bad. I was just looking at something else, and noticed the syscard bram functions
save the entire memory layout. And then map actual BRAM data to MPR4 ($8000 range).
-
Yeah, $8000 range.
Ok, so I just tried it with bank $69 in mpr7 and bank $f7 in mpr4. Still no luck. I really think this is an emulator issue. Guess I'll just stick with sys card routines for CD projects. The BRAM lib code work for hucard projects, so I guess it's not a total loss.
-
Ok, so I just tried it with bank $69 in mpr7 and bank $f7 in mpr4.
Okay. One more silly observation, then I'll leave it alone.
As I was tracing through the routines, I noticed that the bram re-lock routine turned the interrupts on.
So I went back and checked, and the bram unlock routine turns them off before going to low speed mode and unlocking bram.
[That's why one of the routines does some processing og the interrupts on it's own, I think. ]
-
It's definitely an emulator thing with mednafen. I switched over to using the sys card bram routines instead, and stepping through the code - it won't show any changes to bram (bm_format). So something with the emulator itself when running a CD game. Because stepping through BRAM code (my own, or an official hucard), in the emulator works find with hucards. It's like one of those quantum physics things; observing it changes the behavior ;>_>
As I was tracing through the routines, I noticed that the bram re-lock routine turned the interrupts on.
So I went back and checked, and the bram unlock routine turns them off before going to low speed mode and unlocking bram.
Yeah, I followed that procedure. I figured it was extra safe guards when accessing BRAM - because handling save data is pretty important. Though I do the PHP, SEI, CSL and CSH, PLP. Just in case any higher up functions already had interrupts disabled.
-
Also, the CDREAD routine is annoying. I can only read in as many free banks as I have logical address range for (32k at a time). Loading in 256k results in multiple calls to CDREAD. I'm using the docs from syscard 1.0. Is there an update to the CDREAD routine with more parameters?
I don't want to waste a full 8k just to use the updated CDREAD lib routine I ripped from Seiya monogatari.
-
It's definitely an emulator thing with mednafen. I switched over to using the sys card bram routines instead,...
That sounds so damn familiar...I wish I could remember what we did to fix it...
First, check your mednafen.cfg file, and make sure its set up for bram saves; I vaguely recall if you don't specify a path for something, it won't actually save to a file.
Second, delete any old bram files you find. I do remember everytime I changed the cd image, mednafen created a new bram file (empty of course) with a different name. I believe the name was based on a hash of the code, and if things in the iso changed, you got a new save file.
Other than that ask the mednafen author what's going on / if he has any ideas. He's a pretty ok guy explaining why things do what they do. And if it's really an emulation problems, he does get it fixed.
Also, the CDREAD routine is annoying. I can only read in as many free banks as I have logical address range for (32k at a time)
The syscard 3.0 (?) CD_READ uses DH as a read type; the nice (or not) thing is you can specify an MPR bank to use for the read, and it is capable of filling consecutive banks for you.
And I -think- it may even load partial banks if the length isn't a multiple of 4 sectors.
Somewhere around there there used to be a HuCD7_final.pdf file that had the details on how the bios did things; not sure if it was 2.0 or 3.0, but the things it says do work on a 3.0 card.
That's how we figured out how to do MML :)
-
Yeah, I set _DH to the MPR page and put the starting bank in _BL. Maybe I missed something. I'll give it another try. It seems weird that they wouldn't allow all 256k to be loaded in a single pass (#$80 sectors).
-
Somewhere around there there used to be a HuCD7_final.pdf file that had the details on how the bios did things; not sure if it was 2.0 or 3.0, but the things it says do work on a 3.0 card.
I have it. It's listed as CD-ROM BIOS ver 1.00
-
Ok. I tracked down the problem with BRAM code. For some reason, mednafen won't unlock BRAM if you write "Hu",$80 to port $1807 if the emulator is in CD mode. It only works if you write only $80 to the port. So definitely an emulator thing. And the other thing that I noted; you can't see the contents of BRAM while you're stepping through the routine in the debugger if the emulator is in CD mode. For hucard mode, this isn't an issue.
So it was a two fold problem. I was able to mix and match sys card and my own routines now, in a CD project.
-
Ok. I tracked down the problem with BRAM code.
Good to hear. Now, when can we expect Dragon Warrior?
-
Yeah, I set _DH to the MPR page and put the starting bank in _BL.
lda #4 ; $8000 range / sta _DH / lda #80 /sta BL kinda thing?
As I found out, there's a gap in page numbers...so it probably can only load 64K at a time.
[Syscard 3.0 banks are at $60-$6F, iirc. Then you jump to $80-$8F for 'stock' pages.
I could be wrong though, with the ranges. I just remember they aren't consecutive.]
-
Ok. I tracked down the problem with BRAM code. For some reason, mednafen won't unlock BRAM if you write "Hu",$80 to port $1807 if the emulator is in CD mode. It only works if you write only $80 to the port. So definitely an emulator thing.
Do you have a Mednafen patch for that, or are you working around it in your PCE test-code?
-
I ended up using an .ifndef for an assembler variable/argument. Declaring _CDPROJ switches to the different unlock code.
-
Just wanted to say that I started real system tests, since ironing out the problems with the emulator, and everything seems to work as it should (the custom bram lib). And as expected, the real CD unit doesn't care what's written to port $1807; only the last byte being $80. So that's totally a mednafen thing.
-
[Syscard 3.0 banks are at $60-$6F, iirc. Then you jump to $80-$8F for 'stock' pages.
I could be wrong though, with the ranges. I just remember they aren't consecutive.]
Are you sure about this? Isn't (S)CD RAM consecutive from bank $68-$87, with $80-$87 being standard CD RAM?
-
[Syscard 3.0 banks are at $60-$6F, iirc. Then you jump to $80-$8F for 'stock' pages.
I could be wrong though, with the ranges. I just remember they aren't consecutive.]
Are you sure about this? Isn't (S)CD RAM consecutive from bank $68-$87, with $80-$87 being standard CD RAM?
I'm with Chris on this... I'm certain that the "additional" memory goes to $7F, to make memory contiguous.
Dave
-
I'm certain that the "additional" memory goes to $7F, to make memory contiguous.
Okay. Being wrong is part of learning.
I have a hard enough time remembering things, anyway. (At least since I turned XX)
So, to do this the card either has a 128K RAM + 64 K RAM + 64K ROM and a decoder sith some glue chips, or 3 * 64K RAM + 64K ROM + decoder....
Hmm. must have been a pain to get wired.
And the bios converts number-of-sectors to read to number-of-bytes to read, which is where the 64K limit comes in. Got it.
<Now, can it be fixed.....>
-
<edit>
256 K ROM
(16+15 = 31 * 8 = 256K)
-
Just wanted to say that I started real system tests, since ironing out the problems with the emulator, and everything seems to work as it should (the custom bram lib). And as expected, the real CD unit doesn't care what's written to port $1807; only the last byte being $80. So that's totally a mednafen thing.
I can fix a bug if you provide a test program with accompanying source code.